From eb9383fe409ebc678170c696a35d9dd43551ae27 Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Thu, 17 Sep 2015 08:38:38 -0700 Subject: [PATCH 0001/1029] Update LICENSE.txt --- LICENSE.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 LICENSE.txt diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000000..0bdc1962b6 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,12 @@ +Copyright (c) .NET Foundation. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +these files except in compliance with the License. You may obtain a copy of the +License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. From dbd4aa98fc99cfe3477539dc7c636f239f035294 Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Thu, 17 Sep 2015 08:39:00 -0700 Subject: [PATCH 0002/1029] Create CONTRIBUTING.md --- CONTRIBUTING.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..64ff041d5c --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,4 @@ +Contributing +====== + +Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/dev/CONTRIBUTING.md) in the Home repo. From 62caf09ac4766f6b72dd184f4b047ba566f65bf5 Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Thu, 17 Sep 2015 08:44:43 -0700 Subject: [PATCH 0003/1029] Create README.md --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000000..628dcdbce3 --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +dnx-watch +=== +AppVeyor: [![AppVeyor](https://ci.appveyor.com/api/projects/status/fxhto3omtehio3aj/branch/dev?svg=true)](https://ci.appveyor.com/project/aspnetci/dnx-watch/branch/dev) + +Travis: [![Travis](https://travis-ci.org/aspnet/dnx-watch.svg?branch=dev)](https://travis-ci.org/aspnet/dnx-watch) + +This project is part of ASP.NET 5. You can find samples, documentation and getting started instructions for ASP.NET 5 at the [Home](https://github.com/aspnet/home) repo. + From 408759ec991674051d3a09560aff09ce1ad42a29 Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Thu, 17 Sep 2015 09:36:36 -0700 Subject: [PATCH 0004/1029] Update LICENSE.txt --- LICENSE.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 LICENSE.txt diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000000..0bdc1962b6 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,12 @@ +Copyright (c) .NET Foundation. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +these files except in compliance with the License. You may obtain a copy of the +License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. From b63d1b618710ab5e6064e013c62dc1d51aa5c877 Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Thu, 17 Sep 2015 09:36:53 -0700 Subject: [PATCH 0005/1029] Create CONTRIBUTING.md --- CONTRIBUTING.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..64ff041d5c --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,4 @@ +Contributing +====== + +Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/dev/CONTRIBUTING.md) in the Home repo. From 98ce82ed72a2c8a02717c615082e3d9a4decef3e Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Thu, 17 Sep 2015 09:41:13 -0700 Subject: [PATCH 0006/1029] Create README.md --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000000..c30d38e62f --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +JsonPatch +=== +AppVeyor: [![AppVeyor](https://ci.appveyor.com/api/projects/status/51gggjks5k3q6pr5/branch/dev?svg=true)](https://ci.appveyor.com/project/aspnetci/JsonPatch/branch/dev) + +Travis: [![Travis](https://travis-ci.org/aspnet/JsonPatch.svg?branch=dev)](https://travis-ci.org/aspnet/JsonPatch) + +This project is part of ASP.NET 5. You can find samples, documentation and getting started instructions for ASP.NET 5 at the [Home](https://github.com/aspnet/home) repo. + + From d3f2b240d752e7eb90f0510d7e0d60e6f51cf625 Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Mon, 21 Sep 2015 10:42:05 -0700 Subject: [PATCH 0007/1029] Add build-template files --- .gitignore | 36 ++++++++++++++++++++++++++++++++++++ .travis.yml | 13 +++++++++++++ NuGet.config | 7 +++++++ appveyor.yml | 7 +++++++ build.cmd | 39 +++++++++++++++++++++++++++++++++++++++ build.sh | 41 +++++++++++++++++++++++++++++++++++++++++ global.json | 3 +++ makefile.shade | 12 ++++++++++++ 8 files changed, 158 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 NuGet.config create mode 100644 appveyor.yml create mode 100644 build.cmd create mode 100644 build.sh create mode 100644 global.json create mode 100644 makefile.shade diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..8a9bbc3a43 --- /dev/null +++ b/.gitignore @@ -0,0 +1,36 @@ +[Oo]bj/ +[Bb]in/ +TestResults/ +.nuget/ +*.sln.ide/ +_ReSharper.*/ +packages/ +artifacts/ +PublishProfiles/ +.vs/ +bower_components/ +node_modules/ +**/wwwroot/lib/ +debugSettings.json +project.lock.json +*.user +*.suo +*.cache +*.docstates +_ReSharper.* +nuget.exe +*net45.csproj +*net451.csproj +*k10.csproj +*.psess +*.vsp +*.pidb +*.userprefs +*DS_Store +*.ncrunchsolution +*.*sdf +*.ipch +.settings +*.sln.ide +node_modules +**/[Cc]ompiler/[Rr]esources/**/*.js diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..568e2673e9 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,13 @@ +language: csharp +sudo: false +mono: + - beta +env: + - MONO_THREADS_PER_CPU=2000 MONO_MANAGED_WATCHER=disabled +os: + - linux + - osx +before_script: + - if [ $TRAVIS_OS_NAME == "osx" ] ; then sudo sysctl -w kern.maxfiles=64000 ; sudo sysctl -w kern.maxfilesperproc=64000 ; sudo launchctl limit maxfiles 64000 64000 ; fi ; ulimit -n 64000 +script: + - ./build.sh --quiet verify \ No newline at end of file diff --git a/NuGet.config b/NuGet.config new file mode 100644 index 0000000000..52bf414192 --- /dev/null +++ b/NuGet.config @@ -0,0 +1,7 @@ + + + + + + + diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000000..58a3e1bc22 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,7 @@ +init: + - git config --global core.autocrlf true +build_script: + - build.cmd --quiet --parallel verify +clone_depth: 1 +test: off +deploy: off \ No newline at end of file diff --git a/build.cmd b/build.cmd new file mode 100644 index 0000000000..177997c42e --- /dev/null +++ b/build.cmd @@ -0,0 +1,39 @@ +@echo off +cd %~dp0 + +SETLOCAL +SET NUGET_VERSION=latest +SET CACHED_NUGET=%LocalAppData%\NuGet\nuget.%NUGET_VERSION%.exe +SET BUILDCMD_KOREBUILD_VERSION="" +SET BUILDCMD_DNX_VERSION="" + +IF EXIST %CACHED_NUGET% goto copynuget +echo Downloading latest version of NuGet.exe... +IF NOT EXIST %LocalAppData%\NuGet md %LocalAppData%\NuGet +@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/%NUGET_VERSION%/nuget.exe' -OutFile '%CACHED_NUGET%'" + +:copynuget +IF EXIST .nuget\nuget.exe goto restore +md .nuget +copy %CACHED_NUGET% .nuget\nuget.exe > nul + +:restore +IF EXIST packages\KoreBuild goto run +IF %BUILDCMD_KOREBUILD_VERSION%=="" ( + .nuget\nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre +) ELSE ( + .nuget\nuget.exe install KoreBuild -version %BUILDCMD_KOREBUILD_VERSION% -ExcludeVersion -o packages -nocache -pre +) +.nuget\nuget.exe install Sake -ExcludeVersion -Out packages + +IF "%SKIP_DNX_INSTALL%"=="1" goto run +IF %BUILDCMD_DNX_VERSION%=="" ( + CALL packages\KoreBuild\build\dnvm upgrade -runtime CLR -arch x86 +) ELSE ( + CALL packages\KoreBuild\build\dnvm install %BUILDCMD_DNX_VERSION% -runtime CLR -arch x86 -a default +) +CALL packages\KoreBuild\build\dnvm install default -runtime CoreCLR -arch x86 + +:run +CALL packages\KoreBuild\build\dnvm use default -runtime CLR -arch x86 +packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %* \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100644 index 0000000000..0c66139817 --- /dev/null +++ b/build.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +if test `uname` = Darwin; then + cachedir=~/Library/Caches/KBuild +else + if [ -z $XDG_DATA_HOME ]; then + cachedir=$HOME/.local/share + else + cachedir=$XDG_DATA_HOME; + fi +fi +mkdir -p $cachedir +nugetVersion=latest +cachePath=$cachedir/nuget.$nugetVersion.exe + +url=https://dist.nuget.org/win-x86-commandline/$nugetVersion/nuget.exe + +if test ! -f $cachePath; then + wget -O $cachePath $url 2>/dev/null || curl -o $cachePath --location $url /dev/null +fi + +if test ! -e .nuget; then + mkdir .nuget + cp $cachePath .nuget/nuget.exe +fi + +if test ! -d packages/KoreBuild; then + mono .nuget/nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre + mono .nuget/nuget.exe install Sake -ExcludeVersion -Out packages +fi + +if ! type dnvm > /dev/null 2>&1; then + source packages/KoreBuild/build/dnvm.sh +fi + +if ! type dnx > /dev/null 2>&1; then + dnvm upgrade +fi + +mono packages/Sake/tools/Sake.exe -I packages/KoreBuild/build -f makefile.shade "$@" + diff --git a/global.json b/global.json new file mode 100644 index 0000000000..fad3dfeab0 --- /dev/null +++ b/global.json @@ -0,0 +1,3 @@ +{ + "projects": ["src", "test/WebSites", "samples"] +} diff --git a/makefile.shade b/makefile.shade new file mode 100644 index 0000000000..c87524a3ef --- /dev/null +++ b/makefile.shade @@ -0,0 +1,12 @@ + +var VERSION='0.1' +var FULL_VERSION='0.1' +var AUTHORS='Microsoft Open Technologies, Inc.' + +use-standard-lifecycle +k-standard-goals + +#xml-docs-test .clean .build-compile description='Check generated XML documentation files for errors' target='package' + k-xml-docs-test + + From e0ac69c9f79d8486357531f0ea5125bbef3c42fa Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Mon, 21 Sep 2015 11:15:18 -0700 Subject: [PATCH 0008/1029] Add JsonPatch Moved from https://github.com/aspnet/Mvc --- JsonPatch.sln | 36 + NuGet.config | 2 +- .../Adapters/IObjectAdapter.cs | 19 + .../Adapters/ObjectAdapter.cs | 1105 +++++++++ .../Converters/JsonPatchDocumentConverter.cs | 76 + .../TypedJsonPatchDocumentConverter.cs | 65 + .../Exceptions/JsonPatchException.cs | 38 + .../Helpers/ActualPropertyPathResult.cs | 22 + .../Helpers/ConversionResult.cs | 17 + .../ExpandoObjectDictionaryExtensions.cs | 77 + .../Helpers/ExpressionHelpers.cs | 99 + .../Helpers/GetValueResult.cs | 30 + .../Helpers/JsonPatchProperty.cs | 43 + .../Helpers/ObjectTreeAnalyisResult.cs | 210 ++ .../Helpers/PathHelpers.cs | 31 + .../Helpers/RemovedPropertyTypeResult.cs | 38 + .../IJsonPatchDocument.cs | 16 + .../JsonPatchDocument.cs | 222 ++ .../JsonPatchDocumentOfT.cs | 700 ++++++ .../JsonPatchError.cs | 50 + .../Microsoft.AspNet.JsonPatch.xproj | 17 + .../Operations/Operation.cs | 74 + .../Operations/OperationBase.cs | 57 + .../Operations/OperationOfT.cs | 83 + .../Operations/OperationType.cs | 15 + .../Properties/AssemblyInfo.cs | 8 + .../Properties/Resources.Designer.cs | 270 +++ src/Microsoft.AspNet.JsonPatch/Resources.resx | 165 ++ src/Microsoft.AspNet.JsonPatch/project.json | 25 + .../Dynamic/AddOperationTests.cs | 569 +++++ .../Dynamic/AddTypedOperationTests.cs | 121 + .../Dynamic/CopyOperationTests.cs | 245 ++ .../Dynamic/CopyTypedOperationTests.cs | 268 +++ .../Dynamic/MoveOperationTests.cs | 338 +++ .../Dynamic/MoveTypedOperationTests.cs | 138 ++ .../Dynamic/NestedDTO.cs | 11 + .../Dynamic/PatchDocumentTests.cs | 95 + .../Dynamic/RemoveOperationTests.cs | 302 +++ .../Dynamic/RemoveTypedOperationTests.cs | 244 ++ .../Dynamic/ReplaceOperationTests.cs | 242 ++ .../Dynamic/ReplaceTypedOperationTests.cs | 191 ++ .../Dynamic/SimpleDTO.cs | 21 + .../Dynamic/SimpleDTOWithNestedDTO.cs | 22 + .../Microsoft.AspNet.JsonPatch.Test.xproj | 20 + .../NestedDTO.cs | 10 + .../NestedObjectTests.cs | 2041 +++++++++++++++++ .../ObjectAdapterTests.cs | 1737 ++++++++++++++ .../SimpleDTO.cs | 22 + .../SimpleDTOWithNestedDTO.cs | 27 + .../TestErrorLogger.cs | 15 + .../project.json | 18 + 51 files changed, 10306 insertions(+), 1 deletion(-) create mode 100644 JsonPatch.sln create mode 100644 src/Microsoft.AspNet.JsonPatch/Adapters/IObjectAdapter.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/Adapters/ObjectAdapter.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/Converters/JsonPatchDocumentConverter.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/Exceptions/JsonPatchException.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/Helpers/ActualPropertyPathResult.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/Helpers/ConversionResult.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/Helpers/ExpandoObjectDictionaryExtensions.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/Helpers/ExpressionHelpers.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/Helpers/GetValueResult.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/Helpers/JsonPatchProperty.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/Helpers/ObjectTreeAnalyisResult.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/Helpers/PathHelpers.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/Helpers/RemovedPropertyTypeResult.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/IJsonPatchDocument.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/JsonPatchDocument.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/JsonPatchDocumentOfT.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/JsonPatchError.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/Microsoft.AspNet.JsonPatch.xproj create mode 100644 src/Microsoft.AspNet.JsonPatch/Operations/Operation.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/Operations/OperationBase.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/Operations/OperationOfT.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/Operations/OperationType.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/Properties/AssemblyInfo.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/Properties/Resources.Designer.cs create mode 100644 src/Microsoft.AspNet.JsonPatch/Resources.resx create mode 100644 src/Microsoft.AspNet.JsonPatch/project.json create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/Dynamic/AddOperationTests.cs create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/Dynamic/CopyOperationTests.cs create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/Dynamic/MoveOperationTests.cs create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/Dynamic/NestedDTO.cs create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/Dynamic/PatchDocumentTests.cs create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/Dynamic/RemoveOperationTests.cs create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/Dynamic/ReplaceTypedOperationTests.cs create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/Dynamic/SimpleDTO.cs create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/Dynamic/SimpleDTOWithNestedDTO.cs create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/Microsoft.AspNet.JsonPatch.Test.xproj create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/NestedDTO.cs create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/NestedObjectTests.cs create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/ObjectAdapterTests.cs create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/SimpleDTO.cs create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/SimpleDTOWithNestedDTO.cs create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/TestErrorLogger.cs create mode 100644 test/Microsoft.AspNet.JsonPatch.Test/project.json diff --git a/JsonPatch.sln b/JsonPatch.sln new file mode 100644 index 0000000000..01e02f3125 --- /dev/null +++ b/JsonPatch.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.23107.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{430B59ED-F960-4D3A-8FFE-3370008E168D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{36CD6341-AB44-44EB-B3AA-BF98C89FECDD}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.JsonPatch", "src\Microsoft.AspNet.JsonPatch\Microsoft.AspNet.JsonPatch.xproj", "{4D55F4D8-633B-462F-A5B1-FEB84BD2D534}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.JsonPatch.Test", "test\Microsoft.AspNet.JsonPatch.Test\Microsoft.AspNet.JsonPatch.Test.xproj", "{81C20848-E063-4E12-AC40-0B55A532C16C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4D55F4D8-633B-462F-A5B1-FEB84BD2D534}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4D55F4D8-633B-462F-A5B1-FEB84BD2D534}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4D55F4D8-633B-462F-A5B1-FEB84BD2D534}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4D55F4D8-633B-462F-A5B1-FEB84BD2D534}.Release|Any CPU.Build.0 = Release|Any CPU + {81C20848-E063-4E12-AC40-0B55A532C16C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {81C20848-E063-4E12-AC40-0B55A532C16C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {81C20848-E063-4E12-AC40-0B55A532C16C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {81C20848-E063-4E12-AC40-0B55A532C16C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {4D55F4D8-633B-462F-A5B1-FEB84BD2D534} = {430B59ED-F960-4D3A-8FFE-3370008E168D} + {81C20848-E063-4E12-AC40-0B55A532C16C} = {36CD6341-AB44-44EB-B3AA-BF98C89FECDD} + EndGlobalSection +EndGlobal diff --git a/NuGet.config b/NuGet.config index 52bf414192..5500f6d507 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,4 +1,4 @@ - + diff --git a/src/Microsoft.AspNet.JsonPatch/Adapters/IObjectAdapter.cs b/src/Microsoft.AspNet.JsonPatch/Adapters/IObjectAdapter.cs new file mode 100644 index 0000000000..724dfe3f79 --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Adapters/IObjectAdapter.cs @@ -0,0 +1,19 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.JsonPatch.Operations; + +namespace Microsoft.AspNet.JsonPatch.Adapters +{ + /// + /// Defines the operations that can be performed on a JSON patch document. + /// + public interface IObjectAdapter + { + void Add(Operation operation, object objectToApplyTo); + void Copy(Operation operation, object objectToApplyTo); + void Move(Operation operation, object objectToApplyTo); + void Remove(Operation operation, object objectToApplyTo); + void Replace(Operation operation, object objectToApplyTo); + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.JsonPatch/Adapters/ObjectAdapter.cs b/src/Microsoft.AspNet.JsonPatch/Adapters/ObjectAdapter.cs new file mode 100644 index 0000000000..4640e97039 --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Adapters/ObjectAdapter.cs @@ -0,0 +1,1105 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using Microsoft.AspNet.JsonPatch.Exceptions; +using Microsoft.AspNet.JsonPatch.Helpers; +using Microsoft.AspNet.JsonPatch.Operations; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; + +namespace Microsoft.AspNet.JsonPatch.Adapters +{ + /// + public class ObjectAdapter : IObjectAdapter + { + /// + /// Initializes a new instance of . + /// + /// The . + /// The for logging . + public ObjectAdapter( + IContractResolver contractResolver, + Action logErrorAction) + { + if (contractResolver == null) + { + throw new ArgumentNullException(nameof(contractResolver)); + } + + ContractResolver = contractResolver; + LogErrorAction = logErrorAction; + } + + /// + /// Gets or sets the . + /// + public IContractResolver ContractResolver { get; } + + /// + /// Action for logging . + /// + public Action LogErrorAction { get; } + + /// + /// The "add" operation performs one of the following functions, + /// depending upon what the target location references: + /// + /// o If the target location specifies an array index, a new value is + /// inserted into the array at the specified index. + /// + /// o If the target location specifies an object member that does not + /// already exist, a new member is added to the object. + /// + /// o If the target location specifies an object member that does exist, + /// that member's value is replaced. + /// + /// The operation object MUST contain a "value" member whose content + /// specifies the value to be added. + /// + /// For example: + /// + /// { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] } + /// + /// When the operation is applied, the target location MUST reference one + /// of: + /// + /// o The root of the target document - whereupon the specified value + /// becomes the entire content of the target document. + /// + /// o A member to add to an existing object - whereupon the supplied + /// value is added to that object at the indicated location. If the + /// member already exists, it is replaced by the specified value. + /// + /// o An element to add to an existing array - whereupon the supplied + /// value is added to the array at the indicated location. Any + /// elements at or above the specified index are shifted one position + /// to the right. The specified index MUST NOT be greater than the + /// number of elements in the array. If the "-" character is used to + /// index the end of the array (see [RFC6901]), this has the effect of + /// appending the value to the array. + /// + /// Because this operation is designed to add to existing objects and + /// arrays, its target location will often not exist. Although the + /// pointer's error handling algorithm will thus be invoked, this + /// specification defines the error handling behavior for "add" pointers + /// to ignore that error and add the value as specified. + /// + /// However, the object itself or an array containing it does need to + /// exist, and it remains an error for that not to be the case. For + /// example, an "add" with a target location of "/a/b" starting with this + /// document: + /// + /// { "a": { "foo": 1 } } + /// + /// is not an error, because "a" exists, and "b" will be added to its + /// value. It is an error in this document: + /// + /// { "q": { "bar": 2 } } + /// + /// because "a" does not exist. + /// + /// The add operation. + /// Object to apply the operation to. + public void Add(Operation operation, object objectToApplyTo) + { + if (operation == null) + { + throw new ArgumentNullException(nameof(operation)); + } + + if (objectToApplyTo == null) + { + throw new ArgumentNullException(nameof(objectToApplyTo)); + } + + Add(operation.path, operation.value, objectToApplyTo, operation); + } + + /// + /// Add is used by various operations (eg: add, copy, ...), yet through different operations; + /// This method allows code reuse yet reporting the correct operation on error + /// + private void Add( + string path, + object value, + object objectToApplyTo, + Operation operationToReport) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + if (objectToApplyTo == null) + { + throw new ArgumentNullException(nameof(objectToApplyTo)); + } + + if (operationToReport == null) + { + throw new ArgumentNullException(nameof(operationToReport)); + } + + // first up: if the path ends in a numeric value, we're inserting in a list and + // that value represents the position; if the path ends in "-", we're appending + // to the list. + + // get path result + var pathResult = GetActualPropertyPath( + path, + objectToApplyTo, + operationToReport); + if (pathResult == null) + { + return; + } + + var appendList = pathResult.ExecuteAtEnd; + var positionAsInteger = pathResult.NumericEnd; + var actualPathToProperty = pathResult.PathToProperty; + + var treeAnalysisResult = new ObjectTreeAnalysisResult( + objectToApplyTo, + actualPathToProperty, + ContractResolver); + + if (!treeAnalysisResult.IsValidPathForAdd) + { + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatPropertyCannotBeAdded(path))); + return; + } + + if (treeAnalysisResult.UseDynamicLogic) + { + var container = treeAnalysisResult.Container; + if (container.ContainsCaseInsensitiveKey(treeAnalysisResult.PropertyPathInParent)) + { + // Existing property. + // If it's not an array, we need to check if the value fits the property type + // + // If it's an array, we need to check if the value fits in that array type, + // and add it at the correct position (if allowed). + if (appendList || positionAsInteger > -1) + { + // get the actual type + var propertyValue = container.GetValueForCaseInsensitiveKey(treeAnalysisResult.PropertyPathInParent); + var typeOfPathProperty = propertyValue.GetType(); + + if (!IsNonStringArray(typeOfPathProperty)) + { + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatInvalidIndexForArrayProperty(operationToReport.op, path))); + return; + } + + // now, get the generic type of the enumerable + var genericTypeOfArray = GetIListType(typeOfPathProperty); + var conversionResult = ConvertToActualType(genericTypeOfArray, value); + if (!conversionResult.CanBeConverted) + { + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatInvalidValueForProperty(value, path))); + return; + } + + // get value (it can be cast, we just checked that) + var array = treeAnalysisResult.Container.GetValueForCaseInsensitiveKey( + treeAnalysisResult.PropertyPathInParent) as IList; + + if (appendList) + { + array.Add(conversionResult.ConvertedInstance); + treeAnalysisResult.Container.SetValueForCaseInsensitiveKey( + treeAnalysisResult.PropertyPathInParent, array); + } + else + { + // specified index must not be greater than + // the amount of items in the array + if (positionAsInteger > array.Count) + { + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatInvalidIndexForArrayProperty( + operationToReport.op, + path))); + return; + } + + array.Insert(positionAsInteger, conversionResult.ConvertedInstance); + treeAnalysisResult.Container.SetValueForCaseInsensitiveKey( + treeAnalysisResult.PropertyPathInParent, array); + } + } + else + { + // get the actual type + var typeOfPathProperty = treeAnalysisResult.Container + .GetValueForCaseInsensitiveKey(treeAnalysisResult.PropertyPathInParent).GetType(); + + // can the value be converted to the actual type? + var conversionResult = ConvertToActualType(typeOfPathProperty, value); + if (conversionResult.CanBeConverted) + { + treeAnalysisResult.Container.SetValueForCaseInsensitiveKey( + treeAnalysisResult.PropertyPathInParent, + conversionResult.ConvertedInstance); + } + else + { + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatInvalidValueForProperty(conversionResult.ConvertedInstance, path))); + return; + } + } + } + else + { + // New property - add it. + treeAnalysisResult.Container.Add(treeAnalysisResult.PropertyPathInParent, value); + } + } + else + { + // If it's an array, add to that array. If it's not, we replace. + + // is the path an array (but not a string (= char[]))? In this case, + // the path must end with "/position" or "/-", which we already determined before. + + var patchProperty = treeAnalysisResult.JsonPatchProperty; + + if (appendList || positionAsInteger > -1) + { + if (!IsNonStringArray(patchProperty.Property.PropertyType)) + { + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatInvalidIndexForArrayProperty(operationToReport.op, path))); + return; + } + + // now, get the generic type of the IList<> from Property type. + var genericTypeOfArray = GetIListType(patchProperty.Property.PropertyType); + var conversionResult = ConvertToActualType(genericTypeOfArray, value); + if (!conversionResult.CanBeConverted) + { + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatInvalidValueForProperty(conversionResult.ConvertedInstance, path))); + return; + } + + if (!patchProperty.Property.Readable) + { + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatCannotReadProperty(path))); + return; + } + + var array = (IList)patchProperty.Property.ValueProvider.GetValue(patchProperty.Parent); + if (appendList) + { + array.Add(conversionResult.ConvertedInstance); + } + else if (positionAsInteger <= array.Count) + { + array.Insert(positionAsInteger, conversionResult.ConvertedInstance); + } + else + { + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatInvalidIndexForArrayProperty(operationToReport.op, path))); + return; + } + } + else + { + var conversionResultTuple = ConvertToActualType( + patchProperty.Property.PropertyType, + value); + + if (!conversionResultTuple.CanBeConverted) + { + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatInvalidValueForProperty(value, path))); + return; + } + + if (!patchProperty.Property.Writable) + { + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatCannotUpdateProperty(path))); + return; + } + + patchProperty.Property.ValueProvider.SetValue( + patchProperty.Parent, + conversionResultTuple.ConvertedInstance); + } + } + } + + /// + /// The "move" operation removes the value at a specified location and + /// adds it to the target location. + /// + /// The operation object MUST contain a "from" member, which is a string + /// containing a JSON Pointer value that references the location in the + /// target document to move the value from. + /// + /// The "from" location MUST exist for the operation to be successful. + /// + /// For example: + /// + /// { "op": "move", "from": "/a/b/c", "path": "/a/b/d" } + /// + /// This operation is functionally identical to a "remove" operation on + /// the "from" location, followed immediately by an "add" operation at + /// the target location with the value that was just removed. + /// + /// The "from" location MUST NOT be a proper prefix of the "path" + /// location; i.e., a location cannot be moved into one of its children. + /// + /// The move operation. + /// Object to apply the operation to. + public void Move(Operation operation, object objectToApplyTo) + { + if (operation == null) + { + throw new ArgumentNullException(nameof(operation)); + } + + if (objectToApplyTo == null) + { + throw new ArgumentNullException(nameof(objectToApplyTo)); + } + + var valueAtFromLocationResult = GetValueAtLocation(operation.from, objectToApplyTo, operation); + + if (valueAtFromLocationResult.HasError) + { + // Error has already been logged in GetValueAtLocation. We + // must return, because remove / add should not be allowed to continue + return; + } + + // remove that value + var removeResult = Remove(operation.from, objectToApplyTo, operation); + + if (removeResult.HasError) + { + // Return => error has already been logged in remove method. We must + // return, because add should not be allowed to continue + return; + } + + // add that value to the path location + Add(operation.path, + valueAtFromLocationResult.PropertyValue, + objectToApplyTo, + operation); + } + + /// + /// The "remove" operation removes the value at the target location. + /// + /// The target location MUST exist for the operation to be successful. + /// + /// For example: + /// + /// { "op": "remove", "path": "/a/b/c" } + /// + /// If removing an element from an array, any elements above the + /// specified index are shifted one position to the left. + /// + /// The remove operation. + /// Object to apply the operation to. + public void Remove(Operation operation, object objectToApplyTo) + { + if (operation == null) + { + throw new ArgumentNullException(nameof(operation)); + } + + if (objectToApplyTo == null) + { + throw new ArgumentNullException(nameof(objectToApplyTo)); + } + + Remove(operation.path, objectToApplyTo, operation); + } + + + /// + /// Remove is used by various operations (eg: remove, move, ...), yet through different operations; + /// This method allows code reuse yet reporting the correct operation on error. The return value + /// contains the type of the item that has been removed (and a bool possibly signifying an error) + /// This can be used by other methods, like replace, to ensure that we can pass in the correctly + /// typed value to whatever method follows. + /// + private RemovedPropertyTypeResult Remove(string path, object objectToApplyTo, Operation operationToReport) + { + // get path result + var pathResult = GetActualPropertyPath( + path, + objectToApplyTo, + operationToReport); + + if (pathResult == null) + { + return new RemovedPropertyTypeResult(null, true); + } + + var removeFromList = pathResult.ExecuteAtEnd; + var positionAsInteger = pathResult.NumericEnd; + var actualPathToProperty = pathResult.PathToProperty; + + var treeAnalysisResult = new ObjectTreeAnalysisResult( + objectToApplyTo, + actualPathToProperty, + ContractResolver); + + if (!treeAnalysisResult.IsValidPathForRemove) + { + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatPropertyCannotBeRemoved(path))); + return new RemovedPropertyTypeResult(null, true); + } + + if (treeAnalysisResult.UseDynamicLogic) + { + // if it's not an array, we can remove the property from + // the dictionary. If it's an array, we need to check the position first. + if (removeFromList || positionAsInteger > -1) + { + var propertyValue = treeAnalysisResult.Container + .GetValueForCaseInsensitiveKey(treeAnalysisResult.PropertyPathInParent); + + // we cannot continue when the value is null, because to be able to + // continue we need to be able to check if the array is a non-string array + if (propertyValue == null) + { + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatCannotDeterminePropertyType(path))); + return new RemovedPropertyTypeResult(null, true); + } + + var typeOfPathProperty = propertyValue.GetType(); + + if (!IsNonStringArray(typeOfPathProperty)) + { + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatInvalidIndexForArrayProperty(operationToReport.op, path))); + return new RemovedPropertyTypeResult(null, true); + } + + // now, get the generic type of the enumerable (we'll return this type) + var genericTypeOfArray = GetIListType(typeOfPathProperty); + + // get the array + var array = (IList)treeAnalysisResult.Container.GetValueForCaseInsensitiveKey( + treeAnalysisResult.PropertyPathInParent); + + if (array.Count == 0) + { + // if the array is empty, we should throw an error + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatInvalidIndexForArrayProperty( + operationToReport.op, + path))); + return new RemovedPropertyTypeResult(null, true); + } + + if (removeFromList) + { + array.RemoveAt(array.Count - 1); + treeAnalysisResult.Container.SetValueForCaseInsensitiveKey( + treeAnalysisResult.PropertyPathInParent, array); + + // return the type of the value that has been removed. + return new RemovedPropertyTypeResult(genericTypeOfArray, false); + } + else + { + if (positionAsInteger >= array.Count) + { + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatInvalidIndexForArrayProperty( + operationToReport.op, + path))); + return new RemovedPropertyTypeResult(null, true); + } + + array.RemoveAt(positionAsInteger); + treeAnalysisResult.Container.SetValueForCaseInsensitiveKey( + treeAnalysisResult.PropertyPathInParent, array); + + // return the type of the value that has been removed. + return new RemovedPropertyTypeResult(genericTypeOfArray, false); + } + } + else + { + // get the property + var getResult = treeAnalysisResult.Container.GetValueForCaseInsensitiveKey( + treeAnalysisResult.PropertyPathInParent); + + // remove the property + treeAnalysisResult.Container.RemoveValueForCaseInsensitiveKey( + treeAnalysisResult.PropertyPathInParent); + + // value is not null, we can determine the type + if (getResult != null) + { + var actualType = getResult.GetType(); + return new RemovedPropertyTypeResult(actualType, false); + } + else + { + return new RemovedPropertyTypeResult(null, false); + } + } + } + else + { + // not dynamic + var patchProperty = treeAnalysisResult.JsonPatchProperty; + + if (removeFromList || positionAsInteger > -1) + { + if (!IsNonStringArray(patchProperty.Property.PropertyType)) + { + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatInvalidIndexForArrayProperty(operationToReport.op, path))); + return new RemovedPropertyTypeResult(null, true); + } + + // now, get the generic type of the IList<> from Property type. + var genericTypeOfArray = GetIListType(patchProperty.Property.PropertyType); + + if (!patchProperty.Property.Readable) + { + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatCannotReadProperty(path))); + return new RemovedPropertyTypeResult(null, true); + } + + var array = (IList)patchProperty.Property.ValueProvider + .GetValue(patchProperty.Parent); + + if (array.Count == 0) + { + // if the array is empty, we should throw an error + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatInvalidIndexForArrayProperty( + operationToReport.op, + path))); + return new RemovedPropertyTypeResult(null, true); + } + + if (removeFromList) + { + array.RemoveAt(array.Count - 1); + + // return the type of the value that has been removed + return new RemovedPropertyTypeResult(genericTypeOfArray, false); + } + else + { + if (positionAsInteger >= array.Count) + { + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatInvalidIndexForArrayProperty( + operationToReport.op, + path))); + return new RemovedPropertyTypeResult(null, true); + } + + array.RemoveAt(positionAsInteger); + + // return the type of the value that has been removed + return new RemovedPropertyTypeResult(genericTypeOfArray, false); + } + } + else + { + if (!patchProperty.Property.Writable) + { + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatCannotUpdateProperty(path))); + return new RemovedPropertyTypeResult(null, true); + } + + // setting the value to "null" will use the default value in case of value types, and + // null in case of reference types + object value = null; + + if (patchProperty.Property.PropertyType.GetTypeInfo().IsValueType + && Nullable.GetUnderlyingType(patchProperty.Property.PropertyType) == null) + { + value = Activator.CreateInstance(patchProperty.Property.PropertyType); + } + + patchProperty.Property.ValueProvider.SetValue(patchProperty.Parent, value); + return new RemovedPropertyTypeResult(patchProperty.Property.PropertyType, false); + } + } + } + + /// + /// The "replace" operation replaces the value at the target location + /// with a new value. The operation object MUST contain a "value" member + /// whose content specifies the replacement value. + /// + /// The target location MUST exist for the operation to be successful. + /// + /// For example: + /// + /// { "op": "replace", "path": "/a/b/c", "value": 42 } + /// + /// This operation is functionally identical to a "remove" operation for + /// a value, followed immediately by an "add" operation at the same + /// location with the replacement value. + /// + /// Note: even though it's the same functionally, we do not call remove + add + /// for performance reasons (multiple checks of same requirements). + /// + /// The replace operation. + /// Object to apply the operation to. + public void Replace(Operation operation, object objectToApplyTo) + { + if (operation == null) + { + throw new ArgumentNullException(nameof(operation)); + } + + if (objectToApplyTo == null) + { + throw new ArgumentNullException(nameof(objectToApplyTo)); + } + + var removeResult = Remove(operation.path, objectToApplyTo, operation); + + if (removeResult.HasError) + { + // return => error has already been logged in remove method + return; + } + + if (!removeResult.HasError && removeResult.ActualType == null) + { + // the remove operation completed succesfully, but we could not determine the type. + LogError(new JsonPatchError( + objectToApplyTo, + operation, + Resources.FormatCannotDeterminePropertyType(operation.from))); + return; + } + + var conversionResult = ConvertToActualType(removeResult.ActualType, operation.value); + + if (!conversionResult.CanBeConverted) + { + // invalid value for path + LogError(new JsonPatchError( + objectToApplyTo, + operation, + Resources.FormatInvalidValueForProperty(operation.value, operation.path))); + return; + } + + Add(operation.path, conversionResult.ConvertedInstance, objectToApplyTo, operation); + } + + /// + /// The "copy" operation copies the value at a specified location to the + /// target location. + /// + /// The operation object MUST contain a "from" member, which is a string + /// containing a JSON Pointer value that references the location in the + /// target document to copy the value from. + /// + /// The "from" location MUST exist for the operation to be successful. + /// + /// For example: + /// + /// { "op": "copy", "from": "/a/b/c", "path": "/a/b/e" } + /// + /// This operation is functionally identical to an "add" operation at the + /// target location using the value specified in the "from" member. + /// + /// Note: even though it's the same functionally, we do not call add with + /// the value specified in from for performance reasons (multiple checks of same requirements). + /// + /// The copy operation. + /// Object to apply the operation to. + public void Copy(Operation operation, object objectToApplyTo) + { + if (operation == null) + { + throw new ArgumentNullException(nameof(operation)); + } + + if (objectToApplyTo == null) + { + throw new ArgumentNullException(nameof(objectToApplyTo)); + } + + // get value at from location and add that value to the path location + var valueAtFromLocationResult = GetValueAtLocation(operation.from, objectToApplyTo, operation); + + if (valueAtFromLocationResult.HasError) + { + // Return, error has already been logged in GetValueAtLocation + return; + } + + Add(operation.path, + valueAtFromLocationResult.PropertyValue, + objectToApplyTo, + operation); + } + + /// + /// Method is used by Copy and Move to avoid duplicate code + /// + /// Location where value should be + /// Object to inspect for the desired value + /// Operation to report in case of an error + /// GetValueResult containing value and a bool signifying a possible error + private GetValueResult GetValueAtLocation( + string location, + object objectToGetValueFrom, + Operation operationToReport) + { + if (location == null) + { + throw new ArgumentNullException(nameof(location)); + } + + if (objectToGetValueFrom == null) + { + throw new ArgumentNullException(nameof(objectToGetValueFrom)); + } + + if (operationToReport == null) + { + throw new ArgumentNullException(nameof(operationToReport)); + } + + // get path result + var pathResult = GetActualPropertyPath( + location, + objectToGetValueFrom, + operationToReport); + + if (pathResult == null) + { + return new GetValueResult(null, true); + } + + var getAtEndOfList = pathResult.ExecuteAtEnd; + var positionAsInteger = pathResult.NumericEnd; + var actualPathToProperty = pathResult.PathToProperty; + + var treeAnalysisResult = new ObjectTreeAnalysisResult( + objectToGetValueFrom, + actualPathToProperty, + ContractResolver); + + if (treeAnalysisResult.UseDynamicLogic) + { + // if it's not an array, we can remove the property from + // the dictionary. If it's an array, we need to check the position first. + if (getAtEndOfList || positionAsInteger > -1) + { + var propertyValue = treeAnalysisResult.Container + .GetValueForCaseInsensitiveKey(treeAnalysisResult.PropertyPathInParent); + + // we cannot continue when the value is null, because to be able to + // continue we need to be able to check if the array is a non-string array + if (propertyValue == null) + { + LogError(new JsonPatchError( + objectToGetValueFrom, + operationToReport, + Resources.FormatCannotDeterminePropertyType(location))); + return new GetValueResult(null, true); + } + + var typeOfPathProperty = propertyValue.GetType(); + + if (!IsNonStringArray(typeOfPathProperty)) + { + LogError(new JsonPatchError( + objectToGetValueFrom, + operationToReport, + Resources.FormatInvalidIndexForArrayProperty(operationToReport.op, location))); + return new GetValueResult(null, true); + } + + // get the array + var array = (IList)treeAnalysisResult.Container.GetValueForCaseInsensitiveKey( + treeAnalysisResult.PropertyPathInParent); + + if (positionAsInteger >= array.Count) + { + LogError(new JsonPatchError( + objectToGetValueFrom, + operationToReport, + Resources.FormatInvalidIndexForArrayProperty( + operationToReport.op, + location))); + return new GetValueResult(null, true); + } + + if (getAtEndOfList) + { + return new GetValueResult(array[array.Count - 1], false); + } + else + { + return new GetValueResult(array[positionAsInteger], false); + } + } + else + { + // get the property + var propertyValueAtLocation = treeAnalysisResult.Container.GetValueForCaseInsensitiveKey( + treeAnalysisResult.PropertyPathInParent); + + return new GetValueResult(propertyValueAtLocation, false); + } + } + else + { + // not dynamic + var patchProperty = treeAnalysisResult.JsonPatchProperty; + + if (getAtEndOfList || positionAsInteger > -1) + { + if (!IsNonStringArray(patchProperty.Property.PropertyType)) + { + LogError(new JsonPatchError( + objectToGetValueFrom, + operationToReport, + Resources.FormatInvalidIndexForArrayProperty(operationToReport.op, location))); + return new GetValueResult(null, true); + } + + if (!patchProperty.Property.Readable) + { + LogError(new JsonPatchError( + objectToGetValueFrom, + operationToReport, + Resources.FormatCannotReadProperty(location))); + return new GetValueResult(null, true); + } + + var array = (IList)patchProperty.Property.ValueProvider + .GetValue(patchProperty.Parent); + + if (positionAsInteger >= array.Count) + { + LogError(new JsonPatchError( + objectToGetValueFrom, + operationToReport, + Resources.FormatInvalidIndexForArrayProperty( + operationToReport.op, + location))); + return new GetValueResult(null, true); + } + + if (getAtEndOfList) + { + return new GetValueResult(array[array.Count - 1], false); + } + else + { + return new GetValueResult(array[positionAsInteger], false); + } + } + else + { + if (!patchProperty.Property.Readable) + { + LogError(new JsonPatchError( + objectToGetValueFrom, + operationToReport, + Resources.FormatCannotReadProperty( + location))); + return new GetValueResult(null, true); + } + + var propertyValueAtLocation = patchProperty.Property.ValueProvider + .GetValue(patchProperty.Parent); + + return new GetValueResult(propertyValueAtLocation, false); + } + } + } + + private bool IsNonStringArray(Type type) + { + if (GetIListType(type) != null) + { + return true; + } + + return (!(type == typeof(string)) && typeof(IList).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo())); + } + + private void LogError(JsonPatchError jsonPatchError) + { + if (LogErrorAction != null) + { + LogErrorAction(jsonPatchError); + } + else + { + throw new JsonPatchException(jsonPatchError); + } + } + + private ConversionResult ConvertToActualType(Type propertyType, object value) + { + try + { + var o = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(value), propertyType); + + return new ConversionResult(true, o); + } + catch (Exception) + { + return new ConversionResult(false, null); + } + } + + private Type GetIListType(Type type) + { + if (IsGenericListType(type)) + { + return type.GetGenericArguments()[0]; + } + + foreach (Type interfaceType in type.GetTypeInfo().ImplementedInterfaces) + { + if (IsGenericListType(interfaceType)) + { + return interfaceType.GetGenericArguments()[0]; + } + } + + return null; + } + + private bool IsGenericListType(Type type) + { + if (type.GetTypeInfo().IsGenericType && + type.GetGenericTypeDefinition() == typeof(IList<>)) + { + return true; + } + + return false; + } + + private ActualPropertyPathResult GetActualPropertyPath( + string propertyPath, + object objectToApplyTo, + Operation operationToReport) + { + if (propertyPath == null) + { + throw new ArgumentNullException(nameof(propertyPath)); + } + + if (objectToApplyTo == null) + { + throw new ArgumentNullException(nameof(objectToApplyTo)); + } + + if (operationToReport == null) + { + throw new ArgumentNullException(nameof(operationToReport)); + } + + if (propertyPath.EndsWith("/-")) + { + return new ActualPropertyPathResult(-1, propertyPath.Substring(0, propertyPath.Length - 2), true); + } + else + { + var possibleIndex = propertyPath.Substring(propertyPath.LastIndexOf("/") + 1); + int castedIndex = -1; + if (int.TryParse(possibleIndex, out castedIndex)) + { + // has numeric end. + if (castedIndex > -1) + { + var pathToProperty = propertyPath.Substring( + 0, + propertyPath.LastIndexOf('/' + castedIndex.ToString())); + + return new ActualPropertyPathResult(castedIndex, pathToProperty, false); + } + else + { + // negative position - invalid path + LogError(new JsonPatchError( + objectToApplyTo, + operationToReport, + Resources.FormatNegativeIndexForArrayProperty(operationToReport.op, propertyPath))); + return null; + } + } + + return new ActualPropertyPathResult(-1, propertyPath, false); + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.JsonPatch/Converters/JsonPatchDocumentConverter.cs b/src/Microsoft.AspNet.JsonPatch/Converters/JsonPatchDocumentConverter.cs new file mode 100644 index 0000000000..4551f64043 --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Converters/JsonPatchDocumentConverter.cs @@ -0,0 +1,76 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using Microsoft.AspNet.JsonPatch.Exceptions; +using Microsoft.AspNet.JsonPatch.Operations; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Serialization; + +namespace Microsoft.AspNet.JsonPatch.Converters +{ + public class JsonPatchDocumentConverter : JsonConverter + { + public override bool CanConvert(Type objectType) + { + return true; + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, + JsonSerializer serializer) + { + if (objectType != typeof(JsonPatchDocument)) + { + throw new ArgumentException(Resources.FormatParameterMustMatchType("objectType", "JsonPatchDocument"), "objectType"); + } + + try + { + if (reader.TokenType == JsonToken.Null) + { + return null; + } + + // load jObject + var jObject = JArray.Load(reader); + + // Create target object for Json => list of operations + var targetOperations = new List(); + + // Create a new reader for this jObject, and set all properties + // to match the original reader. + var jObjectReader = jObject.CreateReader(); + jObjectReader.Culture = reader.Culture; + jObjectReader.DateParseHandling = reader.DateParseHandling; + jObjectReader.DateTimeZoneHandling = reader.DateTimeZoneHandling; + jObjectReader.FloatParseHandling = reader.FloatParseHandling; + + // Populate the object properties + serializer.Populate(jObjectReader, targetOperations); + + // container target: the JsonPatchDocument. + var container = new JsonPatchDocument(targetOperations, new DefaultContractResolver()); + + return container; + } + catch (Exception ex) + { + throw new JsonPatchException(Resources.FormatInvalidJsonPatchDocument(objectType.Name), ex); + } + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + if (value is IJsonPatchDocument) + { + var jsonPatchDoc = (IJsonPatchDocument)value; + var lst = jsonPatchDoc.GetOperations(); + + // write out the operations, no envelope + serializer.Serialize(writer, lst); + } + } + } +} diff --git a/src/Microsoft.AspNet.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs b/src/Microsoft.AspNet.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs new file mode 100644 index 0000000000..7b6bb77e17 --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs @@ -0,0 +1,65 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Reflection; +using Microsoft.AspNet.JsonPatch.Exceptions; +using Microsoft.AspNet.JsonPatch.Operations; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Serialization; + +namespace Microsoft.AspNet.JsonPatch.Converters +{ + public class TypedJsonPatchDocumentConverter : JsonPatchDocumentConverter + { + public override object ReadJson( + JsonReader reader, + Type objectType, + object existingValue, + JsonSerializer serializer) + { + try + { + if (reader.TokenType == JsonToken.Null) + { + return null; + } + + var genericType = objectType.GetGenericArguments()[0]; + + // load jObject + var jObject = JArray.Load(reader); + + // Create target object for Json => list of operations, typed to genericType + var genericOperation = typeof(Operation<>); + var concreteOperationType = genericOperation.MakeGenericType(genericType); + + var genericList = typeof(List<>); + var concreteList = genericList.MakeGenericType(concreteOperationType); + + var targetOperations = Activator.CreateInstance(concreteList); + + //Create a new reader for this jObject, and set all properties to match the original reader. + var jObjectReader = jObject.CreateReader(); + jObjectReader.Culture = reader.Culture; + jObjectReader.DateParseHandling = reader.DateParseHandling; + jObjectReader.DateTimeZoneHandling = reader.DateTimeZoneHandling; + jObjectReader.FloatParseHandling = reader.FloatParseHandling; + + // Populate the object properties + serializer.Populate(jObjectReader, targetOperations); + + // container target: the typed JsonPatchDocument. + var container = Activator.CreateInstance(objectType, targetOperations, new DefaultContractResolver()); + + return container; + } + catch (Exception ex) + { + throw new JsonPatchException(Resources.FormatInvalidJsonPatchDocument(objectType.Name), ex); + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.JsonPatch/Exceptions/JsonPatchException.cs b/src/Microsoft.AspNet.JsonPatch/Exceptions/JsonPatchException.cs new file mode 100644 index 0000000000..ac5222a2bb --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Exceptions/JsonPatchException.cs @@ -0,0 +1,38 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.AspNet.JsonPatch.Operations; + +namespace Microsoft.AspNet.JsonPatch.Exceptions +{ + public class JsonPatchException : Exception + { + public Operation FailedOperation { get; private set; } + public object AffectedObject { get; private set; } + + + public JsonPatchException() + { + + } + + public JsonPatchException(JsonPatchError jsonPatchError, Exception innerException) + : base(jsonPatchError.ErrorMessage, innerException) + { + FailedOperation = jsonPatchError.Operation; + AffectedObject = jsonPatchError.AffectedObject; + } + + public JsonPatchException(JsonPatchError jsonPatchError) + : this(jsonPatchError, null) + { + } + + public JsonPatchException(string message, Exception innerException) + : base (message, innerException) + { + + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.JsonPatch/Helpers/ActualPropertyPathResult.cs b/src/Microsoft.AspNet.JsonPatch/Helpers/ActualPropertyPathResult.cs new file mode 100644 index 0000000000..d22d1bf830 --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Helpers/ActualPropertyPathResult.cs @@ -0,0 +1,22 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.AspNet.JsonPatch.Helpers +{ + internal class ActualPropertyPathResult + { + public int NumericEnd { get; private set; } + public string PathToProperty { get; set; } + public bool ExecuteAtEnd { get; set; } + + public ActualPropertyPathResult( + int numericEnd, + string pathToProperty, + bool executeAtEnd) + { + NumericEnd = numericEnd; + PathToProperty = pathToProperty; + ExecuteAtEnd = executeAtEnd; + } + } +} diff --git a/src/Microsoft.AspNet.JsonPatch/Helpers/ConversionResult.cs b/src/Microsoft.AspNet.JsonPatch/Helpers/ConversionResult.cs new file mode 100644 index 0000000000..aba4913f2d --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Helpers/ConversionResult.cs @@ -0,0 +1,17 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.AspNet.JsonPatch.Helpers +{ + internal class ConversionResult + { + public bool CanBeConverted { get; private set; } + public object ConvertedInstance { get; private set; } + + public ConversionResult(bool canBeConverted, object convertedInstance) + { + CanBeConverted = canBeConverted; + ConvertedInstance = convertedInstance; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.JsonPatch/Helpers/ExpandoObjectDictionaryExtensions.cs b/src/Microsoft.AspNet.JsonPatch/Helpers/ExpandoObjectDictionaryExtensions.cs new file mode 100644 index 0000000000..a5911dded2 --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Helpers/ExpandoObjectDictionaryExtensions.cs @@ -0,0 +1,77 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; + +namespace Microsoft.AspNet.JsonPatch.Helpers +{ + // Helper methods to allow case-insensitive key search + internal static class ExpandoObjectDictionaryExtensions + { + internal static void SetValueForCaseInsensitiveKey( + this IDictionary propertyDictionary, + string key, + object value) + { + foreach (KeyValuePair kvp in propertyDictionary) + { + if (string.Equals(kvp.Key, key, StringComparison.OrdinalIgnoreCase)) + { + propertyDictionary[kvp.Key] = value; + break; + } + } + } + + internal static void RemoveValueForCaseInsensitiveKey( + this IDictionary propertyDictionary, + string key) + { + string realKey = null; + foreach (KeyValuePair kvp in propertyDictionary) + { + if (string.Equals(kvp.Key, key, StringComparison.OrdinalIgnoreCase)) + { + realKey = kvp.Key; + break; + } + } + + if (realKey != null) + { + propertyDictionary.Remove(realKey); + } + } + + internal static object GetValueForCaseInsensitiveKey( + this IDictionary propertyDictionary, + string key) + { + foreach (KeyValuePair kvp in propertyDictionary) + { + if (string.Equals(kvp.Key, key, StringComparison.OrdinalIgnoreCase)) + { + return kvp.Value; + } + } + + throw new ArgumentException(Resources.FormatDictionaryKeyNotFound(key)); + } + + internal static bool ContainsCaseInsensitiveKey( + this IDictionary propertyDictionary, + string key) + { + foreach (KeyValuePair kvp in propertyDictionary) + { + if (string.Equals(kvp.Key, key, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + + return false; + } + } +} diff --git a/src/Microsoft.AspNet.JsonPatch/Helpers/ExpressionHelpers.cs b/src/Microsoft.AspNet.JsonPatch/Helpers/ExpressionHelpers.cs new file mode 100644 index 0000000000..6a0279876c --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Helpers/ExpressionHelpers.cs @@ -0,0 +1,99 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Globalization; +using System.Linq.Expressions; + +namespace Microsoft.AspNet.JsonPatch.Helpers +{ + internal static class ExpressionHelpers + { + public static string GetPath(Expression> expr) where TModel : class + { + return "/" + GetPath(expr.Body, true); + } + + private static string GetPath(Expression expr, bool firstTime) + { + switch (expr.NodeType) + { + case ExpressionType.ArrayIndex: + var binaryExpression = (BinaryExpression)expr; + + if (ContinueWithSubPath(binaryExpression.Left.NodeType, false)) + { + var leftFromBinaryExpression = GetPath(binaryExpression.Left, false); + return leftFromBinaryExpression + "/" + binaryExpression.Right.ToString(); + } + else + { + return binaryExpression.Right.ToString(); + } + case ExpressionType.Call: + var methodCallExpression = (MethodCallExpression)expr; + + if (ContinueWithSubPath(methodCallExpression.Object.NodeType, false)) + { + var leftFromMemberCallExpression = GetPath(methodCallExpression.Object, false); + return leftFromMemberCallExpression + "/" + + GetIndexerInvocation(methodCallExpression.Arguments[0]); + } + else + { + return GetIndexerInvocation(methodCallExpression.Arguments[0]); + } + case ExpressionType.Convert: + return GetPath(((UnaryExpression)expr).Operand, false); + case ExpressionType.MemberAccess: + var memberExpression = expr as MemberExpression; + + if (ContinueWithSubPath(memberExpression.Expression.NodeType, false)) + { + var left = GetPath(memberExpression.Expression, false); + return left + "/" + memberExpression.Member.Name; + } + else + { + return memberExpression.Member.Name; + } + case ExpressionType.Parameter: + // Fits "x => x" (the whole document which is "" as JSON pointer) + return firstTime ? string.Empty : null; + default: + return string.Empty; + } + } + + private static bool ContinueWithSubPath(ExpressionType expressionType, bool firstTime) + { + if (firstTime) + { + return (expressionType == ExpressionType.ArrayIndex + || expressionType == ExpressionType.Call + || expressionType == ExpressionType.Convert + || expressionType == ExpressionType.MemberAccess + || expressionType == ExpressionType.Parameter); + } + else + { + return (expressionType == ExpressionType.ArrayIndex + || expressionType == ExpressionType.Call + || expressionType == ExpressionType.Convert + || expressionType == ExpressionType.MemberAccess); + } + } + + private static string GetIndexerInvocation(Expression expression) + { + var converted = Expression.Convert(expression, typeof(object)); + var fakeParameter = Expression.Parameter(typeof(object), null); + var lambda = Expression.Lambda>(converted, fakeParameter); + Func func; + + func = lambda.Compile(); + + return Convert.ToString(func(null), CultureInfo.InvariantCulture); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.JsonPatch/Helpers/GetValueResult.cs b/src/Microsoft.AspNet.JsonPatch/Helpers/GetValueResult.cs new file mode 100644 index 0000000000..89b7c93520 --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Helpers/GetValueResult.cs @@ -0,0 +1,30 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.AspNet.JsonPatch.Helpers +{ + /// + /// Return value for the helper method used by Copy/Move. Needed to ensure we can make a different + /// decision in the calling method when the value is null because it cannot be fetched (HasError = true) + /// versus when it actually is null (much like why RemovedPropertyTypeResult is used for returning + /// type in the Remove operation). + /// + public class GetValueResult + { + public GetValueResult(object propertyValue, bool hasError) + { + PropertyValue = propertyValue; + HasError = hasError; + } + + /// + /// The value of the property we're trying to get + /// + public object PropertyValue { get; private set; } + + /// + /// HasError: true when an error occurred, the operation didn't complete succesfully + /// + public bool HasError { get; private set; } + } +} diff --git a/src/Microsoft.AspNet.JsonPatch/Helpers/JsonPatchProperty.cs b/src/Microsoft.AspNet.JsonPatch/Helpers/JsonPatchProperty.cs new file mode 100644 index 0000000000..0539d230a3 --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Helpers/JsonPatchProperty.cs @@ -0,0 +1,43 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Newtonsoft.Json.Serialization; + +namespace Microsoft.AspNet.JsonPatch +{ + /// + /// Metadata for JsonProperty. + /// + public class JsonPatchProperty + { + /// + /// Initializes a new instance. + /// + public JsonPatchProperty(JsonProperty property, object parent) + { + if (property == null) + { + throw new ArgumentNullException(nameof(property)); + } + + if (parent == null) + { + throw new ArgumentNullException(nameof(parent)); + } + + Property = property; + Parent = parent; + } + + /// + /// Gets or sets JsonProperty. + /// + public JsonProperty Property { get; set; } + + /// + /// Gets or sets Parent. + /// + public object Parent { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.JsonPatch/Helpers/ObjectTreeAnalyisResult.cs b/src/Microsoft.AspNet.JsonPatch/Helpers/ObjectTreeAnalyisResult.cs new file mode 100644 index 0000000000..91d5ee129d --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Helpers/ObjectTreeAnalyisResult.cs @@ -0,0 +1,210 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json.Serialization; + +namespace Microsoft.AspNet.JsonPatch.Helpers +{ + internal class ObjectTreeAnalysisResult + { + // either the property is part of the container dictionary, + // or we have a direct reference to a JsonPatchProperty instance + + public bool UseDynamicLogic { get; private set; } + + public bool IsValidPathForAdd { get; private set; } + + public bool IsValidPathForRemove { get; private set; } + + public IDictionary Container { get; private set; } + + public string PropertyPathInParent { get; private set; } + + public JsonPatchProperty JsonPatchProperty { get; private set; } + + public ObjectTreeAnalysisResult( + object objectToSearch, + string propertyPath, + IContractResolver contractResolver) + { + // construct the analysis result. + + // split the propertypath, and if necessary, remove the first + // empty item (that's the case when it starts with a "/") + var propertyPathTree = propertyPath.Split( + new char[] { '/' }, + StringSplitOptions.RemoveEmptyEntries); + + // we've now got a split up property tree "base/property/otherproperty/..." + int lastPosition = 0; + object targetObject = objectToSearch; + for (int i = 0; i < propertyPathTree.Length; i++) + { + lastPosition = i; + + // if the current target object is an ExpandoObject (IDictionary), + // we cannot use the ContractResolver. + var dictionary = targetObject as IDictionary; + if (dictionary != null) + { + // find the value in the dictionary + if (dictionary.ContainsCaseInsensitiveKey(propertyPathTree[i])) + { + var possibleNewTargetObject = dictionary.GetValueForCaseInsensitiveKey(propertyPathTree[i]); + + // unless we're at the last item, we should set the targetobject + // to the new object. If we're at the last item, we need to stop + if (i != propertyPathTree.Length - 1) + { + targetObject = possibleNewTargetObject; + } + } + else + { + break; + } + } + else + { + // if the current part of the path is numeric, this means we're trying + // to get the propertyInfo of a specific object in an array. To allow + // for this, the previous value (targetObject) must be an IEnumerable, and + // the position must exist. + + int numericValue = -1; + if (int.TryParse(propertyPathTree[i], out numericValue)) + { + var element = GetElementAtFromObject(targetObject, numericValue); + if (element != null) + { + targetObject = element; + } + else + { + break; + } + } + else + { + var jsonContract = (JsonObjectContract)contractResolver.ResolveContract(targetObject.GetType()); + + // does the property exist? + var attemptedProperty = jsonContract + .Properties + .FirstOrDefault(p => string.Equals(p.PropertyName, propertyPathTree[i], StringComparison.OrdinalIgnoreCase)); + + if (attemptedProperty != null) + { + // unless we're at the last item, we should continue searching. + // If we're at the last item, we need to stop + if ((i != propertyPathTree.Length - 1)) + { + targetObject = attemptedProperty.ValueProvider.GetValue(targetObject); + } + } + else + { + // property cannot be found, and we're not working with dynamics. + // Stop, and return invalid path. + break; + } + } + } + } + + if (propertyPathTree.Length - lastPosition != 1) + { + IsValidPathForAdd = false; + IsValidPathForRemove = false; + return; + } + + // two things can happen now. The targetproperty can be an IDictionary - in that + // case, it's valid for add if there's 1 item left in the propertyPathTree. + // + // it can also be a property info. In that case, if there's nothing left in the path + // tree we're at the end, if there's one left we can try and set that. + if (targetObject is IDictionary) + { + UseDynamicLogic = true; + + Container = (IDictionary)targetObject; + IsValidPathForAdd = true; + PropertyPathInParent = propertyPathTree[propertyPathTree.Length - 1]; + + // to be able to remove this property, it must exist + IsValidPathForRemove = Container.ContainsCaseInsensitiveKey(PropertyPathInParent); + } + else if (targetObject is IList) + { + System.Diagnostics.Debugger.Launch(); + UseDynamicLogic = false; + + int index; + if (!Int32.TryParse(propertyPathTree[propertyPathTree.Length - 1], out index)) + { + // We only support indexing into a list + IsValidPathForAdd = false; + IsValidPathForRemove = false; + return; + } + + IsValidPathForAdd = true; + IsValidPathForRemove = ((IList)targetObject).Count > index; + PropertyPathInParent = propertyPathTree[propertyPathTree.Length - 1]; + } + else + { + UseDynamicLogic = false; + + var property = propertyPathTree[propertyPathTree.Length - 1]; + var jsonContract = (JsonObjectContract)contractResolver.ResolveContract(targetObject.GetType()); + var attemptedProperty = jsonContract + .Properties + .FirstOrDefault(p => string.Equals(p.PropertyName, property, StringComparison.OrdinalIgnoreCase)); + + if (attemptedProperty == null) + { + IsValidPathForAdd = false; + IsValidPathForRemove = false; + } + else + { + IsValidPathForAdd = true; + IsValidPathForRemove = true; + JsonPatchProperty = new JsonPatchProperty(attemptedProperty, targetObject); + PropertyPathInParent = property; + } + } + } + + private object GetElementAtFromObject(object targetObject, int numericValue) + { + if (numericValue > -1) + { + // Check if the targetobject is an IEnumerable, + // and if the position is valid. + if (targetObject is IEnumerable) + { + var indexable = ((IEnumerable)targetObject).Cast(); + + if (indexable.Count() >= numericValue) + { + return indexable.ElementAt(numericValue); + } + else { return null; } + } + else { return null; } + } + else + { + return null; + } + } + + } +} diff --git a/src/Microsoft.AspNet.JsonPatch/Helpers/PathHelpers.cs b/src/Microsoft.AspNet.JsonPatch/Helpers/PathHelpers.cs new file mode 100644 index 0000000000..28683e7c98 --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Helpers/PathHelpers.cs @@ -0,0 +1,31 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.JsonPatch.Exceptions; + +namespace Microsoft.AspNet.JsonPatch.Helpers +{ + internal static class PathHelpers + { + internal static string NormalizePath(string path) + { + // check for most common path errors on create. This is not + // absolutely necessary, but it allows us to already catch mistakes + // on creation of the patch document rather than on execute. + + if (path.Contains(".") || path.Contains("//") || path.Contains(" ") || path.Contains("\\")) + { + throw new JsonPatchException(Resources.FormatInvalidValueForPath(path), null); + } + + if (!(path.StartsWith("/"))) + { + return "/" + path; + } + else + { + return path; + } + } + } +} diff --git a/src/Microsoft.AspNet.JsonPatch/Helpers/RemovedPropertyTypeResult.cs b/src/Microsoft.AspNet.JsonPatch/Helpers/RemovedPropertyTypeResult.cs new file mode 100644 index 0000000000..9f5b97a868 --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Helpers/RemovedPropertyTypeResult.cs @@ -0,0 +1,38 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.AspNet.JsonPatch.Helpers +{ + /// + /// Return value for Remove operation. The combination tells us what to do next (if this operation + /// is called from inside another operation, eg: Replace, Copy. + /// + /// Possible combo: + /// - ActualType contains type: operation succesfully completed, can continue when called from inside + /// another operation + /// - ActualType null and HasError true: operation not completed succesfully, should not be allowed to continue + /// - ActualType null and HasError false: operation completed succesfully, but we should not be allowed to + /// continue when called from inside another method as we could not verify the type of the removed property. + /// This happens when the value of an item in an ExpandoObject dictionary is null. + /// + internal class RemovedPropertyTypeResult + { + /// + /// The type of the removed property (value) + /// + public Type ActualType { get; private set; } + + /// + /// HasError: true when an error occurred, the operation didn't complete succesfully + /// + public bool HasError { get; set; } + + public RemovedPropertyTypeResult(Type actualType, bool hasError) + { + ActualType = actualType; + HasError = hasError; + } + } +} diff --git a/src/Microsoft.AspNet.JsonPatch/IJsonPatchDocument.cs b/src/Microsoft.AspNet.JsonPatch/IJsonPatchDocument.cs new file mode 100644 index 0000000000..18033e82f0 --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/IJsonPatchDocument.cs @@ -0,0 +1,16 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.JsonPatch.Operations; +using System.Collections.Generic; +using Newtonsoft.Json.Serialization; + +namespace Microsoft.AspNet.JsonPatch +{ + public interface IJsonPatchDocument + { + IContractResolver ContractResolver { get; set; } + + IList GetOperations(); + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.JsonPatch/JsonPatchDocument.cs b/src/Microsoft.AspNet.JsonPatch/JsonPatchDocument.cs new file mode 100644 index 0000000000..fc2e73030a --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/JsonPatchDocument.cs @@ -0,0 +1,222 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using Microsoft.AspNet.JsonPatch.Adapters; +using Microsoft.AspNet.JsonPatch.Converters; +using Microsoft.AspNet.JsonPatch.Helpers; +using Microsoft.AspNet.JsonPatch.Operations; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; + +namespace Microsoft.AspNet.JsonPatch +{ + // Implementation details: the purpose of this type of patch document is to allow creation of such + // documents for cases where there's no class/DTO to work on. Typical use case: backend not built in + // .NET or architecture doesn't contain a shared DTO layer. + [JsonConverter(typeof(JsonPatchDocumentConverter))] + public class JsonPatchDocument : IJsonPatchDocument + { + public List Operations { get; private set; } + + [JsonIgnore] + public IContractResolver ContractResolver { get; set; } + + public JsonPatchDocument() + { + Operations = new List(); + ContractResolver = new DefaultContractResolver(); + } + + public JsonPatchDocument(List operations, IContractResolver contractResolver) + { + if (operations == null) + { + throw new ArgumentNullException(nameof(operations)); + } + + if (contractResolver == null) + { + throw new ArgumentNullException(nameof(contractResolver)); + } + + Operations = operations; + ContractResolver = contractResolver; + } + + /// + /// Add operation. Will result in, for example, + /// { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] } + /// + /// target location + /// value + /// + public JsonPatchDocument Add(string path, object value) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation("add", PathHelpers.NormalizePath(path), null, value)); + return this; + } + + /// + /// Remove value at target location. Will result in, for example, + /// { "op": "remove", "path": "/a/b/c" } + /// + /// target location + /// + public JsonPatchDocument Remove(string path) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation("remove", PathHelpers.NormalizePath(path), null, null)); + return this; + } + + /// + /// Replace value. Will result in, for example, + /// { "op": "replace", "path": "/a/b/c", "value": 42 } + /// + /// target location + /// value + /// + public JsonPatchDocument Replace(string path, object value) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation("replace", PathHelpers.NormalizePath(path), null, value)); + return this; + } + + /// + /// Removes value at specified location and add it to the target location. Will result in, for example: + /// { "op": "move", "from": "/a/b/c", "path": "/a/b/d" } + /// + /// source location + /// target location + /// + public JsonPatchDocument Move(string from, string path) + { + if (from == null) + { + throw new ArgumentNullException(nameof(from)); + } + + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation("move", PathHelpers.NormalizePath(path), PathHelpers.NormalizePath(from))); + return this; + } + + /// + /// Copy the value at specified location to the target location. Willr esult in, for example: + /// { "op": "copy", "from": "/a/b/c", "path": "/a/b/e" } + /// + /// source location + /// target location + /// + public JsonPatchDocument Copy(string from, string path) + { + if (from == null) + { + throw new ArgumentNullException(nameof(from)); + } + + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation("copy", PathHelpers.NormalizePath(path), PathHelpers.NormalizePath(from))); + return this; + } + + /// + /// Apply this JsonPatchDocument + /// + /// Object to apply the JsonPatchDocument to + public void ApplyTo(object objectToApplyTo) + { + if (objectToApplyTo == null) + { + throw new ArgumentNullException(nameof(objectToApplyTo)); + } + + ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction: null)); + } + + /// + /// Apply this JsonPatchDocument + /// + /// Object to apply the JsonPatchDocument to + /// Action to log errors + public void ApplyTo(object objectToApplyTo, Action logErrorAction) + { + if (objectToApplyTo == null) + { + throw new ArgumentNullException(nameof(objectToApplyTo)); + } + + ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction)); + } + + /// + /// Apply this JsonPatchDocument + /// + /// Object to apply the JsonPatchDocument to + /// IObjectAdapter instance to use when applying + public void ApplyTo(object objectToApplyTo, IObjectAdapter adapter) + { + if (objectToApplyTo == null) + { + throw new ArgumentNullException(nameof(objectToApplyTo)); + } + + if (adapter == null) + { + throw new ArgumentNullException(nameof(adapter)); + } + + // apply each operation in order + foreach (var op in Operations) + { + op.Apply(objectToApplyTo, adapter); + } + } + + IList IJsonPatchDocument.GetOperations() + { + var allOps = new List(); + + if (Operations != null) + { + foreach (var op in Operations) + { + var untypedOp = new Operation(); + + untypedOp.op = op.op; + untypedOp.value = op.value; + untypedOp.path = op.path; + untypedOp.from = op.from; + + allOps.Add(untypedOp); + } + } + + return allOps; + } + } +} diff --git a/src/Microsoft.AspNet.JsonPatch/JsonPatchDocumentOfT.cs b/src/Microsoft.AspNet.JsonPatch/JsonPatchDocumentOfT.cs new file mode 100644 index 0000000000..7b03f1644c --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/JsonPatchDocumentOfT.cs @@ -0,0 +1,700 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using Microsoft.AspNet.JsonPatch.Adapters; +using Microsoft.AspNet.JsonPatch.Converters; +using Microsoft.AspNet.JsonPatch.Helpers; +using Microsoft.AspNet.JsonPatch.Operations; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; + +namespace Microsoft.AspNet.JsonPatch +{ + // Implementation details: the purpose of this type of patch document is to ensure we can do type-checking + // when producing a JsonPatchDocument. However, we cannot send this "typed" over the wire, as that would require + // including type data in the JsonPatchDocument serialized as JSON (to allow for correct deserialization) - that's + // not according to RFC 6902, and would thus break cross-platform compatibility. + [JsonConverter(typeof(TypedJsonPatchDocumentConverter))] + public class JsonPatchDocument : IJsonPatchDocument where TModel : class + { + public List> Operations { get; private set; } + + [JsonIgnore] + public IContractResolver ContractResolver { get; set; } + + public JsonPatchDocument() + { + Operations = new List>(); + ContractResolver = new DefaultContractResolver(); + } + + // Create from list of operations + public JsonPatchDocument(List> operations, IContractResolver contractResolver) + { + if (operations == null) + { + throw new ArgumentNullException(nameof(operations)); + } + + if (contractResolver == null) + { + throw new ArgumentNullException(nameof(contractResolver)); + } + + Operations = operations; + ContractResolver = contractResolver; + } + + /// + /// Add operation. Will result in, for example, + /// { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] } + /// + /// value type + /// target location + /// value + /// + public JsonPatchDocument Add(Expression> path, TProp value) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "add", + ExpressionHelpers.GetPath(path).ToLowerInvariant(), + from: null, + value: value)); + + return this; + } + + /// + /// Add value to list at given position + /// + /// value type + /// target location + /// value + /// position + /// + public JsonPatchDocument Add( + Expression>> path, + TProp value, + int position) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "add", + ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + position, + from: null, + value: value)); + + return this; + } + + /// + /// At value at end of list + /// + /// value type + /// target location + /// value + /// + public JsonPatchDocument Add(Expression>> path, TProp value) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "add", + ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-", + from: null, + value: value)); + + return this; + } + + /// + /// Remove value at target location. Will result in, for example, + /// { "op": "remove", "path": "/a/b/c" } + /// + /// target location + /// + public JsonPatchDocument Remove(Expression> path) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation("remove", ExpressionHelpers.GetPath(path).ToLowerInvariant(), from: null)); + + return this; + } + + /// + /// Remove value from list at given position + /// + /// value type + /// target location + /// position + /// + public JsonPatchDocument Remove(Expression>> path, int position) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "remove", + ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + position, + from: null)); + + return this; + } + + /// + /// Remove value from end of list + /// + /// value type + /// target location + /// + public JsonPatchDocument Remove(Expression>> path) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "remove", + ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-", + from: null)); + + return this; + } + + /// + /// Replace value. Will result in, for example, + /// { "op": "replace", "path": "/a/b/c", "value": 42 } + /// + /// target location + /// value + /// + public JsonPatchDocument Replace(Expression> path, TProp value) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "replace", + ExpressionHelpers.GetPath(path).ToLowerInvariant(), + from: null, + value: value)); + + return this; + } + + /// + /// Replace value in a list at given position + /// + /// value type + /// target location + /// value + /// position + /// + public JsonPatchDocument Replace(Expression>> path, + TProp value, int position) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "replace", + ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + position, + from: null, + value: value)); + + return this; + } + + /// + /// Replace value at end of a list + /// + /// value type + /// target location + /// value + /// + public JsonPatchDocument Replace(Expression>> path, TProp value) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "replace", + ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-", + from: null, + value: value)); + + return this; + } + + /// + /// Removes value at specified location and add it to the target location. Will result in, for example: + /// { "op": "move", "from": "/a/b/c", "path": "/a/b/d" } + /// + /// source location + /// target location + /// + public JsonPatchDocument Move( + Expression> from, + Expression> path) + { + if (from == null) + { + throw new ArgumentNullException(nameof(from)); + } + + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "move", + ExpressionHelpers.GetPath(path).ToLowerInvariant(), + ExpressionHelpers.GetPath(from).ToLowerInvariant())); + + return this; + } + + /// + /// Move from a position in a list to a new location + /// + /// + /// source location + /// position + /// target location + /// + public JsonPatchDocument Move( + Expression>> from, + int positionFrom, + Expression> path) + { + if (from == null) + { + throw new ArgumentNullException(nameof(from)); + } + + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "move", + ExpressionHelpers.GetPath(path).ToLowerInvariant(), + ExpressionHelpers.GetPath(from).ToLowerInvariant() + "/" + positionFrom)); + + return this; + } + + /// + /// Move from a property to a location in a list + /// + /// + /// source location + /// target location + /// position + /// + public JsonPatchDocument Move( + Expression> from, + Expression>> path, + int positionTo) + { + if (from == null) + { + throw new ArgumentNullException(nameof(from)); + } + + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "move", + ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + positionTo, + ExpressionHelpers.GetPath(from).ToLowerInvariant())); + + return this; + } + + /// + /// Move from a position in a list to another location in a list + /// + /// + /// source location + /// position (source) + /// target location + /// position (target) + /// + public JsonPatchDocument Move( + Expression>> from, + int positionFrom, + Expression>> path, + int positionTo) + { + if (from == null) + { + throw new ArgumentNullException(nameof(from)); + } + + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "move", + ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + positionTo, + ExpressionHelpers.GetPath(from).ToLowerInvariant() + "/" + positionFrom)); + + return this; + } + + /// + /// Move from a position in a list to the end of another list + /// + /// + /// source location + /// position + /// target location + /// + public JsonPatchDocument Move( + Expression>> from, + int positionFrom, + Expression>> path) + { + if (from == null) + { + throw new ArgumentNullException(nameof(from)); + } + + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "move", + ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-", + ExpressionHelpers.GetPath(from).ToLowerInvariant() + "/" + positionFrom)); + + return this; + } + + /// + /// Move to the end of a list + /// + /// + /// source location + /// target location + /// + public JsonPatchDocument Move( + Expression> from, + Expression>> path) + { + if (from == null) + { + throw new ArgumentNullException(nameof(from)); + } + + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "move", + ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-", + ExpressionHelpers.GetPath(from).ToLowerInvariant())); + + return this; + } + + /// + /// Copy the value at specified location to the target location. Willr esult in, for example: + /// { "op": "copy", "from": "/a/b/c", "path": "/a/b/e" } + /// + /// source location + /// target location + /// + public JsonPatchDocument Copy( + Expression> from, + Expression> path) + { + if (from == null) + { + throw new ArgumentNullException(nameof(from)); + } + + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "copy", + ExpressionHelpers.GetPath(path).ToLowerInvariant() + , ExpressionHelpers.GetPath(from).ToLowerInvariant())); + + return this; + } + + /// + /// Copy from a position in a list to a new location + /// + /// + /// source location + /// position + /// target location + /// + public JsonPatchDocument Copy( + Expression>> from, + int positionFrom, + Expression> path) + { + if (from == null) + { + throw new ArgumentNullException(nameof(from)); + } + + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "copy", + ExpressionHelpers.GetPath(path).ToLowerInvariant(), + ExpressionHelpers.GetPath(from).ToLowerInvariant() + "/" + positionFrom)); + + return this; + } + + /// + /// Copy from a property to a location in a list + /// + /// + /// source location + /// target location + /// position + /// + public JsonPatchDocument Copy( + Expression> from, + Expression>> path, + int positionTo) + { + if (from == null) + { + throw new ArgumentNullException(nameof(from)); + } + + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "copy", + ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + positionTo, + ExpressionHelpers.GetPath(from).ToLowerInvariant())); + + return this; + } + + /// + /// Copy from a position in a list to a new location in a list + /// + /// + /// source location + /// position (source) + /// target location + /// position (target) + /// + public JsonPatchDocument Copy( + Expression>> from, + int positionFrom, + Expression>> path, + int positionTo) + { + if (from == null) + { + throw new ArgumentNullException(nameof(from)); + } + + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "copy", + ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + positionTo, + ExpressionHelpers.GetPath(from).ToLowerInvariant() + "/" + positionFrom)); + + return this; + } + + /// + /// Copy from a position in a list to the end of another list + /// + /// + /// source location + /// position + /// target location + /// + public JsonPatchDocument Copy( + Expression>> from, + int positionFrom, + Expression>> path) + { + if (from == null) + { + throw new ArgumentNullException(nameof(from)); + } + + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "copy", + ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-", + ExpressionHelpers.GetPath(from).ToLowerInvariant() + "/" + positionFrom)); + + return this; + } + + /// + /// Copy to the end of a list + /// + /// + /// source location + /// target location + /// + public JsonPatchDocument Copy( + Expression> from, + Expression>> path) + { + if (from == null) + { + throw new ArgumentNullException(nameof(from)); + } + + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "copy", + ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-", + ExpressionHelpers.GetPath(from).ToLowerInvariant())); + + return this; + } + + /// + /// Apply this JsonPatchDocument + /// + /// Object to apply the JsonPatchDocument to + public void ApplyTo(TModel objectToApplyTo) + { + if (objectToApplyTo == null) + { + throw new ArgumentNullException(nameof(objectToApplyTo)); + } + + ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction: null)); + } + + /// + /// Apply this JsonPatchDocument + /// + /// Object to apply the JsonPatchDocument to + /// Action to log errors + public void ApplyTo(TModel objectToApplyTo, Action logErrorAction) + { + if (objectToApplyTo == null) + { + throw new ArgumentNullException(nameof(objectToApplyTo)); + } + + ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction)); + } + + /// + /// Apply this JsonPatchDocument + /// + /// Object to apply the JsonPatchDocument to + /// IObjectAdapter instance to use when applying + public void ApplyTo(TModel objectToApplyTo, IObjectAdapter adapter) + { + if (objectToApplyTo == null) + { + throw new ArgumentNullException(nameof(objectToApplyTo)); + } + + if (adapter == null) + { + throw new ArgumentNullException(nameof(adapter)); + } + + // apply each operation in order + foreach (var op in Operations) + { + op.Apply(objectToApplyTo, adapter); + } + } + + IList IJsonPatchDocument.GetOperations() + { + var allOps = new List(); + + if (Operations != null) + { + foreach (var op in Operations) + { + var untypedOp = new Operation(); + + untypedOp.op = op.op; + untypedOp.value = op.value; + untypedOp.path = op.path; + untypedOp.from = op.from; + + allOps.Add(untypedOp); + } + } + + return allOps; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.JsonPatch/JsonPatchError.cs b/src/Microsoft.AspNet.JsonPatch/JsonPatchError.cs new file mode 100644 index 0000000000..a140f0d4c1 --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/JsonPatchError.cs @@ -0,0 +1,50 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.AspNet.JsonPatch.Operations; + +namespace Microsoft.AspNet.JsonPatch +{ + /// + /// Captures error message and the related entity and the operation that caused it. + /// + public class JsonPatchError + { + /// + /// Initializes a new instance of . + /// + /// The object that is affected by the error. + /// The that caused the error. + /// The error message. + public JsonPatchError( + object affectedObject, + Operation operation, + string errorMessage) + { + if (errorMessage == null) + { + throw new ArgumentNullException(nameof(errorMessage)); + } + + AffectedObject = affectedObject; + Operation = operation; + ErrorMessage = errorMessage; + } + + /// + /// Gets the object that is affected by the error. + /// + public object AffectedObject { get; } + + /// + /// Gets the that caused the error. + /// + public Operation Operation { get; } + + /// + /// Gets the error message. + /// + public string ErrorMessage { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.JsonPatch/Microsoft.AspNet.JsonPatch.xproj b/src/Microsoft.AspNet.JsonPatch/Microsoft.AspNet.JsonPatch.xproj new file mode 100644 index 0000000000..f9fb187ecd --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Microsoft.AspNet.JsonPatch.xproj @@ -0,0 +1,17 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 4d55f4d8-633b-462f-a5b1-feb84bd2d534 + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + 2.0 + + + \ No newline at end of file diff --git a/src/Microsoft.AspNet.JsonPatch/Operations/Operation.cs b/src/Microsoft.AspNet.JsonPatch/Operations/Operation.cs new file mode 100644 index 0000000000..7f056f41bf --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Operations/Operation.cs @@ -0,0 +1,74 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.AspNet.JsonPatch.Adapters; +using Newtonsoft.Json; + +namespace Microsoft.AspNet.JsonPatch.Operations +{ + public class Operation : OperationBase + { + [JsonProperty("value")] + public object value { get; set; } + + public Operation() + { + + } + + public Operation(string op, string path, string from, object value) + : base(op, path, from) + { + this.value = value; + } + + public Operation(string op, string path, string from) + : base(op, path, from) + { + } + + public void Apply(object objectToApplyTo, IObjectAdapter adapter) + { + if (objectToApplyTo == null) + { + throw new ArgumentNullException(nameof(objectToApplyTo)); + } + + if (adapter == null) + { + throw new ArgumentNullException(nameof(adapter)); + } + + switch (OperationType) + { + case OperationType.Add: + adapter.Add(this, objectToApplyTo); + break; + case OperationType.Remove: + adapter.Remove(this, objectToApplyTo); + break; + case OperationType.Replace: + adapter.Replace(this, objectToApplyTo); + break; + case OperationType.Move: + adapter.Move(this, objectToApplyTo); + break; + case OperationType.Copy: + adapter.Copy(this, objectToApplyTo); + break; + case OperationType.Test: + throw new NotSupportedException(Resources.TestOperationNotSupported); + default: + break; + } + } + + public bool ShouldSerializevalue() + { + return (OperationType == OperationType.Add + || OperationType == OperationType.Replace + || OperationType == OperationType.Test); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.JsonPatch/Operations/OperationBase.cs b/src/Microsoft.AspNet.JsonPatch/Operations/OperationBase.cs new file mode 100644 index 0000000000..17455f75e8 --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Operations/OperationBase.cs @@ -0,0 +1,57 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Newtonsoft.Json; + +namespace Microsoft.AspNet.JsonPatch.Operations +{ + public class OperationBase + { + [JsonIgnore] + public OperationType OperationType + { + get + { + return (OperationType)Enum.Parse(typeof(OperationType), op, true); + } + } + + [JsonProperty("path")] + public string path { get; set; } + + [JsonProperty("op")] + public string op { get; set; } + + [JsonProperty("from")] + public string from { get; set; } + + public OperationBase() + { + + } + + public OperationBase(string op, string path, string from) + { + if (op == null) + { + throw new ArgumentNullException(nameof(op)); + } + + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + this.op = op; + this.path = path; + this.from = from; + } + + public bool ShouldSerializefrom() + { + return (OperationType == OperationType.Move + || OperationType == OperationType.Copy); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.JsonPatch/Operations/OperationOfT.cs b/src/Microsoft.AspNet.JsonPatch/Operations/OperationOfT.cs new file mode 100644 index 0000000000..63663f70d9 --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Operations/OperationOfT.cs @@ -0,0 +1,83 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.AspNet.JsonPatch.Adapters; + +namespace Microsoft.AspNet.JsonPatch.Operations +{ + public class Operation : Operation where TModel : class + { + public Operation() + { + + } + + public Operation(string op, string path, string from, object value) + : base(op, path, from) + { + if (op == null) + { + throw new ArgumentNullException(nameof(op)); + } + + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + this.value = value; + } + + public Operation(string op, string path, string from) + : base(op, path, from) + { + if (op == null) + { + throw new ArgumentNullException(nameof(op)); + } + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + } + + public void Apply(TModel objectToApplyTo, IObjectAdapter adapter) + { + if (objectToApplyTo == null) + { + throw new ArgumentNullException(nameof(objectToApplyTo)); + } + + if (adapter == null) + { + throw new ArgumentNullException(nameof(adapter)); + } + + switch (OperationType) + { + case OperationType.Add: + adapter.Add(this, objectToApplyTo); + break; + case OperationType.Remove: + adapter.Remove(this, objectToApplyTo); + break; + case OperationType.Replace: + adapter.Replace(this, objectToApplyTo); + break; + case OperationType.Move: + adapter.Move(this, objectToApplyTo); + break; + case OperationType.Copy: + adapter.Copy(this, objectToApplyTo); + break; + case OperationType.Test: + throw new NotSupportedException(Resources.TestOperationNotSupported); + default: + break; + } + } + + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.JsonPatch/Operations/OperationType.cs b/src/Microsoft.AspNet.JsonPatch/Operations/OperationType.cs new file mode 100644 index 0000000000..a4d006bc51 --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Operations/OperationType.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.AspNet.JsonPatch.Operations +{ + public enum OperationType + { + Add, + Remove, + Replace, + Move, + Copy, + Test + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.JsonPatch/Properties/AssemblyInfo.cs b/src/Microsoft.AspNet.JsonPatch/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..b2437d9ad6 --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Properties/AssemblyInfo.cs @@ -0,0 +1,8 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Reflection; +using System.Resources; + +[assembly: AssemblyMetadata("Serviceable", "True")] +[assembly: NeutralResourcesLanguage("en-us")] \ No newline at end of file diff --git a/src/Microsoft.AspNet.JsonPatch/Properties/Resources.Designer.cs b/src/Microsoft.AspNet.JsonPatch/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..f0ee7f2439 --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Properties/Resources.Designer.cs @@ -0,0 +1,270 @@ +// +namespace Microsoft.AspNet.JsonPatch +{ + using System.Globalization; + using System.Reflection; + using System.Resources; + + internal static class Resources + { + private static readonly ResourceManager _resourceManager + = new ResourceManager("Microsoft.AspNet.JsonPatch.Resources", typeof(Resources).GetTypeInfo().Assembly); + + /// + /// The type of the property at path '{0}' could not be determined. + /// + internal static string CannotDeterminePropertyType + { + get { return GetString("CannotDeterminePropertyType"); } + } + + /// + /// The type of the property at path '{0}' could not be determined. + /// + internal static string FormatCannotDeterminePropertyType(object p0) + { + return string.Format(CultureInfo.CurrentCulture, GetString("CannotDeterminePropertyType"), p0); + } + + /// + /// The property at '{0}' could not be read. + /// + internal static string CannotReadProperty + { + get { return GetString("CannotReadProperty"); } + } + + /// + /// The property at '{0}' could not be read. + /// + internal static string FormatCannotReadProperty(object p0) + { + return string.Format(CultureInfo.CurrentCulture, GetString("CannotReadProperty"), p0); + } + + /// + /// The property at path '{0}' could not be updated. + /// + internal static string CannotUpdateProperty + { + get { return GetString("CannotUpdateProperty"); } + } + + /// + /// The property at path '{0}' could not be updated. + /// + internal static string FormatCannotUpdateProperty(object p0) + { + return string.Format(CultureInfo.CurrentCulture, GetString("CannotUpdateProperty"), p0); + } + + /// + /// The key '{0}' was not found. + /// + internal static string DictionaryKeyNotFound + { + get { return GetString("DictionaryKeyNotFound"); } + } + + /// + /// The key '{0}' was not found. + /// + internal static string FormatDictionaryKeyNotFound(object p0) + { + return string.Format(CultureInfo.CurrentCulture, GetString("DictionaryKeyNotFound"), p0); + } + + /// + /// For operation '{0}' on array property at path '{1}', the index is larger than the array size. + /// + internal static string InvalidIndexForArrayProperty + { + get { return GetString("InvalidIndexForArrayProperty"); } + } + + /// + /// For operation '{0}' on array property at path '{1}', the index is larger than the array size. + /// + internal static string FormatInvalidIndexForArrayProperty(object p0, object p1) + { + return string.Format(CultureInfo.CurrentCulture, GetString("InvalidIndexForArrayProperty"), p0, p1); + } + + /// + /// The type '{0}' was malformed and could not be parsed. + /// + internal static string InvalidJsonPatchDocument + { + get { return GetString("InvalidJsonPatchDocument"); } + } + + /// + /// The type '{0}' was malformed and could not be parsed. + /// + internal static string FormatInvalidJsonPatchDocument(object p0) + { + return string.Format(CultureInfo.CurrentCulture, GetString("InvalidJsonPatchDocument"), p0); + } + + /// + /// For operation '{0}', the provided path is invalid for array property at path '{1}'. + /// + internal static string InvalidPathForArrayProperty + { + get { return GetString("InvalidPathForArrayProperty"); } + } + + /// + /// For operation '{0}', the provided path is invalid for array property at path '{1}'. + /// + internal static string FormatInvalidPathForArrayProperty(object p0, object p1) + { + return string.Format(CultureInfo.CurrentCulture, GetString("InvalidPathForArrayProperty"), p0, p1); + } + + /// + /// The provided string '{0}' is an invalid path. + /// + internal static string InvalidValueForPath + { + get { return GetString("InvalidValueForPath"); } + } + + /// + /// The provided string '{0}' is an invalid path. + /// + internal static string FormatInvalidValueForPath(object p0) + { + return string.Format(CultureInfo.CurrentCulture, GetString("InvalidValueForPath"), p0); + } + + /// + /// The value '{0}' is invalid for property at path '{1}'. + /// + internal static string InvalidValueForProperty + { + get { return GetString("InvalidValueForProperty"); } + } + + /// + /// The value '{0}' is invalid for property at path '{1}'. + /// + internal static string FormatInvalidValueForProperty(object p0, object p1) + { + return string.Format(CultureInfo.CurrentCulture, GetString("InvalidValueForProperty"), p0, p1); + } + + /// + /// For operation '{0}' on array property at path '{1}', the index is negative. + /// + internal static string NegativeIndexForArrayProperty + { + get { return GetString("NegativeIndexForArrayProperty"); } + } + + /// + /// For operation '{0}' on array property at path '{1}', the index is negative. + /// + internal static string FormatNegativeIndexForArrayProperty(object p0, object p1) + { + return string.Format(CultureInfo.CurrentCulture, GetString("NegativeIndexForArrayProperty"), p0, p1); + } + + /// + /// '{0}' must be of type '{1}'. + /// + internal static string ParameterMustMatchType + { + get { return GetString("ParameterMustMatchType"); } + } + + /// + /// '{0}' must be of type '{1}'. + /// + internal static string FormatParameterMustMatchType(object p0, object p1) + { + return string.Format(CultureInfo.CurrentCulture, GetString("ParameterMustMatchType"), p0, p1); + } + + /// + /// The property at path '{0}' could not be added. + /// + internal static string PropertyCannotBeAdded + { + get { return GetString("PropertyCannotBeAdded"); } + } + + /// + /// The property at path '{0}' could not be added. + /// + internal static string FormatPropertyCannotBeAdded(object p0) + { + return string.Format(CultureInfo.CurrentCulture, GetString("PropertyCannotBeAdded"), p0); + } + + /// + /// The property at path '{0}' could not be removed. + /// + internal static string PropertyCannotBeRemoved + { + get { return GetString("PropertyCannotBeRemoved"); } + } + + /// + /// The property at path '{0}' could not be removed. + /// + internal static string FormatPropertyCannotBeRemoved(object p0) + { + return string.Format(CultureInfo.CurrentCulture, GetString("PropertyCannotBeRemoved"), p0); + } + + /// + /// Property does not exist at path '{0}'. + /// + internal static string PropertyDoesNotExist + { + get { return GetString("PropertyDoesNotExist"); } + } + + /// + /// Property does not exist at path '{0}'. + /// + internal static string FormatPropertyDoesNotExist(object p0) + { + return string.Format(CultureInfo.CurrentCulture, GetString("PropertyDoesNotExist"), p0); + } + + /// + /// The test operation is not supported. + /// + internal static string TestOperationNotSupported + { + get { return GetString("TestOperationNotSupported"); } + } + + /// + /// The test operation is not supported. + /// + internal static string FormatTestOperationNotSupported() + { + return GetString("TestOperationNotSupported"); + } + + private static string GetString(string name, params string[] formatterNames) + { + var value = _resourceManager.GetString(name); + + System.Diagnostics.Debug.Assert(value != null); + + if (formatterNames != null) + { + for (var i = 0; i < formatterNames.Length; i++) + { + value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); + } + } + + return value; + } + } +} diff --git a/src/Microsoft.AspNet.JsonPatch/Resources.resx b/src/Microsoft.AspNet.JsonPatch/Resources.resx new file mode 100644 index 0000000000..59ae2b59c3 --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/Resources.resx @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + The type of the property at path '{0}' could not be determined. + + + The property at '{0}' could not be read. + + + The property at path '{0}' could not be updated. + + + The key '{0}' was not found. + + + For operation '{0}' on array property at path '{1}', the index is larger than the array size. + + + The type '{0}' was malformed and could not be parsed. + + + For operation '{0}', the provided path is invalid for array property at path '{1}'. + + + The provided string '{0}' is an invalid path. + + + The value '{0}' is invalid for property at path '{1}'. + + + For operation '{0}' on array property at path '{1}', the index is negative. + + + '{0}' must be of type '{1}'. + + + The property at path '{0}' could not be added. + + + The property at path '{0}' could not be removed. + + + Property does not exist at path '{0}'. + + + The test operation is not supported. + + \ No newline at end of file diff --git a/src/Microsoft.AspNet.JsonPatch/project.json b/src/Microsoft.AspNet.JsonPatch/project.json new file mode 100644 index 0000000000..8d67ec1808 --- /dev/null +++ b/src/Microsoft.AspNet.JsonPatch/project.json @@ -0,0 +1,25 @@ +{ + "version": "1.0.0-*", + "repository": { + "type": "git", + "url": "git://github.com/aspnet/mvc" + }, + "dependencies": { + "Newtonsoft.Json": "6.0.6" + }, + "frameworks": { + "dnx451": { }, + "dnxcore50": { + "dependencies": { + "Microsoft.CSharp": "4.0.1-beta-*", + "System.Collections.Concurrent": "4.0.11-beta-*", + "System.ComponentModel.TypeConverter": "4.0.1-beta-*", + "System.Globalization": "4.0.11-beta-*", + "System.Reflection.Extensions": "4.0.1-beta-*", + "System.Resources.ResourceManager": "4.0.1-beta-*", + "System.Runtime.Extensions": "4.0.11-beta-*", + "System.Text.Encoding.Extensions": "4.0.11-beta-*" + } + } + } +} diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/AddOperationTests.cs b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/AddOperationTests.cs new file mode 100644 index 0000000000..3c2523c5fb --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/AddOperationTests.cs @@ -0,0 +1,569 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Dynamic; +using Microsoft.AspNet.JsonPatch.Exceptions; +using Newtonsoft.Json; +using Xunit; + +namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +{ + public class AddOperationTests + { + [Fact] + public void AddNewPropertyShouldFailIfRootIsNotAnExpandoObject() + { + dynamic doc = new + { + Test = 1 + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("NewInt", 1); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "The property at path '/NewInt' could not be added.", + exception.Message); + } + + [Fact] + public void AddNewProperty() + { + dynamic obj = new ExpandoObject(); + obj.Test = 1; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("NewInt", 1); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(obj); + + Assert.Equal(1, obj.NewInt); + Assert.Equal(1, obj.Test); + } + + [Fact] + public void AddNewPropertyToNestedAnonymousObjectShouldFail() + { + dynamic doc = new + { + Test = 1, + nested = new { } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("Nested/NewInt", 1); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "The property at path '/Nested/NewInt' could not be added.", + exception.Message); + } + + [Fact] + public void AddNewPropertyToTypedObjectShouldFail() + { + dynamic doc = new + { + Test = 1, + nested = new NestedDTO() + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("Nested/NewInt", 1); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "The property at path '/Nested/NewInt' could not be added.", + exception.Message); + } + + [Fact] + public void AddToExistingPropertyOnNestedObject() + { + dynamic doc = new + { + Test = 1, + nested = new NestedDTO() + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("Nested/StringProperty", "A"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal("A", doc.nested.StringProperty); + Assert.Equal(1, doc.Test); + } + + [Fact] + public void AddNewPropertyToExpandoOject() + { + dynamic doc = new + { + Test = 1, + nested = new ExpandoObject() + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("Nested/NewInt", 1); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(1, doc.nested.NewInt); + Assert.Equal(1, doc.Test); + } + + [Fact] + public void AddNewPropertyToExpandoOjectInTypedObject() + { + var doc = new NestedDTO() + { + DynamicProperty = new ExpandoObject() + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("DynamicProperty/NewInt", 1); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(1, doc.DynamicProperty.NewInt); + } + + [Fact] + public void AddNewPropertyToTypedObjectInExpandoObject() + { + dynamic dynamicProperty = new ExpandoObject(); + dynamicProperty.StringProperty = "A"; + + var doc = new NestedDTO() + { + DynamicProperty = dynamicProperty + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("DynamicProperty/StringProperty", "B"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal("B", doc.DynamicProperty.StringProperty); + } + + [Fact] + public void AddNewPropertyToAnonymousObjectShouldFail() + { + dynamic doc = new + { + Test = 1 + }; + + dynamic valueToAdd = new { IntValue = 1, StringValue = "test", GuidValue = Guid.NewGuid() }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("ComplexProperty", valueToAdd); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "The property at path '/ComplexProperty' could not be added.", + exception.Message); + } + + [Fact] + public void AddResultsReplaceShouldFailOnAnonymousDueToNoSetter() + { + var doc = new + { + StringProperty = "A" + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("StringProperty", "B"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "The property at path '/StringProperty' could not be updated.", + exception.Message); + } + + [Fact] + public void AddResultsShouldReplace() + { + dynamic doc = new ExpandoObject(); + doc.StringProperty = "A"; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("StringProperty", "B"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal("B", doc.StringProperty); + } + + [Fact] + public void AddResultsShouldReplaceInNested() + { + dynamic doc = new ExpandoObject(); + doc.InBetweenFirst = new ExpandoObject(); + doc.InBetweenFirst.InBetweenSecond = new ExpandoObject(); + doc.InBetweenFirst.InBetweenSecond.StringProperty = "A"; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("/InBetweenFirst/InBetweenSecond/StringProperty", "B"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal("B", doc.InBetweenFirst.InBetweenSecond.StringProperty); + } + + [Fact] + public void AddResultsShouldReplaceInNestedInDynamic() + { + dynamic doc = new ExpandoObject(); + doc.Nested = new NestedDTO(); + doc.Nested.DynamicProperty = new ExpandoObject(); + doc.Nested.DynamicProperty.InBetweenFirst = new ExpandoObject(); + doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond = new ExpandoObject(); + doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond.StringProperty = "A"; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("/Nested/DynamicProperty/InBetweenFirst/InBetweenSecond/StringProperty", "B"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal("B", doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond.StringProperty); + } + + [Fact] + public void ShouldNotBeAbleToAddToNonExistingPropertyThatIsNotTheRoot() + { + //Adding to a Nonexistent Target + // + // An example target JSON document: + // { "foo": "bar" } + // A JSON Patch document: + // [ + // { "op": "add", "path": "/baz/bat", "value": "qux" } + // ] + // This JSON Patch document, applied to the target JSON document above, + // would result in an error (therefore, it would not be applied), + // because the "add" operation's target location that references neither + // the root of the document, nor a member of an existing object, nor a + // member of an existing array. + + var doc = new NestedDTO() + { + DynamicProperty = new ExpandoObject() + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("DynamicProperty/OtherProperty/IntProperty", 1); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "The property at path '/DynamicProperty/OtherProperty/IntProperty' could not be added.", + exception.Message); + } + + [Fact] + public void ShouldNotBeAbleToAddToNonExistingPropertyInNestedPropertyThatIsNotTheRoot() + { + //Adding to a Nonexistent Target + // + // An example target JSON document: + // { "foo": "bar" } + // A JSON Patch document: + // [ + // { "op": "add", "path": "/baz/bat", "value": "qux" } + // ] + // This JSON Patch document, applied to the target JSON document above, + // would result in an error (therefore, it would not be applied), + // because the "add" operation's target location that references neither + // the root of the document, nor a member of an existing object, nor a + // member of an existing array. + + var doc = new + { + Foo = "bar" + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("baz/bat", "qux"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "The property at path '/baz/bat' could not be added.", + exception.Message); + } + + [Fact] + public void ShouldReplacePropertyWithDifferentCase() + { + dynamic doc = new ExpandoObject(); + doc.StringProperty = "A"; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("stringproperty", "B"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal("B", doc.StringProperty); + } + + [Fact] + public void AddToList() + { + var doc = new + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("IntegerList/0", 4); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void AddToListNegativePosition() + { + dynamic doc = new ExpandoObject(); + doc.IntegerList = new List() { 1, 2, 3 }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("IntegerList/-1", 4); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "For operation 'add' on array property at path '/IntegerList/-1', the index is negative.", + exception.Message); + } + + [Fact] + public void ShouldAddToListWithDifferentCase() + { + var doc = new + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("integerlist/0", 4); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void AddToListInvalidPositionTooLarge() + { + var doc = new + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("IntegerList/4", 4); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "For operation 'add' on array property at path '/IntegerList/4', the index is larger than the array size.", + exception.Message); + } + + [Fact] + public void AddToListAtEndWithSerialization() + { + var doc = new + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("IntegerList/3", 4); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 2, 3, 4 }, doc.IntegerList); + } + + [Fact] + public void AddToListAtBeginning() + { + var doc = new + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("IntegerList/0", 4); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void AddToListInvalidPositionTooSmall() + { + var doc = new + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("IntegerList/-1", 4); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "For operation 'add' on array property at path '/IntegerList/-1', the index is negative.", + exception.Message); + } + + [Fact] + public void AddToListAppend() + { + var doc = new + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("IntegerList/-", 4); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 2, 3, 4 }, doc.IntegerList); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs new file mode 100644 index 0000000000..4d2e8c646d --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs @@ -0,0 +1,121 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using Microsoft.AspNet.JsonPatch.Exceptions; +using Newtonsoft.Json; +using Xunit; + +namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +{ + public class AddTypedOperationTests + { + [Fact] + public void AddToListNegativePosition() + { + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("IntegerList/-1", 4); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "For operation 'add' on array property at path '/IntegerList/-1', the index is negative.", + exception.Message); + } + + [Fact] + public void AddToListInList() + { + var doc = new SimpleDTOWithNestedDTO() + { + ListOfSimpleDTO = new List() + { + new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("ListOfSimpleDTO/0/IntegerList/0", 4); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.ListOfSimpleDTO[0].IntegerList); + } + + [Fact] + public void AddToListInListInvalidPositionTooSmall() + { + var doc = new SimpleDTOWithNestedDTO() + { + ListOfSimpleDTO = new List() + { + new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("ListOfSimpleDTO/-1/IntegerList/0", 4); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "The property at path '/ListOfSimpleDTO/-1/IntegerList/0' could not be added.", + exception.Message); + } + + [Fact] + public void AddToListInListInvalidPositionTooLarge() + { + var doc = new SimpleDTOWithNestedDTO() + { + ListOfSimpleDTO = new List() + { + new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + } + }; + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Add("ListOfSimpleDTO/20/IntegerList/0", 4); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "The property at path '/ListOfSimpleDTO/20/IntegerList/0' could not be added.", + exception.Message); + } + } +} diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/CopyOperationTests.cs b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/CopyOperationTests.cs new file mode 100644 index 0000000000..3fa546faac --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/CopyOperationTests.cs @@ -0,0 +1,245 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Dynamic; +using Newtonsoft.Json; +using Xunit; + +namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +{ + public class CopyOperationTests + { + [Fact] + public void Copy() + { + dynamic doc = new ExpandoObject(); + + doc.StringProperty = "A"; + doc.AnotherStringProperty = "B"; + + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("StringProperty", "AnotherStringProperty"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + deserialized.ApplyTo(doc); + + Assert.Equal("A", doc.AnotherStringProperty); + } + + [Fact] + public void CopyInList() + { + dynamic doc = new ExpandoObject(); + doc.IntegerList = new List() { 1, 2, 3 }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("IntegerList/0", "IntegerList/1"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 1, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void CopyFromListToEndOfList() + { + dynamic doc = new ExpandoObject(); + doc.IntegerList = new List() { 1, 2, 3 }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("IntegerList/0", "IntegerList/-"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 2, 3, 1 }, doc.IntegerList); + } + + [Fact] + public void CopyFromListToNonList() + { + dynamic doc = new ExpandoObject(); + doc.IntegerList = new List() { 1, 2, 3 }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("IntegerList/0", "IntegerValue"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(1, doc.IntegerValue); + } + + [Fact] + public void CopyFromNonListToList() + { + dynamic doc = new ExpandoObject(); + doc.IntegerValue = 5; + doc.IntegerList = new List() { 1, 2, 3 }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("IntegerValue", "IntegerList/0"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void CopyToEndOfList() + { + dynamic doc = new ExpandoObject(); + doc.IntegerValue = 5; + doc.IntegerList = new List() { 1, 2, 3 }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("IntegerValue", "IntegerList/-"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.IntegerList); + } + + [Fact] + public void NestedCopy() + { + dynamic doc = new ExpandoObject(); + doc.SimpleDTO = new SimpleDTO() + { + StringProperty = "A", + AnotherStringProperty = "B" + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("SimpleDTO/StringProperty", "SimpleDTO/AnotherStringProperty"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty); + } + + [Fact] + public void NestedCopyInList() + { + dynamic doc = new ExpandoObject(); + doc.SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/1"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void NestedCopyFromListToEndOfList() + { + dynamic doc = new ExpandoObject(); + doc.SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/-"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 2, 3, 1 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void NestedCopyFromListToNonList() + { + dynamic doc = new ExpandoObject(); + doc.SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerValue"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + deserialized.ApplyTo(doc); + + Assert.Equal(1, doc.SimpleDTO.IntegerValue); + } + + [Fact] + public void NestedCopyFromNonListToList() + { + dynamic doc = new ExpandoObject(); + doc.SimpleDTO = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/0"); + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void NestedCopyToEndOfList() + { + dynamic doc = new ExpandoObject(); + doc.SimpleDTO = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/-"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleDTO.IntegerList); + } + } +} diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs new file mode 100644 index 0000000000..5b015416ac --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs @@ -0,0 +1,268 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using Newtonsoft.Json; +using Xunit; + +namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +{ + public class CopyTypedOperationTests + { + [Fact] + public void Copy() + { + var doc = new SimpleDTO() + { + StringProperty = "A", + AnotherStringProperty = "B" + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("StringProperty", "AnotherStringProperty"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + deserialized.ApplyTo(doc); + + Assert.Equal("A", doc.AnotherStringProperty); + } + + [Fact] + public void CopyInList() + { + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("IntegerList/0", "IntegerList/1"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 1, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void CopyFromListToEndOfList() + { + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("IntegerList/0", "IntegerList/-"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 2, 3, 1 }, doc.IntegerList); + } + + [Fact] + public void CopyFromListToNonList() + { + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("IntegerList/0", "IntegerValue"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(1, doc.IntegerValue); + } + + [Fact] + public void CopyFromNonListToList() + { + var doc = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("IntegerValue", "IntegerList/0"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void CopyToEndOfList() + { + var doc = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("IntegerValue", "IntegerList/-"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.IntegerList); + } + + [Fact] + public void NestedCopy() + { + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + StringProperty = "A", + AnotherStringProperty = "B" + } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("SimpleDTO/StringProperty", "SimpleDTO/AnotherStringProperty"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty); + } + + [Fact] + public void NestedCopyInList() + { + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/1"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void NestedCopyFromListToEndOfList() + { + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/-"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 2, 3, 1 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void NestedCopyFromListToNonList() + { + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerValue"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + deserialized.ApplyTo(doc); + + Assert.Equal(1, doc.SimpleDTO.IntegerValue); + } + + [Fact] + public void NestedCopyFromNonListToList() + { + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/0"); + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void NestedCopyToEndOfList() + { + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/-"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleDTO.IntegerList); + } + } +} diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/MoveOperationTests.cs b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/MoveOperationTests.cs new file mode 100644 index 0000000000..dea2b6ee32 --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/MoveOperationTests.cs @@ -0,0 +1,338 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Dynamic; +using Newtonsoft.Json; +using Xunit; + +namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +{ + public class MoveOperationTests + { + [Fact] + public void Move() + { + dynamic doc = new ExpandoObject(); + doc.StringProperty = "A"; + doc.AnotherStringProperty = "B"; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("StringProperty", "AnotherStringProperty"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal("A", doc.AnotherStringProperty); + + var cont = doc as IDictionary; + object valueFromDictionary; + cont.TryGetValue("StringProperty", out valueFromDictionary); + Assert.Null(valueFromDictionary); + } + + [Fact] + public void MoveToNonExisting() + { + dynamic doc = new ExpandoObject(); + doc.StringProperty = "A"; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("StringProperty", "AnotherStringProperty"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal("A", doc.AnotherStringProperty); + + var cont = doc as IDictionary; + object valueFromDictionary; + cont.TryGetValue("StringProperty", out valueFromDictionary); + Assert.Null(valueFromDictionary); + } + + [Fact] + public void MoveDynamicToTyped() + { + dynamic doc = new ExpandoObject(); + doc.StringProperty = "A"; + doc.SimpleDTO = new SimpleDTO() { AnotherStringProperty = "B" }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("StringProperty", "SimpleDTO/AnotherStringProperty"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty); + + var cont = doc as IDictionary; + object valueFromDictionary; + cont.TryGetValue("StringProperty", out valueFromDictionary); + Assert.Null(valueFromDictionary); + } + + [Fact] + public void MoveTypedToDynamic() + { + dynamic doc = new ExpandoObject(); + doc.StringProperty = "A"; + doc.SimpleDTO = new SimpleDTO() { AnotherStringProperty = "B" }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("SimpleDTO/AnotherStringProperty", "StringProperty"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal("B", doc.StringProperty); + Assert.Equal(null, doc.SimpleDTO.AnotherStringProperty); + } + + [Fact] + public void NestedMove() + { + dynamic doc = new ExpandoObject(); + doc.Nested = new SimpleDTO() + { + StringProperty = "A", + AnotherStringProperty = "B" + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("Nested/StringProperty", "Nested/AnotherStringProperty"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal("A", doc.Nested.AnotherStringProperty); + Assert.Equal(null, doc.Nested.StringProperty); + } + + [Fact] + public void MoveInList() + { + dynamic doc = new ExpandoObject(); + doc.IntegerList = new List() { 1, 2, 3 }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("IntegerList/0", "IntegerList/1"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 2, 1, 3 }, doc.IntegerList); + } + + [Fact] + public void NestedMoveInList() + { + dynamic doc = new ExpandoObject(); + doc.Nested = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("Nested/IntegerList/0", "Nested/IntegerList/1"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 2, 1, 3 }, doc.Nested.IntegerList); + } + + [Fact] + public void MoveFromListToEndOfList() + { + dynamic doc = new ExpandoObject(); + doc.IntegerList = new List() { 1, 2, 3 }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("IntegerList/0", "IntegerList/-"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 2, 3, 1 }, doc.IntegerList); + } + + [Fact] + public void NestedMoveFromListToEndOfList() + { + dynamic doc = new ExpandoObject(); + doc.Nested = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("Nested/IntegerList/0", "Nested/IntegerList/-"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 2, 3, 1 }, doc.Nested.IntegerList); + } + + [Fact] + public void MoveFomListToNonList() + { + dynamic doc = new ExpandoObject(); + doc.IntegerList = new List() { 1, 2, 3 }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("IntegerList/0", "IntegerValue"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 2, 3 }, doc.IntegerList); + Assert.Equal(1, doc.IntegerValue); + } + + [Fact] + public void NestedMoveFomListToNonList() + { + dynamic doc = new ExpandoObject(); + doc.Nested = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("Nested/IntegerList/0", "Nested/IntegerValue"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 2, 3 }, doc.Nested.IntegerList); + Assert.Equal(1, doc.Nested.IntegerValue); + } + + [Fact] + public void MoveFromNonListToList() + { + dynamic doc = new ExpandoObject(); + doc.IntegerValue = 5; + doc.IntegerList = new List() { 1, 2, 3 }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("IntegerValue", "IntegerList/0"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + var cont = doc as IDictionary; + object valueFromDictionary; + cont.TryGetValue("IntegerValue", out valueFromDictionary); + Assert.Null(valueFromDictionary); + + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void NestedMoveFromNonListToList() + { + dynamic doc = new ExpandoObject(); + doc.Nested = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("Nested/IntegerValue", "Nested/IntegerList/0"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(0, doc.Nested.IntegerValue); + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.Nested.IntegerList); + } + + [Fact] + public void MoveToEndOfList() + { + dynamic doc = new ExpandoObject(); + doc.IntegerValue = 5; + doc.IntegerList = new List() { 1, 2, 3 }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("IntegerValue", "IntegerList/-"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + var cont = doc as IDictionary; + object valueFromDictionary; + cont.TryGetValue("IntegerValue", out valueFromDictionary); + Assert.Null(valueFromDictionary); + + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.IntegerList); + } + + [Fact] + public void NestedMoveToEndOfList() + { + dynamic doc = new ExpandoObject(); + doc.Nested = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("Nested/IntegerValue", "Nested/IntegerList/-"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(0, doc.Nested.IntegerValue); + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.Nested.IntegerList); + } + } +} diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs new file mode 100644 index 0000000000..3d356a3401 --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs @@ -0,0 +1,138 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using Newtonsoft.Json; +using Xunit; + +namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +{ + public class MoveTypedOperationTests + { + [Fact] + public void Move() + { + var doc = new SimpleDTO() + { + StringProperty = "A", + AnotherStringProperty = "B" + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("StringProperty", "AnotherStringProperty"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal("A", doc.AnotherStringProperty); + Assert.Equal(null, doc.StringProperty); + } + + [Fact] + public void MoveInList() + { + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("IntegerList/0", "IntegerList/1"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 2, 1, 3 }, doc.IntegerList); + } + + [Fact] + public void MoveFromListToEndOfList() + { + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("IntegerList/0", "IntegerList/-"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 2, 3, 1 }, doc.IntegerList); + } + + [Fact] + public void MoveFomListToNonList() + { + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("IntegerList/0", "IntegerValue"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 2, 3 }, doc.IntegerList); + Assert.Equal(1, doc.IntegerValue); + } + + [Fact] + public void MoveFromNonListToList() + { + var doc = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("IntegerValue", "IntegerList/0"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(0, doc.IntegerValue); + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void MoveToEndOfList() + { + var doc = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Move("IntegerValue", "IntegerList/-"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(0, doc.IntegerValue); + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.IntegerList); + } + } +} diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/NestedDTO.cs b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/NestedDTO.cs new file mode 100644 index 0000000000..4d30cf60f2 --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/NestedDTO.cs @@ -0,0 +1,11 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +{ + public class NestedDTO + { + public string StringProperty { get; set; } + public dynamic DynamicProperty { get; set; } + } +} diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/PatchDocumentTests.cs b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/PatchDocumentTests.cs new file mode 100644 index 0000000000..e15f85da8e --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/PatchDocumentTests.cs @@ -0,0 +1,95 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.JsonPatch.Exceptions; +using Newtonsoft.Json; +using Xunit; + +namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +{ + public class PatchDocumentTests + { + [Fact] + public void InvalidPathAtBeginningShouldThrowException() + { + JsonPatchDocument patchDoc = new JsonPatchDocument(); + var exception = Assert.Throws(() => + { + patchDoc.Add("//NewInt", 1); + }); + Assert.Equal( + "The provided string '//NewInt' is an invalid path.", + exception.Message); + } + + [Fact] + public void InvalidPathAtEndShouldThrowException() + { + JsonPatchDocument patchDoc = new JsonPatchDocument(); + var exception = Assert.Throws(() => + { + patchDoc.Add("NewInt//", 1); + }); + Assert.Equal( + "The provided string 'NewInt//' is an invalid path.", + exception.Message); + } + + [Fact] + public void InvalidPathWithDotShouldThrowException() + { + JsonPatchDocument patchDoc = new JsonPatchDocument(); + var exception = Assert.Throws(() => + { + patchDoc.Add("NewInt.Test", 1); + }); + Assert.Equal( + "The provided string 'NewInt.Test' is an invalid path.", + exception.Message); + } + + [Fact] + public void NonGenericPatchDocToGenericMustSerialize() + { + var doc = new SimpleDTO() + { + StringProperty = "A", + AnotherStringProperty = "B" + }; + + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Copy("StringProperty", "AnotherStringProperty"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal("A", doc.AnotherStringProperty); + } + + [Fact] + public void GenericPatchDocToNonGenericMustSerialize() + { + var doc = new SimpleDTO() + { + StringProperty = "A", + AnotherStringProperty = "B" + }; + + JsonPatchDocument patchDocTyped = new JsonPatchDocument(); + patchDocTyped.Copy(o => o.StringProperty, o => o.AnotherStringProperty); + + JsonPatchDocument patchDocUntyped = new JsonPatchDocument(); + patchDocUntyped.Copy("StringProperty", "AnotherStringProperty"); + + var serializedTyped = JsonConvert.SerializeObject(patchDocTyped); + var serializedUntyped = JsonConvert.SerializeObject(patchDocUntyped); + var deserialized = JsonConvert.DeserializeObject(serializedTyped); + + deserialized.ApplyTo(doc); + + Assert.Equal("A", doc.AnotherStringProperty); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/RemoveOperationTests.cs b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/RemoveOperationTests.cs new file mode 100644 index 0000000000..9ef28ad7cc --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/RemoveOperationTests.cs @@ -0,0 +1,302 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Dynamic; +using Microsoft.AspNet.JsonPatch.Exceptions; +using Newtonsoft.Json; +using Xunit; + +namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +{ + public class RemoveOperationTests + { + [Fact] + public void RemovePropertyShouldFailIfRootIsAnonymous() + { + dynamic doc = new + { + Test = 1 + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("Test"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "The property at path '/Test' could not be updated.", + exception.Message); + } + + [Fact] + public void RemovePropertyShouldFailIfItDoesntExist() + { + dynamic doc = new ExpandoObject(); + doc.Test = 1; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("NonExisting"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "The property at path '/NonExisting' could not be removed.", + exception.Message); + } + + [Fact] + public void RemovePropertyFromExpandoObject() + { + dynamic obj = new ExpandoObject(); + obj.Test = 1; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("Test"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(obj); + + var cont = obj as IDictionary; + object valueFromDictionary; + + cont.TryGetValue("Test", out valueFromDictionary); + Assert.Null(valueFromDictionary); + } + + [Fact] + public void RemovePropertyFromExpandoObjectMixedCase() + { + dynamic obj = new ExpandoObject(); + obj.Test = 1; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("test"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(obj); + + var cont = obj as IDictionary; + object valueFromDictionary; + + cont.TryGetValue("Test", out valueFromDictionary); + Assert.Null(valueFromDictionary); + } + + [Fact] + public void RemoveNestedPropertyFromExpandoObject() + { + dynamic obj = new ExpandoObject(); + obj.Test = new ExpandoObject(); + obj.Test.AnotherTest = "A"; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("Test"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(obj); + + var cont = obj as IDictionary; + object valueFromDictionary; + + cont.TryGetValue("Test", out valueFromDictionary); + Assert.Null(valueFromDictionary); + } + + [Fact] + public void RemoveNestedPropertyFromExpandoObjectMixedCase() + { + dynamic obj = new ExpandoObject(); + obj.Test = new ExpandoObject(); + obj.Test.AnotherTest = "A"; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("test"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(obj); + var cont = obj as IDictionary; + + object valueFromDictionary; + cont.TryGetValue("Test", out valueFromDictionary); + Assert.Null(valueFromDictionary); + } + + [Fact] + public void NestedRemove() + { + dynamic doc = new ExpandoObject(); + doc.SimpleDTO = new SimpleDTO() + { + StringProperty = "A" + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("SimpleDTO/StringProperty"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + Assert.Equal(null, doc.SimpleDTO.StringProperty); + } + + [Fact] + public void NestedRemoveMixedCase() + { + dynamic doc = new ExpandoObject(); + doc.SimpleDTO = new SimpleDTO() + { + StringProperty = "A" + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("Simpledto/stringProperty"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(null, doc.SimpleDTO.StringProperty); + } + + [Fact] + public void NestedRemoveFromList() + { + dynamic doc = new ExpandoObject(); + doc.SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("SimpleDTO/IntegerList/2"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 2 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void NestedRemoveFromListMixedCase() + { + dynamic doc = new ExpandoObject(); + doc.SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("SimpleDTO/Integerlist/2"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 2 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void NestedRemoveFromListInvalidPositionTooLarge() + { + dynamic doc = new ExpandoObject(); + doc.SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("SimpleDTO/IntegerList/3"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "For operation 'remove' on array property at path '/SimpleDTO/IntegerList/3', the index is larger than the array size.", + exception.Message); + } + + [Fact] + public void NestedRemoveFromListInvalidPositionTooSmall() + { + dynamic doc = new ExpandoObject(); + doc.SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("SimpleDTO/IntegerList/-1"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "For operation 'remove' on array property at path '/SimpleDTO/IntegerList/-1', the index is negative.", + exception.Message); + } + + [Fact] + public void NestedRemoveFromEndOfList() + { + dynamic doc = new ExpandoObject(); + doc.SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("SimpleDTO/IntegerList/-"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + Assert.Equal(new List() { 1, 2 }, doc.SimpleDTO.IntegerList); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs new file mode 100644 index 0000000000..db5d6502d1 --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs @@ -0,0 +1,244 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using Microsoft.AspNet.JsonPatch.Exceptions; +using Newtonsoft.Json; +using Xunit; + +namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +{ + public class RemoveTypedOperationTests + { + [Fact] + public void Remove() + { + var doc = new SimpleDTO() + { + StringProperty = "A" + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("StringProperty"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(null, doc.StringProperty); + } + + [Fact] + public void RemoveFromList() + { + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("IntegerList/2"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 2 }, doc.IntegerList); + } + + [Fact] + public void RemoveFromListInvalidPositionTooLarge() + { + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("IntegerList/3"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "For operation 'remove' on array property at path '/IntegerList/3', the index is larger than the array size.", + exception.Message); + } + + [Fact] + public void RemoveFromListInvalidPositionTooSmall() + { + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("IntegerList/-1"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "For operation 'remove' on array property at path '/IntegerList/-1', the index is negative.", + exception.Message); + } + + [Fact] + public void RemoveFromEndOfList() + { + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("IntegerList/-"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 2 }, doc.IntegerList); + } + + [Fact] + public void NestedRemove() + { + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + StringProperty = "A" + } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("SimpleDTO/StringProperty"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(null, doc.SimpleDTO.StringProperty); + } + + [Fact] + public void NestedRemoveFromList() + { + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("SimpleDTO/IntegerList/2"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 2 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void NestedRemoveFromListInvalidPositionTooLarge() + { + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("SimpleDTO/IntegerList/3"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "For operation 'remove' on array property at path '/SimpleDTO/IntegerList/3', the index is larger than the array size.", + exception.Message); + } + + [Fact] + public void NestedRemoveFromListInvalidPositionTooSmall() + { + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("SimpleDTO/IntegerList/-1"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "For operation 'remove' on array property at path '/SimpleDTO/IntegerList/-1', the index is negative.", + exception.Message); + } + + [Fact] + public void NestedRemoveFromEndOfList() + { + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Remove("SimpleDTO/IntegerList/-"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 2 }, doc.SimpleDTO.IntegerList); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs new file mode 100644 index 0000000000..c7573c0286 --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs @@ -0,0 +1,242 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Dynamic; +using Newtonsoft.Json; +using Xunit; + +namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +{ + public class ReplaceOperationTests + { + [Fact] + public void ReplaceGuidTest() + { + dynamic doc = new SimpleDTO() + { + GuidValue = Guid.NewGuid() + }; + + var newGuid = Guid.NewGuid(); + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Replace("GuidValue", newGuid); + + // serialize & deserialize + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserizalized = JsonConvert.DeserializeObject(serialized); + + deserizalized.ApplyTo(doc); + + Assert.Equal(newGuid, doc.GuidValue); + } + + [Fact] + public void ReplaceGuidTestExpandoObject() + { + dynamic doc = new ExpandoObject(); + doc.GuidValue = Guid.NewGuid(); + + var newGuid = Guid.NewGuid(); + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Replace("GuidValue", newGuid); + + // serialize & deserialize + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserizalized = JsonConvert.DeserializeObject(serialized); + + deserizalized.ApplyTo(doc); + + Assert.Equal(newGuid, doc.GuidValue); + } + + [Fact] + public void ReplaceGuidTestExpandoObjectInAnonymous() + { + dynamic nestedObject = new ExpandoObject(); + nestedObject.GuidValue = Guid.NewGuid(); + + dynamic doc = new + { + NestedObject = nestedObject + }; + + var newGuid = Guid.NewGuid(); + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Replace("nestedobject/GuidValue", newGuid); + + // serialize & deserialize + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserizalized = JsonConvert.DeserializeObject(serialized); + + deserizalized.ApplyTo(doc); + + Assert.Equal(newGuid, doc.NestedObject.GuidValue); + } + + [Fact] + public void ReplaceNestedObjectTest() + { + dynamic doc = new ExpandoObject(); + doc.SimpleDTO = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + }; + + var newDTO = new SimpleDTO() + { + DoubleValue = 1 + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Replace("SimpleDTO", newDTO); + + // serialize & deserialize + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(1, doc.SimpleDTO.DoubleValue); + Assert.Equal(0, doc.SimpleDTO.IntegerValue); + Assert.Equal(null, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void ReplaceInList() + { + dynamic doc = new ExpandoObject(); + doc.IntegerList = new List() { 1, 2, 3 }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Replace("IntegerList/0", 5); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 5, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void ReplaceFullList() + { + dynamic doc = new ExpandoObject(); + doc.IntegerList = new List() { 1, 2, 3 }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Replace("IntegerList", new List() { 4, 5, 6 }); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); + } + + [Fact] + public void ReplaceInListInList() + { + dynamic doc = new ExpandoObject(); + doc.SimpleDTOList = new List() { + new SimpleDTO() { + IntegerList = new List(){1,2,3} + }}; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Replace("SimpleDTOList/0/IntegerList/0", 4); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(4, doc.SimpleDTOList[0].IntegerList[0]); + } + + [Fact] + public void ReplaceInListInListAtEnd() + { + dynamic doc = new ExpandoObject(); + doc.SimpleDTOList = new List() { + new SimpleDTO() { + IntegerList = new List(){1,2,3} + }}; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Replace("SimpleDTOList/0/IntegerList/-", 4); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(4, doc.SimpleDTOList[0].IntegerList[2]); + } + + [Fact] + public void ReplaceFullListFromEnumerable() + { + dynamic doc = new ExpandoObject(); + doc.IntegerList = new List() { 1, 2, 3 }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Replace("IntegerList", new List() { 4, 5, 6 }); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); + } + + [Fact] + public void ReplaceFullListWithCollection() + { + dynamic doc = new ExpandoObject(); + doc.IntegerList = new List() { 1, 2, 3 }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Replace("IntegerList", new Collection() { 4, 5, 6 }); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); + } + + [Fact] + public void ReplaceAtEndOfList() + { + dynamic doc = new ExpandoObject(); + doc.IntegerList = new List() { 1, 2, 3 }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Replace("IntegerList/-", 5); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 2, 5 }, doc.IntegerList); + } + } +} diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/ReplaceTypedOperationTests.cs b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/ReplaceTypedOperationTests.cs new file mode 100644 index 0000000000..ccdd86f1a7 --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/ReplaceTypedOperationTests.cs @@ -0,0 +1,191 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using Newtonsoft.Json; +using Xunit; + +namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +{ + public class ReplaceTypedOperationTests + { + [Fact] + public void ReplaceGuidTest() + { + var doc = new SimpleDTO() + { + GuidValue = Guid.NewGuid() + }; + + var newGuid = Guid.NewGuid(); + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Replace("GuidValue", newGuid); + + // serialize & deserialize + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserizalized = JsonConvert.DeserializeObject(serialized); + + deserizalized.ApplyTo(doc); + + Assert.Equal(newGuid, doc.GuidValue); + } + + [Fact] + public void SerializeAndReplaceNestedObjectTest() + { + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + } + }; + + var newDTO = new SimpleDTO() + { + DoubleValue = 1 + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Replace("SimpleDTO", newDTO); + + // serialize & deserialize + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(1, doc.SimpleDTO.DoubleValue); + Assert.Equal(0, doc.SimpleDTO.IntegerValue); + Assert.Equal(null, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void ReplaceInList() + { + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Replace("IntegerList/0", 5); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 5, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void ReplaceFullList() + { + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Replace("IntegerList", new List() { 4, 5, 6 }); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); + } + + [Fact] + public void ReplaceInListInList() + { + var doc = new SimpleDTO() + { + SimpleDTOList = new List() { + new SimpleDTO() { + IntegerList = new List(){1,2,3} + }} + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Replace("SimpleDTOList/0/IntegerList/0", 4); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(4, doc.SimpleDTOList.First().IntegerList.First()); + } + + [Fact] + public void ReplaceFullListFromEnumerable() + { + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Replace("IntegerList", new List() { 4, 5, 6 }); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); + } + + [Fact] + public void ReplaceFullListWithCollection() + { + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Replace("IntegerList", new Collection() { 4, 5, 6 }); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); + } + + [Fact] + public void ReplaceAtEndOfList() + { + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + JsonPatchDocument patchDoc = new JsonPatchDocument(); + patchDoc.Replace("IntegerList/-", 5); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject(serialized); + deserialized.ApplyTo(doc); + + Assert.Equal(new List() { 1, 2, 5 }, doc.IntegerList); + } + } +} diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/SimpleDTO.cs b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/SimpleDTO.cs new file mode 100644 index 0000000000..a6938dd992 --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/SimpleDTO.cs @@ -0,0 +1,21 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; + +namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +{ + public class SimpleDTO + { + public List SimpleDTOList { get; set; } + public List IntegerList { get; set; } + public int IntegerValue { get; set; } + public string StringProperty { get; set; } + public string AnotherStringProperty { get; set; } + public decimal DecimalValue { get; set; } + public double DoubleValue { get; set; } + public float FloatValue { get; set; } + public Guid GuidValue { get; set; } + } +} diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/SimpleDTOWithNestedDTO.cs b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/SimpleDTOWithNestedDTO.cs new file mode 100644 index 0000000000..2147fcceb1 --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/SimpleDTOWithNestedDTO.cs @@ -0,0 +1,22 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; + +namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +{ + public class SimpleDTOWithNestedDTO + { + public int IntegerValue { get; set; } + public NestedDTO NestedDTO { get; set; } + public SimpleDTO SimpleDTO { get; set; } + public List ListOfSimpleDTO { get; set; } + + public SimpleDTOWithNestedDTO() + { + NestedDTO = new NestedDTO(); + SimpleDTO = new SimpleDTO(); + ListOfSimpleDTO = new List(); + } + } +} diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Microsoft.AspNet.JsonPatch.Test.xproj b/test/Microsoft.AspNet.JsonPatch.Test/Microsoft.AspNet.JsonPatch.Test.xproj new file mode 100644 index 0000000000..74e0fef687 --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/Microsoft.AspNet.JsonPatch.Test.xproj @@ -0,0 +1,20 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 81c20848-e063-4e12-ac40-0b55a532c16c + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + 2.0 + + + + + + \ No newline at end of file diff --git a/test/Microsoft.AspNet.JsonPatch.Test/NestedDTO.cs b/test/Microsoft.AspNet.JsonPatch.Test/NestedDTO.cs new file mode 100644 index 0000000000..6dd5ce8852 --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/NestedDTO.cs @@ -0,0 +1,10 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.AspNet.JsonPatch.Test +{ + public class NestedDTO + { + public string StringProperty { get; set; } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.JsonPatch.Test/NestedObjectTests.cs b/test/Microsoft.AspNet.JsonPatch.Test/NestedObjectTests.cs new file mode 100644 index 0000000000..33649b7788 --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/NestedObjectTests.cs @@ -0,0 +1,2041 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.JsonPatch.Exceptions; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Xunit; + +namespace Microsoft.AspNet.JsonPatch.Test +{ + public class NestedObjectTests + { + [Fact] + public void ReplacePropertyInNestedObject() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + IntegerValue = 1 + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.NestedDTO.StringProperty, "B"); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal("B", doc.NestedDTO.StringProperty); + } + + [Fact] + public void ReplacePropertyInNestedObjectWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + IntegerValue = 1 + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.NestedDTO.StringProperty, "B"); + + // serialize & deserialize + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal("B", doc.NestedDTO.StringProperty); + } + + [Fact] + public void ReplaceNestedObject() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + IntegerValue = 1 + }; + + var newNested = new NestedDTO() { StringProperty = "B" }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.NestedDTO, newNested); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal("B", doc.NestedDTO.StringProperty); + } + + [Fact] + public void ReplaceNestedObjectWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + IntegerValue = 1 + }; + + var newNested = new NestedDTO() { StringProperty = "B" }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.NestedDTO, newNested); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal("B", doc.NestedDTO.StringProperty); + } + + [Fact] + public void AddResultsInReplace() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + StringProperty = "A" + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleDTO.StringProperty, "B"); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal("B", doc.SimpleDTO.StringProperty); + } + + [Fact] + public void AddResultsInReplaceWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + StringProperty = "A" + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleDTO.StringProperty, "B"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal("B", doc.SimpleDTO.StringProperty); + } + + [Fact] + public void AddToList() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleDTO.IntegerList, 4, 0); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void AddToListWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleDTO.IntegerList, 4, 0); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void AddToIntegerIList() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerIList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => (List)o.SimpleDTO.IntegerIList, 4, 0); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleDTO.IntegerIList); + } + + [Fact] + public void AddToIntegerIListWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerIList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => (List)o.SimpleDTO.IntegerIList, 4, 0); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleDTO.IntegerIList); + } + + [Fact] + public void AddToNestedIntegerIList() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTOIList = new List + { + new SimpleDTO + { + IntegerIList = new List() { 1, 2, 3 } + } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => (List)o.SimpleDTOIList[0].IntegerIList, 4, 0); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleDTOIList[0].IntegerIList); + } + + [Fact] + public void AddToNestedIntegerIListWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTOIList = new List + { + new SimpleDTO + { + IntegerIList = new List() { 1, 2, 3 } + } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => (List)o.SimpleDTOIList[0].IntegerIList, 4, 0); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleDTOIList[0].IntegerIList); + } + + [Fact] + public void AddToComplextTypeListSpecifyIndex() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTOList = new List() + { + new SimpleDTO + { + StringProperty = "String1" + }, + new SimpleDTO + { + StringProperty = "String2" + } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleDTOList[0].StringProperty, "ChangedString1"); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal("ChangedString1", doc.SimpleDTOList[0].StringProperty); + } + + [Fact] + public void AddToComplextTypeListSpecifyIndexWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTOList = new List() + { + new SimpleDTO + { + StringProperty = "String1" + }, + new SimpleDTO + { + StringProperty = "String2" + } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleDTOList[0].StringProperty, "ChangedString1"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal("ChangedString1", doc.SimpleDTOList[0].StringProperty); + } + + [Fact] + public void AddToListInvalidPositionTooLarge() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleDTO.IntegerList, 4, 4); + + // Act & Assert + var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); + Assert.Equal( + "For operation 'add' on array property at path '/simpledto/integerlist/4', the index is " + + "larger than the array size.", + exception.Message); + + } + + [Fact] + public void AddToListInvalidPositionTooLargeWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleDTO.IntegerList, 4, 4); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act & Assert + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "For operation 'add' on array property at path '/simpledto/integerlist/4', the index is " + + "larger than the array size.", + exception.Message); + } + + [Fact] + public void AddToListInvalidPositionTooLarge_LogsError() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleDTO.IntegerList, 4, 4); + + var logger = new TestErrorLogger(); + + patchDoc.ApplyTo(doc, logger.LogErrorMessage); + + + //Assert + Assert.Equal( + "For operation 'add' on array property at path '/simpledto/integerlist/4', the index is larger than " + + "the array size.", + logger.ErrorMessage); + + } + + [Fact] + public void AddToListInvalidPositionTooSmall() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleDTO.IntegerList, 4, -1); + + // Act & Assert + var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); + Assert.Equal( + "For operation 'add' on array property at path '/simpledto/integerlist/-1', the index is negative.", + exception.Message); + } + + [Fact] + public void AddToListInvalidPositionTooSmallWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleDTO.IntegerList, 4, -1); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act & Assert + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "For operation 'add' on array property at path '/simpledto/integerlist/-1', the index is negative.", + exception.Message); + } + + [Fact] + public void AddToListInvalidPositionTooSmall_LogsError() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleDTO.IntegerList, 4, -1); + + var logger = new TestErrorLogger(); + + + patchDoc.ApplyTo(doc, logger.LogErrorMessage); + + + //Assert + Assert.Equal( + "For operation 'add' on array property at path '/simpledto/integerlist/-1', the index is negative.", + logger.ErrorMessage); + } + + [Fact] + public void AddToListAppend() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleDTO.IntegerList, 4); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2, 3, 4 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void AddToListAppendWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleDTO.IntegerList, 4); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2, 3, 4 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void Remove() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + StringProperty = "A" + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleDTO.StringProperty); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(null, doc.SimpleDTO.StringProperty); + } + + [Fact] + public void RemoveWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + StringProperty = "A" + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleDTO.StringProperty); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(null, doc.SimpleDTO.StringProperty); + } + + [Fact] + public void RemoveFromList() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleDTO.IntegerList, 2); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void RemoveFromListWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleDTO.IntegerList, 2); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void RemoveFromListInvalidPositionTooLarge() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleDTO.IntegerList, 3); + + // Act & Assert + var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); + Assert.Equal( + "For operation 'remove' on array property at path '/simpledto/integerlist/3', the index is " + + "larger than the array size.", + exception.Message); + } + + [Fact] + public void RemoveFromListInvalidPositionTooLargeWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleDTO.IntegerList, 3); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act & Assert + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "For operation 'remove' on array property at path '/simpledto/integerlist/3', the index is " + + "larger than the array size.", + exception.Message); + } + + [Fact] + public void RemoveFromListInvalidPositionTooLarge_LogsError() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleDTO.IntegerList, 3); + + var logger = new TestErrorLogger(); + + patchDoc.ApplyTo(doc, logger.LogErrorMessage); + + // Assert + Assert.Equal( + "For operation 'remove' on array property at path '/simpledto/integerlist/3', the index is " + + "larger than the array size.", + logger.ErrorMessage); + } + + [Fact] + public void RemoveFromListInvalidPositionTooSmall() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleDTO.IntegerList, -1); + + // Act & Assert + var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); + Assert.Equal("For operation 'remove' on array property at path '/simpledto/integerlist/-1', the index is negative.", exception.Message); + } + + [Fact] + public void RemoveFromListInvalidPositionTooSmallWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleDTO.IntegerList, -1); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act & Assert + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal("For operation 'remove' on array property at path '/simpledto/integerlist/-1', the index is negative.", exception.Message); + } + + [Fact] + public void RemoveFromListInvalidPositionTooSmall_LogsError() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleDTO.IntegerList, -1); + + var logger = new TestErrorLogger(); + + + patchDoc.ApplyTo(doc, logger.LogErrorMessage); + + // Assert + Assert.Equal("For operation 'remove' on array property at path '/simpledto/integerlist/-1', the index is negative.", logger.ErrorMessage); + } + + [Fact] + public void RemoveFromEndOfList() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleDTO.IntegerList); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void RemoveFromEndOfListWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleDTO.IntegerList); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void Replace() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + StringProperty = "A", + DecimalValue = 10 + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleDTO.StringProperty, "B"); + patchDoc.Replace(o => o.SimpleDTO.DecimalValue, 12); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal("B", doc.SimpleDTO.StringProperty); + Assert.Equal(12, doc.SimpleDTO.DecimalValue); + } + + [Fact] + public void ReplaceWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + StringProperty = "A", + DecimalValue = 10 + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleDTO.StringProperty, "B"); + patchDoc.Replace(o => o.SimpleDTO.DecimalValue, 12); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal("B", doc.SimpleDTO.StringProperty); + Assert.Equal(12, doc.SimpleDTO.DecimalValue); + } + + [Fact] + public void SerializationTests() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + StringProperty = "A", + DecimalValue = 10, + DoubleValue = 10, + FloatValue = 10, + IntegerValue = 10 + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleDTO.StringProperty, "B"); + patchDoc.Replace(o => o.SimpleDTO.DecimalValue, 12); + patchDoc.Replace(o => o.SimpleDTO.DoubleValue, 12); + patchDoc.Replace(o => o.SimpleDTO.FloatValue, 12); + patchDoc.Replace(o => o.SimpleDTO.IntegerValue, 12); + + // serialize & deserialize + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserizalized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserizalized.ApplyTo(doc); + + // Assert + Assert.Equal("B", doc.SimpleDTO.StringProperty); + Assert.Equal(12, doc.SimpleDTO.DecimalValue); + Assert.Equal(12, doc.SimpleDTO.DoubleValue); + Assert.Equal(12, doc.SimpleDTO.FloatValue); + Assert.Equal(12, doc.SimpleDTO.IntegerValue); + } + + [Fact] + public void ReplaceInList() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5, 0); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 5, 2, 3 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void ReplaceInListWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5, 0); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 5, 2, 3 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void ReplaceFullList() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace>(o => o.SimpleDTO.IntegerList, new List() { 4, 5, 6 }); + + // Act + patchDoc.ApplyTo(doc); + + // Arrange + Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void ReplaceFullListWithSerialiation() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace>(o => o.SimpleDTO.IntegerList, new List() { 4, 5, 6 }); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void ReplaceFullListFromEnumerable() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace>(o => o.SimpleDTO.IntegerList, new List() { 4, 5, 6 }); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void ReplaceFullListFromEnumerableWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace>(o => o.SimpleDTO.IntegerList, new List() { 4, 5, 6 }); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void ReplaceFullListWithCollection() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace>(o => o.SimpleDTO.IntegerList, new Collection() { 4, 5, 6 }); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void ReplaceFullListWithCollectionWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace>(o => o.SimpleDTO.IntegerList, new Collection() { 4, 5, 6 }); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void ReplaceAtEndOfList() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2, 5 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void ReplaceAtEndOfListWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2, 5 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void ReplaceInListInvalidInvalidPositionTooLarge() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5, 3); + + // Act & Assert + var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); + Assert.Equal( + "For operation 'replace' on array property at path '/simpledto/integerlist/3', the index is " + + "larger than the array size.", + exception.Message); + } + + [Fact] + public void ReplaceInListInvalidInvalidPositionTooLargeWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5, 3); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act & Assert + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "For operation 'replace' on array property at path '/simpledto/integerlist/3', the index is " + + "larger than the array size.", + exception.Message); + } + + [Fact] + public void ReplaceInListInvalid_PositionTooLarge_LogsError() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5, 3); + + var logger = new TestErrorLogger(); + + + patchDoc.ApplyTo(doc, logger.LogErrorMessage); + + + // Assert + Assert.Equal( + "For operation 'replace' on array property at path '/simpledto/integerlist/3', the index is " + + "larger than the array size.", + logger.ErrorMessage); + } + + [Fact] + public void ReplaceInListInvalidPositionTooSmall() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5, -1); + + // Act & Assert + var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); + Assert.Equal("For operation 'replace' on array property at path '/simpledto/integerlist/-1', the index is negative.", + exception.Message); + } + + [Fact] + public void ReplaceInListInvalidPositionTooSmallWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5, -1); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act & Assert + var exception = Assert.Throws(() => { deserialized.ApplyTo(doc); }); + Assert.Equal( + "For operation 'replace' on array property at path '/simpledto/integerlist/-1', the index is negative.", + exception.Message); + } + + [Fact] + public void ReplaceInListInvalidPositionTooSmall_LogsError() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5, -1); + + var logger = new TestErrorLogger(); + + + patchDoc.ApplyTo(doc, logger.LogErrorMessage); + + + // Assert + Assert.Equal( + "For operation 'replace' on array property at path '/simpledto/integerlist/-1', the index is negative.", + logger.ErrorMessage); + } + + [Fact] + public void Copy() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + StringProperty = "A", + AnotherStringProperty = "B" + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleDTO.StringProperty, o => o.SimpleDTO.AnotherStringProperty); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty); + } + + [Fact] + public void CopyWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + StringProperty = "A", + AnotherStringProperty = "B" + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleDTO.StringProperty, o => o.SimpleDTO.AnotherStringProperty); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty); + } + + [Fact] + public void CopyInList() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerList, 1); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void CopyInListWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerList, 1); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void CopyFromListToEndOfList() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerList); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2, 3, 1 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void CopyFromListToEndOfListWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerList); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2, 3, 1 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void CopyFromListToNonList() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerValue); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(1, doc.SimpleDTO.IntegerValue); + } + + [Fact] + public void CopyFromListToNonListWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerValue); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(1, doc.SimpleDTO.IntegerValue); + } + + [Fact] + public void CopyFromNonListToList() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleDTO.IntegerValue, o => o.SimpleDTO.IntegerList, 0); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void CopyFromNonListToListWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleDTO.IntegerValue, o => o.SimpleDTO.IntegerList, 0); + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void CopyToEndOfList() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleDTO.IntegerValue, o => o.SimpleDTO.IntegerList); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void CopyToEndOfListWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleDTO.IntegerValue, o => o.SimpleDTO.IntegerList); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void Move() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + StringProperty = "A", + AnotherStringProperty = "B" + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleDTO.StringProperty, o => o.SimpleDTO.AnotherStringProperty); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty); + Assert.Equal(null, doc.SimpleDTO.StringProperty); + } + + [Fact] + public void MoveWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + StringProperty = "A", + AnotherStringProperty = "B" + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleDTO.StringProperty, o => o.SimpleDTO.AnotherStringProperty); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty); + Assert.Equal(null, doc.SimpleDTO.StringProperty); + } + + [Fact] + public void MoveInList() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerList, 1); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 2, 1, 3 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void MoveInListWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerList, 1); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 2, 1, 3 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void MoveFromListToEndOfList() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerList); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 2, 3, 1 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void MoveFromListToEndOfListWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerList); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 2, 3, 1 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void MoveFomListToNonList() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerValue); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 2, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(1, doc.SimpleDTO.IntegerValue); + } + + [Fact] + public void MoveFomListToNonListWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerValue); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 2, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(1, doc.SimpleDTO.IntegerValue); + } + + [Fact] + public void MoveFomListToNonListBetweenHierarchy() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleDTO.IntegerList, 0, o => o.IntegerValue); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 2, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(1, doc.IntegerValue); + } + + [Fact] + public void MoveFomListToNonListBetweenHierarchyWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleDTO.IntegerList, 0, o => o.IntegerValue); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 2, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(1, doc.IntegerValue); + } + + [Fact] + public void MoveFromNonListToList() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleDTO.IntegerValue, o => o.SimpleDTO.IntegerList, 0); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(0, doc.IntegerValue); + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void MoveFromNonListToListWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleDTO.IntegerValue, o => o.SimpleDTO.IntegerList, 0); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(0, doc.IntegerValue); + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void MoveToEndOfList() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleDTO.IntegerValue, o => o.SimpleDTO.IntegerList); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(0, doc.IntegerValue); + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void MoveToEndOfListWithSerialization() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleDTO.IntegerValue, o => o.SimpleDTO.IntegerList); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(0, doc.IntegerValue); + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleDTO.IntegerList); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.JsonPatch.Test/ObjectAdapterTests.cs b/test/Microsoft.AspNet.JsonPatch.Test/ObjectAdapterTests.cs new file mode 100644 index 0000000000..0cc97e32c4 --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/ObjectAdapterTests.cs @@ -0,0 +1,1737 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Microsoft.AspNet.JsonPatch.Exceptions; +using Newtonsoft.Json; +using Xunit; + +namespace Microsoft.AspNet.JsonPatch.Test +{ + public class ObjectAdapterTests + { + [Fact] + public void AddResultsShouldReplace() + { + // Arrange + var doc = new SimpleDTO() + { + StringProperty = "A" + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.StringProperty, "B"); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal("B", doc.StringProperty); + } + + [Fact] + public void AddResultsShouldReplaceWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + StringProperty = "A" + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.StringProperty, "B"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal("B", doc.StringProperty); + } + + [Fact] + public void AddToList() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.IntegerList, 4, 0); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void AddToListWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.IntegerList, 4, 0); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void AddToIntegerIList() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerIList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.IntegerIList, 4, 0); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerIList); + } + + [Fact] + public void AddToIntegerIListWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerIList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.IntegerIList, 4, 0); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerIList); + } + + [Fact] + public void AddToListInvalidPositionTooLarge() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.IntegerList, 4, 4); + + // Act & Assert + var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); + Assert.Equal( + "For operation 'add' on array property at path '/integerlist/4', the index is " + + "larger than the array size.", + exception.Message); + } + + [Fact] + public void AddToListInvalidPositionTooLargeWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.IntegerList, 4, 4); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act & Assert + var exception = Assert.Throws(() => { deserialized.ApplyTo(doc); }); + Assert.Equal( + "For operation 'add' on array property at path '/integerlist/4', the index is " + + "larger than the array size.", + exception.Message); + } + + [Fact] + public void AddToListInvalidPositionTooLarge_LogsError() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.IntegerList, 4, 4); + + var logger = new TestErrorLogger(); + + patchDoc.ApplyTo(doc, logger.LogErrorMessage); + + + // Assert + Assert.Equal( + "For operation 'add' on array property at path '/integerlist/4', the index is " + + "larger than the array size.", + logger.ErrorMessage); + } + + [Fact] + public void AddToListAtEnd() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.IntegerList, 4, 3); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2, 3, 4 }, doc.IntegerList); + } + + [Fact] + public void AddToListAtEndWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.IntegerList, 4, 3); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2, 3, 4 }, doc.IntegerList); + } + + [Fact] + public void AddToListAtBeginning() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.IntegerList, 4, 0); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void AddToListAtBeginningWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.IntegerList, 4, 0); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void AddToListInvalidPositionTooSmall() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.IntegerList, 4, -1); + + // Act & Assert + var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); + Assert.Equal( + "For operation 'add' on array property at path '/integerlist/-1', the index is negative.", + exception.Message); + } + + [Fact] + public void AddToListInvalidPositionTooSmallWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.IntegerList, 4, -1); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act & Assert + var exception = Assert.Throws(() => { deserialized.ApplyTo(doc); }); + Assert.Equal( + "For operation 'add' on array property at path '/integerlist/-1', the index is negative.", + exception.Message); + } + + [Fact] + public void AddToListInvalidPositionTooSmall_LogsError() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.IntegerList, 4, -1); + + var logger = new TestErrorLogger(); + + patchDoc.ApplyTo(doc, logger.LogErrorMessage); + + // Assert + Assert.Equal( + "For operation 'add' on array property at path '/integerlist/-1', the index is negative.", + logger.ErrorMessage); + } + + [Fact] + public void AddToListAppend() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.IntegerList, 4); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2, 3, 4 }, doc.IntegerList); + } + + [Fact] + public void AddToListAppendWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.IntegerList, 4); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2, 3, 4 }, doc.IntegerList); + } + + [Fact] + public void Remove() + { + // Arrange + var doc = new SimpleDTO() + { + StringProperty = "A" + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.StringProperty); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(null, doc.StringProperty); + } + + [Fact] + public void RemoveWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + StringProperty = "A" + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.StringProperty); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(null, doc.StringProperty); + } + + [Fact] + public void RemoveFromList() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.IntegerList, 2); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2 }, doc.IntegerList); + } + + [Fact] + public void RemoveFromListWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.IntegerList, 2); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2 }, doc.IntegerList); + } + + [Fact] + public void RemoveFromListInvalidPositionTooLarge() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.IntegerList, 3); + + // Act & Assert + var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); + Assert.Equal( + "For operation 'remove' on array property at path '/integerlist/3', the index is " + + "larger than the array size.", + exception.Message); + } + + [Fact] + public void RemoveFromListInvalidPositionTooLargeWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.IntegerList, 3); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act & Assert + var exception = Assert.Throws(() => { deserialized.ApplyTo(doc); }); + Assert.Equal( + "For operation 'remove' on array property at path '/integerlist/3', the index is " + + "larger than the array size.", + exception.Message); + } + + [Fact] + public void RemoveFromListInvalidPositionTooLarge_LogsError() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.IntegerList, 3); + + var logger = new TestErrorLogger(); + + patchDoc.ApplyTo(doc, logger.LogErrorMessage); + + + // Assert + Assert.Equal( + "For operation 'remove' on array property at path '/integerlist/3', the index is " + + "larger than the array size.", + logger.ErrorMessage); + } + + [Fact] + public void RemoveFromListInvalidPositionTooSmall() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.IntegerList, -1); + + // Act & Assert + var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); + Assert.Equal("For operation 'remove' on array property at path '/integerlist/-1', the index is negative.", exception.Message); + } + + [Fact] + public void RemoveFromListInvalidPositionTooSmallWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.IntegerList, -1); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act & Assert + var exception = Assert.Throws(() => { deserialized.ApplyTo(doc); }); + Assert.Equal("For operation 'remove' on array property at path '/integerlist/-1', the index is negative.", exception.Message); + } + + [Fact] + public void RemoveFromListInvalidPositionTooSmall_LogsError() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.IntegerList, -1); + + var logger = new TestErrorLogger(); + + + patchDoc.ApplyTo(doc, logger.LogErrorMessage); + + + // Assert + Assert.Equal("For operation 'remove' on array property at path '/integerlist/-1', the index is negative.", logger.ErrorMessage); + } + + [Fact] + public void RemoveFromEndOfList() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.IntegerList); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2 }, doc.IntegerList); + } + + [Fact] + public void RemoveFromEndOfListWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.IntegerList); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2 }, doc.IntegerList); + } + + [Fact] + public void Replace() + { + // Arrange + var doc = new SimpleDTO() + { + StringProperty = "A", + DecimalValue = 10 + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.StringProperty, "B"); + + patchDoc.Replace(o => o.DecimalValue, 12); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal("B", doc.StringProperty); + Assert.Equal(12, doc.DecimalValue); + } + + [Fact] + public void ReplaceWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + StringProperty = "A", + DecimalValue = 10 + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.StringProperty, "B"); + + patchDoc.Replace(o => o.DecimalValue, 12); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal("B", doc.StringProperty); + Assert.Equal(12, doc.DecimalValue); + } + + [Fact] + public void SerializationMustNotIncudeEnvelope() + { + // Arrange + var doc = new SimpleDTO() + { + StringProperty = "A", + DecimalValue = 10, + DoubleValue = 10, + FloatValue = 10, + IntegerValue = 10 + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.StringProperty, "B"); + patchDoc.Replace(o => o.DecimalValue, 12); + patchDoc.Replace(o => o.DoubleValue, 12); + patchDoc.Replace(o => o.FloatValue, 12); + patchDoc.Replace(o => o.IntegerValue, 12); + + // Act + var serialized = JsonConvert.SerializeObject(patchDoc); + + // Assert + Assert.Equal(false, serialized.Contains("operations")); + Assert.Equal(false, serialized.Contains("Operations")); + } + + [Fact] + public void DeserializationMustWorkWithoutEnvelope() + { + // Arrange + var doc = new SimpleDTO() + { + StringProperty = "A", + DecimalValue = 10, + DoubleValue = 10, + FloatValue = 10, + IntegerValue = 10 + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.StringProperty, "B"); + patchDoc.Replace(o => o.DecimalValue, 12); + patchDoc.Replace(o => o.DoubleValue, 12); + patchDoc.Replace(o => o.FloatValue, 12); + patchDoc.Replace(o => o.IntegerValue, 12); + + // default: no envelope + var serialized = JsonConvert.SerializeObject(patchDoc); + + // Act + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Assert + Assert.IsType>(deserialized); + } + + [Fact] + public void DeserializationMustFailWithEnvelope() + { + // Arrange + string serialized = "{\"Operations\": [{ \"op\": \"replace\", \"path\": \"/title\", \"value\": \"New Title\"}]}"; + + // Act & Assert + var exception = Assert.Throws(() => + { + var deserialized + = JsonConvert.DeserializeObject>(serialized); + }); + + Assert.Equal("The type 'JsonPatchDocument`1' was malformed and could not be parsed.", exception.Message); + } + + [Fact] + public void SerializationTests() + { + // Arrange + var doc = new SimpleDTO() + { + StringProperty = "A", + DecimalValue = 10, + DoubleValue = 10, + FloatValue = 10, + IntegerValue = 10 + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.StringProperty, "B"); + patchDoc.Replace(o => o.DecimalValue, 12); + patchDoc.Replace(o => o.DoubleValue, 12); + patchDoc.Replace(o => o.FloatValue, 12); + patchDoc.Replace(o => o.IntegerValue, 12); + + // serialize & deserialize + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserizalized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserizalized.ApplyTo(doc); + + // Assert + Assert.Equal("B", doc.StringProperty); + Assert.Equal(12, doc.DecimalValue); + Assert.Equal(12, doc.DoubleValue); + Assert.Equal(12, doc.FloatValue); + Assert.Equal(12, doc.IntegerValue); + } + + [Fact] + public void SerializeAndReplaceGuidTest() + { + // Arrange + var doc = new SimpleDTO() + { + GuidValue = Guid.NewGuid() + }; + + var newGuid = Guid.NewGuid(); + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.GuidValue, newGuid); + + // serialize & deserialize + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserizalized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserizalized.ApplyTo(doc); + + // Assert + Assert.Equal(newGuid, doc.GuidValue); + } + + [Fact] + public void SerializeAndReplaceNestedObjectTest() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + } + }; + + var newDTO = new SimpleDTO() + { + DoubleValue = 1 + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleDTO, newDTO); + + // serialize & deserialize + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(1, doc.SimpleDTO.DoubleValue); + Assert.Equal(0, doc.SimpleDTO.IntegerValue); + Assert.Equal(null, doc.SimpleDTO.IntegerList); + } + + [Fact] + public void ReplaceInList() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.IntegerList, 5, 0); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 5, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void ReplaceInListWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.IntegerList, 5, 0); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 5, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void ReplaceFullList() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace>(o => o.IntegerList, new List() { 4, 5, 6 }); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); + } + + [Fact] + public void ReplaceFullListWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace>(o => o.IntegerList, new List() { 4, 5, 6 }); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); + } + + [Fact] + public void ReplaceFullListFromEnumerable() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace>(o => o.IntegerList, new List() { 4, 5, 6 }); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); + } + + [Fact] + public void ReplaceFullListFromEnumerableWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace>(o => o.IntegerList, new List() { 4, 5, 6 }); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); + } + + [Fact] + public void ReplaceFullListWithCollection() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace>(o => o.IntegerList, new Collection() { 4, 5, 6 }); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); + } + + [Fact] + public void ReplaceFullListWithCollectionWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace>(o => o.IntegerList, new Collection() { 4, 5, 6 }); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); + } + + [Fact] + public void ReplaceAtEndOfList() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.IntegerList, 5); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2, 5 }, doc.IntegerList); + } + + [Fact] + public void ReplaceAtEndOfListWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.IntegerList, 5); + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2, 5 }, doc.IntegerList); + } + + [Fact] + public void ReplaceInListInvalidInvalidPositionTooLarge() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.IntegerList, 5, 3); + + // Act & Assert + var exception = Assert.Throws(() => + { + patchDoc.ApplyTo(doc); + }); + Assert.Equal( + "For operation 'replace' on array property at path '/integerlist/3', the index is " + + "larger than the array size.", + exception.Message); + } + + [Fact] + public void ReplaceInListInvalidInvalidPositionTooLargeWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.IntegerList, 5, 3); + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act & Assert + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + "For operation 'replace' on array property at path '/integerlist/3', the index is " + + "larger than the array size.", + exception.Message); + } + + [Fact] + public void ReplaceInListInvalidPositionTooSmall() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.IntegerList, 5, -1); + + // Act & Assert + var exception = Assert.Throws(() => + { + patchDoc.ApplyTo(doc); + }); + Assert.Equal("For operation 'replace' on array property at path '/integerlist/-1', the index is negative.", exception.Message); + } + + [Fact] + public void ReplaceInListInvalidPositionTooSmallWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.IntegerList, 5, -1); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act & Assert + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal("For operation 'replace' on array property at path '/integerlist/-1', the index is negative.", exception.Message); + } + + [Fact] + public void Copy() + { + // Arrange + var doc = new SimpleDTO() + { + StringProperty = "A", + AnotherStringProperty = "B" + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.StringProperty, o => o.AnotherStringProperty); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal("A", doc.AnotherStringProperty); + } + + [Fact] + public void CopyWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + StringProperty = "A", + AnotherStringProperty = "B" + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.StringProperty, o => o.AnotherStringProperty); + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal("A", doc.AnotherStringProperty); + } + + [Fact] + public void CopyInList() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.IntegerList, 0, o => o.IntegerList, 1); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 1, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void CopyInListWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.IntegerList, 0, o => o.IntegerList, 1); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 1, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void CopyFromListToEndOfList() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.IntegerList, 0, o => o.IntegerList); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2, 3, 1 }, doc.IntegerList); + } + + [Fact] + public void CopyFromListToEndOfListWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.IntegerList, 0, o => o.IntegerList); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2, 3, 1 }, doc.IntegerList); + } + + [Fact] + public void CopyFromListToNonList() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.IntegerList, 0, o => o.IntegerValue); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(1, doc.IntegerValue); + } + + [Fact] + public void CopyFromListToNonListWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.IntegerList, 0, o => o.IntegerValue); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(1, doc.IntegerValue); + } + + [Fact] + public void CopyFromNonListToList() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.IntegerValue, o => o.IntegerList, 0); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void CopyFromNonListToListWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.IntegerValue, o => o.IntegerList, 0); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void CopyToEndOfList() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.IntegerValue, o => o.IntegerList); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.IntegerList); + } + + [Fact] + public void CopyToEndOfListWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.IntegerValue, o => o.IntegerList); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.IntegerList); + } + + [Fact] + public void Move() + { + // Arrange + var doc = new SimpleDTO() + { + StringProperty = "A", + AnotherStringProperty = "B" + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.StringProperty, o => o.AnotherStringProperty); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal("A", doc.AnotherStringProperty); + Assert.Equal(null, doc.StringProperty); + } + + [Fact] + public void MoveWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + StringProperty = "A", + AnotherStringProperty = "B" + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.StringProperty, o => o.AnotherStringProperty); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal("A", doc.AnotherStringProperty); + Assert.Equal(null, doc.StringProperty); + } + + [Fact] + public void MoveInList() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.IntegerList, 0, o => o.IntegerList, 1); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 2, 1, 3 }, doc.IntegerList); + } + + [Fact] + public void MoveInListWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.IntegerList, 0, o => o.IntegerList, 1); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 2, 1, 3 }, doc.IntegerList); + } + + [Fact] + public void MoveFromListToEndOfList() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.IntegerList, 0, o => o.IntegerList); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 2, 3, 1 }, doc.IntegerList); + } + + [Fact] + public void MoveFromListToEndOfListWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.IntegerList, 0, o => o.IntegerList); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 2, 3, 1 }, doc.IntegerList); + } + + [Fact] + public void MoveFomListToNonList() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.IntegerList, 0, o => o.IntegerValue); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 2, 3 }, doc.IntegerList); + Assert.Equal(1, doc.IntegerValue); + } + + [Fact] + public void MoveFomListToNonListWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.IntegerList, 0, o => o.IntegerValue); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 2, 3 }, doc.IntegerList); + Assert.Equal(1, doc.IntegerValue); + } + + [Fact] + public void MoveFromNonListToList() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.IntegerValue, o => o.IntegerList, 0); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(0, doc.IntegerValue); + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void MoveFromNonListToListWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.IntegerValue, o => o.IntegerList, 0); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(0, doc.IntegerValue); + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.IntegerList); + } + + [Fact] + public void MoveToEndOfList() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.IntegerValue, o => o.IntegerList); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(0, doc.IntegerValue); + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.IntegerList); + } + + [Fact] + public void MoveToEndOfListWithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.IntegerValue, o => o.IntegerList); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(0, doc.IntegerValue); + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.IntegerList); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.JsonPatch.Test/SimpleDTO.cs b/test/Microsoft.AspNet.JsonPatch.Test/SimpleDTO.cs new file mode 100644 index 0000000000..0c29a86e83 --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/SimpleDTO.cs @@ -0,0 +1,22 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.AspNet.JsonPatch.Test +{ + public class SimpleDTO + { + public List IntegerList { get; set; } + public IList IntegerIList { get; set; } + public int IntegerValue { get; set; } + public string StringProperty { get; set; } + public string AnotherStringProperty { get; set; } + public decimal DecimalValue { get; set; } + public double DoubleValue { get; set; } + public float FloatValue { get; set; } + public Guid GuidValue { get; set; } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.JsonPatch.Test/SimpleDTOWithNestedDTO.cs b/test/Microsoft.AspNet.JsonPatch.Test/SimpleDTOWithNestedDTO.cs new file mode 100644 index 0000000000..81aa38e682 --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/SimpleDTOWithNestedDTO.cs @@ -0,0 +1,27 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; + +namespace Microsoft.AspNet.JsonPatch.Test +{ + public class SimpleDTOWithNestedDTO + { + public int IntegerValue { get; set; } + + public NestedDTO NestedDTO { get; set; } + + public SimpleDTO SimpleDTO { get; set; } + + public List SimpleDTOList { get; set; } + + public IList SimpleDTOIList { get; set; } + + public SimpleDTOWithNestedDTO() + { + this.NestedDTO = new NestedDTO(); + this.SimpleDTO = new SimpleDTO(); + this.SimpleDTOList = new List(); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.JsonPatch.Test/TestErrorLogger.cs b/test/Microsoft.AspNet.JsonPatch.Test/TestErrorLogger.cs new file mode 100644 index 0000000000..c254eab3e3 --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/TestErrorLogger.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.AspNet.JsonPatch.Test +{ + public class TestErrorLogger where T: class + { + public string ErrorMessage { get; set; } + + public void LogErrorMessage(JsonPatchError patchError) + { + ErrorMessage = patchError.ErrorMessage; + } + } +} diff --git a/test/Microsoft.AspNet.JsonPatch.Test/project.json b/test/Microsoft.AspNet.JsonPatch.Test/project.json new file mode 100644 index 0000000000..629b7a1be3 --- /dev/null +++ b/test/Microsoft.AspNet.JsonPatch.Test/project.json @@ -0,0 +1,18 @@ +{ + "compilationOptions": { + "warningsAsErrors": true + }, + "dependencies": { + "Microsoft.AspNet.JsonPatch": "1.0.0-*", + "Microsoft.AspNet.Testing": "1.0.0-*", + "Moq": "4.2.1312.1622", + "Newtonsoft.Json": "6.0.6", + "xunit.runner.aspnet": "2.0.0-aspnet-*" + }, + "commands": { + "test": "xunit.runner.aspnet" + }, + "frameworks": { + "dnx451": { } + } +} \ No newline at end of file From ae0baac22742650e734a41a26e67f864be859b55 Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Mon, 21 Sep 2015 11:47:54 -0700 Subject: [PATCH 0009/1029] simplify .travis.yml --- .travis.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 568e2673e9..947bf868ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,4 @@ language: csharp sudo: false -mono: - - beta -env: - - MONO_THREADS_PER_CPU=2000 MONO_MANAGED_WATCHER=disabled -os: - - linux - - osx -before_script: - - if [ $TRAVIS_OS_NAME == "osx" ] ; then sudo sysctl -w kern.maxfiles=64000 ; sudo sysctl -w kern.maxfilesperproc=64000 ; sudo launchctl limit maxfiles 64000 64000 ; fi ; ulimit -n 64000 script: - ./build.sh --quiet verify \ No newline at end of file From 22f22c04076c598735469306b291075b7ebfde62 Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Mon, 21 Sep 2015 12:48:21 -0700 Subject: [PATCH 0010/1029] chmod+x on build.sh --- build.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 build.sh diff --git a/build.sh b/build.sh old mode 100644 new mode 100755 From 7b697e8ec9aa2a7278d834189dc1cfc324eac8f0 Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Tue, 22 Sep 2015 16:06:18 -0700 Subject: [PATCH 0011/1029] Enabling NuGetPackageVerifier --- NuGetPackageVerifier.json | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 NuGetPackageVerifier.json diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json new file mode 100644 index 0000000000..a45e74c44d --- /dev/null +++ b/NuGetPackageVerifier.json @@ -0,0 +1,25 @@ +{ + "adx": { // Packages written by the ADX team and that ship on NuGet.org + "rules": [ + "AssemblyHasDocumentFileRule", + "AssemblyHasVersionAttributesRule", + "AssemblyHasServicingAttributeRule", + "AssemblyHasNeutralResourcesLanguageAttributeRule", + "SatellitePackageRule", + "StrictSemanticVersionValidationRule" + ], + "packages": { + "Microsoft.AspNet.JsonPatch": { } + } + }, + "Default": { // Rules to run for packages not listed in any other set. + "rules": [ + "AssemblyHasDocumentFileRule", + "AssemblyHasVersionAttributesRule", + "AssemblyHasServicingAttributeRule", + "AssemblyHasNeutralResourcesLanguageAttributeRule", + "SatellitePackageRule", + "StrictSemanticVersionValidationRule" + ] + } +} \ No newline at end of file From 3f40980d0200aa4491ec94042dd49987c52f3c3a Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Thu, 17 Sep 2015 14:05:33 -0700 Subject: [PATCH 0012/1029] First version of dnx watch --- .gitattributes | 50 +++ .gitignore | 27 ++ .travis.yml | 9 + NuGet.config | 7 + appveyor.yml | 7 + build.cmd | 39 +++ build.sh | 41 +++ dnx-watch.sln | 49 +++ global.json | 3 + makefile.shade | 7 + .../Abstractions/IFileWatcher.cs | 18 + .../Abstractions/IProcessWatcher.cs | 15 + .../Abstractions/IProject.cs | 16 + .../Abstractions/IProjectProvider.cs | 10 + .../DictionaryExtensions.cs | 23 ++ src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs | 225 ++++++++++++ .../External/Runtime/Constants.cs | 34 ++ .../External/Runtime/FileFormatException.cs | 123 +++++++ .../External/Runtime/LockFile.cs | 16 + .../Runtime/LockFileProjectLibrary.cs | 12 + .../External/Runtime/LockFileReader.cs | 220 ++++++++++++ .../External/Runtime/NamedResourceReader.cs | 75 ++++ .../External/Runtime/PackIncludeEntry.cs | 45 +++ .../External/Runtime/PathUtility.cs | 196 +++++++++++ .../External/Runtime/PatternGroup.cs | 123 +++++++ .../Runtime/PatternsCollectionHelper.cs | 106 ++++++ .../External/Runtime/Project.cs | 126 +++++++ .../Runtime/ProjectFilesCollection.cs | 202 +++++++++++ .../External/Runtime/ProjectReader.cs | 144 ++++++++ .../Runtime/RuntimeEnvironmentHelper.cs | 50 +++ .../External/Runtime/SemanticVersion.cs | 330 ++++++++++++++++++ .../FileSystem/FileSystemWatcherRoot.cs | 30 ++ .../FileSystem/FileWatcher.cs | 217 ++++++++++++ .../FileSystem/IWatcherRoot.cs | 12 + .../Impl/ProcessWatcher.cs | 97 +++++ .../Impl/Project.cs | 45 +++ .../Impl/ProjectProvider.cs | 53 +++ .../Microsoft.Dnx.Watcher.Core.xproj | 20 ++ src/Microsoft.Dnx.Watcher.Core/project.json | 36 ++ .../CommandOutputLogger.cs | 64 ++++ .../CommandOutputProvider.cs | 30 ++ .../Microsoft.Dnx.Watcher.xproj | 20 ++ src/Microsoft.Dnx.Watcher/Program.cs | 133 +++++++ .../Properties/AssemblyInfo.cs | 6 + src/Microsoft.Dnx.Watcher/project.json | 23 ++ .../CommandLineParsingTests.cs | 48 +++ .../Microsoft.Dnx.Watcher.Tests.xproj | 21 ++ test/Microsoft.Dnx.Watcher.Tests/project.json | 15 + 48 files changed, 3218 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 NuGet.config create mode 100644 appveyor.yml create mode 100644 build.cmd create mode 100755 build.sh create mode 100644 dnx-watch.sln create mode 100644 global.json create mode 100644 makefile.shade create mode 100644 src/Microsoft.Dnx.Watcher.Core/Abstractions/IFileWatcher.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/Abstractions/IProcessWatcher.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/Abstractions/IProject.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/Abstractions/IProjectProvider.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/DictionaryExtensions.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/Constants.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/FileFormatException.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFile.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFileProjectLibrary.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFileReader.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/NamedResourceReader.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/PackIncludeEntry.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/PathUtility.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternsCollectionHelper.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/Project.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectFilesCollection.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectReader.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/RuntimeEnvironmentHelper.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/SemanticVersion.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/FileSystem/FileSystemWatcherRoot.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/FileSystem/FileWatcher.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/FileSystem/IWatcherRoot.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/Impl/ProcessWatcher.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/Impl/Project.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs create mode 100644 src/Microsoft.Dnx.Watcher.Core/Microsoft.Dnx.Watcher.Core.xproj create mode 100644 src/Microsoft.Dnx.Watcher.Core/project.json create mode 100644 src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs create mode 100644 src/Microsoft.Dnx.Watcher/CommandOutputProvider.cs create mode 100644 src/Microsoft.Dnx.Watcher/Microsoft.Dnx.Watcher.xproj create mode 100644 src/Microsoft.Dnx.Watcher/Program.cs create mode 100644 src/Microsoft.Dnx.Watcher/Properties/AssemblyInfo.cs create mode 100644 src/Microsoft.Dnx.Watcher/project.json create mode 100644 test/Microsoft.Dnx.Watcher.Tests/CommandLineParsingTests.cs create mode 100644 test/Microsoft.Dnx.Watcher.Tests/Microsoft.Dnx.Watcher.Tests.xproj create mode 100644 test/Microsoft.Dnx.Watcher.Tests/project.json diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..bdaa5ba982 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,50 @@ +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain + +*.jpg binary +*.png binary +*.gif binary + +*.cs text=auto diff=csharp +*.vb text=auto +*.resx text=auto +*.c text=auto +*.cpp text=auto +*.cxx text=auto +*.h text=auto +*.hxx text=auto +*.py text=auto +*.rb text=auto +*.java text=auto +*.html text=auto +*.htm text=auto +*.css text=auto +*.scss text=auto +*.sass text=auto +*.less text=auto +*.js text=auto +*.lisp text=auto +*.clj text=auto +*.sql text=auto +*.php text=auto +*.lua text=auto +*.m text=auto +*.asm text=auto +*.erl text=auto +*.fs text=auto +*.fsx text=auto +*.hs text=auto + +*.csproj text=auto +*.vbproj text=auto +*.fsproj text=auto +*.dbproj text=auto +*.sln text=auto eol=crlf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..ac82da7568 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +[Oo]bj/ +[Bb]in/ +TestResults/ +.nuget/ +_ReSharper.*/ +packages/ +artifacts/ +PublishProfiles/ +*.user +*.suo +*.cache +*.docstates +_ReSharper.* +nuget.exe +*net45.csproj +*net451.csproj +*k10.csproj +*.psess +*.vsp +*.pidb +*.userprefs +*DS_Store +*.ncrunchsolution +*.*sdf +*.ipch +*.sln.ide +project.lock.json diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..f01ee5a79a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +language: csharp +sudo: false +env: + - MONO_THREADS_PER_CPU=2000 +os: + - linux + - osx +script: + - ./build.sh --quiet verify \ No newline at end of file diff --git a/NuGet.config b/NuGet.config new file mode 100644 index 0000000000..03704957e8 --- /dev/null +++ b/NuGet.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000000..636a7618d3 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,7 @@ +init: + - git config --global core.autocrlf true +build_script: + - build.cmd --quiet verify +clone_depth: 1 +test: off +deploy: off \ No newline at end of file diff --git a/build.cmd b/build.cmd new file mode 100644 index 0000000000..177997c42e --- /dev/null +++ b/build.cmd @@ -0,0 +1,39 @@ +@echo off +cd %~dp0 + +SETLOCAL +SET NUGET_VERSION=latest +SET CACHED_NUGET=%LocalAppData%\NuGet\nuget.%NUGET_VERSION%.exe +SET BUILDCMD_KOREBUILD_VERSION="" +SET BUILDCMD_DNX_VERSION="" + +IF EXIST %CACHED_NUGET% goto copynuget +echo Downloading latest version of NuGet.exe... +IF NOT EXIST %LocalAppData%\NuGet md %LocalAppData%\NuGet +@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/%NUGET_VERSION%/nuget.exe' -OutFile '%CACHED_NUGET%'" + +:copynuget +IF EXIST .nuget\nuget.exe goto restore +md .nuget +copy %CACHED_NUGET% .nuget\nuget.exe > nul + +:restore +IF EXIST packages\KoreBuild goto run +IF %BUILDCMD_KOREBUILD_VERSION%=="" ( + .nuget\nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre +) ELSE ( + .nuget\nuget.exe install KoreBuild -version %BUILDCMD_KOREBUILD_VERSION% -ExcludeVersion -o packages -nocache -pre +) +.nuget\nuget.exe install Sake -ExcludeVersion -Out packages + +IF "%SKIP_DNX_INSTALL%"=="1" goto run +IF %BUILDCMD_DNX_VERSION%=="" ( + CALL packages\KoreBuild\build\dnvm upgrade -runtime CLR -arch x86 +) ELSE ( + CALL packages\KoreBuild\build\dnvm install %BUILDCMD_DNX_VERSION% -runtime CLR -arch x86 -a default +) +CALL packages\KoreBuild\build\dnvm install default -runtime CoreCLR -arch x86 + +:run +CALL packages\KoreBuild\build\dnvm use default -runtime CLR -arch x86 +packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %* \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100755 index 0000000000..0c66139817 --- /dev/null +++ b/build.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +if test `uname` = Darwin; then + cachedir=~/Library/Caches/KBuild +else + if [ -z $XDG_DATA_HOME ]; then + cachedir=$HOME/.local/share + else + cachedir=$XDG_DATA_HOME; + fi +fi +mkdir -p $cachedir +nugetVersion=latest +cachePath=$cachedir/nuget.$nugetVersion.exe + +url=https://dist.nuget.org/win-x86-commandline/$nugetVersion/nuget.exe + +if test ! -f $cachePath; then + wget -O $cachePath $url 2>/dev/null || curl -o $cachePath --location $url /dev/null +fi + +if test ! -e .nuget; then + mkdir .nuget + cp $cachePath .nuget/nuget.exe +fi + +if test ! -d packages/KoreBuild; then + mono .nuget/nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre + mono .nuget/nuget.exe install Sake -ExcludeVersion -Out packages +fi + +if ! type dnvm > /dev/null 2>&1; then + source packages/KoreBuild/build/dnvm.sh +fi + +if ! type dnx > /dev/null 2>&1; then + dnvm upgrade +fi + +mono packages/Sake/tools/Sake.exe -I packages/KoreBuild/build -f makefile.shade "$@" + diff --git a/dnx-watch.sln b/dnx-watch.sln new file mode 100644 index 0000000000..6b01701d71 --- /dev/null +++ b/dnx-watch.sln @@ -0,0 +1,49 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.23107.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66517987-2A5A-4330-B130-207039378FD4}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Dnx.Watcher", "src\Microsoft.Dnx.Watcher\Microsoft.Dnx.Watcher.xproj", "{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Dnx.Watcher.Core", "src\Microsoft.Dnx.Watcher.Core\Microsoft.Dnx.Watcher.Core.xproj", "{D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8321E0D1-9A47-4D2F-AED8-3AE636D44E35}" + ProjectSection(SolutionItems) = preProject + global.json = global.json + NuGet.Config = NuGet.Config + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{442A6A17-4C5A-4E11-B547-A554063FD338}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Dnx.Watcher.Tests", "test\Microsoft.Dnx.Watcher.Tests\Microsoft.Dnx.Watcher.Tests.xproj", "{640D190B-26DB-4DDE-88EE-55814C86C43E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Release|Any CPU.Build.0 = Release|Any CPU + {D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}.Release|Any CPU.Build.0 = Release|Any CPU + {640D190B-26DB-4DDE-88EE-55814C86C43E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {640D190B-26DB-4DDE-88EE-55814C86C43E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {640D190B-26DB-4DDE-88EE-55814C86C43E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {640D190B-26DB-4DDE-88EE-55814C86C43E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46} = {66517987-2A5A-4330-B130-207039378FD4} + {D3DA3BBB-E206-404F-AEE6-17FB9B6F1221} = {66517987-2A5A-4330-B130-207039378FD4} + {640D190B-26DB-4DDE-88EE-55814C86C43E} = {442A6A17-4C5A-4E11-B547-A554063FD338} + EndGlobalSection +EndGlobal diff --git a/global.json b/global.json new file mode 100644 index 0000000000..553b2244a3 --- /dev/null +++ b/global.json @@ -0,0 +1,3 @@ +{ + "projects": [ "src"] +} diff --git a/makefile.shade b/makefile.shade new file mode 100644 index 0000000000..562494d144 --- /dev/null +++ b/makefile.shade @@ -0,0 +1,7 @@ + +var VERSION='0.1' +var FULL_VERSION='0.1' +var AUTHORS='Microsoft Open Technologies, Inc.' + +use-standard-lifecycle +k-standard-goals diff --git a/src/Microsoft.Dnx.Watcher.Core/Abstractions/IFileWatcher.cs b/src/Microsoft.Dnx.Watcher.Core/Abstractions/IFileWatcher.cs new file mode 100644 index 0000000000..8dfd44f1e5 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/Abstractions/IFileWatcher.cs @@ -0,0 +1,18 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.Dnx.Watcher.Core +{ + public interface IFileWatcher : IDisposable + { + event Action OnChanged; + + void WatchDirectory(string path, string extension); + + bool WatchFile(string path); + + void WatchProject(string path); + } +} diff --git a/src/Microsoft.Dnx.Watcher.Core/Abstractions/IProcessWatcher.cs b/src/Microsoft.Dnx.Watcher.Core/Abstractions/IProcessWatcher.cs new file mode 100644 index 0000000000..d075bd519a --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/Abstractions/IProcessWatcher.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.Dnx.Watcher.Core +{ + public interface IProcessWatcher + { + int Start(string executable, string arguments, string workingDir); + + Task WaitForExitAsync(CancellationToken cancellationToken); + } +} diff --git a/src/Microsoft.Dnx.Watcher.Core/Abstractions/IProject.cs b/src/Microsoft.Dnx.Watcher.Core/Abstractions/IProject.cs new file mode 100644 index 0000000000..cad54e0997 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/Abstractions/IProject.cs @@ -0,0 +1,16 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; + +namespace Microsoft.Dnx.Watcher.Core +{ + public interface IProject + { + string ProjectFile { get; } + + IEnumerable Files { get; } + + IEnumerable ProjectDependencies { get; } + } +} diff --git a/src/Microsoft.Dnx.Watcher.Core/Abstractions/IProjectProvider.cs b/src/Microsoft.Dnx.Watcher.Core/Abstractions/IProjectProvider.cs new file mode 100644 index 0000000000..77abc7bbb1 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/Abstractions/IProjectProvider.cs @@ -0,0 +1,10 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Dnx.Watcher.Core +{ + public interface IProjectProvider + { + bool TryReadProject(string projectFile, out IProject project, out string errors); + } +} diff --git a/src/Microsoft.Dnx.Watcher.Core/DictionaryExtensions.cs b/src/Microsoft.Dnx.Watcher.Core/DictionaryExtensions.cs new file mode 100644 index 0000000000..0b318da824 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/DictionaryExtensions.cs @@ -0,0 +1,23 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace System.Collections.Generic +{ + internal static class DictionaryExtensions + { + public static TValue GetOrAdd(this IDictionary dictionary, TKey key, Func factory) + { + lock (dictionary) + { + TValue value; + if (!dictionary.TryGetValue(key, out value)) + { + value = factory(key); + dictionary[key] = value; + } + + return value; + } + } + } +} diff --git a/src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs b/src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs new file mode 100644 index 0000000000..b71de61d59 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs @@ -0,0 +1,225 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Framework.Logging; + +namespace Microsoft.Dnx.Watcher.Core +{ + public class DnxWatcher + { + private readonly Func _fileWatcherFactory; + private readonly Func _processWatcherFactory; + private readonly IProjectProvider _projectProvider; + private readonly ILoggerFactory _loggerFactory; + + private readonly ILogger _logger; + + public DnxWatcher( + Func fileWatcherFactory, + Func processWatcherFactory, + IProjectProvider projectProvider, + ILoggerFactory loggerFactory) + { + _fileWatcherFactory = fileWatcherFactory; + _processWatcherFactory = processWatcherFactory; + _projectProvider = projectProvider; + _loggerFactory = loggerFactory; + + _logger = _loggerFactory.CreateLogger(nameof(DnxWatcher)); + } + public async Task WatchAsync(string projectFile, string[] dnxArguments, string workingDir, CancellationToken cancellationToken) + { + dnxArguments = new string[] { "--project", projectFile } + .Concat(dnxArguments) + .Select(arg => + { + // If the argument has spaces, make sure we quote it + if (arg.Contains(" ") || arg.Contains("\t")) + { + return $"\"{arg}\""; + } + + return arg; + }) + .ToArray(); + + var dnxArgumentsAsString = string.Join(" ", dnxArguments); + + while (true) + { + var project = await WaitForValidProjectJsonAsync(projectFile, cancellationToken); + cancellationToken.ThrowIfCancellationRequested(); + + using (var currentRunCancellationSource = new CancellationTokenSource()) + using (var combinedCancellationSource = CancellationTokenSource.CreateLinkedTokenSource( + cancellationToken, + currentRunCancellationSource.Token)) + { + var fileWatchingTask = WaitForProjectFileToChangeAsync(project, combinedCancellationSource.Token); + var dnxTask = WaitForDnxToExitAsync(dnxArgumentsAsString, workingDir, combinedCancellationSource.Token); + + var tasksToWait = new Task[] { dnxTask, fileWatchingTask }; + + int finishedTaskIndex = Task.WaitAny(tasksToWait, cancellationToken); + + // Regardless of the outcome, make sure everything is cancelled + // and wait for dnx to exit. We don't want orphan processes + currentRunCancellationSource.Cancel(); + Task.WaitAll(tasksToWait); + + cancellationToken.ThrowIfCancellationRequested(); + + if (finishedTaskIndex == 0) + { + // This is the dnx task + var dnxExitCode = dnxTask.Result; + + if (dnxExitCode == 0) + { + _logger.LogInformation($"dnx exit code: {dnxExitCode}"); + } + else + { + _logger.LogError($"dnx exit code: {dnxExitCode}"); + } + + _logger.LogInformation("Waiting for a file to change before restarting dnx..."); + // Now wait for a file to change before restarting dnx + await WaitForProjectFileToChangeAsync(project, cancellationToken); + } + else + { + // This is a file watcher task + string changedFile = fileWatchingTask.Result; + _logger.LogInformation($"File changed: {fileWatchingTask.Result}"); + } + } + } + } + + private async Task WaitForProjectFileToChangeAsync(IProject project, CancellationToken cancellationToken) + { + using (var fileWatcher = _fileWatcherFactory(Path.GetDirectoryName(project.ProjectFile))) + { + AddProjectAndDependeciesToWatcher(project, fileWatcher); + return await WatchForFileChangeAsync(fileWatcher, cancellationToken); + } + } + + private Task WaitForDnxToExitAsync(string dnxArguments, string workingDir, CancellationToken cancellationToken) + { + _logger.LogInformation($"Running dnx with the following arguments: {dnxArguments}"); + + var dnxWatcher = _processWatcherFactory(); + int dnxProcessId = dnxWatcher.Start("dnx", dnxArguments, workingDir); + _logger.LogInformation($"dnx process id: {dnxProcessId}"); + + return dnxWatcher.WaitForExitAsync(cancellationToken); + } + + private async Task WaitForValidProjectJsonAsync(string projectFile, CancellationToken cancellationToken) + { + IProject project = null; + + while (true) + { + string errors; + if (_projectProvider.TryReadProject(projectFile, out project, out errors)) + { + return project; + } + + _logger.LogError($"Error(s) reading project file '{projectFile}': "); + _logger.LogError(errors); + _logger.LogInformation("Fix the error to continue."); + + using (var fileWatcher = _fileWatcherFactory(Path.GetDirectoryName(projectFile))) + { + fileWatcher.WatchFile(projectFile); + fileWatcher.WatchProject(projectFile); + + await WatchForFileChangeAsync(fileWatcher, cancellationToken); + + if (cancellationToken.IsCancellationRequested) + { + return null; + } + + _logger.LogInformation($"File changed: {projectFile}"); + } + } + } + + private void AddProjectAndDependeciesToWatcher(string projectFile, IFileWatcher fileWatcher) + { + IProject project; + string errors; + + if (_projectProvider.TryReadProject(projectFile, out project, out errors)) + { + AddProjectAndDependeciesToWatcher(project, fileWatcher); + } + } + + private void AddProjectAndDependeciesToWatcher(IProject project, IFileWatcher fileWatcher) + { + foreach (var file in project.Files) + { + if (!string.IsNullOrEmpty(file)) + { + fileWatcher.WatchDirectory( + Path.GetDirectoryName(file), + Path.GetExtension(file)); + } + } + + fileWatcher.WatchProject(project.ProjectFile); + + foreach (var projFile in project.ProjectDependencies) + { + //var fullProjectFilePath = Path.Combine(Path.GetDirectoryName(project.ProjectFile), projFile); + + AddProjectAndDependeciesToWatcher(projFile, fileWatcher); + } + } + + private Task WatchForFileChangeAsync(IFileWatcher fileWatcher, CancellationToken cancellationToken) + { + return Task.Run(() => + { + using (var fileChangeEvent = new ManualResetEvent(false)) + { + string changedFile = null; + + fileWatcher.OnChanged += path => + { + changedFile = path; + fileChangeEvent.Set(); + }; + + while (!cancellationToken.IsCancellationRequested && + !fileChangeEvent.WaitOne(500)) + { + } + + return changedFile; + } + }); + } + + public static DnxWatcher CreateDefault(ILoggerFactory loggerFactory) + { + return new DnxWatcher( + fileWatcherFactory: root => { return new FileWatcher(root); }, + processWatcherFactory: () => { return new ProcessWatcher(); }, + projectProvider: new ProjectProvider(), + loggerFactory: loggerFactory); + } + + } +} diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/Constants.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/Constants.cs new file mode 100644 index 0000000000..9c2e502b02 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/Constants.cs @@ -0,0 +1,34 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.Dnx.Runtime +{ + internal static class Constants + { + public const string BootstrapperExeName = "dnx"; + public const string BootstrapperFullName = "Microsoft .NET Execution environment"; + public const string DefaultLocalRuntimeHomeDir = ".dnx"; + public const string RuntimeShortName = "dnx"; + public const string RuntimeLongName = "Microsoft DNX"; + public const string RuntimeNamePrefix = RuntimeShortName + "-"; + public const string WebConfigRuntimeVersion = RuntimeNamePrefix + "version"; + public const string WebConfigRuntimeFlavor = RuntimeNamePrefix + "clr"; + public const string WebConfigRuntimeAppBase = RuntimeNamePrefix + "app-base"; + public const string WebConfigBootstrapperVersion = "bootstrapper-version"; + public const string WebConfigRuntimePath = "runtime-path"; + public const string BootstrapperHostName = RuntimeShortName + ".host"; + public const string BootstrapperClrName = RuntimeShortName + ".clr"; + + public const int LockFileVersion = 2; + + public static readonly TimeSpan RegexMatchTimeout = TimeSpan.FromSeconds(10); + public static readonly string AppConfigurationFileName = "app.config"; + + public static readonly Version Version35 = new Version(3, 5); + public static readonly Version Version40 = new Version(4, 0); + public static readonly Version Version50 = new Version(5, 0); + public static readonly Version Version10_0 = new Version(10, 0); + } +} diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/FileFormatException.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/FileFormatException.cs new file mode 100644 index 0000000000..e895f724f7 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/FileFormatException.cs @@ -0,0 +1,123 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.Dnx.Runtime.Json; + +namespace Microsoft.Dnx.Runtime +{ + internal sealed class FileFormatException : Exception + { + private FileFormatException(string message) : + base(message) + { + } + + private FileFormatException(string message, Exception innerException) : + base(message, innerException) + { + } + + public string Path { get; private set; } + public int Line { get; private set; } + public int Column { get; private set; } + + public override string ToString() + { + return $"{Path}({Line},{Column}): Error: {base.ToString()}"; + } + + internal static FileFormatException Create(Exception exception, string filePath) + { + if (exception is JsonDeserializerException) + { + return new FileFormatException(exception.Message, exception) + .WithFilePath(filePath) + .WithLineInfo((JsonDeserializerException)exception); + } + else + { + return new FileFormatException(exception.Message, exception) + .WithFilePath(filePath); + } + } + + internal static FileFormatException Create(Exception exception, JsonValue jsonValue, string filePath) + { + var result = Create(exception, jsonValue) + .WithFilePath(filePath); + + return result; + } + + internal static FileFormatException Create(Exception exception, JsonValue jsonValue) + { + var result = new FileFormatException(exception.Message, exception) + .WithLineInfo(jsonValue); + + return result; + } + + internal static FileFormatException Create(string message, JsonValue jsonValue, string filePath) + { + var result = Create(message, jsonValue) + .WithFilePath(filePath); + + return result; + } + + internal static FileFormatException Create(string message, string filePath) + { + var result = new FileFormatException(message) + .WithFilePath(filePath); + + return result; + } + + internal static FileFormatException Create(string message, JsonValue jsonValue) + { + var result = new FileFormatException(message) + .WithLineInfo(jsonValue); + + return result; + } + + internal FileFormatException WithFilePath(string path) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Path = path; + + return this; + } + + private FileFormatException WithLineInfo(JsonValue value) + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + Line = value.Line; + Column = value.Column; + + return this; + } + + private FileFormatException WithLineInfo(JsonDeserializerException exception) + { + if (exception == null) + { + throw new ArgumentNullException(nameof(exception)); + } + + Line = exception.Line; + Column = exception.Column; + + return this; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFile.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFile.cs new file mode 100644 index 0000000000..8f07a5f54c --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFile.cs @@ -0,0 +1,16 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.Dnx.Runtime +{ + public class LockFile + { + public int Version { get; set; } + + public IList ProjectLibraries { get; set; } = new List(); + } +} \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFileProjectLibrary.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFileProjectLibrary.cs new file mode 100644 index 0000000000..a131fa32ce --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFileProjectLibrary.cs @@ -0,0 +1,12 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Dnx.Runtime +{ + public class LockFileProjectLibrary + { + public string Name { get; set; } + + public string Path { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFileReader.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFileReader.cs new file mode 100644 index 0000000000..f55b198ace --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFileReader.cs @@ -0,0 +1,220 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Versioning; +using System.Threading; +using Microsoft.Dnx.Runtime.Json; +using NuGet; + +namespace Microsoft.Dnx.Runtime +{ + internal class LockFileReader + { + public const string LockFileName = "project.lock.json"; + + public LockFile Read(string filePath) + { + using (var stream = OpenFileStream(filePath)) + { + try + { + return Read(stream); + } + catch (FileFormatException ex) + { + throw ex.WithFilePath(filePath); + } + catch (Exception ex) + { + throw FileFormatException.Create(ex, filePath); + } + } + } + + private static FileStream OpenFileStream(string filePath) + { + // Retry 3 times before re-throw the exception. + // It mitigates the race condition when DTH read lock file while VS is restoring projects. + + int retry = 3; + while (true) + { + try + { + return new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); + } + catch (Exception) + { + if (retry > 0) + { + retry--; + Thread.Sleep(100); + } + else + { + throw; + } + } + } + + } + + internal LockFile Read(Stream stream) + { + try + { + var reader = new StreamReader(stream); + var jobject = JsonDeserializer.Deserialize(reader) as JsonObject; + + if (jobject != null) + { + return ReadLockFile(jobject); + } + else + { + throw new InvalidDataException(); + } + } + catch + { + // Ran into parsing errors, mark it as unlocked and out-of-date + return new LockFile + { + Version = int.MinValue + }; + } + } + + private LockFile ReadLockFile(JsonObject cursor) + { + var lockFile = new LockFile(); + lockFile.Version = ReadInt(cursor, "version", defaultValue: int.MinValue); + ReadLibrary(cursor.ValueAsJsonObject("libraries"), lockFile); + + return lockFile; + } + + private void ReadLibrary(JsonObject json, LockFile lockFile) + { + if (json == null) + { + return; + } + + foreach (var key in json.Keys) + { + var value = json.ValueAsJsonObject(key); + if (value == null) + { + throw FileFormatException.Create("The value type is not object.", json.Value(key)); + } + + var parts = key.Split(new[] { '/' }, 2); + var name = parts[0]; + var version = parts.Length == 2 ? SemanticVersion.Parse(parts[1]) : null; + + var type = value.ValueAsString("type")?.Value; + + if (type == "project") + { + lockFile.ProjectLibraries.Add(new LockFileProjectLibrary + { + Name = name, + Path = ReadString(value.Value("path")) + }); + } + } + } + + private string ReadFrameworkAssemblyReference(JsonValue json) + { + return ReadString(json); + } + + private IList ReadArray(JsonValue json, Func readItem) + { + if (json == null) + { + return new List(); + } + + var jarray = json as JsonArray; + if (jarray == null) + { + throw FileFormatException.Create("The value type is not array.", json); + } + + var items = new List(); + for (int i = 0; i < jarray.Length; ++i) + { + items.Add(readItem(jarray[i])); + } + return items; + } + + private IList ReadObject(JsonObject json, Func readItem) + { + if (json == null) + { + return new List(); + } + var items = new List(); + foreach (var childKey in json.Keys) + { + items.Add(readItem(childKey, json.Value(childKey))); + } + return items; + } + + private bool ReadBool(JsonObject cursor, string property, bool defaultValue) + { + var valueToken = cursor.Value(property) as JsonBoolean; + if (valueToken == null) + { + return defaultValue; + } + + return valueToken.Value; + } + + private int ReadInt(JsonObject cursor, string property, int defaultValue) + { + var number = cursor.Value(property) as JsonNumber; + if (number == null) + { + return defaultValue; + } + + try + { + var resultInInt = Convert.ToInt32(number.Raw); + return resultInInt; + } + catch (Exception ex) + { + // FormatException or OverflowException + throw FileFormatException.Create(ex, cursor); + } + } + + private string ReadString(JsonValue json) + { + if (json is JsonString) + { + return (json as JsonString).Value; + } + else if (json is JsonNull) + { + return null; + } + else + { + throw FileFormatException.Create("The value type is not string.", json); + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/NamedResourceReader.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/NamedResourceReader.cs new file mode 100644 index 0000000000..1970cd4cb7 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/NamedResourceReader.cs @@ -0,0 +1,75 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.IO; +using Microsoft.Dnx.Runtime.Json; + +namespace Microsoft.Dnx.Runtime +{ + internal static class NamedResourceReader + { + public static IDictionary ReadNamedResources(JsonObject rawProject, string projectFilePath) + { + if (!rawProject.Keys.Contains("namedResource")) + { + return new Dictionary(); + } + + var namedResourceToken = rawProject.ValueAsJsonObject("namedResource"); + if (namedResourceToken == null) + { + throw FileFormatException.Create("Value must be object.", rawProject.Value("namedResource"), projectFilePath); + } + + var namedResources = new Dictionary(); + + foreach (var namedResourceKey in namedResourceToken.Keys) + { + var resourcePath = namedResourceToken.ValueAsString(namedResourceKey); + if (resourcePath == null) + { + throw FileFormatException.Create("Value must be string.", namedResourceToken.Value(namedResourceKey), projectFilePath); + } + + if (resourcePath.Value.Contains("*")) + { + throw FileFormatException.Create("Value cannot contain wildcards.", resourcePath, projectFilePath); + } + + var resourceFileFullPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(projectFilePath), resourcePath)); + + if (namedResources.ContainsKey(namedResourceKey)) + { + throw FileFormatException.Create( + string.Format("The named resource {0} already exists.", namedResourceKey), + resourcePath, + projectFilePath); + } + + namedResources.Add( + namedResourceKey, + resourceFileFullPath); + } + + return namedResources; + } + + public static void ApplyNamedResources(IDictionary namedResources, IDictionary resources) + { + foreach (var namedResource in namedResources) + { + // The named resources dictionary is like the project file + // key = name, value = path to resource + if (resources.ContainsKey(namedResource.Value)) + { + resources[namedResource.Value] = namedResource.Key; + } + else + { + resources.Add(namedResource.Value, namedResource.Key); + } + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PackIncludeEntry.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PackIncludeEntry.cs new file mode 100644 index 0000000000..0819ffed03 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PackIncludeEntry.cs @@ -0,0 +1,45 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Linq; +using Microsoft.Dnx.Runtime.Json; + +namespace Microsoft.Dnx.Runtime +{ + public class PackIncludeEntry + { + public string Target { get; } + public string[] SourceGlobs { get; } + public int Line { get; } + public int Column { get; } + + internal PackIncludeEntry(string target, JsonValue json) + : this(target, ExtractValues(json), json.Line, json.Column) + { + } + + public PackIncludeEntry(string target, string[] sourceGlobs, int line, int column) + { + Target = target; + SourceGlobs = sourceGlobs; + Line = line; + Column = column; + } + + private static string[] ExtractValues(JsonValue json) + { + var valueAsString = json as JsonString; + if (valueAsString != null) + { + return new string[] { valueAsString.Value }; + } + + var valueAsArray = json as JsonArray; + if(valueAsArray != null) + { + return valueAsArray.Values.Select(v => v.ToString()).ToArray(); + } + return new string[0]; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PathUtility.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PathUtility.cs new file mode 100644 index 0000000000..9546881690 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PathUtility.cs @@ -0,0 +1,196 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; + +namespace NuGet +{ + internal static class PathUtility + { + public static bool IsChildOfDirectory(string dir, string candidate) + { + if (dir == null) + { + throw new ArgumentNullException(nameof(dir)); + } + if (candidate == null) + { + throw new ArgumentNullException(nameof(candidate)); + } + dir = Path.GetFullPath(dir); + dir = EnsureTrailingSlash(dir); + candidate = Path.GetFullPath(candidate); + return candidate.StartsWith(dir, StringComparison.OrdinalIgnoreCase); + } + + public static string EnsureTrailingSlash(string path) + { + return EnsureTrailingCharacter(path, Path.DirectorySeparatorChar); + } + + public static string EnsureTrailingForwardSlash(string path) + { + return EnsureTrailingCharacter(path, '/'); + } + + private static string EnsureTrailingCharacter(string path, char trailingCharacter) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + // if the path is empty, we want to return the original string instead of a single trailing character. + if (path.Length == 0 || path[path.Length - 1] == trailingCharacter) + { + return path; + } + + return path + trailingCharacter; + } + + public static void EnsureParentDirectory(string filePath) + { + string directory = Path.GetDirectoryName(filePath); + if (!Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + } + + /// + /// Returns path2 relative to path1, with Path.DirectorySeparatorChar as separator + /// + public static string GetRelativePath(string path1, string path2) + { + return GetRelativePath(path1, path2, Path.DirectorySeparatorChar); + } + + /// + /// Returns path2 relative to path1, with given path separator + /// + public static string GetRelativePath(string path1, string path2, char separator) + { + if (string.IsNullOrEmpty(path1)) + { + throw new ArgumentException("Path must have a value", nameof(path1)); + } + + if (string.IsNullOrEmpty(path2)) + { + throw new ArgumentException("Path must have a value", nameof(path2)); + } + + StringComparison compare; + if (Microsoft.Dnx.Runtime.RuntimeEnvironmentHelper.IsWindows) + { + compare = StringComparison.OrdinalIgnoreCase; + // check if paths are on the same volume + if (!string.Equals(Path.GetPathRoot(path1), Path.GetPathRoot(path2))) + { + // on different volumes, "relative" path is just path2 + return path2; + } + } + else + { + compare = StringComparison.Ordinal; + } + + var index = 0; + var path1Segments = path1.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + var path2Segments = path2.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + // if path1 does not end with / it is assumed the end is not a directory + // we will assume that is isn't a directory by ignoring the last split + var len1 = path1Segments.Length - 1; + var len2 = path2Segments.Length; + + // find largest common absolute path between both paths + var min = Math.Min(len1, len2); + while (min > index) + { + if (!string.Equals(path1Segments[index], path2Segments[index], compare)) + { + break; + } + // Handle scenarios where folder and file have same name (only if os supports same name for file and directory) + // e.g. /file/name /file/name/app + else if ((len1 == index && len2 > index + 1) || (len1 > index && len2 == index + 1)) + { + break; + } + ++index; + } + + var path = ""; + + // check if path2 ends with a non-directory separator and if path1 has the same non-directory at the end + if (len1 + 1 == len2 && !string.IsNullOrEmpty(path1Segments[index]) && + string.Equals(path1Segments[index], path2Segments[index], compare)) + { + return path; + } + + for (var i = index; len1 > i; ++i) + { + path += ".." + separator; + } + for (var i = index; len2 - 1 > i; ++i) + { + path += path2Segments[i] + separator; + } + // if path2 doesn't end with an empty string it means it ended with a non-directory name, so we add it back + if (!string.IsNullOrEmpty(path2Segments[len2 - 1])) + { + path += path2Segments[len2 - 1]; + } + + return path; + } + + public static string GetAbsolutePath(string basePath, string relativePath) + { + if (basePath == null) + { + throw new ArgumentNullException(nameof(basePath)); + } + + if (relativePath == null) + { + throw new ArgumentNullException(nameof(relativePath)); + } + + Uri resultUri = new Uri(new Uri(basePath), new Uri(relativePath, UriKind.Relative)); + return resultUri.LocalPath; + } + + public static string GetDirectoryName(string path) + { + path = path.TrimEnd(Path.DirectorySeparatorChar); + return path.Substring(Path.GetDirectoryName(path).Length).Trim(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + } + + public static string GetPathWithForwardSlashes(string path) + { + return path.Replace('\\', '/'); + } + + public static string GetPathWithBackSlashes(string path) + { + return path.Replace('/', '\\'); + } + + public static string GetPathWithDirectorySeparator(string path) + { + if (Path.DirectorySeparatorChar == '/') + { + return GetPathWithForwardSlashes(path); + } + else + { + return GetPathWithBackSlashes(path); + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs new file mode 100644 index 0000000000..50012a7a35 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs @@ -0,0 +1,123 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.Framework.FileSystemGlobbing; +using Microsoft.Dnx.Runtime.Json; + +namespace Microsoft.Dnx.Runtime +{ + public class PatternGroup + { + private readonly List _excludeGroups = new List(); + private readonly Matcher _matcher = new Matcher(); + + internal PatternGroup(IEnumerable includePatterns) + { + IncludeLiterals = Enumerable.Empty(); + IncludePatterns = includePatterns; + ExcludePatterns = Enumerable.Empty(); + _matcher.AddIncludePatterns(IncludePatterns); + } + + internal PatternGroup(IEnumerable includePatterns, IEnumerable excludePatterns, IEnumerable includeLiterals) + { + IncludeLiterals = includeLiterals; + IncludePatterns = includePatterns; + ExcludePatterns = excludePatterns; + + _matcher.AddIncludePatterns(IncludePatterns); + _matcher.AddExcludePatterns(ExcludePatterns); + } + + internal static PatternGroup Build(JsonObject rawProject, + string projectDirectory, + string projectFilePath, + string name, + IEnumerable fallbackIncluding = null, + IEnumerable additionalIncluding = null, + IEnumerable additionalExcluding = null, + bool includePatternsOnly = false, + ICollection warnings = null) + { + string includePropertyName = name; + additionalIncluding = additionalIncluding ?? Enumerable.Empty(); + var includePatterns = PatternsCollectionHelper.GetPatternsCollection(rawProject, projectDirectory, projectFilePath, includePropertyName, defaultPatterns: fallbackIncluding) + .Concat(additionalIncluding) + .Distinct(); + + if (includePatternsOnly) + { + return new PatternGroup(includePatterns); + } + + additionalExcluding = additionalExcluding ?? Enumerable.Empty(); + var excludePatterns = PatternsCollectionHelper.GetPatternsCollection(rawProject, projectDirectory, projectFilePath, propertyName: name + "Exclude") + .Concat(additionalExcluding) + .Distinct(); + + var includeLiterals = PatternsCollectionHelper.GetPatternsCollection(rawProject, projectDirectory, projectFilePath, propertyName: name + "Files", literalPath: true) + .Distinct(); + + return new PatternGroup(includePatterns, excludePatterns, includeLiterals); + } + + public IEnumerable IncludeLiterals { get; } + + public IEnumerable IncludePatterns { get; } + + public IEnumerable ExcludePatterns { get; } + + public IEnumerable ExcludePatternsGroup { get { return _excludeGroups; } } + + public PatternGroup ExcludeGroup(PatternGroup group) + { + _excludeGroups.Add(group); + + return this; + } + + public IEnumerable SearchFiles(string rootPath) + { + // literal included files are added at the last, but the search happens early + // so as to make the process fail early in case there is missing file. fail early + // helps to avoid unnecessary globing for performance optimization + var literalIncludedFiles = new List(); + foreach (var literalRelativePath in IncludeLiterals) + { + var fullPath = Path.GetFullPath(Path.Combine(rootPath, literalRelativePath)); + + if (!File.Exists(fullPath)) + { + throw new InvalidOperationException(string.Format("Can't find file {0}", literalRelativePath)); + } + + // TODO: extract utility like NuGet.PathUtility.GetPathWithForwardSlashes() + literalIncludedFiles.Add(fullPath.Replace('\\', '/')); + } + + // globing files + var globbingResults = _matcher.GetResultsInFullPath(rootPath); + + // if there is no results generated in globing, skip excluding other groups + // for performance optimization. + if (globbingResults.Any()) + { + foreach (var group in _excludeGroups) + { + globbingResults = globbingResults.Except(group.SearchFiles(rootPath)); + } + } + + return globbingResults.Concat(literalIncludedFiles).Distinct(); + } + + public override string ToString() + { + return string.Format("Pattern group: Literals [{0}] Includes [{1}] Excludes [{2}]", string.Join(", ", IncludeLiterals), string.Join(", ", IncludePatterns), string.Join(", ", ExcludePatterns)); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternsCollectionHelper.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternsCollectionHelper.cs new file mode 100644 index 0000000000..33cb2f12de --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternsCollectionHelper.cs @@ -0,0 +1,106 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.Dnx.Runtime.Json; + +namespace Microsoft.Dnx.Runtime +{ + internal static class PatternsCollectionHelper + { + private static readonly char[] PatternSeparator = new[] { ';' }; + + public static IEnumerable GetPatternsCollection(JsonObject rawProject, + string projectDirectory, + string projectFilePath, + string propertyName, + IEnumerable defaultPatterns = null, + bool literalPath = false) + { + defaultPatterns = defaultPatterns ?? Enumerable.Empty(); + + try + { + if (!rawProject.Keys.Contains(propertyName)) + { + return CreateCollection(projectDirectory, propertyName, defaultPatterns, literalPath); + } + + var valueInString = rawProject.ValueAsString(propertyName); + if (valueInString != null) + { + return CreateCollection(projectDirectory, propertyName, new string[] { valueInString }, literalPath); + } + + var valuesInArray = rawProject.ValueAsStringArray(propertyName); + if (valuesInArray != null) + { + return CreateCollection(projectDirectory, propertyName, valuesInArray.Select(s => s.ToString()), literalPath); + } + } + catch (Exception ex) + { + throw FileFormatException.Create(ex, rawProject.Value(propertyName), projectFilePath); + } + + throw FileFormatException.Create("Value must be either string or array.", rawProject.Value(propertyName), projectFilePath); + } + + private static IEnumerable CreateCollection(string projectDirectory, string propertyName, IEnumerable patternsStrings, bool literalPath) + { + var patterns = patternsStrings.SelectMany(patternsString => GetSourcesSplit(patternsString)) + .Select(patternString => patternString.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar)); + + foreach (var pattern in patterns) + { + if (Path.IsPathRooted(pattern)) + { + throw new InvalidOperationException($"The '{propertyName}' property cannot be a rooted path."); + } + + if (literalPath && pattern.Contains('*')) + { + throw new InvalidOperationException($"The '{propertyName}' property cannot contain wildcard characters."); + } + } + + return new List(patterns.Select(pattern => FolderToPattern(pattern, projectDirectory))); + } + + private static IEnumerable GetSourcesSplit(string sourceDescription) + { + if (string.IsNullOrEmpty(sourceDescription)) + { + return Enumerable.Empty(); + } + + return sourceDescription.Split(PatternSeparator, StringSplitOptions.RemoveEmptyEntries); + } + + private static string FolderToPattern(string candidate, string projectDir) + { + // This conversion is needed to support current template + + // If it's already a pattern, no change is needed + if (candidate.Contains('*')) + { + return candidate; + } + + // If the given string ends with a path separator, or it is an existing directory + // we convert this folder name to a pattern matching all files in the folder + if (candidate.EndsWith(@"\") || + candidate.EndsWith("/") || + Directory.Exists(Path.Combine(projectDir, candidate))) + { + return Path.Combine(candidate, "**", "*"); + } + + // Otherwise, it represents a single file + return candidate; + } + } +} diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/Project.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/Project.cs new file mode 100644 index 0000000000..e9a610c29c --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/Project.cs @@ -0,0 +1,126 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Versioning; +using NuGet; + +namespace Microsoft.Dnx.Runtime +{ + public class Project + { + public const string ProjectFileName = "project.json"; + + public Project() + { + } + + public string ProjectFilePath { get; set; } + + public string ProjectDirectory + { + get + { + return Path.GetDirectoryName(ProjectFilePath); + } + } + + public string Name { get; set; } + + public string Title { get; set; } + + public string Description { get; set; } + + public string Copyright { get; set; } + + public string Summary { get; set; } + + public string Language { get; set; } + + public string ReleaseNotes { get; set; } + + public string[] Authors { get; set; } + + public string[] Owners { get; set; } + + public bool EmbedInteropTypes { get; set; } + + public Version AssemblyFileVersion { get; set; } + public string WebRoot { get; set; } + + public string EntryPoint { get; set; } + + public string ProjectUrl { get; set; } + + public string LicenseUrl { get; set; } + + public string IconUrl { get; set; } + + public bool RequireLicenseAcceptance { get; set; } + + public string[] Tags { get; set; } + + public bool IsLoadable { get; set; } + + public ProjectFilesCollection Files { get; set; } + + public IDictionary Commands { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase); + + public IDictionary> Scripts { get; } = new Dictionary>(StringComparer.OrdinalIgnoreCase); + + public static bool HasProjectFile(string path) + { + string projectPath = Path.Combine(path, ProjectFileName); + + return File.Exists(projectPath); + } + + public static bool TryGetProject(string path, out Project project, ICollection diagnostics = null) + { + project = null; + + string projectPath = null; + + if (string.Equals(Path.GetFileName(path), ProjectFileName, StringComparison.OrdinalIgnoreCase)) + { + projectPath = path; + path = Path.GetDirectoryName(path); + } + else if (!HasProjectFile(path)) + { + return false; + } + else + { + projectPath = Path.Combine(path, ProjectFileName); + } + + // Assume the directory name is the project name if none was specified + var projectName = PathUtility.GetDirectoryName(path); + projectPath = Path.GetFullPath(projectPath); + + if (!File.Exists(projectPath)) + { + return false; + } + + try + { + using (var stream = File.OpenRead(projectPath)) + { + var reader = new ProjectReader(); + project = reader.ReadProject(stream, projectName, projectPath, diagnostics); + } + } + catch (Exception ex) + { + throw FileFormatException.Create(ex, projectPath); + } + + return true; + } + } +} diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectFilesCollection.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectFilesCollection.cs new file mode 100644 index 0000000000..9ee0056e5c --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectFilesCollection.cs @@ -0,0 +1,202 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using Microsoft.Dnx.Runtime.Json; + +namespace Microsoft.Dnx.Runtime +{ + public class ProjectFilesCollection + { + public static readonly string[] DefaultCompileBuiltInPatterns = new[] { @"**/*.cs" }; + public static readonly string[] DefaultPublishExcludePatterns = new[] { @"obj/**/*.*", @"bin/**/*.*", @"**/.*/**", @"**/global.json" }; + public static readonly string[] DefaultPreprocessPatterns = new[] { @"compiler/preprocess/**/*.cs" }; + public static readonly string[] DefaultSharedPatterns = new[] { @"compiler/shared/**/*.cs" }; + public static readonly string[] DefaultResourcesBuiltInPatterns = new[] { @"compiler/resources/**/*", "**/*.resx" }; + public static readonly string[] DefaultContentsBuiltInPatterns = new[] { @"**/*" }; + + public static readonly string[] DefaultBuiltInExcludePatterns = new[] { "bin/**", "obj/**", "**/*.xproj" }; + + public static readonly string PackIncludePropertyName = "packInclude"; + + private PatternGroup _sharedPatternsGroup; + private PatternGroup _resourcePatternsGroup; + private PatternGroup _preprocessPatternsGroup; + private PatternGroup _compilePatternsGroup; + private PatternGroup _contentPatternsGroup; + private IDictionary _namedResources; + private IEnumerable _publishExcludePatterns; + private IEnumerable _packInclude; + + private readonly string _projectDirectory; + private readonly string _projectFilePath; + + private JsonObject _rawProject; + private bool _initialized; + + internal ProjectFilesCollection(JsonObject rawProject, string projectDirectory, string projectFilePath) + { + _projectDirectory = projectDirectory; + _projectFilePath = projectFilePath; + _rawProject = rawProject; + } + + internal void EnsureInitialized() + { + if (_initialized) + { + return; + } + + var excludeBuiltIns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "excludeBuiltIn", DefaultBuiltInExcludePatterns); + var excludePatterns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "exclude") + .Concat(excludeBuiltIns); + var contentBuiltIns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "contentBuiltIn", DefaultContentsBuiltInPatterns); + var compileBuiltIns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "compileBuiltIn", DefaultCompileBuiltInPatterns); + var resourceBuiltIns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "resourceBuiltIn", DefaultResourcesBuiltInPatterns); + + _publishExcludePatterns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "publishExclude", DefaultPublishExcludePatterns); + + _sharedPatternsGroup = PatternGroup.Build(_rawProject, _projectDirectory, _projectFilePath, "shared", fallbackIncluding: DefaultSharedPatterns, additionalExcluding: excludePatterns); + + _resourcePatternsGroup = PatternGroup.Build(_rawProject, _projectDirectory, _projectFilePath, "resource", additionalIncluding: resourceBuiltIns, additionalExcluding: excludePatterns); + + _preprocessPatternsGroup = PatternGroup.Build(_rawProject, _projectDirectory, _projectFilePath, "preprocess", fallbackIncluding: DefaultPreprocessPatterns, additionalExcluding: excludePatterns) + .ExcludeGroup(_sharedPatternsGroup) + .ExcludeGroup(_resourcePatternsGroup); + + _compilePatternsGroup = PatternGroup.Build(_rawProject, _projectDirectory, _projectFilePath, "compile", additionalIncluding: compileBuiltIns, additionalExcluding: excludePatterns) + .ExcludeGroup(_sharedPatternsGroup) + .ExcludeGroup(_preprocessPatternsGroup) + .ExcludeGroup(_resourcePatternsGroup); + + _contentPatternsGroup = PatternGroup.Build(_rawProject, _projectDirectory, _projectFilePath, "content", additionalIncluding: contentBuiltIns, additionalExcluding: excludePatterns.Concat(_publishExcludePatterns)) + .ExcludeGroup(_compilePatternsGroup) + .ExcludeGroup(_preprocessPatternsGroup) + .ExcludeGroup(_sharedPatternsGroup) + .ExcludeGroup(_resourcePatternsGroup); + + _namedResources = NamedResourceReader.ReadNamedResources(_rawProject, _projectFilePath); + + // Files to be packed along with the project + var packIncludeJson = _rawProject.ValueAsJsonObject(PackIncludePropertyName); + if (packIncludeJson != null) + { + _packInclude = packIncludeJson + .Keys + .Select(k => new PackIncludeEntry(k, packIncludeJson.Value(k))) + .ToList(); + } + else + { + _packInclude = new List(); + } + + _initialized = true; + _rawProject = null; + } + + public IEnumerable PackInclude + { + get + { + EnsureInitialized(); + return _packInclude; + } + } + + public IEnumerable SourceFiles + { + get { return CompilePatternsGroup.SearchFiles(_projectDirectory).Distinct(); } + } + + public IEnumerable PreprocessSourceFiles + { + get { return PreprocessPatternsGroup.SearchFiles(_projectDirectory).Distinct(); } + } + + public IDictionary ResourceFiles + { + get + { + var resources = ResourcePatternsGroup + .SearchFiles(_projectDirectory) + .Distinct() + .ToDictionary(res => res, res => (string)null); + + NamedResourceReader.ApplyNamedResources(_namedResources, resources); + + return resources; + } + } + + public IEnumerable SharedFiles + { + get { return SharedPatternsGroup.SearchFiles(_projectDirectory).Distinct(); } + } + + public IEnumerable GetFilesForBundling(bool includeSource, IEnumerable additionalExcludePatterns) + { + var patternGroup = new PatternGroup(ContentPatternsGroup.IncludePatterns, + ContentPatternsGroup.ExcludePatterns.Concat(additionalExcludePatterns), + ContentPatternsGroup.IncludeLiterals); + if (!includeSource) + { + foreach (var excludedGroup in ContentPatternsGroup.ExcludePatternsGroup) + { + patternGroup.ExcludeGroup(excludedGroup); + } + } + + return patternGroup.SearchFiles(_projectDirectory); + } + + internal PatternGroup CompilePatternsGroup + { + get + { + EnsureInitialized(); + return _compilePatternsGroup; + } + } + + internal PatternGroup SharedPatternsGroup + { + get + { + EnsureInitialized(); + return _sharedPatternsGroup; + } + } + + internal PatternGroup ResourcePatternsGroup + { + get + { + EnsureInitialized(); + return _resourcePatternsGroup; + } + } + + internal PatternGroup PreprocessPatternsGroup + { + get + { + EnsureInitialized(); + return _preprocessPatternsGroup; + } + } + + internal PatternGroup ContentPatternsGroup + { + get + { + EnsureInitialized(); + return _contentPatternsGroup; + } + } + } +} diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectReader.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectReader.cs new file mode 100644 index 0000000000..b8aeb4734a --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectReader.cs @@ -0,0 +1,144 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.Dnx.Runtime.Json; +using NuGet; + +namespace Microsoft.Dnx.Runtime +{ + public class ProjectReader + { + public Project ReadProject(Stream stream, string projectName, string projectPath, ICollection diagnostics) + { + var project = new Project(); + + var reader = new StreamReader(stream); + var rawProject = JsonDeserializer.Deserialize(reader) as JsonObject; + if (rawProject == null) + { + throw FileFormatException.Create( + "The JSON file can't be deserialized to a JSON object.", + projectPath); + } + + // Meta-data properties + project.Name = projectName; + project.ProjectFilePath = Path.GetFullPath(projectPath); + + var version = rawProject.Value("version") as JsonString; + + project.Description = rawProject.ValueAsString("description"); + project.Summary = rawProject.ValueAsString("summary"); + project.Copyright = rawProject.ValueAsString("copyright"); + project.Title = rawProject.ValueAsString("title"); + project.WebRoot = rawProject.ValueAsString("webroot"); + project.EntryPoint = rawProject.ValueAsString("entryPoint"); + project.ProjectUrl = rawProject.ValueAsString("projectUrl"); + project.LicenseUrl = rawProject.ValueAsString("licenseUrl"); + project.IconUrl = rawProject.ValueAsString("iconUrl"); + + project.Authors = rawProject.ValueAsStringArray("authors") ?? new string[] { }; + project.Owners = rawProject.ValueAsStringArray("owners") ?? new string[] { }; + project.Tags = rawProject.ValueAsStringArray("tags") ?? new string[] { }; + + project.Language = rawProject.ValueAsString("language"); + project.ReleaseNotes = rawProject.ValueAsString("releaseNotes"); + + project.RequireLicenseAcceptance = rawProject.ValueAsBoolean("requireLicenseAcceptance", defaultValue: false); + project.IsLoadable = rawProject.ValueAsBoolean("loadable", defaultValue: true); + // TODO: Move this to the dependencies node + project.EmbedInteropTypes = rawProject.ValueAsBoolean("embedInteropTypes", defaultValue: false); + + // Project files + project.Files = new ProjectFilesCollection(rawProject, project.ProjectDirectory, project.ProjectFilePath); + + var commands = rawProject.Value("commands") as JsonObject; + if (commands != null) + { + foreach (var key in commands.Keys) + { + var value = commands.ValueAsString(key); + if (value != null) + { + project.Commands[key] = value; + } + } + } + + var scripts = rawProject.Value("scripts") as JsonObject; + if (scripts != null) + { + foreach (var key in scripts.Keys) + { + var stringValue = scripts.ValueAsString(key); + if (stringValue != null) + { + project.Scripts[key] = new string[] { stringValue }; + continue; + } + + var arrayValue = scripts.ValueAsStringArray(key); + if (arrayValue != null) + { + project.Scripts[key] = arrayValue; + continue; + } + + throw FileFormatException.Create( + string.Format("The value of a script in {0} can only be a string or an array of strings", Project.ProjectFileName), + scripts.Value(key), + project.ProjectFilePath); + } + } + + return project; + } + + private static SemanticVersion SpecifySnapshot(string version, string snapshotValue) + { + if (version.EndsWith("-*")) + { + if (string.IsNullOrEmpty(snapshotValue)) + { + version = version.Substring(0, version.Length - 2); + } + else + { + version = version.Substring(0, version.Length - 1) + snapshotValue; + } + } + + return new SemanticVersion(version); + } + + private static bool TryGetStringEnumerable(JsonObject parent, string property, out IEnumerable result) + { + var collection = new List(); + var valueInString = parent.ValueAsString(property); + if (valueInString != null) + { + collection.Add(valueInString); + } + else + { + var valueInArray = parent.ValueAsStringArray(property); + if (valueInArray != null) + { + collection.AddRange(valueInArray); + } + else + { + result = null; + return false; + } + } + + result = collection.SelectMany(value => value.Split(new[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries)); + return true; + } + } +} diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/RuntimeEnvironmentHelper.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/RuntimeEnvironmentHelper.cs new file mode 100644 index 0000000000..4003c3fee4 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/RuntimeEnvironmentHelper.cs @@ -0,0 +1,50 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.Dnx.Runtime +{ + internal static class RuntimeEnvironmentHelper + { + private static Lazy _isMono = new Lazy(() => + _runtimeEnv.Value.RuntimeType == "Mono"); + + private static Lazy _isWindows = new Lazy(() => + _runtimeEnv.Value.OperatingSystem == "Windows"); + + private static Lazy _runtimeEnv = new Lazy(() => + GetRuntimeEnvironment()); + + private static IRuntimeEnvironment GetRuntimeEnvironment() + { + var provider = Infrastructure.CallContextServiceLocator.Locator.ServiceProvider; + var environment = (IRuntimeEnvironment)provider?.GetService(typeof(IRuntimeEnvironment)); + + if (environment == null) + { + throw new InvalidOperationException("Failed to resolve IRuntimeEnvironment"); + } + + return environment; + } + + public static IRuntimeEnvironment RuntimeEnvironment + { + get + { + return _runtimeEnv.Value; + } + } + + public static bool IsWindows + { + get { return _isWindows.Value; } + } + + public static bool IsMono + { + get { return _isMono.Value; } + } + } +} diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/SemanticVersion.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/SemanticVersion.cs new file mode 100644 index 0000000000..59846a2cf9 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/SemanticVersion.cs @@ -0,0 +1,330 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Text; + +namespace NuGet +{ + /// + /// A hybrid implementation of SemVer that supports semantic versioning as described at http://semver.org while not strictly enforcing it to + /// allow older 4-digit versioning schemes to continue working. + /// + internal sealed class SemanticVersion : IComparable, IComparable, IEquatable + { + private string _normalizedVersionString; + + public SemanticVersion(string version) + : this(Parse(version)) + { + } + + public SemanticVersion(int major, int minor, int build, int revision) + : this(new Version(major, minor, build, revision)) + { + } + + public SemanticVersion(int major, int minor, int build, string specialVersion) + : this(new Version(major, minor, build), specialVersion) + { + } + + public SemanticVersion(Version version) + : this(version, string.Empty) + { + } + + public SemanticVersion(Version version, string specialVersion) + { + if (version == null) + { + throw new ArgumentNullException(nameof(version)); + } + Version = NormalizeVersionValue(version); + SpecialVersion = specialVersion ?? string.Empty; + } + + internal SemanticVersion(SemanticVersion semVer) + { + Version = semVer.Version; + SpecialVersion = semVer.SpecialVersion; + } + + /// + /// Gets the normalized version portion. + /// + public Version Version + { + get; + private set; + } + + /// + /// Gets the optional special version. + /// + public string SpecialVersion + { + get; + private set; + } + + private static string[] SplitAndPadVersionString(string version) + { + string[] a = version.Split('.'); + if (a.Length == 4) + { + return a; + } + else + { + // if 'a' has less than 4 elements, we pad the '0' at the end + // to make it 4. + var b = new string[4] { "0", "0", "0", "0" }; + Array.Copy(a, 0, b, 0, a.Length); + return b; + } + } + + /// + /// Parses a version string using loose semantic versioning rules that allows 2-4 version components followed by an optional special version. + /// + public static SemanticVersion Parse(string version) + { + if (string.IsNullOrEmpty(version)) + { + throw new ArgumentNullException(nameof(version)); + } + + SemanticVersion semVer; + if (!TryParse(version, out semVer)) + { + throw new ArgumentException(nameof(version)); + } + return semVer; + } + + /// + /// Parses a version string using loose semantic versioning rules that allows 2-4 version components followed by an optional special version. + /// + public static bool TryParse(string version, out SemanticVersion value) + { + return TryParseInternal(version, strict: false, semVer: out value); + } + + /// + /// Parses a version string using strict semantic versioning rules that allows exactly 3 components and an optional special version. + /// + public static bool TryParseStrict(string version, out SemanticVersion value) + { + return TryParseInternal(version, strict: true, semVer: out value); + } + + private static bool TryParseInternal(string version, bool strict, out SemanticVersion semVer) + { + semVer = null; + if (string.IsNullOrEmpty(version)) + { + return false; + } + + version = version.Trim(); + var versionPart = version; + + string specialVersion = string.Empty; + if (version.IndexOf('-') != -1) + { + var parts = version.Split(new char[] { '-' }, 2, StringSplitOptions.RemoveEmptyEntries); + if (parts.Length != 2) + { + return false; + } + + versionPart = parts[0]; + specialVersion = parts[1]; + } + + Version versionValue; + if (!Version.TryParse(versionPart, out versionValue)) + { + return false; + } + + if (strict) + { + // Must have major, minor and build only. + if (versionValue.Major == -1 || + versionValue.Minor == -1 || + versionValue.Build == -1 || + versionValue.Revision != -1) + { + return false; + } + } + + semVer = new SemanticVersion(NormalizeVersionValue(versionValue), specialVersion); + return true; + } + + /// + /// Attempts to parse the version token as a SemanticVersion. + /// + /// An instance of SemanticVersion if it parses correctly, null otherwise. + public static SemanticVersion ParseOptionalVersion(string version) + { + SemanticVersion semVer; + TryParse(version, out semVer); + return semVer; + } + + private static Version NormalizeVersionValue(Version version) + { + return new Version(version.Major, + version.Minor, + Math.Max(version.Build, 0), + Math.Max(version.Revision, 0)); + } + + public int CompareTo(object obj) + { + if (Object.ReferenceEquals(obj, null)) + { + return 1; + } + SemanticVersion other = obj as SemanticVersion; + if (other == null) + { + throw new ArgumentException(nameof(obj)); + } + return CompareTo(other); + } + + public int CompareTo(SemanticVersion other) + { + if (Object.ReferenceEquals(other, null)) + { + return 1; + } + + int result = Version.CompareTo(other.Version); + + if (result != 0) + { + return result; + } + + bool empty = string.IsNullOrEmpty(SpecialVersion); + bool otherEmpty = string.IsNullOrEmpty(other.SpecialVersion); + if (empty && otherEmpty) + { + return 0; + } + else if (empty) + { + return 1; + } + else if (otherEmpty) + { + return -1; + } + return StringComparer.OrdinalIgnoreCase.Compare(SpecialVersion, other.SpecialVersion); + } + + public static bool operator ==(SemanticVersion version1, SemanticVersion version2) + { + if (Object.ReferenceEquals(version1, null)) + { + return Object.ReferenceEquals(version2, null); + } + return version1.Equals(version2); + } + + public static bool operator !=(SemanticVersion version1, SemanticVersion version2) + { + return !(version1 == version2); + } + + public static bool operator <(SemanticVersion version1, SemanticVersion version2) + { + if (version1 == null) + { + throw new ArgumentNullException(nameof(version1)); + } + return version1.CompareTo(version2) < 0; + } + + public static bool operator <=(SemanticVersion version1, SemanticVersion version2) + { + return (version1 == version2) || (version1 < version2); + } + + public static bool operator >(SemanticVersion version1, SemanticVersion version2) + { + if (version1 == null) + { + throw new ArgumentNullException(nameof(version1)); + } + return version2 < version1; + } + + public static bool operator >=(SemanticVersion version1, SemanticVersion version2) + { + return (version1 == version2) || (version1 > version2); + } + + public override string ToString() + { + if (_normalizedVersionString == null) + { + var builder = new StringBuilder(); + builder + .Append(Version.Major) + .Append('.') + .Append(Version.Minor) + .Append('.') + .Append(Math.Max(0, Version.Build)); + + if (Version.Revision > 0) + { + builder + .Append('.') + .Append(Version.Revision); + } + + if (!string.IsNullOrEmpty(SpecialVersion)) + { + builder + .Append('-') + .Append(SpecialVersion); + } + + _normalizedVersionString = builder.ToString(); + } + + return _normalizedVersionString; + } + + public bool Equals(SemanticVersion other) + { + return !Object.ReferenceEquals(null, other) && + Version.Equals(other.Version) && + SpecialVersion.Equals(other.SpecialVersion, StringComparison.OrdinalIgnoreCase); + } + + public override bool Equals(object obj) + { + SemanticVersion semVer = obj as SemanticVersion; + return !Object.ReferenceEquals(null, semVer) && Equals(semVer); + } + + public override int GetHashCode() + { + int hashCode = Version.GetHashCode(); + if (SpecialVersion != null) + { + hashCode = hashCode * 4567 + SpecialVersion.GetHashCode(); + } + + return hashCode; + } + } +} diff --git a/src/Microsoft.Dnx.Watcher.Core/FileSystem/FileSystemWatcherRoot.cs b/src/Microsoft.Dnx.Watcher.Core/FileSystem/FileSystemWatcherRoot.cs new file mode 100644 index 0000000000..3c4fb517c1 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/FileSystem/FileSystemWatcherRoot.cs @@ -0,0 +1,30 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; + +namespace Microsoft.Dnx.Watcher.Core +{ + internal class FileSystemWatcherRoot : IWatcherRoot + { + private readonly FileSystemWatcher _watcher; + + public FileSystemWatcherRoot(FileSystemWatcher watcher) + { + _watcher = watcher; + } + + public string Path + { + get + { + return _watcher.Path; + } + } + + public void Dispose() + { + _watcher.Dispose(); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/FileSystem/FileWatcher.cs b/src/Microsoft.Dnx.Watcher.Core/FileSystem/FileWatcher.cs new file mode 100644 index 0000000000..fe9921336e --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/FileSystem/FileWatcher.cs @@ -0,0 +1,217 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; + +namespace Microsoft.Dnx.Watcher.Core +{ + public class FileWatcher : IFileWatcher + { + private readonly HashSet _files = new HashSet(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary> _directories = new Dictionary>(StringComparer.OrdinalIgnoreCase); + + private readonly List _watchers = new List(); + + internal FileWatcher() + { + } + + public FileWatcher(string path) + { + AddWatcher(path); + } + + public event Action OnChanged; + + public void WatchDirectory(string path, string extension) + { + var extensions = _directories.GetOrAdd(path, _ => new HashSet(StringComparer.OrdinalIgnoreCase)); + + extensions.Add(extension); + } + + public bool WatchFile(string path) + { + return _files.Add(path); + } + + public void WatchProject(string projectPath) + { + if (string.IsNullOrEmpty(projectPath)) + { + return; + } + + // If any watchers already handle this path then noop + if (!IsAlreadyWatched(projectPath)) + { + // To reduce the number of watchers we have we add a watcher to the root + // of this project so that we'll be notified if anything we care + // about changes + var rootPath = ResolveRootDirectory(projectPath); + AddWatcher(rootPath); + } + } + + // For testing + internal bool IsAlreadyWatched(string projectPath) + { + if (string.IsNullOrEmpty(projectPath)) + { + return false; + } + + bool anyWatchers = false; + + foreach (var watcher in _watchers) + { + // REVIEW: This needs to work x-platform, should this be case + // sensitive? + if (EnsureTrailingSlash(projectPath).StartsWith(EnsureTrailingSlash(watcher.Path), StringComparison.OrdinalIgnoreCase)) + { + anyWatchers = true; + } + } + + return anyWatchers; + } + + public void Dispose() + { + foreach (var w in _watchers) + { + w.Dispose(); + } + + _watchers.Clear(); + } + + public bool ReportChange(string newPath, WatcherChangeTypes changeType) + { + return ReportChange(oldPath: null, newPath: newPath, changeType: changeType); + } + + public bool ReportChange(string oldPath, string newPath, WatcherChangeTypes changeType) + { + if (HasChanged(oldPath, newPath, changeType)) + { + if (OnChanged != null) + { + OnChanged(oldPath ?? newPath); + } + + return true; + } + + return false; + } + + private static string EnsureTrailingSlash(string path) + { + if (string.IsNullOrEmpty(path)) + { + return path; + } + + if (path[path.Length - 1] != Path.DirectorySeparatorChar) + { + return path + Path.DirectorySeparatorChar; + } + + return path; + } + + // For testing only + internal void AddWatcher(IWatcherRoot watcherRoot) + { + _watchers.Add(watcherRoot); + } + + private void AddWatcher(string path) + { + var watcher = new FileSystemWatcher(path); + watcher.IncludeSubdirectories = true; + watcher.EnableRaisingEvents = true; + + watcher.Changed += OnWatcherChanged; + watcher.Renamed += OnRenamed; + watcher.Deleted += OnWatcherChanged; + watcher.Created += OnWatcherChanged; + + _watchers.Add(new FileSystemWatcherRoot(watcher)); + } + + private void OnRenamed(object sender, RenamedEventArgs e) + { + ReportChange(e.OldFullPath, e.FullPath, e.ChangeType); + } + + private void OnWatcherChanged(object sender, FileSystemEventArgs e) + { + ReportChange(e.FullPath, e.ChangeType); + } + + private bool HasChanged(string oldPath, string newPath, WatcherChangeTypes changeType) + { + // File changes + if (_files.Contains(newPath) || + (oldPath != null && _files.Contains(oldPath))) + { + return true; + } + + HashSet extensions; + if (_directories.TryGetValue(newPath, out extensions) || + _directories.TryGetValue(Path.GetDirectoryName(newPath), out extensions)) + { + string extension = Path.GetExtension(newPath); + + if (String.IsNullOrEmpty(extension)) + { + // Assume it's a directory + if (changeType == WatcherChangeTypes.Created || + changeType == WatcherChangeTypes.Renamed) + { + foreach (var e in extensions) + { + WatchDirectory(newPath, e); + } + } + else if (changeType == WatcherChangeTypes.Deleted) + { + return true; + } + + // Ignore anything else + return false; + } + + return extensions.Contains(extension); + } + + return false; + } + + private static string ResolveRootDirectory(string projectPath) + { + var di = new DirectoryInfo(projectPath); + + while (di.Parent != null) + { + var globalJsonPath = Path.Combine(di.FullName, "global.json"); + + if (File.Exists(globalJsonPath)) + { + return di.FullName; + } + + di = di.Parent; + } + + // If we don't find any files then make the project folder the root + return projectPath; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/FileSystem/IWatcherRoot.cs b/src/Microsoft.Dnx.Watcher.Core/FileSystem/IWatcherRoot.cs new file mode 100644 index 0000000000..ffc7a86f6b --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/FileSystem/IWatcherRoot.cs @@ -0,0 +1,12 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.Dnx.Watcher.Core +{ + internal interface IWatcherRoot : IDisposable + { + string Path { get; } + } +} diff --git a/src/Microsoft.Dnx.Watcher.Core/Impl/ProcessWatcher.cs b/src/Microsoft.Dnx.Watcher.Core/Impl/ProcessWatcher.cs new file mode 100644 index 0000000000..86b3cc13d7 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/Impl/ProcessWatcher.cs @@ -0,0 +1,97 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.Dnx.Watcher.Core +{ + public class ProcessWatcher : IProcessWatcher + { + private Process _runningProcess; + + public int Start(string executable, string arguments, string workingDir) + { + // This is not thread safe but it will not run in a multithreaded environment so don't worry + if (_runningProcess != null) + { + throw new InvalidOperationException("The previous process is still running"); + } + + _runningProcess = new Process(); + _runningProcess.StartInfo = new ProcessStartInfo() + { + FileName = executable, + Arguments = arguments, + UseShellExecute = false, + WorkingDirectory = workingDir + }; + + RemoveCompilationPortEnvironmentVariable(_runningProcess.StartInfo); + + _runningProcess.Start(); + + return _runningProcess.Id; + } + + public async Task WaitForExitAsync(CancellationToken cancellationToken) + { + try + { + await Task.Run(() => + { + while (!cancellationToken.IsCancellationRequested) + { + if (_runningProcess.WaitForExit(500)) + { + break; + } + } + + if (!_runningProcess.HasExited) + { + _runningProcess.Kill(); + } + + }); + + return _runningProcess.ExitCode; + } + finally + { + _runningProcess = null; + } + } + + private static void RemoveCompilationPortEnvironmentVariable(ProcessStartInfo procStartInfo) + { + string[] _environmentVariablesToRemove = new string[] + { + "DNX_COMPILATION_SERVER_PORT", + }; + +#if DNX451 + var environmentVariables = procStartInfo.EnvironmentVariables.Keys.Cast(); +#else + var environmentVariables = procStartInfo.Environment.Keys; +#endif + + var envVarsToRemove = environmentVariables + .Where(envVar => _environmentVariablesToRemove.Contains(envVar, StringComparer.OrdinalIgnoreCase)) + .ToArray(); + + // Workaround for the DNX start issue (it passes some environment variables that it shouldn't) + foreach (var envVar in envVarsToRemove) + { +#if DNX451 + procStartInfo.EnvironmentVariables.Remove(envVar); +#else + procStartInfo.Environment.Remove(envVar); +#endif + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/Impl/Project.cs b/src/Microsoft.Dnx.Watcher.Core/Impl/Project.cs new file mode 100644 index 0000000000..8df5bd2ec8 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/Impl/Project.cs @@ -0,0 +1,45 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.Dnx.Runtime; + +namespace Microsoft.Dnx.Watcher.Core +{ + internal class Project : IProject + { + public Project(Runtime.Project runtimeProject) + { + ProjectFile = runtimeProject.ProjectFilePath; + + Files = runtimeProject.Files.SourceFiles.Concat( + runtimeProject.Files.ResourceFiles.Values.Concat( + runtimeProject.Files.PreprocessSourceFiles.Concat( + runtimeProject.Files.SharedFiles))).Concat( + new string[] { runtimeProject.ProjectFilePath }) + .ToList(); + + var projectLockJsonPath = Path.Combine(runtimeProject.ProjectDirectory, LockFileReader.LockFileName); + var lockFileReader = new LockFileReader(); + + if (File.Exists(projectLockJsonPath)) + { + var lockFile = lockFileReader.Read(projectLockJsonPath); + ProjectDependencies = lockFile.ProjectLibraries.Select(dep => dep.Path).ToList(); + } + else + { + ProjectDependencies = new string[0]; + } + } + + public IEnumerable ProjectDependencies { get; private set; } + + public IEnumerable Files { get; private set; } + + public string ProjectFile { get; private set; } + } +} diff --git a/src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs b/src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs new file mode 100644 index 0000000000..f7efad6d78 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs @@ -0,0 +1,53 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Dnx.Runtime; + +namespace Microsoft.Dnx.Watcher.Core +{ + public class ProjectProvider : IProjectProvider + { + public bool TryReadProject(string projectFile, out IProject project, out string errors) + { + Runtime.Project runtimeProject; + if (!TryGetProject(projectFile, out runtimeProject, out errors)) + { + project = null; + return false; + } + + errors = null; + project = new Project(runtimeProject); + + return true; + } + + // Same as TryGetProject but it doesn't throw + private bool TryGetProject(string projectFile, out Runtime.Project project, out string errorMessage) + { + try + { + var errors = new List(); + if (!Runtime.Project.TryGetProject(projectFile, out project, errors)) + { + errorMessage = string.Join(Environment.NewLine, errors.Select(e => e.ToString())); + } + else + { + errorMessage = null; + return true; + } + } + catch (Exception ex) + { + errorMessage = ex.Message; + } + + project = null; + return false; + } + } +} diff --git a/src/Microsoft.Dnx.Watcher.Core/Microsoft.Dnx.Watcher.Core.xproj b/src/Microsoft.Dnx.Watcher.Core/Microsoft.Dnx.Watcher.Core.xproj new file mode 100644 index 0000000000..27b8206579 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/Microsoft.Dnx.Watcher.Core.xproj @@ -0,0 +1,20 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + d3da3bbb-e206-404f-aee6-17fb9b6f1221 + Microsoft.Dnx.Watcher.Core + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + diff --git a/src/Microsoft.Dnx.Watcher.Core/project.json b/src/Microsoft.Dnx.Watcher.Core/project.json new file mode 100644 index 0000000000..a8fbd226df --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/project.json @@ -0,0 +1,36 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { "warningsAsErrors": true }, + "dependencies": { + "Microsoft.AspNet.FileProviders.Abstractions": "1.0.0-*", + "Microsoft.AspNet.FileProviders.Physical": "1.0.0-*", + "Microsoft.Dnx.Runtime.Abstractions": "1.0.0-*", + "Microsoft.Dnx.Runtime.Json.Sources": { + "type": "build", + "version": "1.0.0-*" + }, + "Microsoft.Framework.Logging.Abstractions": "1.0.0-*", + "Microsoft.Framework.FileSystemGlobbing": "1.0.0-*" + }, + "frameworks": { + "dnx451": { + "frameworkAssemblies": { + "System.Collections": "", + "System.Runtime": "" + } + }, + "dnxcore50": { + "dependencies": { + "System.Diagnostics.Process": "4.1.0-beta-*", + "System.Linq": "4.0.1-beta-*", + "System.Runtime.Extensions": "4.0.11-beta-*", + "System.Threading.Thread": "4.0.0-beta-*" + } + } + }, + + "scripts": { + "postbuild": [ + ] + } +} diff --git a/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs b/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs new file mode 100644 index 0000000000..934f8e272a --- /dev/null +++ b/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs @@ -0,0 +1,64 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.Dnx.Runtime.Common.CommandLine; +using Microsoft.Framework.Logging; + +namespace Microsoft.Dnx.Watcher +{ + /// + /// Logger to print formatted command output. + /// + public class CommandOutputLogger : ILogger + { + private readonly CommandOutputProvider _provider; + private readonly AnsiConsole _outConsole; + private readonly string _loggerName; + + public CommandOutputLogger(CommandOutputProvider commandOutputProvider, string loggerName, bool useConsoleColor) + { + _provider = commandOutputProvider; + _outConsole = AnsiConsole.GetOutput(useConsoleColor); + _loggerName = loggerName; + } + + public IDisposable BeginScopeImpl(object state) + { + throw new NotImplementedException(); + } + + public bool IsEnabled(LogLevel logLevel) + { + if (logLevel < _provider.LogLevel) + { + return false; + } + + return true; + } + + public void Log(LogLevel logLevel, int eventId, object state, Exception exception, Func formatter) + { + if (IsEnabled(logLevel)) + { + _outConsole.WriteLine($"[{_loggerName}] {Caption(logLevel)}: {formatter(state, exception)}"); + } + } + + private string Caption(LogLevel logLevel) + { + switch (logLevel) + { + case LogLevel.Debug: return "\x1b[35mdebug\x1b[39m"; + case LogLevel.Verbose: return "\x1b[35mverbose\x1b[39m"; + case LogLevel.Information: return "\x1b[32minfo\x1b[39m"; + case LogLevel.Warning: return "\x1b[33mwarn\x1b[39m"; + case LogLevel.Error: return "\x1b[31mfail\x1b[39m"; + case LogLevel.Critical: return "\x1b[31mcritical\x1b[39m"; + } + + throw new Exception("Unknown LogLevel"); + } + } +} diff --git a/src/Microsoft.Dnx.Watcher/CommandOutputProvider.cs b/src/Microsoft.Dnx.Watcher/CommandOutputProvider.cs new file mode 100644 index 0000000000..3a98395b53 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher/CommandOutputProvider.cs @@ -0,0 +1,30 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.Dnx.Runtime; +using Microsoft.Framework.Logging; + +namespace Microsoft.Dnx.Watcher +{ + public class CommandOutputProvider : ILoggerProvider + { + private readonly bool _isWindows; + + public CommandOutputProvider(IRuntimeEnvironment runtimeEnv) + { + _isWindows = runtimeEnv.OperatingSystem == "Windows"; + } + + public ILogger CreateLogger(string name) + { + return new CommandOutputLogger(this, name, useConsoleColor: _isWindows); + } + + public void Dispose() + { + } + + public LogLevel LogLevel { get; set; } = LogLevel.Information; + } +} diff --git a/src/Microsoft.Dnx.Watcher/Microsoft.Dnx.Watcher.xproj b/src/Microsoft.Dnx.Watcher/Microsoft.Dnx.Watcher.xproj new file mode 100644 index 0000000000..c3c42491f3 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher/Microsoft.Dnx.Watcher.xproj @@ -0,0 +1,20 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + 8a8ceabc-ac47-43ff-a5df-69224f7e1f46 + Microsoft.Dnx.Watcher + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + diff --git a/src/Microsoft.Dnx.Watcher/Program.cs b/src/Microsoft.Dnx.Watcher/Program.cs new file mode 100644 index 0000000000..ec4e43f6d7 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher/Program.cs @@ -0,0 +1,133 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Dnx.Runtime; +using Microsoft.Dnx.Runtime.Common.CommandLine; +using Microsoft.Dnx.Watcher.Core; +using Microsoft.Framework.Logging; + +namespace Microsoft.Dnx.Watcher +{ + public class Program + { + private const string DnxWatchArgumentSeparator = "--dnx-args"; + + private readonly ILoggerFactory _loggerFactory; + + public Program(IRuntimeEnvironment runtimeEnvironment) + { + _loggerFactory = new LoggerFactory(); + + var commandProvider = new CommandOutputProvider(runtimeEnvironment); + _loggerFactory.AddProvider(commandProvider); + } + + public int Main(string[] args) + { + using (CancellationTokenSource ctrlCTokenSource = new CancellationTokenSource()) + { + Console.CancelKeyPress += (sender, ev) => + { + ctrlCTokenSource.Cancel(); + ev.Cancel = false; + }; + + string[] watchArgs, dnxArgs; + SeparateWatchArguments(args, out watchArgs, out dnxArgs); + + return MainInternal(watchArgs, dnxArgs, ctrlCTokenSource.Token); + } + } + + internal static void SeparateWatchArguments(string[] args, out string[] watchArgs, out string[] dnxArgs) + { + int argsIndex = -1; + watchArgs = args.TakeWhile((arg, idx) => + { + argsIndex = idx; + return !string.Equals(arg, DnxWatchArgumentSeparator, StringComparison.OrdinalIgnoreCase); + }).ToArray(); + + dnxArgs = args.Skip(argsIndex + 1).ToArray(); + + if (dnxArgs.Length == 0) + { + // If no explicit dnx arguments then all arguments get passed to dnx + dnxArgs = watchArgs; + watchArgs = new string[0]; + } + } + + private int MainInternal(string[] watchArgs, string[] dnxArgs, CancellationToken cancellationToken) + { + var app = new CommandLineApplication(); + app.Name = "dnx-watch"; + app.FullName = "Microsoft .NET DNX File Watcher"; + + app.HelpOption("-?|-h|--help"); + + // Show help information if no subcommand/option was specified + app.OnExecute(() => + { + app.ShowHelp(); + return 2; + }); + + var projectArg = app.Option( + "--project ", + "Path to the project.json file or the application folder. Defaults to the current folder if not provided. Will be passed to DNX.", + CommandOptionType.SingleValue); + + var workingDirArg = app.Option( + "--workingDir ", + "The working directory for DNX. Defaults to the current directory.", + CommandOptionType.SingleValue); + + // This option is here just to be displayed in help + // it will not be parsed because it is removed before the code is executed + app.Option( + $"{DnxWatchArgumentSeparator} ", + "Marks the arguments that will be passed to DNX. Anything following this option is passed. If not specified, all the arguments are passed to DNX.", + CommandOptionType.SingleValue); + + app.OnExecute(() => + { + var projectToRun = projectArg.HasValue() ? + projectArg.Value() : + Directory.GetCurrentDirectory(); + + if (!projectToRun.EndsWith("project.json", StringComparison.Ordinal)) + { + projectToRun = Path.Combine(projectToRun, "project.json"); + } + + var workingDir = workingDirArg.HasValue() ? + workingDirArg.Value() : + Directory.GetCurrentDirectory(); + + var watcher = DnxWatcher.CreateDefault(_loggerFactory); + try + { + watcher.WatchAsync(projectToRun, dnxArgs, workingDir, cancellationToken).Wait(); + } + catch (AggregateException ex) + { + if (ex.InnerExceptions.Count != 1 || !(ex.InnerException is TaskCanceledException)) + { + throw; + } + } + + + return 1; + }); + + return app.Execute(watchArgs); + } + } +} diff --git a/src/Microsoft.Dnx.Watcher/Properties/AssemblyInfo.cs b/src/Microsoft.Dnx.Watcher/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..2cd8231774 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher/Properties/AssemblyInfo.cs @@ -0,0 +1,6 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Runtime.CompilerServices; + +[assembly:InternalsVisibleTo("Microsoft.Dnx.Watcher.Tests")] diff --git a/src/Microsoft.Dnx.Watcher/project.json b/src/Microsoft.Dnx.Watcher/project.json new file mode 100644 index 0000000000..cbe70ae529 --- /dev/null +++ b/src/Microsoft.Dnx.Watcher/project.json @@ -0,0 +1,23 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { "warningsAsErrors": true }, + "dependencies": { + "Microsoft.Dnx.Watcher.Core": "1.0.0-*", + "Microsoft.Framework.CommandLineUtils.Sources": { "version": "1.0.0-*", "type": "build" }, + "Microsoft.Framework.Logging": "1.0.0-*", + "Microsoft.Framework.Logging.Console": "1.0.0-*" + }, + "frameworks": { + "dnx451": { }, + "dnxcore50": { } + }, + + "commands": { + "dnx-watch": "Microsoft.Dnx.Watcher" + }, + + "scripts": { + "postbuild": [ + ] + } +} diff --git a/test/Microsoft.Dnx.Watcher.Tests/CommandLineParsingTests.cs b/test/Microsoft.Dnx.Watcher.Tests/CommandLineParsingTests.cs new file mode 100644 index 0000000000..c4ac14008b --- /dev/null +++ b/test/Microsoft.Dnx.Watcher.Tests/CommandLineParsingTests.cs @@ -0,0 +1,48 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Xunit; + +namespace Microsoft.Dnx.Watcher.Tests +{ + // This project can output the Class library as a NuGet Package. + // To enable this option, right-click on the project and select the Properties menu item. In the Build tab select "Produce outputs on build". + public class CommandLineParsingTests + { + [Fact] + public void NoWatcherArgs() + { + var args = "--arg1 v1 --arg2 v2".Split(' '); + + string[] watcherArgs, dnxArgs; + Program.SeparateWatchArguments(args, out watcherArgs, out dnxArgs); + + Assert.Empty(watcherArgs); + Assert.Equal(args, dnxArgs); + } + + [Fact] + public void ArgsForBothDnxAndWatcher() + { + var args = "--arg1 v1 --arg2 v2 --dnx-args --arg3 --arg4 v4".Split(' '); + + string[] watcherArgs, dnxArgs; + Program.SeparateWatchArguments(args, out watcherArgs, out dnxArgs); + + Assert.Equal(new string[] {"--arg1", "v1", "--arg2", "v2" }, watcherArgs); + Assert.Equal(new string[] { "--arg3", "--arg4", "v4" }, dnxArgs); + } + + [Fact] + public void MultipleSeparators() + { + var args = "--arg1 v1 --arg2 v2 --dnx-args --arg3 --dnxArgs --arg4 v4".Split(' '); + + string[] watcherArgs, dnxArgs; + Program.SeparateWatchArguments(args, out watcherArgs, out dnxArgs); + + Assert.Equal(new string[] { "--arg1", "v1", "--arg2", "v2" }, watcherArgs); + Assert.Equal(new string[] { "--arg3", "--dnxArgs", "--arg4", "v4" }, dnxArgs); + } + } +} diff --git a/test/Microsoft.Dnx.Watcher.Tests/Microsoft.Dnx.Watcher.Tests.xproj b/test/Microsoft.Dnx.Watcher.Tests/Microsoft.Dnx.Watcher.Tests.xproj new file mode 100644 index 0000000000..7c8ac87ba2 --- /dev/null +++ b/test/Microsoft.Dnx.Watcher.Tests/Microsoft.Dnx.Watcher.Tests.xproj @@ -0,0 +1,21 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 640d190b-26db-4dde-88ee-55814c86c43e + Microsoft.Dnx.Watcher.Tests + ..\artifacts\obj\$(MSBuildProjectName) + ..\artifacts\bin\$(MSBuildProjectName)\ + + + 2.0 + + + + + + \ No newline at end of file diff --git a/test/Microsoft.Dnx.Watcher.Tests/project.json b/test/Microsoft.Dnx.Watcher.Tests/project.json new file mode 100644 index 0000000000..fc449ab49d --- /dev/null +++ b/test/Microsoft.Dnx.Watcher.Tests/project.json @@ -0,0 +1,15 @@ +{ + "dependencies": { + "Microsoft.Dnx.Runtime.Abstractions": "1.0.0-*", + "Microsoft.Dnx.Watcher": "1.0.0-*", + "xunit.runner.aspnet": "2.0.0-aspnet-*" + }, + "frameworks": { + "dnx451": { }, + "dnxcore50": { } + }, + "commands": { + "test": "xunit.runner.aspnet" + } +} + From 22d13c4b349f6d27f1a54a370f82a9d4422d2a4d Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sun, 27 Sep 2015 22:31:20 -0700 Subject: [PATCH 0013/1029] Fixed some small usage issues - Simplify waiting for changes - Fixed project dependencies --- src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs | 37 ++++++++----------- .../Impl/ProcessWatcher.cs | 32 +++++----------- .../Impl/Project.cs | 10 ++++- 3 files changed, 34 insertions(+), 45 deletions(-) diff --git a/src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs b/src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs index b71de61d59..3044b4e06c 100644 --- a/src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs +++ b/src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs @@ -182,41 +182,36 @@ namespace Microsoft.Dnx.Watcher.Core foreach (var projFile in project.ProjectDependencies) { - //var fullProjectFilePath = Path.Combine(Path.GetDirectoryName(project.ProjectFile), projFile); - AddProjectAndDependeciesToWatcher(projFile, fileWatcher); } } - private Task WatchForFileChangeAsync(IFileWatcher fileWatcher, CancellationToken cancellationToken) + private async Task WatchForFileChangeAsync(IFileWatcher fileWatcher, CancellationToken cancellationToken) { - return Task.Run(() => + var tcs = new TaskCompletionSource(); + + cancellationToken.Register(() => tcs.TrySetResult(null)); + + Action callback = path => { - using (var fileChangeEvent = new ManualResetEvent(false)) - { - string changedFile = null; + tcs.TrySetResult(path); + }; - fileWatcher.OnChanged += path => - { - changedFile = path; - fileChangeEvent.Set(); - }; + fileWatcher.OnChanged += callback; - while (!cancellationToken.IsCancellationRequested && - !fileChangeEvent.WaitOne(500)) - { - } + var changedPath = await tcs.Task; - return changedFile; - } - }); + // Don't need to listen anymore + fileWatcher.OnChanged -= callback; + + return changedPath; } public static DnxWatcher CreateDefault(ILoggerFactory loggerFactory) { return new DnxWatcher( - fileWatcherFactory: root => { return new FileWatcher(root); }, - processWatcherFactory: () => { return new ProcessWatcher(); }, + fileWatcherFactory: root => new FileWatcher(root), + processWatcherFactory: () => new ProcessWatcher(), projectProvider: new ProjectProvider(), loggerFactory: loggerFactory); } diff --git a/src/Microsoft.Dnx.Watcher.Core/Impl/ProcessWatcher.cs b/src/Microsoft.Dnx.Watcher.Core/Impl/ProcessWatcher.cs index 86b3cc13d7..153979d659 100644 --- a/src/Microsoft.Dnx.Watcher.Core/Impl/ProcessWatcher.cs +++ b/src/Microsoft.Dnx.Watcher.Core/Impl/ProcessWatcher.cs @@ -37,33 +37,19 @@ namespace Microsoft.Dnx.Watcher.Core return _runningProcess.Id; } - public async Task WaitForExitAsync(CancellationToken cancellationToken) + public Task WaitForExitAsync(CancellationToken cancellationToken) { - try + cancellationToken.Register(() => _runningProcess?.Kill()); + + return Task.Run(() => { - await Task.Run(() => - { - while (!cancellationToken.IsCancellationRequested) - { - if (_runningProcess.WaitForExit(500)) - { - break; - } - } + _runningProcess.WaitForExit(); - if (!_runningProcess.HasExited) - { - _runningProcess.Kill(); - } - - }); - - return _runningProcess.ExitCode; - } - finally - { + var exitCode = _runningProcess.ExitCode; _runningProcess = null; - } + + return exitCode; + }); } private static void RemoveCompilationPortEnvironmentVariable(ProcessStartInfo procStartInfo) diff --git a/src/Microsoft.Dnx.Watcher.Core/Impl/Project.cs b/src/Microsoft.Dnx.Watcher.Core/Impl/Project.cs index 8df5bd2ec8..a863154ce2 100644 --- a/src/Microsoft.Dnx.Watcher.Core/Impl/Project.cs +++ b/src/Microsoft.Dnx.Watcher.Core/Impl/Project.cs @@ -14,6 +14,7 @@ namespace Microsoft.Dnx.Watcher.Core public Project(Runtime.Project runtimeProject) { ProjectFile = runtimeProject.ProjectFilePath; + ProjectDirectory = runtimeProject.ProjectDirectory; Files = runtimeProject.Files.SourceFiles.Concat( runtimeProject.Files.ResourceFiles.Values.Concat( @@ -28,7 +29,7 @@ namespace Microsoft.Dnx.Watcher.Core if (File.Exists(projectLockJsonPath)) { var lockFile = lockFileReader.Read(projectLockJsonPath); - ProjectDependencies = lockFile.ProjectLibraries.Select(dep => dep.Path).ToList(); + ProjectDependencies = lockFile.ProjectLibraries.Select(dep => GetProjectRelativeFullPath(dep.Path)).ToList(); } else { @@ -41,5 +42,12 @@ namespace Microsoft.Dnx.Watcher.Core public IEnumerable Files { get; private set; } public string ProjectFile { get; private set; } + + public string ProjectDirectory { get; private set; } + + private string GetProjectRelativeFullPath(string path) + { + return Path.GetFullPath(Path.Combine(ProjectDirectory, path)); + } } } From c7e3f98cdd33e49dce08120a105e31dc0fb6653e Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Mon, 28 Sep 2015 18:11:01 -0700 Subject: [PATCH 0014/1029] Enabling NuGetPackageVerifier --- NuGetPackageVerifier.json | 26 +++++++++++++++++++ .../Properties/AssemblyInfo.cs | 8 ++++++ .../Properties/AssemblyInfo.cs | 4 +++ 3 files changed, 38 insertions(+) create mode 100644 NuGetPackageVerifier.json create mode 100644 src/Microsoft.Dnx.Watcher.Core/Properties/AssemblyInfo.cs diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json new file mode 100644 index 0000000000..c989ccf13a --- /dev/null +++ b/NuGetPackageVerifier.json @@ -0,0 +1,26 @@ +{ + "adx": { // Packages written by the ADX team and that ship on NuGet.org + "rules": [ + "AssemblyHasDocumentFileRule", + "AssemblyHasVersionAttributesRule", + "AssemblyHasServicingAttributeRule", + "AssemblyHasNeutralResourcesLanguageAttributeRule", + "SatellitePackageRule", + "StrictSemanticVersionValidationRule" + ], + "packages": { + "Microsoft.Dnx.Watcher": { }, + "Microsoft.Dnx.Watcher.Core": { } + } + }, + "Default": { // Rules to run for packages not listed in any other set. + "rules": [ + "AssemblyHasDocumentFileRule", + "AssemblyHasVersionAttributesRule", + "AssemblyHasServicingAttributeRule", + "AssemblyHasNeutralResourcesLanguageAttributeRule", + "SatellitePackageRule", + "StrictSemanticVersionValidationRule" + ] + } +} \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/Properties/AssemblyInfo.cs b/src/Microsoft.Dnx.Watcher.Core/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..9cb7b1f01b --- /dev/null +++ b/src/Microsoft.Dnx.Watcher.Core/Properties/AssemblyInfo.cs @@ -0,0 +1,8 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Reflection; +using System.Resources; + +[assembly: AssemblyMetadata("Serviceable", "True")] +[assembly: NeutralResourcesLanguage("en-US")] diff --git a/src/Microsoft.Dnx.Watcher/Properties/AssemblyInfo.cs b/src/Microsoft.Dnx.Watcher/Properties/AssemblyInfo.cs index 2cd8231774..956d80dbfe 100644 --- a/src/Microsoft.Dnx.Watcher/Properties/AssemblyInfo.cs +++ b/src/Microsoft.Dnx.Watcher/Properties/AssemblyInfo.cs @@ -1,6 +1,10 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Reflection; +using System.Resources; using System.Runtime.CompilerServices; [assembly:InternalsVisibleTo("Microsoft.Dnx.Watcher.Tests")] +[assembly: AssemblyMetadata("Serviceable", "True")] +[assembly: NeutralResourcesLanguage("en-US")] From a2685ee03b0d7093abd298b56abb4e5278dad38d Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 28 Sep 2015 23:20:03 -0700 Subject: [PATCH 0015/1029] Updating to release NuGet.config. --- NuGet.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NuGet.config b/NuGet.config index 03704957e8..9db87a421e 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + - + \ No newline at end of file From bed133858e92099df6dcb269761d6ceb000c40cf Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 29 Sep 2015 12:39:30 -0700 Subject: [PATCH 0016/1029] Updating to release NuGet.config --- NuGet.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NuGet.config b/NuGet.config index 5500f6d507..20950d3df6 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@  - + From 182b7d588c94085f663788a659eb65fd2506e8d0 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Thu, 1 Oct 2015 12:13:37 -0700 Subject: [PATCH 0017/1029] Update 'build.cmd' alias parameter to use full name. --- build.cmd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.cmd b/build.cmd index 177997c42e..30b3dbba60 100644 --- a/build.cmd +++ b/build.cmd @@ -30,10 +30,10 @@ IF "%SKIP_DNX_INSTALL%"=="1" goto run IF %BUILDCMD_DNX_VERSION%=="" ( CALL packages\KoreBuild\build\dnvm upgrade -runtime CLR -arch x86 ) ELSE ( - CALL packages\KoreBuild\build\dnvm install %BUILDCMD_DNX_VERSION% -runtime CLR -arch x86 -a default + CALL packages\KoreBuild\build\dnvm install %BUILDCMD_DNX_VERSION% -runtime CLR -arch x86 -alias default ) CALL packages\KoreBuild\build\dnvm install default -runtime CoreCLR -arch x86 :run CALL packages\KoreBuild\build\dnvm use default -runtime CLR -arch x86 -packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %* \ No newline at end of file +packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %* From ac6e441f15e75b74faea1209b3d9e4a03116c8dc Mon Sep 17 00:00:00 2001 From: Pranav K Date: Sat, 3 Oct 2015 15:44:58 -0700 Subject: [PATCH 0018/1029] Renaming Microsoft.Framework.* -> Microsoft.Extensions.* --- src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs | 4 ++-- .../External/Runtime/PatternGroup.cs | 2 +- src/Microsoft.Dnx.Watcher.Core/project.json | 4 ++-- src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs | 4 ++-- src/Microsoft.Dnx.Watcher/CommandOutputProvider.cs | 4 ++-- src/Microsoft.Dnx.Watcher/Program.cs | 4 ++-- src/Microsoft.Dnx.Watcher/project.json | 8 ++++---- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs b/src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs index 3044b4e06c..e8f03f8e6b 100644 --- a/src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs +++ b/src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -6,7 +6,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.Framework.Logging; +using Microsoft.Extensions.Logging; namespace Microsoft.Dnx.Watcher.Core { diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs index 50012a7a35..3479cb6e22 100644 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using Microsoft.Framework.FileSystemGlobbing; +using Microsoft.Extensions.FileSystemGlobbing; using Microsoft.Dnx.Runtime.Json; namespace Microsoft.Dnx.Runtime diff --git a/src/Microsoft.Dnx.Watcher.Core/project.json b/src/Microsoft.Dnx.Watcher.Core/project.json index a8fbd226df..4158b1a243 100644 --- a/src/Microsoft.Dnx.Watcher.Core/project.json +++ b/src/Microsoft.Dnx.Watcher.Core/project.json @@ -9,8 +9,8 @@ "type": "build", "version": "1.0.0-*" }, - "Microsoft.Framework.Logging.Abstractions": "1.0.0-*", - "Microsoft.Framework.FileSystemGlobbing": "1.0.0-*" + "Microsoft.Extensions.Logging.Abstractions": "1.0.0-*", + "Microsoft.Extensions.FileSystemGlobbing": "1.0.0-*" }, "frameworks": { "dnx451": { diff --git a/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs b/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs index 934f8e272a..8c9e79f80c 100644 --- a/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs +++ b/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs @@ -1,9 +1,9 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using Microsoft.Dnx.Runtime.Common.CommandLine; -using Microsoft.Framework.Logging; +using Microsoft.Extensions.Logging; namespace Microsoft.Dnx.Watcher { diff --git a/src/Microsoft.Dnx.Watcher/CommandOutputProvider.cs b/src/Microsoft.Dnx.Watcher/CommandOutputProvider.cs index 3a98395b53..c4b6147600 100644 --- a/src/Microsoft.Dnx.Watcher/CommandOutputProvider.cs +++ b/src/Microsoft.Dnx.Watcher/CommandOutputProvider.cs @@ -1,9 +1,9 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using Microsoft.Dnx.Runtime; -using Microsoft.Framework.Logging; +using Microsoft.Extensions.Logging; namespace Microsoft.Dnx.Watcher { diff --git a/src/Microsoft.Dnx.Watcher/Program.cs b/src/Microsoft.Dnx.Watcher/Program.cs index ec4e43f6d7..06e2163d5d 100644 --- a/src/Microsoft.Dnx.Watcher/Program.cs +++ b/src/Microsoft.Dnx.Watcher/Program.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -9,7 +9,7 @@ using System.Threading.Tasks; using Microsoft.Dnx.Runtime; using Microsoft.Dnx.Runtime.Common.CommandLine; using Microsoft.Dnx.Watcher.Core; -using Microsoft.Framework.Logging; +using Microsoft.Extensions.Logging; namespace Microsoft.Dnx.Watcher { diff --git a/src/Microsoft.Dnx.Watcher/project.json b/src/Microsoft.Dnx.Watcher/project.json index cbe70ae529..77d1225de8 100644 --- a/src/Microsoft.Dnx.Watcher/project.json +++ b/src/Microsoft.Dnx.Watcher/project.json @@ -1,11 +1,11 @@ -{ +{ "version": "1.0.0-*", "compilationOptions": { "warningsAsErrors": true }, "dependencies": { "Microsoft.Dnx.Watcher.Core": "1.0.0-*", - "Microsoft.Framework.CommandLineUtils.Sources": { "version": "1.0.0-*", "type": "build" }, - "Microsoft.Framework.Logging": "1.0.0-*", - "Microsoft.Framework.Logging.Console": "1.0.0-*" + "Microsoft.Extensions.CommandLineUtils.Sources": { "version": "1.0.0-*", "type": "build" }, + "Microsoft.Extensions.Logging": "1.0.0-*", + "Microsoft.Extensions.Logging.Console": "1.0.0-*" }, "frameworks": { "dnx451": { }, From df66c60e24a38330ff2a4a2a15c8d30d0d7690a3 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 7 Oct 2015 11:28:57 -0700 Subject: [PATCH 0019/1029] Reacting to JsonParser renames --- NuGet.config | 2 +- .../External/Runtime/FileFormatException.cs | 2 +- .../External/Runtime/LockFileReader.cs | 4 +--- .../External/Runtime/NamedResourceReader.cs | 2 +- .../External/Runtime/PackIncludeEntry.cs | 2 +- .../External/Runtime/PatternGroup.cs | 21 ++++++++++--------- .../Runtime/PatternsCollectionHelper.cs | 15 ++++++------- .../Runtime/ProjectFilesCollection.cs | 4 +--- .../External/Runtime/ProjectReader.cs | 2 +- .../Impl/Project.cs | 1 - src/Microsoft.Dnx.Watcher.Core/project.json | 7 +------ 11 files changed, 27 insertions(+), 35 deletions(-) diff --git a/NuGet.config b/NuGet.config index 03704957e8..cb71c64a79 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@  - + \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/FileFormatException.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/FileFormatException.cs index e895f724f7..0efa1871d1 100644 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/FileFormatException.cs +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/FileFormatException.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.Dnx.Runtime.Json; +using Microsoft.Extensions.JsonParser.Sources; namespace Microsoft.Dnx.Runtime { diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFileReader.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFileReader.cs index f55b198ace..5cc3821fd9 100644 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFileReader.cs +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFileReader.cs @@ -4,10 +4,8 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Runtime.Versioning; using System.Threading; -using Microsoft.Dnx.Runtime.Json; +using Microsoft.Extensions.JsonParser.Sources; using NuGet; namespace Microsoft.Dnx.Runtime diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/NamedResourceReader.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/NamedResourceReader.cs index 1970cd4cb7..54bfed296b 100644 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/NamedResourceReader.cs +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/NamedResourceReader.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.IO; -using Microsoft.Dnx.Runtime.Json; +using Microsoft.Extensions.JsonParser.Sources; namespace Microsoft.Dnx.Runtime { diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PackIncludeEntry.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PackIncludeEntry.cs index 0819ffed03..8ba9c19515 100644 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PackIncludeEntry.cs +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PackIncludeEntry.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq; -using Microsoft.Dnx.Runtime.Json; +using Microsoft.Extensions.JsonParser.Sources; namespace Microsoft.Dnx.Runtime { diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs index 3479cb6e22..ebdc19bdbf 100644 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using Microsoft.Extensions.FileSystemGlobbing; -using Microsoft.Dnx.Runtime.Json; +using Microsoft.Extensions.JsonParser.Sources; namespace Microsoft.Dnx.Runtime { @@ -33,15 +33,16 @@ namespace Microsoft.Dnx.Runtime _matcher.AddExcludePatterns(ExcludePatterns); } - internal static PatternGroup Build(JsonObject rawProject, - string projectDirectory, - string projectFilePath, - string name, - IEnumerable fallbackIncluding = null, - IEnumerable additionalIncluding = null, - IEnumerable additionalExcluding = null, - bool includePatternsOnly = false, - ICollection warnings = null) + internal static PatternGroup Build( + JsonObject rawProject, + string projectDirectory, + string projectFilePath, + string name, + IEnumerable fallbackIncluding = null, + IEnumerable additionalIncluding = null, + IEnumerable additionalExcluding = null, + bool includePatternsOnly = false, + ICollection warnings = null) { string includePropertyName = name; additionalIncluding = additionalIncluding ?? Enumerable.Empty(); diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternsCollectionHelper.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternsCollectionHelper.cs index 33cb2f12de..ed3bb607b3 100644 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternsCollectionHelper.cs +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternsCollectionHelper.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using Microsoft.Dnx.Runtime.Json; +using Microsoft.Extensions.JsonParser.Sources; namespace Microsoft.Dnx.Runtime { @@ -13,12 +13,13 @@ namespace Microsoft.Dnx.Runtime { private static readonly char[] PatternSeparator = new[] { ';' }; - public static IEnumerable GetPatternsCollection(JsonObject rawProject, - string projectDirectory, - string projectFilePath, - string propertyName, - IEnumerable defaultPatterns = null, - bool literalPath = false) + public static IEnumerable GetPatternsCollection( + JsonObject rawProject, + string projectDirectory, + string projectFilePath, + string propertyName, + IEnumerable defaultPatterns = null, + bool literalPath = false) { defaultPatterns = defaultPatterns ?? Enumerable.Empty(); diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectFilesCollection.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectFilesCollection.cs index 9ee0056e5c..2fe99407b3 100644 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectFilesCollection.cs +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectFilesCollection.cs @@ -1,11 +1,9 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.Collections.Generic; using System.Linq; -using System.Threading; -using Microsoft.Dnx.Runtime.Json; +using Microsoft.Extensions.JsonParser.Sources; namespace Microsoft.Dnx.Runtime { diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectReader.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectReader.cs index b8aeb4734a..0f92fc5bc3 100644 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectReader.cs +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectReader.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using Microsoft.Dnx.Runtime.Json; +using Microsoft.Extensions.JsonParser.Sources; using NuGet; namespace Microsoft.Dnx.Runtime diff --git a/src/Microsoft.Dnx.Watcher.Core/Impl/Project.cs b/src/Microsoft.Dnx.Watcher.Core/Impl/Project.cs index a863154ce2..a2a3a8a450 100644 --- a/src/Microsoft.Dnx.Watcher.Core/Impl/Project.cs +++ b/src/Microsoft.Dnx.Watcher.Core/Impl/Project.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/src/Microsoft.Dnx.Watcher.Core/project.json b/src/Microsoft.Dnx.Watcher.Core/project.json index 4158b1a243..2a9b6ca875 100644 --- a/src/Microsoft.Dnx.Watcher.Core/project.json +++ b/src/Microsoft.Dnx.Watcher.Core/project.json @@ -5,7 +5,7 @@ "Microsoft.AspNet.FileProviders.Abstractions": "1.0.0-*", "Microsoft.AspNet.FileProviders.Physical": "1.0.0-*", "Microsoft.Dnx.Runtime.Abstractions": "1.0.0-*", - "Microsoft.Dnx.Runtime.Json.Sources": { + "Microsoft.Extensions.JsonParser.Sources": { "type": "build", "version": "1.0.0-*" }, @@ -27,10 +27,5 @@ "System.Threading.Thread": "4.0.0-beta-*" } } - }, - - "scripts": { - "postbuild": [ - ] } } From 21a1c2063c7474cd67c9cae5a2969f18df49a499 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Thu, 8 Oct 2015 19:00:51 -0700 Subject: [PATCH 0020/1029] React to aspnet/Universe#290 fix --- build.cmd | 23 ++++++++++++----------- build.sh | 12 +++++++----- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/build.cmd b/build.cmd index 30b3dbba60..84dc87e480 100644 --- a/build.cmd +++ b/build.cmd @@ -18,22 +18,23 @@ md .nuget copy %CACHED_NUGET% .nuget\nuget.exe > nul :restore -IF EXIST packages\KoreBuild goto run +IF EXIST packages\Sake goto getdnx IF %BUILDCMD_KOREBUILD_VERSION%=="" ( - .nuget\nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre + .nuget\nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre ) ELSE ( - .nuget\nuget.exe install KoreBuild -version %BUILDCMD_KOREBUILD_VERSION% -ExcludeVersion -o packages -nocache -pre + .nuget\nuget.exe install KoreBuild -version %BUILDCMD_KOREBUILD_VERSION% -ExcludeVersion -o packages -nocache -pre ) -.nuget\nuget.exe install Sake -ExcludeVersion -Out packages +.nuget\NuGet.exe install Sake -ExcludeVersion -Source https://www.nuget.org/api/v2/ -Out packages -IF "%SKIP_DNX_INSTALL%"=="1" goto run -IF %BUILDCMD_DNX_VERSION%=="" ( - CALL packages\KoreBuild\build\dnvm upgrade -runtime CLR -arch x86 +:getdnx +IF "%SKIP_DNX_INSTALL%"=="" ( + IF "%BUILDCMD_DNX_VERSION%"=="" ( + BUILDCMD_DNX_VERSION=latest + ) + CALL packages\KoreBuild\build\dnvm install %BUILDCMD_DNX_VERSION% -runtime CoreCLR -arch x86 -alias default + CALL packages\KoreBuild\build\dnvm install default -runtime CLR -arch x86 -alias default ) ELSE ( - CALL packages\KoreBuild\build\dnvm install %BUILDCMD_DNX_VERSION% -runtime CLR -arch x86 -alias default + CALL packages\KoreBuild\build\dnvm use default -runtime CLR -arch x86 ) -CALL packages\KoreBuild\build\dnvm install default -runtime CoreCLR -arch x86 -:run -CALL packages\KoreBuild\build\dnvm use default -runtime CLR -arch x86 packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %* diff --git a/build.sh b/build.sh index 0c66139817..da4e3fcd1c 100755 --- a/build.sh +++ b/build.sh @@ -24,18 +24,20 @@ if test ! -e .nuget; then cp $cachePath .nuget/nuget.exe fi -if test ! -d packages/KoreBuild; then +if test ! -d packages/Sake; then mono .nuget/nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre - mono .nuget/nuget.exe install Sake -ExcludeVersion -Out packages + mono .nuget/nuget.exe install Sake -ExcludeVersion -Source https://www.nuget.org/api/v2/ -Out packages fi if ! type dnvm > /dev/null 2>&1; then source packages/KoreBuild/build/dnvm.sh fi -if ! type dnx > /dev/null 2>&1; then - dnvm upgrade +if ! type dnx > /dev/null 2>&1 || [ -z "$SKIP_DNX_INSTALL" ]; then + dnvm install latest -runtime coreclr -alias default + dnvm install default -runtime mono -alias default +else + dnvm use default -runtime mono fi mono packages/Sake/tools/Sake.exe -I packages/KoreBuild/build -f makefile.shade "$@" - From 3d61bbf3579f35f53c30c05f2850bd723cbbe0da Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Sun, 11 Oct 2015 00:50:01 -0700 Subject: [PATCH 0021/1029] React to aspnet/Universe#290 fix - pick up latest `build.cmd` and `build.sh` files - oops, this shouldn't be using a volatile feed --- NuGet.config | 2 +- build.cmd | 25 +++++++++++++------------ build.sh | 12 +++++++----- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/NuGet.config b/NuGet.config index cb71c64a79..03704957e8 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@  - + \ No newline at end of file diff --git a/build.cmd b/build.cmd index 177997c42e..84dc87e480 100644 --- a/build.cmd +++ b/build.cmd @@ -18,22 +18,23 @@ md .nuget copy %CACHED_NUGET% .nuget\nuget.exe > nul :restore -IF EXIST packages\KoreBuild goto run +IF EXIST packages\Sake goto getdnx IF %BUILDCMD_KOREBUILD_VERSION%=="" ( - .nuget\nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre + .nuget\nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre ) ELSE ( - .nuget\nuget.exe install KoreBuild -version %BUILDCMD_KOREBUILD_VERSION% -ExcludeVersion -o packages -nocache -pre + .nuget\nuget.exe install KoreBuild -version %BUILDCMD_KOREBUILD_VERSION% -ExcludeVersion -o packages -nocache -pre ) -.nuget\nuget.exe install Sake -ExcludeVersion -Out packages +.nuget\NuGet.exe install Sake -ExcludeVersion -Source https://www.nuget.org/api/v2/ -Out packages -IF "%SKIP_DNX_INSTALL%"=="1" goto run -IF %BUILDCMD_DNX_VERSION%=="" ( - CALL packages\KoreBuild\build\dnvm upgrade -runtime CLR -arch x86 +:getdnx +IF "%SKIP_DNX_INSTALL%"=="" ( + IF "%BUILDCMD_DNX_VERSION%"=="" ( + BUILDCMD_DNX_VERSION=latest + ) + CALL packages\KoreBuild\build\dnvm install %BUILDCMD_DNX_VERSION% -runtime CoreCLR -arch x86 -alias default + CALL packages\KoreBuild\build\dnvm install default -runtime CLR -arch x86 -alias default ) ELSE ( - CALL packages\KoreBuild\build\dnvm install %BUILDCMD_DNX_VERSION% -runtime CLR -arch x86 -a default + CALL packages\KoreBuild\build\dnvm use default -runtime CLR -arch x86 ) -CALL packages\KoreBuild\build\dnvm install default -runtime CoreCLR -arch x86 -:run -CALL packages\KoreBuild\build\dnvm use default -runtime CLR -arch x86 -packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %* \ No newline at end of file +packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %* diff --git a/build.sh b/build.sh index 0c66139817..da4e3fcd1c 100755 --- a/build.sh +++ b/build.sh @@ -24,18 +24,20 @@ if test ! -e .nuget; then cp $cachePath .nuget/nuget.exe fi -if test ! -d packages/KoreBuild; then +if test ! -d packages/Sake; then mono .nuget/nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre - mono .nuget/nuget.exe install Sake -ExcludeVersion -Out packages + mono .nuget/nuget.exe install Sake -ExcludeVersion -Source https://www.nuget.org/api/v2/ -Out packages fi if ! type dnvm > /dev/null 2>&1; then source packages/KoreBuild/build/dnvm.sh fi -if ! type dnx > /dev/null 2>&1; then - dnvm upgrade +if ! type dnx > /dev/null 2>&1 || [ -z "$SKIP_DNX_INSTALL" ]; then + dnvm install latest -runtime coreclr -alias default + dnvm install default -runtime mono -alias default +else + dnvm use default -runtime mono fi mono packages/Sake/tools/Sake.exe -I packages/KoreBuild/build -f makefile.shade "$@" - From 0ebd00548142b6ec0df7121201000753b34274d2 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Mon, 12 Oct 2015 12:52:31 -0700 Subject: [PATCH 0022/1029] Fix local build break --- build.cmd | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build.cmd b/build.cmd index 84dc87e480..553e3929a0 100644 --- a/build.cmd +++ b/build.cmd @@ -4,8 +4,8 @@ cd %~dp0 SETLOCAL SET NUGET_VERSION=latest SET CACHED_NUGET=%LocalAppData%\NuGet\nuget.%NUGET_VERSION%.exe -SET BUILDCMD_KOREBUILD_VERSION="" -SET BUILDCMD_DNX_VERSION="" +SET BUILDCMD_KOREBUILD_VERSION= +SET BUILDCMD_DNX_VERSION= IF EXIST %CACHED_NUGET% goto copynuget echo Downloading latest version of NuGet.exe... @@ -19,7 +19,7 @@ copy %CACHED_NUGET% .nuget\nuget.exe > nul :restore IF EXIST packages\Sake goto getdnx -IF %BUILDCMD_KOREBUILD_VERSION%=="" ( +IF "%BUILDCMD_KOREBUILD_VERSION%"=="" ( .nuget\nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre ) ELSE ( .nuget\nuget.exe install KoreBuild -version %BUILDCMD_KOREBUILD_VERSION% -ExcludeVersion -o packages -nocache -pre @@ -27,10 +27,10 @@ IF %BUILDCMD_KOREBUILD_VERSION%=="" ( .nuget\NuGet.exe install Sake -ExcludeVersion -Source https://www.nuget.org/api/v2/ -Out packages :getdnx +IF "%BUILDCMD_DNX_VERSION%"=="" ( + SET BUILDCMD_DNX_VERSION=latest +) IF "%SKIP_DNX_INSTALL%"=="" ( - IF "%BUILDCMD_DNX_VERSION%"=="" ( - BUILDCMD_DNX_VERSION=latest - ) CALL packages\KoreBuild\build\dnvm install %BUILDCMD_DNX_VERSION% -runtime CoreCLR -arch x86 -alias default CALL packages\KoreBuild\build\dnvm install default -runtime CLR -arch x86 -alias default ) ELSE ( From 62ca4d6a8cbc1951dbda0f585fa0ec6282fb6eb3 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Mon, 12 Oct 2015 12:56:34 -0700 Subject: [PATCH 0023/1029] Fix local build break --- build.cmd | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build.cmd b/build.cmd index 84dc87e480..553e3929a0 100644 --- a/build.cmd +++ b/build.cmd @@ -4,8 +4,8 @@ cd %~dp0 SETLOCAL SET NUGET_VERSION=latest SET CACHED_NUGET=%LocalAppData%\NuGet\nuget.%NUGET_VERSION%.exe -SET BUILDCMD_KOREBUILD_VERSION="" -SET BUILDCMD_DNX_VERSION="" +SET BUILDCMD_KOREBUILD_VERSION= +SET BUILDCMD_DNX_VERSION= IF EXIST %CACHED_NUGET% goto copynuget echo Downloading latest version of NuGet.exe... @@ -19,7 +19,7 @@ copy %CACHED_NUGET% .nuget\nuget.exe > nul :restore IF EXIST packages\Sake goto getdnx -IF %BUILDCMD_KOREBUILD_VERSION%=="" ( +IF "%BUILDCMD_KOREBUILD_VERSION%"=="" ( .nuget\nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre ) ELSE ( .nuget\nuget.exe install KoreBuild -version %BUILDCMD_KOREBUILD_VERSION% -ExcludeVersion -o packages -nocache -pre @@ -27,10 +27,10 @@ IF %BUILDCMD_KOREBUILD_VERSION%=="" ( .nuget\NuGet.exe install Sake -ExcludeVersion -Source https://www.nuget.org/api/v2/ -Out packages :getdnx +IF "%BUILDCMD_DNX_VERSION%"=="" ( + SET BUILDCMD_DNX_VERSION=latest +) IF "%SKIP_DNX_INSTALL%"=="" ( - IF "%BUILDCMD_DNX_VERSION%"=="" ( - BUILDCMD_DNX_VERSION=latest - ) CALL packages\KoreBuild\build\dnvm install %BUILDCMD_DNX_VERSION% -runtime CoreCLR -arch x86 -alias default CALL packages\KoreBuild\build\dnvm install default -runtime CLR -arch x86 -alias default ) ELSE ( From 127fc1388537e7c9d2f211942511f40d106de716 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 21 Oct 2015 21:24:19 -0700 Subject: [PATCH 0024/1029] Switching to using generations TFM --- src/Microsoft.AspNet.JsonPatch/project.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.AspNet.JsonPatch/project.json b/src/Microsoft.AspNet.JsonPatch/project.json index 8d67ec1808..c08afdec7e 100644 --- a/src/Microsoft.AspNet.JsonPatch/project.json +++ b/src/Microsoft.AspNet.JsonPatch/project.json @@ -8,8 +8,8 @@ "Newtonsoft.Json": "6.0.6" }, "frameworks": { - "dnx451": { }, - "dnxcore50": { + "net451": {}, + "dotnet5.4": { "dependencies": { "Microsoft.CSharp": "4.0.1-beta-*", "System.Collections.Concurrent": "4.0.11-beta-*", @@ -22,4 +22,4 @@ } } } -} +} \ No newline at end of file From 54af2c339f0cb3204d2564202bb1d792ba499dd3 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Mon, 26 Oct 2015 09:17:10 -0700 Subject: [PATCH 0025/1029] Rename Microsoft.Runtime.Abstractions to Microsoft.Extensions.PlatformAbstractions --- .../External/Runtime/PatternGroup.cs | 1 + .../External/Runtime/Project.cs | 1 + .../External/Runtime/ProjectReader.cs | 1 + .../External/Runtime/RuntimeEnvironmentHelper.cs | 4 ++-- src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs | 2 +- src/Microsoft.Dnx.Watcher.Core/project.json | 2 +- src/Microsoft.Dnx.Watcher/CommandOutputProvider.cs | 2 +- src/Microsoft.Dnx.Watcher/Program.cs | 10 +++++----- test/Microsoft.Dnx.Watcher.Tests/project.json | 2 +- 9 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs index ebdc19bdbf..d1c60347ae 100644 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using Microsoft.Extensions.FileSystemGlobbing; using Microsoft.Extensions.JsonParser.Sources; +using Microsoft.Extensions.PlatformAbstractions; namespace Microsoft.Dnx.Runtime { diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/Project.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/Project.cs index e9a610c29c..c0cb19a0b5 100644 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/Project.cs +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/Project.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.Versioning; +using Microsoft.Extensions.PlatformAbstractions; using NuGet; namespace Microsoft.Dnx.Runtime diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectReader.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectReader.cs index 0f92fc5bc3..6ad60968dc 100644 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectReader.cs +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectReader.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using Microsoft.Extensions.JsonParser.Sources; +using Microsoft.Extensions.PlatformAbstractions; using NuGet; namespace Microsoft.Dnx.Runtime diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/RuntimeEnvironmentHelper.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/RuntimeEnvironmentHelper.cs index 4003c3fee4..27ea21b458 100644 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/RuntimeEnvironmentHelper.cs +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/RuntimeEnvironmentHelper.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using Microsoft.Extensions.PlatformAbstractions; namespace Microsoft.Dnx.Runtime { @@ -18,8 +19,7 @@ namespace Microsoft.Dnx.Runtime private static IRuntimeEnvironment GetRuntimeEnvironment() { - var provider = Infrastructure.CallContextServiceLocator.Locator.ServiceProvider; - var environment = (IRuntimeEnvironment)provider?.GetService(typeof(IRuntimeEnvironment)); + var environment = PlatformServices.Default.Runtime; if (environment == null) { diff --git a/src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs b/src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs index f7efad6d78..a4c0c7f76c 100644 --- a/src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs +++ b/src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Microsoft.Dnx.Runtime; +using Microsoft.Extensions.PlatformAbstractions; namespace Microsoft.Dnx.Watcher.Core { diff --git a/src/Microsoft.Dnx.Watcher.Core/project.json b/src/Microsoft.Dnx.Watcher.Core/project.json index 2a9b6ca875..feb354708e 100644 --- a/src/Microsoft.Dnx.Watcher.Core/project.json +++ b/src/Microsoft.Dnx.Watcher.Core/project.json @@ -4,7 +4,7 @@ "dependencies": { "Microsoft.AspNet.FileProviders.Abstractions": "1.0.0-*", "Microsoft.AspNet.FileProviders.Physical": "1.0.0-*", - "Microsoft.Dnx.Runtime.Abstractions": "1.0.0-*", + "Microsoft.Extensions.PlatformAbstractions": "1.0.0-*", "Microsoft.Extensions.JsonParser.Sources": { "type": "build", "version": "1.0.0-*" diff --git a/src/Microsoft.Dnx.Watcher/CommandOutputProvider.cs b/src/Microsoft.Dnx.Watcher/CommandOutputProvider.cs index c4b6147600..ea8fec48dd 100644 --- a/src/Microsoft.Dnx.Watcher/CommandOutputProvider.cs +++ b/src/Microsoft.Dnx.Watcher/CommandOutputProvider.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.Dnx.Runtime; +using Microsoft.Extensions.PlatformAbstractions; using Microsoft.Extensions.Logging; namespace Microsoft.Dnx.Watcher diff --git a/src/Microsoft.Dnx.Watcher/Program.cs b/src/Microsoft.Dnx.Watcher/Program.cs index 06e2163d5d..e20c5af136 100644 --- a/src/Microsoft.Dnx.Watcher/Program.cs +++ b/src/Microsoft.Dnx.Watcher/Program.cs @@ -6,7 +6,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.Dnx.Runtime; +using Microsoft.Extensions.PlatformAbstractions; using Microsoft.Dnx.Runtime.Common.CommandLine; using Microsoft.Dnx.Watcher.Core; using Microsoft.Extensions.Logging; @@ -19,15 +19,15 @@ namespace Microsoft.Dnx.Watcher private readonly ILoggerFactory _loggerFactory; - public Program(IRuntimeEnvironment runtimeEnvironment) + public Program() { _loggerFactory = new LoggerFactory(); - var commandProvider = new CommandOutputProvider(runtimeEnvironment); + var commandProvider = new CommandOutputProvider(PlatformServices.Default.Runtime); _loggerFactory.AddProvider(commandProvider); } - public int Main(string[] args) + public static int Main(string[] args) { using (CancellationTokenSource ctrlCTokenSource = new CancellationTokenSource()) { @@ -40,7 +40,7 @@ namespace Microsoft.Dnx.Watcher string[] watchArgs, dnxArgs; SeparateWatchArguments(args, out watchArgs, out dnxArgs); - return MainInternal(watchArgs, dnxArgs, ctrlCTokenSource.Token); + return new Program().MainInternal(watchArgs, dnxArgs, ctrlCTokenSource.Token); } } diff --git a/test/Microsoft.Dnx.Watcher.Tests/project.json b/test/Microsoft.Dnx.Watcher.Tests/project.json index fc449ab49d..d093b817ba 100644 --- a/test/Microsoft.Dnx.Watcher.Tests/project.json +++ b/test/Microsoft.Dnx.Watcher.Tests/project.json @@ -1,6 +1,6 @@ { "dependencies": { - "Microsoft.Dnx.Runtime.Abstractions": "1.0.0-*", + "Microsoft.Extensions.PlatformAbstractions": "1.0.0-*", "Microsoft.Dnx.Watcher": "1.0.0-*", "xunit.runner.aspnet": "2.0.0-aspnet-*" }, From e7dc875d750d3777dd86bf1423a99ab048d89599 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Tue, 27 Oct 2015 09:20:40 -0700 Subject: [PATCH 0026/1029] Add emitEntryPoint to dnx-watch --- src/Microsoft.Dnx.Watcher/project.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Dnx.Watcher/project.json b/src/Microsoft.Dnx.Watcher/project.json index 77d1225de8..ad57facb22 100644 --- a/src/Microsoft.Dnx.Watcher/project.json +++ b/src/Microsoft.Dnx.Watcher/project.json @@ -1,6 +1,9 @@ { "version": "1.0.0-*", - "compilationOptions": { "warningsAsErrors": true }, + "compilationOptions": { + "warningsAsErrors": true, + "emitEntryPoint": true + }, "dependencies": { "Microsoft.Dnx.Watcher.Core": "1.0.0-*", "Microsoft.Extensions.CommandLineUtils.Sources": { "version": "1.0.0-*", "type": "build" }, From 76346e48a6e2ce577847be0401ac073c7ceda1ee Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 28 Oct 2015 12:43:05 -0700 Subject: [PATCH 0027/1029] Updating to release NuGet.config. --- NuGet.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NuGet.config b/NuGet.config index 5500f6d507..71b9724a09 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + - + From 42f3a89db5e65092d19f55721904d0403b2bcb26 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 28 Oct 2015 12:43:11 -0700 Subject: [PATCH 0028/1029] Updating to release NuGet.config. --- NuGet.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NuGet.config b/NuGet.config index 03704957e8..9db87a421e 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + - + \ No newline at end of file From 8a0696602401328e3493ac1ebea67061ce1a692b Mon Sep 17 00:00:00 2001 From: Cesar Blum Silveira Date: Fri, 30 Oct 2015 12:19:00 -0700 Subject: [PATCH 0029/1029] Strong name Microsoft.AspNet.JsonPatch. --- src/Microsoft.AspNet.JsonPatch/project.json | 4 ++++ tools/Key.snk | Bin 0 -> 596 bytes 2 files changed, 4 insertions(+) create mode 100644 tools/Key.snk diff --git a/src/Microsoft.AspNet.JsonPatch/project.json b/src/Microsoft.AspNet.JsonPatch/project.json index c08afdec7e..d9b41653fb 100644 --- a/src/Microsoft.AspNet.JsonPatch/project.json +++ b/src/Microsoft.AspNet.JsonPatch/project.json @@ -1,5 +1,9 @@ { "version": "1.0.0-*", + "compilationOptions": { + "warningsAsErrors": true, + "keyFile": "../../tools/Key.snk" + }, "repository": { "type": "git", "url": "git://github.com/aspnet/mvc" diff --git a/tools/Key.snk b/tools/Key.snk new file mode 100644 index 0000000000000000000000000000000000000000..e10e4889c125d3120cd9e81582243d70f7cbb806 GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098=Iw=HCsnz~#iVhm& zj%TU(_THUee?3yHBjk$37ysB?i5#7WD$={H zV4B!OxRPrb|8)HPg~A}8P>^=#y<)56#=E&NzcjOtPK~<4n6GHt=K$ro*T(lhby_@U zEk(hLzk1H)0yXj{A_5>fk-TgNoP|q6(tP2xo8zt8i%212CWM#AeCd?`hS|4~L({h~Moo(~vy&3Z z1uI}`fd^*>o=rwbAGymj6RM^pZm(*Kfhs+Y1#`-2JPWZMK8@;ZWCk2+9bX4YP);~fj-BU*R zQPvWv$89!{Rl9wM+zR>_TSkn^voYxA?2G iKnV#iZ6Ah`K>b=@=IjYJXrxL124zR(38)nxe+&q_$QXwJ literal 0 HcmV?d00001 From 74d89b2e3265794cbb2a6a347ac73639fbfb6552 Mon Sep 17 00:00:00 2001 From: Cesar Blum Silveira Date: Mon, 2 Nov 2015 14:40:58 -0800 Subject: [PATCH 0030/1029] Strong name everything. --- src/Microsoft.Dnx.Watcher.Core/project.json | 5 ++++- .../Properties/AssemblyInfo.cs | 2 +- src/Microsoft.Dnx.Watcher/project.json | 3 ++- test/Microsoft.Dnx.Watcher.Tests/project.json | 4 ++++ tools/Key.snk | Bin 0 -> 596 bytes 5 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 tools/Key.snk diff --git a/src/Microsoft.Dnx.Watcher.Core/project.json b/src/Microsoft.Dnx.Watcher.Core/project.json index feb354708e..ad73128e1e 100644 --- a/src/Microsoft.Dnx.Watcher.Core/project.json +++ b/src/Microsoft.Dnx.Watcher.Core/project.json @@ -1,6 +1,9 @@ { "version": "1.0.0-*", - "compilationOptions": { "warningsAsErrors": true }, + "compilationOptions": { + "warningsAsErrors": true, + "keyFile": "../../tools/Key.snk" + }, "dependencies": { "Microsoft.AspNet.FileProviders.Abstractions": "1.0.0-*", "Microsoft.AspNet.FileProviders.Physical": "1.0.0-*", diff --git a/src/Microsoft.Dnx.Watcher/Properties/AssemblyInfo.cs b/src/Microsoft.Dnx.Watcher/Properties/AssemblyInfo.cs index 956d80dbfe..64dbfc69d0 100644 --- a/src/Microsoft.Dnx.Watcher/Properties/AssemblyInfo.cs +++ b/src/Microsoft.Dnx.Watcher/Properties/AssemblyInfo.cs @@ -5,6 +5,6 @@ using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; -[assembly:InternalsVisibleTo("Microsoft.Dnx.Watcher.Tests")] +[assembly:InternalsVisibleTo("Microsoft.Dnx.Watcher.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: AssemblyMetadata("Serviceable", "True")] [assembly: NeutralResourcesLanguage("en-US")] diff --git a/src/Microsoft.Dnx.Watcher/project.json b/src/Microsoft.Dnx.Watcher/project.json index ad57facb22..2a32dcc292 100644 --- a/src/Microsoft.Dnx.Watcher/project.json +++ b/src/Microsoft.Dnx.Watcher/project.json @@ -2,7 +2,8 @@ "version": "1.0.0-*", "compilationOptions": { "warningsAsErrors": true, - "emitEntryPoint": true + "emitEntryPoint": true, + "keyFile": "../../tools/Key.snk" }, "dependencies": { "Microsoft.Dnx.Watcher.Core": "1.0.0-*", diff --git a/test/Microsoft.Dnx.Watcher.Tests/project.json b/test/Microsoft.Dnx.Watcher.Tests/project.json index d093b817ba..5cc6a0c054 100644 --- a/test/Microsoft.Dnx.Watcher.Tests/project.json +++ b/test/Microsoft.Dnx.Watcher.Tests/project.json @@ -1,4 +1,8 @@ { + "compilationOptions": { + "warningsAsErrors": true, + "keyFile": "../../tools/Key.snk" + }, "dependencies": { "Microsoft.Extensions.PlatformAbstractions": "1.0.0-*", "Microsoft.Dnx.Watcher": "1.0.0-*", diff --git a/tools/Key.snk b/tools/Key.snk new file mode 100644 index 0000000000000000000000000000000000000000..e10e4889c125d3120cd9e81582243d70f7cbb806 GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098=Iw=HCsnz~#iVhm& zj%TU(_THUee?3yHBjk$37ysB?i5#7WD$={H zV4B!OxRPrb|8)HPg~A}8P>^=#y<)56#=E&NzcjOtPK~<4n6GHt=K$ro*T(lhby_@U zEk(hLzk1H)0yXj{A_5>fk-TgNoP|q6(tP2xo8zt8i%212CWM#AeCd?`hS|4~L({h~Moo(~vy&3Z z1uI}`fd^*>o=rwbAGymj6RM^pZm(*Kfhs+Y1#`-2JPWZMK8@;ZWCk2+9bX4YP);~fj-BU*R zQPvWv$89!{Rl9wM+zR>_TSkn^voYxA?2G iKnV#iZ6Ah`K>b=@=IjYJXrxL124zR(38)nxe+&q_$QXwJ literal 0 HcmV?d00001 From f5477d1748905aab3792efa1c4462d5cca6accb8 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Thu, 12 Nov 2015 12:23:18 -0800 Subject: [PATCH 0031/1029] Remove System beta tag in project.json for coreclr packages. --- src/Microsoft.AspNet.JsonPatch/project.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.AspNet.JsonPatch/project.json b/src/Microsoft.AspNet.JsonPatch/project.json index d9b41653fb..4bbe747d4b 100644 --- a/src/Microsoft.AspNet.JsonPatch/project.json +++ b/src/Microsoft.AspNet.JsonPatch/project.json @@ -15,15 +15,15 @@ "net451": {}, "dotnet5.4": { "dependencies": { - "Microsoft.CSharp": "4.0.1-beta-*", - "System.Collections.Concurrent": "4.0.11-beta-*", - "System.ComponentModel.TypeConverter": "4.0.1-beta-*", - "System.Globalization": "4.0.11-beta-*", - "System.Reflection.Extensions": "4.0.1-beta-*", - "System.Resources.ResourceManager": "4.0.1-beta-*", - "System.Runtime.Extensions": "4.0.11-beta-*", - "System.Text.Encoding.Extensions": "4.0.11-beta-*" + "Microsoft.CSharp": "4.0.1-*", + "System.Collections.Concurrent": "4.0.11-*", + "System.ComponentModel.TypeConverter": "4.0.1-*", + "System.Globalization": "4.0.11-*", + "System.Reflection.Extensions": "4.0.1-*", + "System.Resources.ResourceManager": "4.0.1-*", + "System.Runtime.Extensions": "4.0.11-*", + "System.Text.Encoding.Extensions": "4.0.11-*" } } } -} \ No newline at end of file +} From bba44597fccaa172fceddd471bf92861895c5bd4 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Thu, 12 Nov 2015 12:25:07 -0800 Subject: [PATCH 0032/1029] Remove System beta tag in project.json for coreclr packages. --- src/Microsoft.Dnx.Watcher.Core/project.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.Dnx.Watcher.Core/project.json b/src/Microsoft.Dnx.Watcher.Core/project.json index ad73128e1e..aad47b43e6 100644 --- a/src/Microsoft.Dnx.Watcher.Core/project.json +++ b/src/Microsoft.Dnx.Watcher.Core/project.json @@ -24,10 +24,10 @@ }, "dnxcore50": { "dependencies": { - "System.Diagnostics.Process": "4.1.0-beta-*", - "System.Linq": "4.0.1-beta-*", - "System.Runtime.Extensions": "4.0.11-beta-*", - "System.Threading.Thread": "4.0.0-beta-*" + "System.Diagnostics.Process": "4.1.0-*", + "System.Linq": "4.0.1-*", + "System.Runtime.Extensions": "4.0.11-*", + "System.Threading.Thread": "4.0.0-*" } } } From 985d18546616343a187c5d3a427482f61b841ed6 Mon Sep 17 00:00:00 2001 From: John Rowley Date: Thu, 29 Oct 2015 17:35:56 -0700 Subject: [PATCH 0033/1029] Moved content from Announcement to README.md --- README.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 628dcdbce3..45b7eb49dc 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,30 @@ dnx-watch === +`dnx-watch` is a file watcher for `dnx` that restarts the specified application when changes in the source code are detected. Its' purpose is to replace `dnx --watch`. + +### How To Install +From a console window run the following command `dnu commands install Microsoft.Dnx.Watcher` +Then the `dnx-watch` command will become available. + +To install the latest unstable release add the following parameter to the command `--fallbacksource https://myget.org/F/aspnetvnext/api/v3/index.json` + +### How To Use +`dnx-watch ` + +Example: + +* To run the command `kestrel` in the current folder: `dnx-watch kestrel` +* To run the command kestrel in a different folder: `dnx-watch --project C:\myproject --dnx-args kestrel` +* To run the command kestrel in a different folder with extra arguments: `dnx-watch --project C:\myproject --dnx-args kestrel arg1 arg2` + AppVeyor: [![AppVeyor](https://ci.appveyor.com/api/projects/status/fxhto3omtehio3aj/branch/dev?svg=true)](https://ci.appveyor.com/project/aspnetci/dnx-watch/branch/dev) Travis: [![Travis](https://travis-ci.org/aspnet/dnx-watch.svg?branch=dev)](https://travis-ci.org/aspnet/dnx-watch) -This project is part of ASP.NET 5. You can find samples, documentation and getting started instructions for ASP.NET 5 at the [Home](https://github.com/aspnet/home) repo. +### Remarks: + +* Everything after `--dnx-args` is passed to dnx and ignored by the watcher. +* The watcher always passes `--project` to dnx. Do not pass it as a `--dnx-args` argument. + +This project is part of ASP.NET 5. You can find samples, documentation and getting started instructions for ASP.NET 5 at the [Home](https://github.com/aspnet/home) repo. From 8078f691f003e43f61785dfb0781ff13ccbebaf9 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Tue, 17 Nov 2015 10:56:56 -0800 Subject: [PATCH 0034/1029] Explicitly choose Mono 4.0.5 - avoids future problems related to aspnet/External#48 - e.g. when Travis updates default Mono version in `csharp` bundle --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index f01ee5a79a..eb869cd139 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,8 @@ language: csharp sudo: false env: - MONO_THREADS_PER_CPU=2000 +mono: + - 4.0.5 os: - linux - osx From 02e99e341e91bf72bd7ac210a7c581ef6889c4d2 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Tue, 17 Nov 2015 11:03:11 -0800 Subject: [PATCH 0035/1029] Explicitly choose Mono 4.0.5 - avoids future problems related to aspnet/External#48 - e.g. when Travis updates default Mono version in `csharp` bundle --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 947bf868ee..dc44c0f660 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,6 @@ language: csharp sudo: false +mono: + - 4.0.5 script: - ./build.sh --quiet verify \ No newline at end of file From d6542506a8f3c3498509d525b00be602b5efdbb6 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Tue, 17 Nov 2015 12:40:19 -0800 Subject: [PATCH 0036/1029] Move Travis to supported Linux distribution - use Ubuntu 14.04 (Trusty) - Travis support for Trusty is in Beta and currently requires `sudo` - run `dnu restore` with DNX Core since aspnet/External#49 is not fixed in Mono versions we can use - add required dependencies for DNX Core to `.travis.yml` - addresses part of aspnet/Universe#290 --- .travis.yml | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index eb869cd139..8c8e21bfc4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,24 @@ language: csharp -sudo: false +sudo: required +dist: trusty +addons: + apt: + packages: + - gettext + - libcurl4-openssl-dev + - libicu-dev + - libssl-dev + - libunwind8 + - zlib1e +before_install: + - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; fi + - if test "$TRAVIS_OS_NAME" == "osx"; then brew install icu4c; fi env: - - MONO_THREADS_PER_CPU=2000 + - KOREBUILD_DNU_RESTORE_CORECLR=true MONO_THREADS_PER_CPU=2000 mono: - 4.0.5 os: - linux - osx script: - - ./build.sh --quiet verify \ No newline at end of file + - ./build.sh --quiet verify From b09bdc08f48cbddff43a7ad6045a69b4c8258c11 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Tue, 17 Nov 2015 14:01:02 -0800 Subject: [PATCH 0037/1029] Move Travis to supported Linux distribution - use Ubuntu 14.04 (Trusty) - Travis support for Trusty is in Beta and currently requires `sudo` - run `dnu restore` with DNX Core since aspnet/External#49 is not fixed in Mono versions we can use - add required dependencies for DNX Core to `.travis.yml` - addresses part of aspnet/Universe#290 --- .travis.yml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index dc44c0f660..2fc624899f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,18 @@ language: csharp -sudo: false +sudo: required +dist: trusty +addons: + apt: + packages: + - gettext + - libcurl4-openssl-dev + - libicu-dev + - libssl-dev + - libunwind8 + - zlib1g +env: + - KOREBUILD_DNU_RESTORE_CORECLR=true mono: - 4.0.5 script: - - ./build.sh --quiet verify \ No newline at end of file + - ./build.sh --quiet verify From 03a04917d096c1b15a4058e8e8b432778246a2a6 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Tue, 17 Nov 2015 14:53:54 -0800 Subject: [PATCH 0038/1029] Small .travis.yml update: Consolidate `brew` commands under a single `if` --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8c8e21bfc4..74c8293fe2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,8 +11,7 @@ addons: - libunwind8 - zlib1e before_install: - - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; fi - - if test "$TRAVIS_OS_NAME" == "osx"; then brew install icu4c; fi + - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install icu4c; fi env: - KOREBUILD_DNU_RESTORE_CORECLR=true MONO_THREADS_PER_CPU=2000 mono: From 606c97d9f85524b57bb58d8306abfa24e1a2a545 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Tue, 17 Nov 2015 15:40:36 -0800 Subject: [PATCH 0039/1029] Correct `.travis.yml` typo --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 74c8293fe2..2019384e19 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ addons: - libicu-dev - libssl-dev - libunwind8 - - zlib1e + - zlib1g before_install: - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install icu4c; fi env: From 60f5fd591ef301428347de955c02ee06286732db Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 23 Nov 2015 16:40:15 -0800 Subject: [PATCH 0040/1029] Updating tests to run on dnxcore50 --- .../Dynamic/AddOperationTests.cs | 36 +++++++-------- .../Dynamic/AddTypedOperationTests.cs | 6 +-- .../Dynamic/PatchDocumentTests.cs | 12 ++--- .../Dynamic/RemoveOperationTests.cs | 46 +++++++++---------- .../Dynamic/RemoveTypedOperationTests.cs | 8 ++-- .../Dynamic/SimpleDTOWithNestedDTO.cs | 2 +- .../NestedObjectTests.cs | 29 ++++++------ .../ObjectAdapterTests.cs | 8 ++-- .../SimpleDTO.cs | 1 - .../TestErrorLogger.cs | 2 +- .../project.json | 36 +++++++++------ 11 files changed, 96 insertions(+), 90 deletions(-) diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/AddOperationTests.cs b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/AddOperationTests.cs index 3c2523c5fb..f5a3c384ef 100644 --- a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/AddOperationTests.cs +++ b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/AddOperationTests.cs @@ -18,7 +18,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic dynamic doc = new { Test = 1 - }; + }; // create patch JsonPatchDocument patchDoc = new JsonPatchDocument(); @@ -33,14 +33,14 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic }); Assert.Equal( "The property at path '/NewInt' could not be added.", - exception.Message); + exception.Message); } [Fact] public void AddNewProperty() { dynamic obj = new ExpandoObject(); - obj.Test = 1; + obj.Test = 1; // create patch JsonPatchDocument patchDoc = new JsonPatchDocument(); @@ -48,7 +48,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); - + deserialized.ApplyTo(obj); Assert.Equal(1, obj.NewInt); @@ -104,7 +104,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic "The property at path '/Nested/NewInt' could not be added.", exception.Message); } - + [Fact] public void AddToExistingPropertyOnNestedObject() { @@ -120,7 +120,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); - + deserialized.ApplyTo(doc); Assert.Equal("A", doc.nested.StringProperty); @@ -142,13 +142,13 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); - + deserialized.ApplyTo(doc); Assert.Equal(1, doc.nested.NewInt); Assert.Equal(1, doc.Test); } - + [Fact] public void AddNewPropertyToExpandoOjectInTypedObject() { @@ -156,7 +156,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic { DynamicProperty = new ExpandoObject() }; - + // create patch JsonPatchDocument patchDoc = new JsonPatchDocument(); patchDoc.Add("DynamicProperty/NewInt", 1); @@ -168,9 +168,9 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic Assert.Equal(1, doc.DynamicProperty.NewInt); } - + [Fact] - public void AddNewPropertyToTypedObjectInExpandoObject() + public void AddNewPropertyToTypedObjectInExpandoObject() { dynamic dynamicProperty = new ExpandoObject(); dynamicProperty.StringProperty = "A"; @@ -246,7 +246,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic public void AddResultsShouldReplace() { dynamic doc = new ExpandoObject(); - doc.StringProperty = "A"; + doc.StringProperty = "A"; // create patch JsonPatchDocument patchDoc = new JsonPatchDocument(); @@ -289,11 +289,11 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic doc.Nested.DynamicProperty.InBetweenFirst = new ExpandoObject(); doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond = new ExpandoObject(); doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond.StringProperty = "A"; - + // create patch JsonPatchDocument patchDoc = new JsonPatchDocument(); patchDoc.Add("/Nested/DynamicProperty/InBetweenFirst/InBetweenSecond/StringProperty", "B"); - + var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); @@ -301,7 +301,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic Assert.Equal("B", doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond.StringProperty); } - + [Fact] public void ShouldNotBeAbleToAddToNonExistingPropertyThatIsNotTheRoot() { @@ -387,7 +387,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic // create patch JsonPatchDocument patchDoc = new JsonPatchDocument(); patchDoc.Add("stringproperty", "B"); - + var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); @@ -415,7 +415,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerList); } - + [Fact] public void AddToListNegativePosition() { @@ -452,7 +452,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); - + deserialized.ApplyTo(doc); Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerList); diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs index 4d2e8c646d..7913541514 100644 --- a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs +++ b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs @@ -21,7 +21,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic // create patch JsonPatchDocument patchDoc = new JsonPatchDocument(); patchDoc.Add("IntegerList/-1", 4); - + var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); @@ -101,11 +101,11 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic IntegerList = new List() { 1, 2, 3 } } } - }; + }; // create patch JsonPatchDocument patchDoc = new JsonPatchDocument(); patchDoc.Add("ListOfSimpleDTO/20/IntegerList/0", 4); - + var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/PatchDocumentTests.cs b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/PatchDocumentTests.cs index e15f85da8e..8b14c3448b 100644 --- a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/PatchDocumentTests.cs +++ b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/PatchDocumentTests.cs @@ -8,7 +8,7 @@ using Xunit; namespace Microsoft.AspNet.JsonPatch.Test.Dynamic { public class PatchDocumentTests - { + { [Fact] public void InvalidPathAtBeginningShouldThrowException() { @@ -20,11 +20,11 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic Assert.Equal( "The provided string '//NewInt' is an invalid path.", exception.Message); - } + } [Fact] public void InvalidPathAtEndShouldThrowException() - { + { JsonPatchDocument patchDoc = new JsonPatchDocument(); var exception = Assert.Throws(() => { @@ -33,11 +33,11 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic Assert.Equal( "The provided string 'NewInt//' is an invalid path.", exception.Message); - } + } [Fact] public void InvalidPathWithDotShouldThrowException() - { + { JsonPatchDocument patchDoc = new JsonPatchDocument(); var exception = Assert.Throws(() => { @@ -56,7 +56,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic StringProperty = "A", AnotherStringProperty = "B" }; - + JsonPatchDocument patchDoc = new JsonPatchDocument(); patchDoc.Copy("StringProperty", "AnotherStringProperty"); diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/RemoveOperationTests.cs b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/RemoveOperationTests.cs index 9ef28ad7cc..9ecb520b38 100644 --- a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/RemoveOperationTests.cs +++ b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/RemoveOperationTests.cs @@ -39,7 +39,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic public void RemovePropertyShouldFailIfItDoesntExist() { dynamic doc = new ExpandoObject(); - doc.Test = 1; + doc.Test = 1; // create patch JsonPatchDocument patchDoc = new JsonPatchDocument(); @@ -61,7 +61,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic public void RemovePropertyFromExpandoObject() { dynamic obj = new ExpandoObject(); - obj.Test = 1; + obj.Test = 1; // create patch JsonPatchDocument patchDoc = new JsonPatchDocument(); @@ -69,13 +69,13 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); - + deserialized.ApplyTo(obj); var cont = obj as IDictionary; object valueFromDictionary; - cont.TryGetValue("Test", out valueFromDictionary); + cont.TryGetValue("Test", out valueFromDictionary); Assert.Null(valueFromDictionary); } @@ -91,7 +91,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); - + deserialized.ApplyTo(obj); var cont = obj as IDictionary; @@ -137,7 +137,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); - + deserialized.ApplyTo(obj); var cont = obj as IDictionary; @@ -151,9 +151,9 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic { dynamic doc = new ExpandoObject(); doc.SimpleDTO = new SimpleDTO() - { - StringProperty = "A" - }; + { + StringProperty = "A" + }; // create patch JsonPatchDocument patchDoc = new JsonPatchDocument(); @@ -192,10 +192,10 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic { dynamic doc = new ExpandoObject(); doc.SimpleDTO = new SimpleDTO() - { - IntegerList = new List() { 1, 2, 3 } - }; - + { + IntegerList = new List() { 1, 2, 3 } + }; + // create patch JsonPatchDocument patchDoc = new JsonPatchDocument(); patchDoc.Remove("SimpleDTO/IntegerList/2"); @@ -216,7 +216,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic { IntegerList = new List() { 1, 2, 3 } }; - + // create patch JsonPatchDocument patchDoc = new JsonPatchDocument(); patchDoc.Remove("SimpleDTO/Integerlist/2"); @@ -234,9 +234,9 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic { dynamic doc = new ExpandoObject(); doc.SimpleDTO = new SimpleDTO() - { - IntegerList = new List() { 1, 2, 3 } - }; + { + IntegerList = new List() { 1, 2, 3 } + }; // create patch JsonPatchDocument patchDoc = new JsonPatchDocument(); @@ -259,9 +259,9 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic { dynamic doc = new ExpandoObject(); doc.SimpleDTO = new SimpleDTO() - { - IntegerList = new List() { 1, 2, 3 } - }; + { + IntegerList = new List() { 1, 2, 3 } + }; // create patch JsonPatchDocument patchDoc = new JsonPatchDocument(); @@ -284,9 +284,9 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic { dynamic doc = new ExpandoObject(); doc.SimpleDTO = new SimpleDTO() - { - IntegerList = new List() { 1, 2, 3 } - }; + { + IntegerList = new List() { 1, 2, 3 } + }; // create patch JsonPatchDocument patchDoc = new JsonPatchDocument(); diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs index db5d6502d1..802fb27e40 100644 --- a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs +++ b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs @@ -73,7 +73,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic "For operation 'remove' on array property at path '/IntegerList/3', the index is larger than the array size.", exception.Message); } - + [Fact] public void RemoveFromListInvalidPositionTooSmall() { @@ -135,7 +135,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); - + deserialized.ApplyTo(doc); Assert.Equal(null, doc.SimpleDTO.StringProperty); @@ -190,7 +190,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic "For operation 'remove' on array property at path '/SimpleDTO/IntegerList/3', the index is larger than the array size.", exception.Message); } - + [Fact] public void NestedRemoveFromListInvalidPositionTooSmall() { @@ -216,7 +216,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic Assert.Equal( "For operation 'remove' on array property at path '/SimpleDTO/IntegerList/-1', the index is negative.", exception.Message); - } + } [Fact] public void NestedRemoveFromEndOfList() diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/SimpleDTOWithNestedDTO.cs b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/SimpleDTOWithNestedDTO.cs index 2147fcceb1..03c74f8a1b 100644 --- a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/SimpleDTOWithNestedDTO.cs +++ b/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/SimpleDTOWithNestedDTO.cs @@ -11,7 +11,7 @@ namespace Microsoft.AspNet.JsonPatch.Test.Dynamic public NestedDTO NestedDTO { get; set; } public SimpleDTO SimpleDTO { get; set; } public List ListOfSimpleDTO { get; set; } - + public SimpleDTOWithNestedDTO() { NestedDTO = new NestedDTO(); diff --git a/test/Microsoft.AspNet.JsonPatch.Test/NestedObjectTests.cs b/test/Microsoft.AspNet.JsonPatch.Test/NestedObjectTests.cs index 33649b7788..e736373ed8 100644 --- a/test/Microsoft.AspNet.JsonPatch.Test/NestedObjectTests.cs +++ b/test/Microsoft.AspNet.JsonPatch.Test/NestedObjectTests.cs @@ -1,11 +1,10 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Microsoft.AspNet.JsonPatch.Exceptions; -using Newtonsoft.Json; -using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using Microsoft.AspNet.JsonPatch.Exceptions; +using Newtonsoft.Json; using Xunit; namespace Microsoft.AspNet.JsonPatch.Test @@ -388,7 +387,7 @@ namespace Microsoft.AspNet.JsonPatch.Test var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); Assert.Equal( "For operation 'add' on array property at path '/simpledto/integerlist/4', the index is " + - "larger than the array size.", + "larger than the array size.", exception.Message); } @@ -442,7 +441,7 @@ namespace Microsoft.AspNet.JsonPatch.Test var logger = new TestErrorLogger(); patchDoc.ApplyTo(doc, logger.LogErrorMessage); - + //Assert Assert.Equal( @@ -524,8 +523,8 @@ namespace Microsoft.AspNet.JsonPatch.Test patchDoc.ApplyTo(doc, logger.LogErrorMessage); - - + + //Assert Assert.Equal( "For operation 'add' on array property at path '/simpledto/integerlist/-1', the index is negative.", @@ -750,9 +749,9 @@ namespace Microsoft.AspNet.JsonPatch.Test patchDoc.Remove(o => o.SimpleDTO.IntegerList, 3); var logger = new TestErrorLogger(); - + patchDoc.ApplyTo(doc, logger.LogErrorMessage); - + // Assert Assert.Equal( "For operation 'remove' on array property at path '/simpledto/integerlist/3', the index is " + @@ -828,7 +827,7 @@ namespace Microsoft.AspNet.JsonPatch.Test patchDoc.ApplyTo(doc, logger.LogErrorMessage); - + // Assert Assert.Equal("For operation 'remove' on array property at path '/simpledto/integerlist/-1', the index is negative.", logger.ErrorMessage); } @@ -1293,9 +1292,9 @@ namespace Microsoft.AspNet.JsonPatch.Test var logger = new TestErrorLogger(); - + patchDoc.ApplyTo(doc, logger.LogErrorMessage); - + // Assert Assert.Equal( @@ -1319,7 +1318,7 @@ namespace Microsoft.AspNet.JsonPatch.Test // create patch var patchDoc = new JsonPatchDocument(); patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5, -1); - + // Act & Assert var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); Assert.Equal("For operation 'replace' on array property at path '/simpledto/integerlist/-1', the index is negative.", @@ -1371,8 +1370,8 @@ namespace Microsoft.AspNet.JsonPatch.Test var logger = new TestErrorLogger(); - patchDoc.ApplyTo(doc, logger.LogErrorMessage); - + patchDoc.ApplyTo(doc, logger.LogErrorMessage); + // Assert Assert.Equal( diff --git a/test/Microsoft.AspNet.JsonPatch.Test/ObjectAdapterTests.cs b/test/Microsoft.AspNet.JsonPatch.Test/ObjectAdapterTests.cs index 0cc97e32c4..85d9404e6d 100644 --- a/test/Microsoft.AspNet.JsonPatch.Test/ObjectAdapterTests.cs +++ b/test/Microsoft.AspNet.JsonPatch.Test/ObjectAdapterTests.cs @@ -202,7 +202,7 @@ namespace Microsoft.AspNet.JsonPatch.Test var logger = new TestErrorLogger(); patchDoc.ApplyTo(doc, logger.LogErrorMessage); - + // Assert Assert.Equal( @@ -356,7 +356,7 @@ namespace Microsoft.AspNet.JsonPatch.Test var logger = new TestErrorLogger(); patchDoc.ApplyTo(doc, logger.LogErrorMessage); - + // Assert Assert.Equal( "For operation 'add' on array property at path '/integerlist/-1', the index is negative.", @@ -553,7 +553,7 @@ namespace Microsoft.AspNet.JsonPatch.Test var logger = new TestErrorLogger(); patchDoc.ApplyTo(doc, logger.LogErrorMessage); - + // Assert Assert.Equal( @@ -618,7 +618,7 @@ namespace Microsoft.AspNet.JsonPatch.Test patchDoc.ApplyTo(doc, logger.LogErrorMessage); - + // Assert Assert.Equal("For operation 'remove' on array property at path '/integerlist/-1', the index is negative.", logger.ErrorMessage); diff --git a/test/Microsoft.AspNet.JsonPatch.Test/SimpleDTO.cs b/test/Microsoft.AspNet.JsonPatch.Test/SimpleDTO.cs index 0c29a86e83..b1177bc5ce 100644 --- a/test/Microsoft.AspNet.JsonPatch.Test/SimpleDTO.cs +++ b/test/Microsoft.AspNet.JsonPatch.Test/SimpleDTO.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections; using System.Collections.Generic; namespace Microsoft.AspNet.JsonPatch.Test diff --git a/test/Microsoft.AspNet.JsonPatch.Test/TestErrorLogger.cs b/test/Microsoft.AspNet.JsonPatch.Test/TestErrorLogger.cs index c254eab3e3..525321cfb3 100644 --- a/test/Microsoft.AspNet.JsonPatch.Test/TestErrorLogger.cs +++ b/test/Microsoft.AspNet.JsonPatch.Test/TestErrorLogger.cs @@ -3,7 +3,7 @@ namespace Microsoft.AspNet.JsonPatch.Test { - public class TestErrorLogger where T: class + public class TestErrorLogger where T : class { public string ErrorMessage { get; set; } diff --git a/test/Microsoft.AspNet.JsonPatch.Test/project.json b/test/Microsoft.AspNet.JsonPatch.Test/project.json index 629b7a1be3..8b97af645a 100644 --- a/test/Microsoft.AspNet.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNet.JsonPatch.Test/project.json @@ -1,18 +1,26 @@ { - "compilationOptions": { - "warningsAsErrors": true + "compilationOptions": { + "warningsAsErrors": true + }, + "dependencies": { + "Microsoft.AspNet.JsonPatch": "1.0.0-*", + "Microsoft.AspNet.Testing": "1.0.0-*", + "Newtonsoft.Json": "6.0.6", + "xunit.runner.aspnet": "2.0.0-aspnet-*" + }, + "commands": { + "test": "xunit.runner.aspnet" + }, + "frameworks": { + "dnx451": { + "dependencies": { + "Moq": "4.2.1312.1622" + } }, - "dependencies": { - "Microsoft.AspNet.JsonPatch": "1.0.0-*", - "Microsoft.AspNet.Testing": "1.0.0-*", - "Moq": "4.2.1312.1622", - "Newtonsoft.Json": "6.0.6", - "xunit.runner.aspnet": "2.0.0-aspnet-*" - }, - "commands": { - "test": "xunit.runner.aspnet" - }, - "frameworks": { - "dnx451": { } + "dnxcore50": { + "dependencies": { + "moq.netcore": "4.4.0-beta8" + } } + } } \ No newline at end of file From a2e4c4e13362a54a2b1610b9b878cf60d691bc73 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 1 Dec 2015 11:01:13 -0800 Subject: [PATCH 0041/1029] Enabling tests on CoreCLR --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2fc624899f..c0befaffcf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ addons: - libunwind8 - zlib1g env: - - KOREBUILD_DNU_RESTORE_CORECLR=true + - KOREBUILD_DNU_RESTORE_CORECLR=true KOREBUILD_TEST_DNXCORE=true mono: - 4.0.5 script: From 48243bbc0cc25e80a84be37b714ae04833814cf1 Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Tue, 1 Dec 2015 14:35:51 -0800 Subject: [PATCH 0042/1029] Create README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000000..add6834eeb --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +HtmlAbstractions +========== + +HTML abstractions such as `IHtmlContent` and related APIs. + +This project is part of ASP.NET 5. You can find samples, documentation and getting started instructions for ASP.NET 5 at the [Home](https://github.com/aspnet/home) repo. From 95ae9483491ce2f12e6d47fd0064132d1c59c065 Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Tue, 1 Dec 2015 14:36:15 -0800 Subject: [PATCH 0043/1029] Create LICENSE.txt --- LICENSE.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 LICENSE.txt diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000000..0bdc1962b6 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,12 @@ +Copyright (c) .NET Foundation. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +these files except in compliance with the License. You may obtain a copy of the +License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. From b14fa9d990f65c3c07c4e800d1eccfa5479d6a5d Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Tue, 1 Dec 2015 14:36:26 -0800 Subject: [PATCH 0044/1029] Create CONTRIBUTING.md --- CONTRIBUTING.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..64ff041d5c --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,4 @@ +Contributing +====== + +Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/dev/CONTRIBUTING.md) in the Home repo. From f9661e2bf1b799c68396bb38fa4d942516c9f16a Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 1 Dec 2015 14:58:47 -0800 Subject: [PATCH 0045/1029] Initial commit --- .gitattributes | 50 ++ .gitignore | 27 ++ .travis.yml | 18 + HtmlAbstractions.sln | 55 +++ NuGet.config | 7 + NuGetPackageVerifier.json | 25 + appveyor.yml | 7 + build.cmd | 40 ++ build.sh | 43 ++ global.json | 3 + makefile.shade | 10 + .../HtmlContentBuilder.cs | 138 ++++++ .../HtmlContentBuilderExtensions.cs | 324 +++++++++++++ .../HtmlEncodedString.cs | 49 ++ src/Microsoft.AspNet.Html/HtmlTextWriter.cs | 49 ++ src/Microsoft.AspNet.Html/IHtmlContent.cs | 22 + .../IHtmlContentBuilder.cs | 40 ++ .../Microsoft.AspNet.Html.xproj | 19 + .../Properties/AssemblyInfo.cs | 10 + src/Microsoft.AspNet.Html/project.json | 29 ++ .../HtmlContentBuilderExtensionsTest.cs | 436 ++++++++++++++++++ .../HtmlContentBuilderTest.cs | 145 ++++++ .../Microsoft.AspNet.Html.Test.xproj | 21 + test/Microsoft.AspNet.Html.Test/project.json | 19 + tools/Key.snk | Bin 0 -> 596 bytes 25 files changed, 1586 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 HtmlAbstractions.sln create mode 100644 NuGet.config create mode 100644 NuGetPackageVerifier.json create mode 100644 appveyor.yml create mode 100644 build.cmd create mode 100755 build.sh create mode 100644 global.json create mode 100644 makefile.shade create mode 100644 src/Microsoft.AspNet.Html/HtmlContentBuilder.cs create mode 100644 src/Microsoft.AspNet.Html/HtmlContentBuilderExtensions.cs create mode 100644 src/Microsoft.AspNet.Html/HtmlEncodedString.cs create mode 100644 src/Microsoft.AspNet.Html/HtmlTextWriter.cs create mode 100644 src/Microsoft.AspNet.Html/IHtmlContent.cs create mode 100644 src/Microsoft.AspNet.Html/IHtmlContentBuilder.cs create mode 100644 src/Microsoft.AspNet.Html/Microsoft.AspNet.Html.xproj create mode 100644 src/Microsoft.AspNet.Html/Properties/AssemblyInfo.cs create mode 100644 src/Microsoft.AspNet.Html/project.json create mode 100644 test/Microsoft.AspNet.Html.Test/HtmlContentBuilderExtensionsTest.cs create mode 100644 test/Microsoft.AspNet.Html.Test/HtmlContentBuilderTest.cs create mode 100644 test/Microsoft.AspNet.Html.Test/Microsoft.AspNet.Html.Test.xproj create mode 100644 test/Microsoft.AspNet.Html.Test/project.json create mode 100644 tools/Key.snk diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..bdaa5ba982 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,50 @@ +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain + +*.jpg binary +*.png binary +*.gif binary + +*.cs text=auto diff=csharp +*.vb text=auto +*.resx text=auto +*.c text=auto +*.cpp text=auto +*.cxx text=auto +*.h text=auto +*.hxx text=auto +*.py text=auto +*.rb text=auto +*.java text=auto +*.html text=auto +*.htm text=auto +*.css text=auto +*.scss text=auto +*.sass text=auto +*.less text=auto +*.js text=auto +*.lisp text=auto +*.clj text=auto +*.sql text=auto +*.php text=auto +*.lua text=auto +*.m text=auto +*.asm text=auto +*.erl text=auto +*.fs text=auto +*.fsx text=auto +*.hs text=auto + +*.csproj text=auto +*.vbproj text=auto +*.fsproj text=auto +*.dbproj text=auto +*.sln text=auto eol=crlf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..ac82da7568 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +[Oo]bj/ +[Bb]in/ +TestResults/ +.nuget/ +_ReSharper.*/ +packages/ +artifacts/ +PublishProfiles/ +*.user +*.suo +*.cache +*.docstates +_ReSharper.* +nuget.exe +*net45.csproj +*net451.csproj +*k10.csproj +*.psess +*.vsp +*.pidb +*.userprefs +*DS_Store +*.ncrunchsolution +*.*sdf +*.ipch +*.sln.ide +project.lock.json diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..c0befaffcf --- /dev/null +++ b/.travis.yml @@ -0,0 +1,18 @@ +language: csharp +sudo: required +dist: trusty +addons: + apt: + packages: + - gettext + - libcurl4-openssl-dev + - libicu-dev + - libssl-dev + - libunwind8 + - zlib1g +env: + - KOREBUILD_DNU_RESTORE_CORECLR=true KOREBUILD_TEST_DNXCORE=true +mono: + - 4.0.5 +script: + - ./build.sh --quiet verify diff --git a/HtmlAbstractions.sln b/HtmlAbstractions.sln new file mode 100644 index 0000000000..1d1f5118f3 --- /dev/null +++ b/HtmlAbstractions.sln @@ -0,0 +1,55 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24711.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A5A15F1C-885A-452A-A731-B0173DDBD913}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F31FF137-390C-49BF-A3BD-7C6ED3597C21}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Html", "src\Microsoft.AspNet.Html.Abstractions\Microsoft.AspNet.Html.xproj", "{68A28E4A-3ADE-4187-9625-4FF185887CB3}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Html.Test", "test\Microsoft.AspNet.Html.Abstractions.Test\Microsoft.AspNet.Html.Test.xproj", "{2D187B88-94BD-4A39-AC97-F8F8B9363301}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Debug|x86.ActiveCfg = Debug|Any CPU + {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Debug|x86.Build.0 = Debug|Any CPU + {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|Any CPU.Build.0 = Release|Any CPU + {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|x86.ActiveCfg = Release|Any CPU + {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|x86.Build.0 = Release|Any CPU + {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Debug|x86.ActiveCfg = Debug|Any CPU + {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Debug|x86.Build.0 = Debug|Any CPU + {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|Any CPU.Build.0 = Release|Any CPU + {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|x86.ActiveCfg = Release|Any CPU + {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {68A28E4A-3ADE-4187-9625-4FF185887CB3} = {A5A15F1C-885A-452A-A731-B0173DDBD913} + {2D187B88-94BD-4A39-AC97-F8F8B9363301} = {F31FF137-390C-49BF-A3BD-7C6ED3597C21} + EndGlobalSection +EndGlobal diff --git a/NuGet.config b/NuGet.config new file mode 100644 index 0000000000..03704957e8 --- /dev/null +++ b/NuGet.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json new file mode 100644 index 0000000000..c57b2afb17 --- /dev/null +++ b/NuGetPackageVerifier.json @@ -0,0 +1,25 @@ +{ + "adx": { // Packages written by the ADX team and that ship on NuGet.org + "rules": [ + "AssemblyHasDocumentFileRule", + "AssemblyHasVersionAttributesRule", + "AssemblyHasServicingAttributeRule", + "AssemblyHasNeutralResourcesLanguageAttributeRule", + "SatellitePackageRule", + "StrictSemanticVersionValidationRule" + ], + "packages": { + "Microsoft.AspNet.Html.Abstractions": { } + } + }, + "Default": { // Rules to run for packages not listed in any other set. + "rules": [ + "AssemblyHasDocumentFileRule", + "AssemblyHasVersionAttributesRule", + "AssemblyHasServicingAttributeRule", + "AssemblyHasNeutralResourcesLanguageAttributeRule", + "SatellitePackageRule", + "StrictSemanticVersionValidationRule" + ] + } +} \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000000..636a7618d3 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,7 @@ +init: + - git config --global core.autocrlf true +build_script: + - build.cmd --quiet verify +clone_depth: 1 +test: off +deploy: off \ No newline at end of file diff --git a/build.cmd b/build.cmd new file mode 100644 index 0000000000..553e3929a0 --- /dev/null +++ b/build.cmd @@ -0,0 +1,40 @@ +@echo off +cd %~dp0 + +SETLOCAL +SET NUGET_VERSION=latest +SET CACHED_NUGET=%LocalAppData%\NuGet\nuget.%NUGET_VERSION%.exe +SET BUILDCMD_KOREBUILD_VERSION= +SET BUILDCMD_DNX_VERSION= + +IF EXIST %CACHED_NUGET% goto copynuget +echo Downloading latest version of NuGet.exe... +IF NOT EXIST %LocalAppData%\NuGet md %LocalAppData%\NuGet +@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/%NUGET_VERSION%/nuget.exe' -OutFile '%CACHED_NUGET%'" + +:copynuget +IF EXIST .nuget\nuget.exe goto restore +md .nuget +copy %CACHED_NUGET% .nuget\nuget.exe > nul + +:restore +IF EXIST packages\Sake goto getdnx +IF "%BUILDCMD_KOREBUILD_VERSION%"=="" ( + .nuget\nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre +) ELSE ( + .nuget\nuget.exe install KoreBuild -version %BUILDCMD_KOREBUILD_VERSION% -ExcludeVersion -o packages -nocache -pre +) +.nuget\NuGet.exe install Sake -ExcludeVersion -Source https://www.nuget.org/api/v2/ -Out packages + +:getdnx +IF "%BUILDCMD_DNX_VERSION%"=="" ( + SET BUILDCMD_DNX_VERSION=latest +) +IF "%SKIP_DNX_INSTALL%"=="" ( + CALL packages\KoreBuild\build\dnvm install %BUILDCMD_DNX_VERSION% -runtime CoreCLR -arch x86 -alias default + CALL packages\KoreBuild\build\dnvm install default -runtime CLR -arch x86 -alias default +) ELSE ( + CALL packages\KoreBuild\build\dnvm use default -runtime CLR -arch x86 +) + +packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %* diff --git a/build.sh b/build.sh new file mode 100755 index 0000000000..da4e3fcd1c --- /dev/null +++ b/build.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +if test `uname` = Darwin; then + cachedir=~/Library/Caches/KBuild +else + if [ -z $XDG_DATA_HOME ]; then + cachedir=$HOME/.local/share + else + cachedir=$XDG_DATA_HOME; + fi +fi +mkdir -p $cachedir +nugetVersion=latest +cachePath=$cachedir/nuget.$nugetVersion.exe + +url=https://dist.nuget.org/win-x86-commandline/$nugetVersion/nuget.exe + +if test ! -f $cachePath; then + wget -O $cachePath $url 2>/dev/null || curl -o $cachePath --location $url /dev/null +fi + +if test ! -e .nuget; then + mkdir .nuget + cp $cachePath .nuget/nuget.exe +fi + +if test ! -d packages/Sake; then + mono .nuget/nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre + mono .nuget/nuget.exe install Sake -ExcludeVersion -Source https://www.nuget.org/api/v2/ -Out packages +fi + +if ! type dnvm > /dev/null 2>&1; then + source packages/KoreBuild/build/dnvm.sh +fi + +if ! type dnx > /dev/null 2>&1 || [ -z "$SKIP_DNX_INSTALL" ]; then + dnvm install latest -runtime coreclr -alias default + dnvm install default -runtime mono -alias default +else + dnvm use default -runtime mono +fi + +mono packages/Sake/tools/Sake.exe -I packages/KoreBuild/build -f makefile.shade "$@" diff --git a/global.json b/global.json new file mode 100644 index 0000000000..983ba0401e --- /dev/null +++ b/global.json @@ -0,0 +1,3 @@ +{ + "projects": ["src"] +} diff --git a/makefile.shade b/makefile.shade new file mode 100644 index 0000000000..d5e473d558 --- /dev/null +++ b/makefile.shade @@ -0,0 +1,10 @@ + +var VERSION='0.1' +var FULL_VERSION='0.1' +var AUTHORS='Microsoft Open Technologies, Inc.' + +use-standard-lifecycle +k-standard-goals + +#xml-docs-test .clean .build-compile description='Check generated XML documentation files for errors' target='package' + k-xml-docs-test diff --git a/src/Microsoft.AspNet.Html/HtmlContentBuilder.cs b/src/Microsoft.AspNet.Html/HtmlContentBuilder.cs new file mode 100644 index 0000000000..34e59d3318 --- /dev/null +++ b/src/Microsoft.AspNet.Html/HtmlContentBuilder.cs @@ -0,0 +1,138 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Encodings.Web; + +namespace Microsoft.AspNet.Html +{ + /// + /// An implementation using an in memory list. + /// + public class HtmlContentBuilder : IHtmlContentBuilder + { + /// + /// Creates a new . + /// + public HtmlContentBuilder() + : this(new List()) + { + } + + /// + /// Creates a new with the given initial capacity. + /// + /// The initial capacity of the backing store. + public HtmlContentBuilder(int capacity) + : this(new List(capacity)) + { + } + + /// + /// Creates a new with the given list of entries. + /// + /// + /// The list of entries. The will use this list without making a copy. + /// + public HtmlContentBuilder(IList entries) + { + if (entries == null) + { + throw new ArgumentNullException(nameof(entries)); + } + + Entries = entries; + } + + // This is not List because that would lead to wrapping all strings to IHtmlContent + // which is not space performant. + // + // In general unencoded strings are added here. We're optimizing for that case, and allocating + // a wrapper when encoded strings are used. + // + // internal for testing. + internal IList Entries { get; } + + /// + public IHtmlContentBuilder Append(string unencoded) + { + if (!string.IsNullOrEmpty(unencoded)) + { + Entries.Add(unencoded); + } + + return this; + } + + /// + public IHtmlContentBuilder Append(IHtmlContent htmlContent) + { + if (htmlContent == null) + { + return this; + } + + Entries.Add(htmlContent); + return this; + } + + /// + public IHtmlContentBuilder AppendHtml(string encoded) + { + if (!string.IsNullOrEmpty(encoded)) + { + Entries.Add(new HtmlEncodedString(encoded)); + } + + return this; + } + + /// + public IHtmlContentBuilder Clear() + { + Entries.Clear(); + return this; + } + + /// + public void WriteTo(TextWriter writer, HtmlEncoder encoder) + { + if (writer == null) + { + throw new ArgumentNullException(nameof(writer)); + } + + if (encoder == null) + { + throw new ArgumentNullException(nameof(encoder)); + } + + for (var i = 0; i < Entries.Count; i++) + { + var entry = Entries[i]; + + var entryAsString = entry as string; + if (entryAsString != null) + { + encoder.Encode(writer, entryAsString); + } + else + { + // Only string, IHtmlContent values can be added to the buffer. + ((IHtmlContent)entry).WriteTo(writer, encoder); + } + } + } + + private string DebuggerToString() + { + using (var writer = new StringWriter()) + { + WriteTo(writer, HtmlEncoder.Default); + return writer.ToString(); + } + } + } +} diff --git a/src/Microsoft.AspNet.Html/HtmlContentBuilderExtensions.cs b/src/Microsoft.AspNet.Html/HtmlContentBuilderExtensions.cs new file mode 100644 index 0000000000..eabfafbd12 --- /dev/null +++ b/src/Microsoft.AspNet.Html/HtmlContentBuilderExtensions.cs @@ -0,0 +1,324 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Text.Encodings.Web; + +namespace Microsoft.AspNet.Html +{ + /// + /// Extension methods for . + /// + public static class HtmlContentBuilderExtensions + { + /// + /// Appends the specified to the existing content after replacing each format + /// item with the HTML encoded representation of the corresponding item in the + /// array. + /// + /// The . + /// + /// The composite format (see http://msdn.microsoft.com/en-us/library/txafckwd.aspx). + /// The format string is assumed to be HTML encoded as-provided, and no further encoding will be performed. + /// + /// + /// The object array to format. Each element in the array will be formatted and then HTML encoded. + /// + /// A reference to this instance after the append operation has completed. + public static IHtmlContentBuilder AppendFormat( + this IHtmlContentBuilder builder, + string format, + params object[] args) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (format == null) + { + throw new ArgumentNullException(nameof(format)); + } + + if (args == null) + { + throw new ArgumentNullException(nameof(args)); + } + + builder.Append(new HtmlFormatString(format, args)); + return builder; + } + + /// + /// Appends the specified to the existing content with information from the + /// after replacing each format item with the HTML encoded + /// representation of the corresponding item in the array. + /// + /// The . + /// An object that supplies culture-specific formatting information. + /// + /// The composite format (see http://msdn.microsoft.com/en-us/library/txafckwd.aspx). + /// The format string is assumed to be HTML encoded as-provided, and no further encoding will be performed. + /// + /// + /// The object array to format. Each element in the array will be formatted and then HTML encoded. + /// + /// A reference to this instance after the append operation has completed. + public static IHtmlContentBuilder AppendFormat( + this IHtmlContentBuilder builder, + IFormatProvider formatProvider, + string format, + params object[] args) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (format == null) + { + throw new ArgumentNullException(nameof(format)); + } + + if (args == null) + { + throw new ArgumentNullException(nameof(args)); + } + + builder.Append(new HtmlFormatString(formatProvider, format, args)); + return builder; + } + + /// + /// Appends an . + /// + /// The . + /// The . + public static IHtmlContentBuilder AppendLine(this IHtmlContentBuilder builder) + { + builder.Append(HtmlEncodedString.NewLine); + return builder; + } + + /// + /// Appends an after appending the value. + /// The value is treated as unencoded as-provided, and will be HTML encoded before writing to output. + /// + /// The . + /// The to append. + /// The . + public static IHtmlContentBuilder AppendLine(this IHtmlContentBuilder builder, string unencoded) + { + builder.Append(unencoded); + builder.Append(HtmlEncodedString.NewLine); + return builder; + } + + /// + /// Appends an after appending the value. + /// + /// The . + /// The to append. + /// The . + public static IHtmlContentBuilder AppendLine(this IHtmlContentBuilder builder, IHtmlContent content) + { + builder.Append(content); + builder.Append(HtmlEncodedString.NewLine); + return builder; + } + + /// + /// Appends an after appending the value. + /// The value is treated as HTML encoded as-provided, and no further encoding will be performed. + /// + /// The . + /// The HTML encoded to append. + /// The . + public static IHtmlContentBuilder AppendHtmlLine(this IHtmlContentBuilder builder, string encoded) + { + builder.AppendHtml(encoded); + builder.Append(HtmlEncodedString.NewLine); + return builder; + } + + /// + /// Sets the content to the value. The value is treated as unencoded as-provided, + /// and will be HTML encoded before writing to output. + /// + /// The . + /// The value that replaces the content. + /// The . + public static IHtmlContentBuilder SetContent(this IHtmlContentBuilder builder, string unencoded) + { + builder.Clear(); + builder.Append(unencoded); + return builder; + } + + /// + /// Sets the content to the value. + /// + /// The . + /// The value that replaces the content. + /// The . + public static IHtmlContentBuilder SetContent(this IHtmlContentBuilder builder, IHtmlContent content) + { + builder.Clear(); + builder.Append(content); + return builder; + } + + /// + /// Sets the content to the value. The value is treated as HTML encoded as-provided, and + /// no further encoding will be performed. + /// + /// The . + /// The HTML encoded that replaces the content. + /// The . + public static IHtmlContentBuilder SetHtmlContent(this IHtmlContentBuilder builder, string encoded) + { + builder.Clear(); + builder.AppendHtml(encoded); + return builder; + } + + [DebuggerDisplay("{DebuggerToString()}")] + private class HtmlFormatString : IHtmlContent + { + private readonly IFormatProvider _formatProvider; + private readonly string _format; + private readonly object[] _args; + + public HtmlFormatString(string format, object[] args) + : this(null, format, args) + { + } + + public HtmlFormatString(IFormatProvider formatProvider, string format, object[] args) + { + Debug.Assert(format != null); + Debug.Assert(args != null); + + _formatProvider = formatProvider ?? CultureInfo.CurrentCulture; + _format = format; + _args = args; + } + + public void WriteTo(TextWriter writer, HtmlEncoder encoder) + { + if (writer == null) + { + throw new ArgumentNullException(nameof(writer)); + } + + if (encoder == null) + { + throw new ArgumentNullException(nameof(encoder)); + } + + var formatProvider = new EncodingFormatProvider(_formatProvider, encoder); + writer.Write(string.Format(formatProvider, _format, _args)); + } + + private string DebuggerToString() + { + using (var writer = new StringWriter()) + { + WriteTo(writer, HtmlEncoder.Default); + return writer.ToString(); + } + } + } + + // This class implements Html encoding via an ICustomFormatter. Passing an instance of this + // class into a string.Format method or anything similar will evaluate arguments implementing + // IHtmlContent without HTML encoding them, and will give other arguments the standard + // composite format string treatment, and then HTML encode the result. + // + // Plenty of examples of ICustomFormatter and the interactions with string.Format here: + // https://msdn.microsoft.com/en-us/library/system.string.format(v=vs.110).aspx#Format6_Example + private class EncodingFormatProvider : IFormatProvider, ICustomFormatter + { + private readonly HtmlEncoder _encoder; + private readonly IFormatProvider _formatProvider; + + public EncodingFormatProvider(IFormatProvider formatProvider, HtmlEncoder encoder) + { + Debug.Assert(formatProvider != null); + Debug.Assert(encoder != null); + + _formatProvider = formatProvider; + _encoder = encoder; + } + + public string Format(string format, object arg, IFormatProvider formatProvider) + { + // This is the case we need to special case. We trust the IHtmlContent instance to do the + // right thing with encoding. + var htmlContent = arg as IHtmlContent; + if (htmlContent != null) + { + using (var writer = new StringWriter()) + { + htmlContent.WriteTo(writer, _encoder); + return writer.ToString(); + } + } + + // If we get here then 'arg' is not an IHtmlContent, and we want to handle it the way a normal + // string.Format would work, but then HTML encode the result. + // + // First check for an ICustomFormatter - if the IFormatProvider is a CultureInfo, then it's likely + // that ICustomFormatter will be null. + var customFormatter = (ICustomFormatter)_formatProvider.GetFormat(typeof(ICustomFormatter)); + if (customFormatter != null) + { + var result = customFormatter.Format(format, arg, _formatProvider); + if (result != null) + { + return _encoder.Encode(result); + } + } + + // Next check if 'arg' is an IFormattable (DateTime is an example). + // + // An IFormattable will likely call back into the IFormatterProvider and ask for more information + // about how to format itself. This is the typical case when IFormatterProvider is a CultureInfo. + var formattable = arg as IFormattable; + if (formattable != null) + { + var result = formattable.ToString(format, _formatProvider); + if (result != null) + { + return _encoder.Encode(result); + } + } + + // If we get here then there's nothing really smart left to try. + if (arg != null) + { + var result = arg.ToString(); + if (result != null) + { + return _encoder.Encode(result); + } + } + + return string.Empty; + } + + public object GetFormat(Type formatType) + { + if (formatType == typeof(ICustomFormatter)) + { + return this; + } + + return null; + } + } + } +} diff --git a/src/Microsoft.AspNet.Html/HtmlEncodedString.cs b/src/Microsoft.AspNet.Html/HtmlEncodedString.cs new file mode 100644 index 0000000000..348588800f --- /dev/null +++ b/src/Microsoft.AspNet.Html/HtmlEncodedString.cs @@ -0,0 +1,49 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.IO; +using System.Text.Encodings.Web; + +namespace Microsoft.AspNet.Html +{ + /// + /// An impelementation that wraps an HTML encoded . + /// + [DebuggerDisplay("{DebuggerToString()}")] + public class HtmlEncodedString : IHtmlContent + { + /// + /// An instance for . + /// + public static readonly IHtmlContent NewLine = new HtmlEncodedString(Environment.NewLine); + + private readonly string _value; + + /// + /// Creates a new . + /// + /// The HTML encoded value. + public HtmlEncodedString(string value) + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + _value = value; + } + + /// + public void WriteTo(TextWriter writer, HtmlEncoder encoder) + { + writer.Write(_value); + } + + private string DebuggerToString() + { + return _value; + } + } +} diff --git a/src/Microsoft.AspNet.Html/HtmlTextWriter.cs b/src/Microsoft.AspNet.Html/HtmlTextWriter.cs new file mode 100644 index 0000000000..56633f527d --- /dev/null +++ b/src/Microsoft.AspNet.Html/HtmlTextWriter.cs @@ -0,0 +1,49 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; + +namespace Microsoft.AspNet.Html +{ + /// + /// A which supports special processing of . + /// + public abstract class HtmlTextWriter : TextWriter + { + /// + /// Writes an value. + /// + /// The value. + public abstract void Write(IHtmlContent value); + + /// + public override void Write(object value) + { + var htmlContent = value as IHtmlContent; + if (htmlContent == null) + { + base.Write(value); + } + else + { + Write(htmlContent); + } + } + + /// + public override void WriteLine(object value) + { + var htmlContent = value as IHtmlContent; + if (htmlContent == null) + { + base.Write(value); + } + else + { + Write(htmlContent); + } + + base.WriteLine(); + } + } +} diff --git a/src/Microsoft.AspNet.Html/IHtmlContent.cs b/src/Microsoft.AspNet.Html/IHtmlContent.cs new file mode 100644 index 0000000000..0e21889d54 --- /dev/null +++ b/src/Microsoft.AspNet.Html/IHtmlContent.cs @@ -0,0 +1,22 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; +using System.Text.Encodings.Web; + +namespace Microsoft.AspNet.Html +{ + /// + /// HTML content which can be written to a TextWriter. + /// + public interface IHtmlContent + { + /// + /// Writes the content by encoding it with the specified + /// to the specified . + /// + /// The to which the content is written. + /// The which encodes the content to be written. + void WriteTo(TextWriter writer, HtmlEncoder encoder); + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Html/IHtmlContentBuilder.cs b/src/Microsoft.AspNet.Html/IHtmlContentBuilder.cs new file mode 100644 index 0000000000..de4b9ebd90 --- /dev/null +++ b/src/Microsoft.AspNet.Html/IHtmlContentBuilder.cs @@ -0,0 +1,40 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.AspNet.Html +{ + /// + /// A builder for HTML content. + /// + public interface IHtmlContentBuilder : IHtmlContent + { + /// + /// Appends an instance. + /// + /// The to append. + /// The . + IHtmlContentBuilder Append(IHtmlContent content); + + /// + /// Appends a value. The value is treated as unencoded as-provided, and will be HTML + /// encoded before writing to output. + /// + /// The to append. + /// The . + IHtmlContentBuilder Append(string unencoded); + + /// + /// Appends an HTML encoded value. The value is treated as HTML encoded as-provided, and + /// no further encoding will be performed. + /// + /// The HTML encoded to append. + /// The . + IHtmlContentBuilder AppendHtml(string encoded); + + /// + /// Clears the content. + /// + /// The . + IHtmlContentBuilder Clear(); + } +} diff --git a/src/Microsoft.AspNet.Html/Microsoft.AspNet.Html.xproj b/src/Microsoft.AspNet.Html/Microsoft.AspNet.Html.xproj new file mode 100644 index 0000000000..564c800504 --- /dev/null +++ b/src/Microsoft.AspNet.Html/Microsoft.AspNet.Html.xproj @@ -0,0 +1,19 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 68a28e4a-3ade-4187-9625-4ff185887cb3 + Microsoft.AspNet.Html.Abstractions + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + \ No newline at end of file diff --git a/src/Microsoft.AspNet.Html/Properties/AssemblyInfo.cs b/src/Microsoft.AspNet.Html/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..1951d644af --- /dev/null +++ b/src/Microsoft.AspNet.Html/Properties/AssemblyInfo.cs @@ -0,0 +1,10 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; + +[assembly: AssemblyMetadata("Serviceable", "True")] +[assembly: NeutralResourcesLanguage("en-us")] +[assembly: InternalsVisibleTo("Microsoft.AspNet.Html.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] \ No newline at end of file diff --git a/src/Microsoft.AspNet.Html/project.json b/src/Microsoft.AspNet.Html/project.json new file mode 100644 index 0000000000..55cc30d9b1 --- /dev/null +++ b/src/Microsoft.AspNet.Html/project.json @@ -0,0 +1,29 @@ +{ + "version": "1.0.0-*", + "description": "ASP.NET 5 HTML content interface.", + "repository": { + "type": "git", + "url": "git://github.com/aspnet/htmlabstractions" + }, + "compilationOptions": { + "warningsAsErrors": true, + "keyFile": "../../tools/Key.snk" + }, + "dependencies": { + "System.Text.Encodings.Web": "4.0.0-*" + }, + "frameworks": { + "net451": { + "frameworkAssemblies": { + "System.IO": "", + "System.Runtime": "" + } + }, + "dotnet5.4": { + "dependencies": { + "System.Collections": "4.0.11-*", + "System.Resources.ResourceManager": "4.0.1-*" + } + } + } +} diff --git a/test/Microsoft.AspNet.Html.Test/HtmlContentBuilderExtensionsTest.cs b/test/Microsoft.AspNet.Html.Test/HtmlContentBuilderExtensionsTest.cs new file mode 100644 index 0000000000..6253bf9be3 --- /dev/null +++ b/test/Microsoft.AspNet.Html.Test/HtmlContentBuilderExtensionsTest.cs @@ -0,0 +1,436 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Text.Encodings.Web; +using Microsoft.AspNet.Testing; +using Microsoft.Extensions.WebEncoders.Testing; +using Xunit; + +namespace Microsoft.AspNet.Html.Test +{ + public class HtmlContentBuilderExtensionsTest + { + [Fact] + public void Builder_AppendLine_Empty() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + + // Act + builder.AppendLine(); + + // Assert + Assert.Collection( + builder.Entries, + entry => Assert.Equal(Environment.NewLine, HtmlContentToString(entry))); + } + + [Fact] + public void Builder_AppendLine_String() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + + // Act + builder.AppendLine("Hi"); + + // Assert + Assert.Collection( + builder.Entries, + entry => Assert.Equal("Hi", Assert.IsType(entry).Value), + entry => Assert.Equal(Environment.NewLine, HtmlContentToString(entry))); + } + + [Fact] + public void Builder_AppendLine_IHtmlContent() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + var content = new OtherHtmlContent("Hi"); + + // Act + builder.AppendLine(content); + + // Assert + Assert.Collection( + builder.Entries, + entry => Assert.Same(content, entry), + entry => Assert.Equal(Environment.NewLine, HtmlContentToString(entry))); + } + + [Fact] + public void Builder_AppendHtmlLine_String() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + + // Act + builder.AppendHtmlLine("Hi"); + + // Assert + Assert.Collection( + builder.Entries, + entry => Assert.Equal("Hi", Assert.IsType(entry).Value), + entry => Assert.Equal(Environment.NewLine, HtmlContentToString(entry))); + } + + [Fact] + public void Builder_SetContent_String() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + builder.Append("Existing Content. Will be Cleared."); + + // Act + builder.SetContent("Hi"); + + // Assert + Assert.Collection( + builder.Entries, + entry => Assert.Equal("Hi", Assert.IsType(entry).Value)); + } + + [Fact] + public void Builder_SetContent_IHtmlContent() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + builder.Append("Existing Content. Will be Cleared."); + + var content = new OtherHtmlContent("Hi"); + + // Act + builder.SetContent(content); + + // Assert + Assert.Collection( + builder.Entries, + entry => Assert.Same(content, entry)); + } + + [Fact] + public void Builder_SetHtmlContent_String() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + builder.Append("Existing Content. Will be Cleared."); + + // Act + builder.SetHtmlContent("Hi"); + + // Assert + Assert.Collection( + builder.Entries, + entry => Assert.Equal("Hi", Assert.IsType(entry).Value)); + } + + [Fact] + public void Builder_AppendFormat() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + + // Act + builder.AppendFormat("{0} {1} {2} {3}!", "First", "Second", "Third", "Fourth"); + + // Assert + Assert.Equal( + "HtmlEncode[[First]] HtmlEncode[[Second]] HtmlEncode[[Third]] HtmlEncode[[Fourth]]!", + HtmlContentToString(builder)); + } + + [Fact] + public void Builder_AppendFormat_HtmlContent() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + + // Act + builder.AppendFormat("{0}!", new EncodedString("First")); + + // Assert + Assert.Equal( + "First!", + HtmlContentToString(builder)); + } + + [Fact] + public void Builder_AppendFormatContent_With1Argument() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + + // Act + builder.AppendFormat("0x{0:X} - hex equivalent for 50.", 50); + + // Assert + Assert.Equal( + "0xHtmlEncode[[32]] - hex equivalent for 50.", + HtmlContentToString(builder)); + } + + [Fact] + public void Builder_AppendFormatContent_With2Arguments() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + + // Act + builder.AppendFormat("0x{0:X} - hex equivalent for {1}.", 50, 50); + + // Assert + Assert.Equal( + "0xHtmlEncode[[32]] - hex equivalent for HtmlEncode[[50]].", + HtmlContentToString(builder)); + } + + [Fact] + public void Builder_AppendFormatContent_With3Arguments() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + + // Act + builder.AppendFormat("0x{0:X} - {1} equivalent for {2}.", 50, "hex", 50); + + // Assert + Assert.Equal( + "0xHtmlEncode[[32]] - HtmlEncode[[hex]] equivalent for HtmlEncode[[50]].", + HtmlContentToString(builder)); + } + + [Fact] + public void Builder_AppendFormat_WithAlignmentComponent() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + + // Act + builder.AppendFormat("{0, -25} World!", "Hello"); + + // Assert + Assert.Equal( + "HtmlEncode[[Hello]] World!", + HtmlContentToString(builder)); + } + + [Fact] + public void Builder_AppendFormat_WithFormatStringComponent() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + + // Act + builder.AppendFormat("0x{0:X}", 50); + + // Assert + Assert.Equal("0xHtmlEncode[[32]]", HtmlContentToString(builder)); + } + + [Fact] + public void Builder_AppendFormat_WithCulture() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + + // Act + builder.AppendFormat( + CultureInfo.InvariantCulture, + "Numbers in InvariantCulture - {0, -5:N} {1} {2} {3}!", + 1.1, + 2.98, + 145.82, + 32.86); + + // Assert + Assert.Equal( + "Numbers in InvariantCulture - HtmlEncode[[1.10]] HtmlEncode[[2.98]] " + + "HtmlEncode[[145.82]] HtmlEncode[[32.86]]!", + HtmlContentToString(builder)); + } + + [Fact] + public void Builder_AppendFormat_WithCulture_1Argument() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + + // Act + builder.AppendFormat( + CultureInfo.InvariantCulture, + "Numbers in InvariantCulture - {0:N}!", + 1.1); + + // Assert + Assert.Equal( + "Numbers in InvariantCulture - HtmlEncode[[1.10]]!", + HtmlContentToString(builder)); + } + + [Fact] + public void Builder_AppendFormat_WithCulture_2Arguments() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + + // Act + builder.AppendFormat( + CultureInfo.InvariantCulture, + "Numbers in InvariantCulture - {0:N} {1}!", + 1.1, + 2.98); + + // Assert + Assert.Equal( + "Numbers in InvariantCulture - HtmlEncode[[1.10]] HtmlEncode[[2.98]]!", + HtmlContentToString(builder)); + } + + [Fact] + public void Builder_AppendFormat_WithCulture_3Arguments() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + + // Act + builder.AppendFormat( + CultureInfo.InvariantCulture, + "Numbers in InvariantCulture - {0:N} {1} {2}!", + 1.1, + 2.98, + 3.12); + + // Assert + Assert.Equal( + "Numbers in InvariantCulture - HtmlEncode[[1.10]] HtmlEncode[[2.98]] HtmlEncode[[3.12]]!", + HtmlContentToString(builder)); + } + + [Fact] + public void Builder_AppendFormat_WithDifferentCulture() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + var culture = new CultureInfo("fr-FR"); + + // Act + builder.AppendFormat(culture, "{0} in french!", 1.21); + + // Assert + Assert.Equal( + "HtmlEncode[[1,21]] in french!", + HtmlContentToString(builder)); + } + + [Fact] + [ReplaceCulture("de-DE", "de-DE")] + public void Builder_AppendFormat_WithDifferentCurrentCulture() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + + // Act + builder.AppendFormat(CultureInfo.CurrentCulture, "{0:D}", DateTime.Parse("01/02/2015")); + + // Assert + Assert.Equal( + "HtmlEncode[[Sonntag, 1. Februar 2015]]", + HtmlContentToString(builder)); + } + + private static string HtmlContentToString(IHtmlContent content) + { + using (var writer = new StringWriter()) + { + content.WriteTo(writer, new HtmlTestEncoder()); + return writer.ToString(); + } + } + + private class TestHtmlContentBuilder : IHtmlContentBuilder + { + public List Entries { get; } = new List(); + + public IHtmlContentBuilder Append(string unencoded) + { + Entries.Add(new UnencodedString(unencoded)); + return this; + } + + public IHtmlContentBuilder Append(IHtmlContent content) + { + Entries.Add(content); + return this; + } + + public IHtmlContentBuilder AppendHtml(string encoded) + { + Entries.Add(new EncodedString(encoded)); + return this; + } + + public IHtmlContentBuilder Clear() + { + Entries.Clear(); + return this; + } + + public void WriteTo(TextWriter writer, HtmlEncoder encoder) + { + foreach (var entry in Entries) + { + entry.WriteTo(writer, encoder); + } + } + } + + private class EncodedString : IHtmlContent + { + public EncodedString(string value) + { + Value = value; + } + + public string Value { get; } + + public void WriteTo(TextWriter writer, HtmlEncoder encoder) + { + writer.Write(Value); + } + } + + private class UnencodedString : IHtmlContent + { + public UnencodedString(string value) + { + Value = value; + } + + public string Value { get; } + + public void WriteTo(TextWriter writer, HtmlEncoder encoder) + { + encoder.Encode(writer, Value); + } + } + + private class OtherHtmlContent : IHtmlContent + { + public OtherHtmlContent(string value) + { + Value = value; + } + + public string Value { get; } + + public void WriteTo(TextWriter writer, HtmlEncoder encoder) + { + throw new NotImplementedException(); + } + } + } +} diff --git a/test/Microsoft.AspNet.Html.Test/HtmlContentBuilderTest.cs b/test/Microsoft.AspNet.Html.Test/HtmlContentBuilderTest.cs new file mode 100644 index 0000000000..4eee28e219 --- /dev/null +++ b/test/Microsoft.AspNet.Html.Test/HtmlContentBuilderTest.cs @@ -0,0 +1,145 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; +using System.Text.Encodings.Web; +using Microsoft.AspNet.Html; +using Microsoft.Extensions.WebEncoders.Testing; +using Xunit; + +namespace Microsoft.Extensions.Internal +{ + public class HtmlContentBuilderTest + { + [Fact] + public void AppendString_AppendsAString() + { + // Arrange + var content = new HtmlContentBuilder(); + + // Act + content.Append("Hello"); + + // Assert + var result = Assert.Single(content.Entries); + Assert.IsType(result); + } + + [Fact] + public void AppendString_WrittenAsEncoded() + { + // Arrange + var content = new HtmlContentBuilder(); + content.Append("Hello"); + + var writer = new StringWriter(); + + // Act + content.WriteTo(writer, new HtmlTestEncoder()); + + // Assert + Assert.Equal("HtmlEncode[[Hello]]", writer.ToString()); + } + + [Fact] + public void AppendHtml_DoesNotGetWrittenAsEncoded() + { + // Arrange + var content = new HtmlContentBuilder(); + content.AppendHtml("Hello"); + + var writer = new StringWriter(); + + // Act + content.WriteTo(writer, new HtmlTestEncoder()); + + // Assert + Assert.Equal("Hello", writer.ToString()); + } + + [Fact] + public void AppendIHtmlContent_AppendsAsIs() + { + // Arrange + var content = new HtmlContentBuilder(); + var writer = new StringWriter(); + + // Act + content.Append(new TestHtmlContent("Hello")); + + // Assert + var result = Assert.Single(content.Entries); + var testHtmlContent = Assert.IsType(result); + testHtmlContent.WriteTo(writer, new HtmlTestEncoder()); + Assert.Equal("Written from TestHtmlContent: Hello", writer.ToString()); + } + + [Fact] + public void CanAppendMultipleItems() + { + // Arrange + var content = new HtmlContentBuilder(); + + // Act + content.Append(new TestHtmlContent("hello")); + content.Append("Test"); + + // Assert + Assert.Equal(2, content.Entries.Count); + Assert.Equal("Written from TestHtmlContent: hello", content.Entries[0].ToString()); + Assert.Equal("Test", content.Entries[1]); + } + + [Fact] + public void Clear_DeletesAllItems() + { + // Arrange + var content = new HtmlContentBuilder(); + content.Append(new TestHtmlContent("hello")); + content.Append("Test"); + + // Act + content.Clear(); + + // Assert + Assert.Equal(0, content.Entries.Count); + } + + [Fact] + public void WriteTo_WritesAllItems() + { + // Arrange + var content = new HtmlContentBuilder(); + var writer = new StringWriter(); + content.Append(new TestHtmlContent("Hello")); + content.Append("Test"); + + // Act + content.WriteTo(writer, new HtmlTestEncoder()); + + // Assert + Assert.Equal(2, content.Entries.Count); + Assert.Equal("Written from TestHtmlContent: HelloHtmlEncode[[Test]]", writer.ToString()); + } + + private class TestHtmlContent : IHtmlContent + { + private string _content; + + public TestHtmlContent(string content) + { + _content = content; + } + + public void WriteTo(TextWriter writer, HtmlEncoder encoder) + { + writer.Write(ToString()); + } + + public override string ToString() + { + return "Written from TestHtmlContent: " + _content; + } + } + } +} diff --git a/test/Microsoft.AspNet.Html.Test/Microsoft.AspNet.Html.Test.xproj b/test/Microsoft.AspNet.Html.Test/Microsoft.AspNet.Html.Test.xproj new file mode 100644 index 0000000000..4a03567677 --- /dev/null +++ b/test/Microsoft.AspNet.Html.Test/Microsoft.AspNet.Html.Test.xproj @@ -0,0 +1,21 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 2d187b88-94bd-4a39-ac97-f8f8b9363301 + Microsoft.AspNet.Html.Abstractions.Test + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + 2.0 + + + + + + \ No newline at end of file diff --git a/test/Microsoft.AspNet.Html.Test/project.json b/test/Microsoft.AspNet.Html.Test/project.json new file mode 100644 index 0000000000..f5ea4ca7e6 --- /dev/null +++ b/test/Microsoft.AspNet.Html.Test/project.json @@ -0,0 +1,19 @@ +{ + "compilationOptions": { + "warningsAsErrors": true, + "keyFile": "../../tools/Key.snk" + }, + "dependencies": { + "Microsoft.AspNet.Html": "1.0.0-*", + "Microsoft.AspNet.Testing": "1.0.0-*", + "Microsoft.Extensions.WebEncoders": "1.0.0-*", + "xunit.runner.aspnet": "2.0.0-aspnet-*" + }, + "commands": { + "test": "xunit.runner.aspnet" + }, + "frameworks": { + "dnx451": { }, + "dnxcore50": { } + } +} diff --git a/tools/Key.snk b/tools/Key.snk new file mode 100644 index 0000000000000000000000000000000000000000..e10e4889c125d3120cd9e81582243d70f7cbb806 GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098=Iw=HCsnz~#iVhm& zj%TU(_THUee?3yHBjk$37ysB?i5#7WD$={H zV4B!OxRPrb|8)HPg~A}8P>^=#y<)56#=E&NzcjOtPK~<4n6GHt=K$ro*T(lhby_@U zEk(hLzk1H)0yXj{A_5>fk-TgNoP|q6(tP2xo8zt8i%212CWM#AeCd?`hS|4~L({h~Moo(~vy&3Z z1uI}`fd^*>o=rwbAGymj6RM^pZm(*Kfhs+Y1#`-2JPWZMK8@;ZWCk2+9bX4YP);~fj-BU*R zQPvWv$89!{Rl9wM+zR>_TSkn^voYxA?2G iKnV#iZ6Ah`K>b=@=IjYJXrxL124zR(38)nxe+&q_$QXwJ literal 0 HcmV?d00001 From 1b0e2e50e1860ab663233c607662bdcb8a0c28f6 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Wed, 2 Dec 2015 09:15:16 -0800 Subject: [PATCH 0046/1029] Restore previous package name: `Microsoft.AspNet.Html.Abstractions` nit: add a couple of solution items --- HtmlAbstractions.sln | 12 +++++++++--- .../HtmlContentBuilder.cs | 0 .../HtmlContentBuilderExtensions.cs | 0 .../HtmlEncodedString.cs | 0 .../HtmlTextWriter.cs | 0 .../IHtmlContent.cs | 0 .../IHtmlContentBuilder.cs | 0 .../Microsoft.AspNet.Html.Abstractions.xproj} | 0 .../Properties/AssemblyInfo.cs | 10 ++++++++++ .../project.json | 0 src/Microsoft.AspNet.Html/Properties/AssemblyInfo.cs | 10 ---------- .../HtmlContentBuilderExtensionsTest.cs | 0 .../HtmlContentBuilderTest.cs | 0 .../Microsoft.AspNet.Html.Abstractions.Test.xproj} | 0 .../project.json | 2 +- 15 files changed, 20 insertions(+), 14 deletions(-) rename src/{Microsoft.AspNet.Html => Microsoft.AspNet.Html.Abstractions}/HtmlContentBuilder.cs (100%) rename src/{Microsoft.AspNet.Html => Microsoft.AspNet.Html.Abstractions}/HtmlContentBuilderExtensions.cs (100%) rename src/{Microsoft.AspNet.Html => Microsoft.AspNet.Html.Abstractions}/HtmlEncodedString.cs (100%) rename src/{Microsoft.AspNet.Html => Microsoft.AspNet.Html.Abstractions}/HtmlTextWriter.cs (100%) rename src/{Microsoft.AspNet.Html => Microsoft.AspNet.Html.Abstractions}/IHtmlContent.cs (100%) rename src/{Microsoft.AspNet.Html => Microsoft.AspNet.Html.Abstractions}/IHtmlContentBuilder.cs (100%) rename src/{Microsoft.AspNet.Html/Microsoft.AspNet.Html.xproj => Microsoft.AspNet.Html.Abstractions/Microsoft.AspNet.Html.Abstractions.xproj} (100%) create mode 100644 src/Microsoft.AspNet.Html.Abstractions/Properties/AssemblyInfo.cs rename src/{Microsoft.AspNet.Html => Microsoft.AspNet.Html.Abstractions}/project.json (100%) delete mode 100644 src/Microsoft.AspNet.Html/Properties/AssemblyInfo.cs rename test/{Microsoft.AspNet.Html.Test => Microsoft.AspNet.Html.Abstractions.Test}/HtmlContentBuilderExtensionsTest.cs (100%) rename test/{Microsoft.AspNet.Html.Test => Microsoft.AspNet.Html.Abstractions.Test}/HtmlContentBuilderTest.cs (100%) rename test/{Microsoft.AspNet.Html.Test/Microsoft.AspNet.Html.Test.xproj => Microsoft.AspNet.Html.Abstractions.Test/Microsoft.AspNet.Html.Abstractions.Test.xproj} (100%) rename test/{Microsoft.AspNet.Html.Test => Microsoft.AspNet.Html.Abstractions.Test}/project.json (87%) diff --git a/HtmlAbstractions.sln b/HtmlAbstractions.sln index 1d1f5118f3..805c4daa7a 100644 --- a/HtmlAbstractions.sln +++ b/HtmlAbstractions.sln @@ -1,14 +1,20 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.24711.0 +VisualStudioVersion = 14.0.24720.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A5A15F1C-885A-452A-A731-B0173DDBD913}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F31FF137-390C-49BF-A3BD-7C6ED3597C21}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Html", "src\Microsoft.AspNet.Html.Abstractions\Microsoft.AspNet.Html.xproj", "{68A28E4A-3ADE-4187-9625-4FF185887CB3}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Html.Abstractions", "src\Microsoft.AspNet.Html.Abstractions\Microsoft.AspNet.Html.Abstractions.xproj", "{68A28E4A-3ADE-4187-9625-4FF185887CB3}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Html.Test", "test\Microsoft.AspNet.Html.Abstractions.Test\Microsoft.AspNet.Html.Test.xproj", "{2D187B88-94BD-4A39-AC97-F8F8B9363301}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Html.Abstractions.Test", "test\Microsoft.AspNet.Html.Abstractions.Test\Microsoft.AspNet.Html.Abstractions.Test.xproj", "{2D187B88-94BD-4A39-AC97-F8F8B9363301}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B4962A29-BE69-4A18-9B4F-B803EEE31EAA}" + ProjectSection(SolutionItems) = preProject + global.json = global.json + NuGetPackageVerifier.json = NuGetPackageVerifier.json + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/Microsoft.AspNet.Html/HtmlContentBuilder.cs b/src/Microsoft.AspNet.Html.Abstractions/HtmlContentBuilder.cs similarity index 100% rename from src/Microsoft.AspNet.Html/HtmlContentBuilder.cs rename to src/Microsoft.AspNet.Html.Abstractions/HtmlContentBuilder.cs diff --git a/src/Microsoft.AspNet.Html/HtmlContentBuilderExtensions.cs b/src/Microsoft.AspNet.Html.Abstractions/HtmlContentBuilderExtensions.cs similarity index 100% rename from src/Microsoft.AspNet.Html/HtmlContentBuilderExtensions.cs rename to src/Microsoft.AspNet.Html.Abstractions/HtmlContentBuilderExtensions.cs diff --git a/src/Microsoft.AspNet.Html/HtmlEncodedString.cs b/src/Microsoft.AspNet.Html.Abstractions/HtmlEncodedString.cs similarity index 100% rename from src/Microsoft.AspNet.Html/HtmlEncodedString.cs rename to src/Microsoft.AspNet.Html.Abstractions/HtmlEncodedString.cs diff --git a/src/Microsoft.AspNet.Html/HtmlTextWriter.cs b/src/Microsoft.AspNet.Html.Abstractions/HtmlTextWriter.cs similarity index 100% rename from src/Microsoft.AspNet.Html/HtmlTextWriter.cs rename to src/Microsoft.AspNet.Html.Abstractions/HtmlTextWriter.cs diff --git a/src/Microsoft.AspNet.Html/IHtmlContent.cs b/src/Microsoft.AspNet.Html.Abstractions/IHtmlContent.cs similarity index 100% rename from src/Microsoft.AspNet.Html/IHtmlContent.cs rename to src/Microsoft.AspNet.Html.Abstractions/IHtmlContent.cs diff --git a/src/Microsoft.AspNet.Html/IHtmlContentBuilder.cs b/src/Microsoft.AspNet.Html.Abstractions/IHtmlContentBuilder.cs similarity index 100% rename from src/Microsoft.AspNet.Html/IHtmlContentBuilder.cs rename to src/Microsoft.AspNet.Html.Abstractions/IHtmlContentBuilder.cs diff --git a/src/Microsoft.AspNet.Html/Microsoft.AspNet.Html.xproj b/src/Microsoft.AspNet.Html.Abstractions/Microsoft.AspNet.Html.Abstractions.xproj similarity index 100% rename from src/Microsoft.AspNet.Html/Microsoft.AspNet.Html.xproj rename to src/Microsoft.AspNet.Html.Abstractions/Microsoft.AspNet.Html.Abstractions.xproj diff --git a/src/Microsoft.AspNet.Html.Abstractions/Properties/AssemblyInfo.cs b/src/Microsoft.AspNet.Html.Abstractions/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..d310306c25 --- /dev/null +++ b/src/Microsoft.AspNet.Html.Abstractions/Properties/AssemblyInfo.cs @@ -0,0 +1,10 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; + +[assembly: AssemblyMetadata("Serviceable", "True")] +[assembly: NeutralResourcesLanguage("en-us")] +[assembly: InternalsVisibleTo("Microsoft.AspNet.Html.Abstractions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] \ No newline at end of file diff --git a/src/Microsoft.AspNet.Html/project.json b/src/Microsoft.AspNet.Html.Abstractions/project.json similarity index 100% rename from src/Microsoft.AspNet.Html/project.json rename to src/Microsoft.AspNet.Html.Abstractions/project.json diff --git a/src/Microsoft.AspNet.Html/Properties/AssemblyInfo.cs b/src/Microsoft.AspNet.Html/Properties/AssemblyInfo.cs deleted file mode 100644 index 1951d644af..0000000000 --- a/src/Microsoft.AspNet.Html/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Reflection; -using System.Resources; -using System.Runtime.CompilerServices; - -[assembly: AssemblyMetadata("Serviceable", "True")] -[assembly: NeutralResourcesLanguage("en-us")] -[assembly: InternalsVisibleTo("Microsoft.AspNet.Html.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] \ No newline at end of file diff --git a/test/Microsoft.AspNet.Html.Test/HtmlContentBuilderExtensionsTest.cs b/test/Microsoft.AspNet.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs similarity index 100% rename from test/Microsoft.AspNet.Html.Test/HtmlContentBuilderExtensionsTest.cs rename to test/Microsoft.AspNet.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs diff --git a/test/Microsoft.AspNet.Html.Test/HtmlContentBuilderTest.cs b/test/Microsoft.AspNet.Html.Abstractions.Test/HtmlContentBuilderTest.cs similarity index 100% rename from test/Microsoft.AspNet.Html.Test/HtmlContentBuilderTest.cs rename to test/Microsoft.AspNet.Html.Abstractions.Test/HtmlContentBuilderTest.cs diff --git a/test/Microsoft.AspNet.Html.Test/Microsoft.AspNet.Html.Test.xproj b/test/Microsoft.AspNet.Html.Abstractions.Test/Microsoft.AspNet.Html.Abstractions.Test.xproj similarity index 100% rename from test/Microsoft.AspNet.Html.Test/Microsoft.AspNet.Html.Test.xproj rename to test/Microsoft.AspNet.Html.Abstractions.Test/Microsoft.AspNet.Html.Abstractions.Test.xproj diff --git a/test/Microsoft.AspNet.Html.Test/project.json b/test/Microsoft.AspNet.Html.Abstractions.Test/project.json similarity index 87% rename from test/Microsoft.AspNet.Html.Test/project.json rename to test/Microsoft.AspNet.Html.Abstractions.Test/project.json index f5ea4ca7e6..b8e9656f15 100644 --- a/test/Microsoft.AspNet.Html.Test/project.json +++ b/test/Microsoft.AspNet.Html.Abstractions.Test/project.json @@ -4,7 +4,7 @@ "keyFile": "../../tools/Key.snk" }, "dependencies": { - "Microsoft.AspNet.Html": "1.0.0-*", + "Microsoft.AspNet.Html.Abstractions": "1.0.0-*", "Microsoft.AspNet.Testing": "1.0.0-*", "Microsoft.Extensions.WebEncoders": "1.0.0-*", "xunit.runner.aspnet": "2.0.0-aspnet-*" From 086f87a3567e55390f6fe415641f3eb0517aa8dc Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Thu, 3 Dec 2015 12:33:01 -0800 Subject: [PATCH 0047/1029] React to abstraction changes --- .../External/Runtime/PatternGroup.cs | 2 +- src/Microsoft.Dnx.Watcher.Core/External/Runtime/Project.cs | 4 +--- .../External/Runtime/ProjectReader.cs | 2 +- src/Microsoft.Dnx.Watcher.Core/Impl/Project.cs | 1 + src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs | 2 +- src/Microsoft.Dnx.Watcher.Core/project.json | 1 + src/Microsoft.Dnx.Watcher/Program.cs | 1 + 7 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs index d1c60347ae..b7abecd809 100644 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs @@ -5,9 +5,9 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using Microsoft.Extensions.CompilationAbstractions; using Microsoft.Extensions.FileSystemGlobbing; using Microsoft.Extensions.JsonParser.Sources; -using Microsoft.Extensions.PlatformAbstractions; namespace Microsoft.Dnx.Runtime { diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/Project.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/Project.cs index c0cb19a0b5..1b8ddd07d5 100644 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/Project.cs +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/Project.cs @@ -4,9 +4,7 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Runtime.Versioning; -using Microsoft.Extensions.PlatformAbstractions; +using Microsoft.Extensions.CompilationAbstractions; using NuGet; namespace Microsoft.Dnx.Runtime diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectReader.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectReader.cs index 6ad60968dc..1eafcc90a9 100644 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectReader.cs +++ b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectReader.cs @@ -5,8 +5,8 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using Microsoft.Extensions.CompilationAbstractions; using Microsoft.Extensions.JsonParser.Sources; -using Microsoft.Extensions.PlatformAbstractions; using NuGet; namespace Microsoft.Dnx.Runtime diff --git a/src/Microsoft.Dnx.Watcher.Core/Impl/Project.cs b/src/Microsoft.Dnx.Watcher.Core/Impl/Project.cs index a2a3a8a450..04d667c95a 100644 --- a/src/Microsoft.Dnx.Watcher.Core/Impl/Project.cs +++ b/src/Microsoft.Dnx.Watcher.Core/Impl/Project.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using Microsoft.Dnx.Runtime; +using Microsoft.Extensions.CompilationAbstractions; namespace Microsoft.Dnx.Watcher.Core { diff --git a/src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs b/src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs index a4c0c7f76c..bb17b77ebe 100644 --- a/src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs +++ b/src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Microsoft.Extensions.PlatformAbstractions; +using Microsoft.Extensions.CompilationAbstractions; namespace Microsoft.Dnx.Watcher.Core { diff --git a/src/Microsoft.Dnx.Watcher.Core/project.json b/src/Microsoft.Dnx.Watcher.Core/project.json index aad47b43e6..e88a593bb6 100644 --- a/src/Microsoft.Dnx.Watcher.Core/project.json +++ b/src/Microsoft.Dnx.Watcher.Core/project.json @@ -8,6 +8,7 @@ "Microsoft.AspNet.FileProviders.Abstractions": "1.0.0-*", "Microsoft.AspNet.FileProviders.Physical": "1.0.0-*", "Microsoft.Extensions.PlatformAbstractions": "1.0.0-*", + "Microsoft.Extensions.CompilationAbstractions": "1.0.0-*", "Microsoft.Extensions.JsonParser.Sources": { "type": "build", "version": "1.0.0-*" diff --git a/src/Microsoft.Dnx.Watcher/Program.cs b/src/Microsoft.Dnx.Watcher/Program.cs index e20c5af136..75cab38926 100644 --- a/src/Microsoft.Dnx.Watcher/Program.cs +++ b/src/Microsoft.Dnx.Watcher/Program.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.CompilationAbstractions; using Microsoft.Extensions.PlatformAbstractions; using Microsoft.Dnx.Runtime.Common.CommandLine; using Microsoft.Dnx.Watcher.Core; From 78cacfe20b8789b96bb0cc4889e2f8fba6467f43 Mon Sep 17 00:00:00 2001 From: John Luo Date: Wed, 2 Dec 2015 17:13:50 -0800 Subject: [PATCH 0048/1029] Reacting to verbose rename --- src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs b/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs index 8c9e79f80c..ca0763fdc1 100644 --- a/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs +++ b/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs @@ -50,8 +50,8 @@ namespace Microsoft.Dnx.Watcher { switch (logLevel) { + case LogLevel.Trace: return "\x1b[35mtrace\x1b[39m"; case LogLevel.Debug: return "\x1b[35mdebug\x1b[39m"; - case LogLevel.Verbose: return "\x1b[35mverbose\x1b[39m"; case LogLevel.Information: return "\x1b[32minfo\x1b[39m"; case LogLevel.Warning: return "\x1b[33mwarn\x1b[39m"; case LogLevel.Error: return "\x1b[31mfail\x1b[39m"; From 6b7cd4ac18a37956de8ad3647800b6066283b146 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 8 Dec 2015 14:38:35 -0800 Subject: [PATCH 0049/1029] Adding System.Runtime to resolve build issue --- test/Microsoft.AspNet.Html.Abstractions.Test/project.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/Microsoft.AspNet.Html.Abstractions.Test/project.json b/test/Microsoft.AspNet.Html.Abstractions.Test/project.json index b8e9656f15..e3035cbf59 100644 --- a/test/Microsoft.AspNet.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNet.Html.Abstractions.Test/project.json @@ -14,6 +14,10 @@ }, "frameworks": { "dnx451": { }, - "dnxcore50": { } + "dnxcore50": { + "dependencies": { + "System.Runtime": "4.0.21-*" + } + } } } From 4cd2730a39da3f41682243e9d0404cfec90e010c Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 11 Dec 2015 12:22:52 -0800 Subject: [PATCH 0050/1029] Updating to release NuGet.config. --- NuGet.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NuGet.config b/NuGet.config index 5500f6d507..71b9724a09 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + - + From b3f4ab1ddd6af01cf160c8a98a3034c05e2c46a5 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 11 Dec 2015 12:25:21 -0800 Subject: [PATCH 0051/1029] Updating to release NuGet.config. --- NuGet.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NuGet.config b/NuGet.config index 03704957e8..9db87a421e 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + - + \ No newline at end of file From e0d3d7e85d265c599363d0a64974be9c96bb8dba Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 11 Dec 2015 12:36:30 -0800 Subject: [PATCH 0052/1029] Catch and display project validation exceptions correctly --- .../Impl/ProjectProvider.cs | 42 ++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs b/src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs index bb17b77ebe..73005c5d15 100644 --- a/src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs +++ b/src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; using Microsoft.Extensions.CompilationAbstractions; namespace Microsoft.Dnx.Watcher.Core @@ -12,19 +13,28 @@ namespace Microsoft.Dnx.Watcher.Core { public bool TryReadProject(string projectFile, out IProject project, out string errors) { + errors = null; + project = null; + Runtime.Project runtimeProject; if (!TryGetProject(projectFile, out runtimeProject, out errors)) { - project = null; return false; } - errors = null; - project = new Project(runtimeProject); + try + { + project = new Project(runtimeProject); + } + catch (Exception ex) + { + errors = CollectMessages(ex); + return false; + } return true; } - + // Same as TryGetProject but it doesn't throw private bool TryGetProject(string projectFile, out Runtime.Project project, out string errorMessage) { @@ -43,11 +53,33 @@ namespace Microsoft.Dnx.Watcher.Core } catch (Exception ex) { - errorMessage = ex.Message; + errorMessage = CollectMessages(ex); } project = null; return false; } + + private string CollectMessages(Exception exception) + { + var builder = new StringBuilder(); + builder.AppendLine(exception.Message); + + var aggregateException = exception as AggregateException; + if (aggregateException != null) + { + foreach (var message in aggregateException.Flatten().InnerExceptions.Select(CollectMessages)) + { + builder.AppendLine(message); + } + } + + while (exception.InnerException != null) + { + builder.AppendLine(CollectMessages(exception.InnerException)); + exception = exception.InnerException; + } + return builder.ToString(); + } } } From 736f2bcefbd1c1d9bb437bf19d4b0d72593cfb68 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 14 Dec 2015 16:28:23 -0800 Subject: [PATCH 0053/1029] Adding Travis and AppVeyor badges --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index add6834eeb..799d29e1dc 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ HtmlAbstractions ========== +AppVeyor: [![AppVeyor](https://ci.appveyor.com/api/projects/status/cu9y78vsdp19e5on/branch/dev?svg=true)](https://ci.appveyor.com/project/aspnetci/htmlabstractions/branch/dev) + +Travis: [![Travis](https://travis-ci.org/aspnet/HtmlAbstractions.svg?branch=dev)](https://travis-ci.org/aspnet/HtmlAbstractions) HTML abstractions such as `IHtmlContent` and related APIs. From cbc201ac26114f211dba53788b155717dee5983d Mon Sep 17 00:00:00 2001 From: Brennan Date: Tue, 15 Dec 2015 08:53:41 -0800 Subject: [PATCH 0054/1029] Remove unused OnExecute --- src/Microsoft.Dnx.Watcher/Program.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Microsoft.Dnx.Watcher/Program.cs b/src/Microsoft.Dnx.Watcher/Program.cs index 75cab38926..7faf51b813 100644 --- a/src/Microsoft.Dnx.Watcher/Program.cs +++ b/src/Microsoft.Dnx.Watcher/Program.cs @@ -72,13 +72,6 @@ namespace Microsoft.Dnx.Watcher app.HelpOption("-?|-h|--help"); - // Show help information if no subcommand/option was specified - app.OnExecute(() => - { - app.ShowHelp(); - return 2; - }); - var projectArg = app.Option( "--project ", "Path to the project.json file or the application folder. Defaults to the current folder if not provided. Will be passed to DNX.", From 234073cf6e4901d68f1b23e7d1127cacff7455e3 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Tue, 15 Dec 2015 15:27:40 -0800 Subject: [PATCH 0055/1029] Make `HtmlEncodedString` a suitable base for MVC's `HtmlString` - #5 - provide `ToString()` implementation - add missing `null` checks in `WriteTo()`; remove extraneous one in the constructor - special-case `HtmlEncodedString` in `IHtmlContentBuilder.AppendFormat()` extension method nits: - ignore more files - add missing `null` checks in `HtmlContentBuilderExtensions` too --- .gitignore | 12 ++++- .../HtmlContentBuilderExtensions.cs | 45 ++++++++++++++++++- .../HtmlEncodedString.cs | 24 +++++----- .../HtmlContentBuilderExtensionsTest.cs | 13 ++++++ 4 files changed, 81 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index ac82da7568..329a307cda 100644 --- a/.gitignore +++ b/.gitignore @@ -2,10 +2,17 @@ [Bb]in/ TestResults/ .nuget/ +*.sln.ide/ _ReSharper.*/ packages/ artifacts/ PublishProfiles/ +.vs/ +bower_components/ +node_modules/ +**/wwwroot/lib/ +debugSettings.json +project.lock.json *.user *.suo *.cache @@ -23,5 +30,8 @@ nuget.exe *.ncrunchsolution *.*sdf *.ipch +.settings *.sln.ide -project.lock.json +node_modules +**/[Cc]ompiler/[Rr]esources/**/*.js +*launchSettings.json diff --git a/src/Microsoft.AspNet.Html.Abstractions/HtmlContentBuilderExtensions.cs b/src/Microsoft.AspNet.Html.Abstractions/HtmlContentBuilderExtensions.cs index eabfafbd12..5d0b82dd5e 100644 --- a/src/Microsoft.AspNet.Html.Abstractions/HtmlContentBuilderExtensions.cs +++ b/src/Microsoft.AspNet.Html.Abstractions/HtmlContentBuilderExtensions.cs @@ -99,6 +99,11 @@ namespace Microsoft.AspNet.Html /// The . public static IHtmlContentBuilder AppendLine(this IHtmlContentBuilder builder) { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + builder.Append(HtmlEncodedString.NewLine); return builder; } @@ -112,6 +117,11 @@ namespace Microsoft.AspNet.Html /// The . public static IHtmlContentBuilder AppendLine(this IHtmlContentBuilder builder, string unencoded) { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + builder.Append(unencoded); builder.Append(HtmlEncodedString.NewLine); return builder; @@ -125,6 +135,11 @@ namespace Microsoft.AspNet.Html /// The . public static IHtmlContentBuilder AppendLine(this IHtmlContentBuilder builder, IHtmlContent content) { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + builder.Append(content); builder.Append(HtmlEncodedString.NewLine); return builder; @@ -139,6 +154,11 @@ namespace Microsoft.AspNet.Html /// The . public static IHtmlContentBuilder AppendHtmlLine(this IHtmlContentBuilder builder, string encoded) { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + builder.AppendHtml(encoded); builder.Append(HtmlEncodedString.NewLine); return builder; @@ -153,6 +173,11 @@ namespace Microsoft.AspNet.Html /// The . public static IHtmlContentBuilder SetContent(this IHtmlContentBuilder builder, string unencoded) { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + builder.Clear(); builder.Append(unencoded); return builder; @@ -166,6 +191,11 @@ namespace Microsoft.AspNet.Html /// The . public static IHtmlContentBuilder SetContent(this IHtmlContentBuilder builder, IHtmlContent content) { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + builder.Clear(); builder.Append(content); return builder; @@ -180,6 +210,11 @@ namespace Microsoft.AspNet.Html /// The . public static IHtmlContentBuilder SetHtmlContent(this IHtmlContentBuilder builder, string encoded) { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + builder.Clear(); builder.AppendHtml(encoded); return builder; @@ -256,8 +291,14 @@ namespace Microsoft.AspNet.Html public string Format(string format, object arg, IFormatProvider formatProvider) { - // This is the case we need to special case. We trust the IHtmlContent instance to do the - // right thing with encoding. + // These are the cases we need to special case. We trust the HtmlEncodedString or IHtmlContent instance + // to do the right thing with encoding. + var htmlString = arg as HtmlEncodedString; + if (htmlString != null) + { + return htmlString.ToString(); + } + var htmlContent = arg as IHtmlContent; if (htmlContent != null) { diff --git a/src/Microsoft.AspNet.Html.Abstractions/HtmlEncodedString.cs b/src/Microsoft.AspNet.Html.Abstractions/HtmlEncodedString.cs index 348588800f..e5c4ab5003 100644 --- a/src/Microsoft.AspNet.Html.Abstractions/HtmlEncodedString.cs +++ b/src/Microsoft.AspNet.Html.Abstractions/HtmlEncodedString.cs @@ -2,16 +2,14 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Diagnostics; using System.IO; using System.Text.Encodings.Web; namespace Microsoft.AspNet.Html { /// - /// An impelementation that wraps an HTML encoded . + /// An implementation that wraps an HTML encoded . /// - [DebuggerDisplay("{DebuggerToString()}")] public class HtmlEncodedString : IHtmlContent { /// @@ -27,23 +25,29 @@ namespace Microsoft.AspNet.Html /// The HTML encoded value. public HtmlEncodedString(string value) { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - _value = value; } /// public void WriteTo(TextWriter writer, HtmlEncoder encoder) { + if (writer == null) + { + throw new ArgumentNullException(nameof(writer)); + } + + if (encoder == null) + { + throw new ArgumentNullException(nameof(encoder)); + } + writer.Write(_value); } - private string DebuggerToString() + /// + public override string ToString() { - return _value; + return _value ?? string.Empty; } } } diff --git a/test/Microsoft.AspNet.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs b/test/Microsoft.AspNet.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs index 6253bf9be3..9355d507d3 100644 --- a/test/Microsoft.AspNet.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs +++ b/test/Microsoft.AspNet.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs @@ -158,6 +158,19 @@ namespace Microsoft.AspNet.Html.Test HtmlContentToString(builder)); } + [Fact] + public void Builder_AppendFormat_HtmlEncodedString() + { + // Arrange + var builder = new TestHtmlContentBuilder(); + + // Act + builder.AppendFormat("{0}!", new HtmlEncodedString("First")); + + // Assert + Assert.Equal("First!", HtmlContentToString(builder)); + } + [Fact] public void Builder_AppendFormatContent_With1Argument() { From b4239550f3151bcf12211799fdbcbc3dbfec9d1a Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 22 Dec 2015 15:57:35 -0800 Subject: [PATCH 0056/1029] Move Microsoft.Extensions.WebEncoders to HtmlAbstractions --- HtmlAbstractions.sln | 32 +++++- NuGetPackageVerifier.json | 3 +- .../EncoderServiceCollectionExtensions.cs | 64 +++++++++++ .../EncoderServiceProviderExtensions.cs | 50 +++++++++ .../Microsoft.Extensions.WebEncoders.xproj | 17 +++ .../Properties/AssemblyInfo.cs | 8 ++ .../Testing/HtmlTestEncoder.cs | 104 ++++++++++++++++++ .../Testing/JavaScriptTestEncoder.cs | 104 ++++++++++++++++++ .../Testing/UrlTestEncoder.cs | 104 ++++++++++++++++++ .../WebEncoderOptions.cs | 21 ++++ .../project.json | 27 +++++ ...EncoderServiceCollectionExtensionsTests.cs | 90 +++++++++++++++ .../EncoderServiceProviderExtensionsTests.cs | 103 +++++++++++++++++ .../HtmlTestEncoderTest.cs | 26 +++++ ...crosoft.Extensions.WebEncoders.Tests.xproj | 20 ++++ .../project.json | 24 ++++ 16 files changed, 795 insertions(+), 2 deletions(-) create mode 100644 src/Microsoft.Extensions.WebEncoders/EncoderServiceCollectionExtensions.cs create mode 100644 src/Microsoft.Extensions.WebEncoders/EncoderServiceProviderExtensions.cs create mode 100644 src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.xproj create mode 100644 src/Microsoft.Extensions.WebEncoders/Properties/AssemblyInfo.cs create mode 100644 src/Microsoft.Extensions.WebEncoders/Testing/HtmlTestEncoder.cs create mode 100644 src/Microsoft.Extensions.WebEncoders/Testing/JavaScriptTestEncoder.cs create mode 100644 src/Microsoft.Extensions.WebEncoders/Testing/UrlTestEncoder.cs create mode 100644 src/Microsoft.Extensions.WebEncoders/WebEncoderOptions.cs create mode 100644 src/Microsoft.Extensions.WebEncoders/project.json create mode 100644 test/Microsoft.Extensions.WebEncoders.Tests/EncoderServiceCollectionExtensionsTests.cs create mode 100644 test/Microsoft.Extensions.WebEncoders.Tests/EncoderServiceProviderExtensionsTests.cs create mode 100644 test/Microsoft.Extensions.WebEncoders.Tests/HtmlTestEncoderTest.cs create mode 100644 test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.xproj create mode 100644 test/Microsoft.Extensions.WebEncoders.Tests/project.json diff --git a/HtmlAbstractions.sln b/HtmlAbstractions.sln index 805c4daa7a..a45f34a265 100644 --- a/HtmlAbstractions.sln +++ b/HtmlAbstractions.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +VisualStudioVersion = 14.0.24711.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A5A15F1C-885A-452A-A731-B0173DDBD913}" EndProject @@ -16,6 +16,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution NuGetPackageVerifier.json = NuGetPackageVerifier.json EndProjectSection EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.WebEncoders", "src\Microsoft.Extensions.WebEncoders\Microsoft.Extensions.WebEncoders.xproj", "{DD2CE416-765E-4000-A03E-C2FF165DA1B6}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.WebEncoders.Tests", "test\Microsoft.Extensions.WebEncoders.Tests\Microsoft.Extensions.WebEncoders.Tests.xproj", "{7AE2731D-43CD-4CF8-850A-4914DE2CE930}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -50,6 +54,30 @@ Global {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|Mixed Platforms.Build.0 = Release|Any CPU {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|x86.ActiveCfg = Release|Any CPU {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|x86.Build.0 = Release|Any CPU + {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Debug|x86.ActiveCfg = Debug|Any CPU + {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Debug|x86.Build.0 = Debug|Any CPU + {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Release|Any CPU.Build.0 = Release|Any CPU + {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Release|x86.ActiveCfg = Release|Any CPU + {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Release|x86.Build.0 = Release|Any CPU + {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Debug|x86.ActiveCfg = Debug|Any CPU + {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Debug|x86.Build.0 = Debug|Any CPU + {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Release|Any CPU.Build.0 = Release|Any CPU + {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Release|x86.ActiveCfg = Release|Any CPU + {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -57,5 +85,7 @@ Global GlobalSection(NestedProjects) = preSolution {68A28E4A-3ADE-4187-9625-4FF185887CB3} = {A5A15F1C-885A-452A-A731-B0173DDBD913} {2D187B88-94BD-4A39-AC97-F8F8B9363301} = {F31FF137-390C-49BF-A3BD-7C6ED3597C21} + {DD2CE416-765E-4000-A03E-C2FF165DA1B6} = {A5A15F1C-885A-452A-A731-B0173DDBD913} + {7AE2731D-43CD-4CF8-850A-4914DE2CE930} = {F31FF137-390C-49BF-A3BD-7C6ED3597C21} EndGlobalSection EndGlobal diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index c57b2afb17..31f9437602 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -9,7 +9,8 @@ "StrictSemanticVersionValidationRule" ], "packages": { - "Microsoft.AspNet.Html.Abstractions": { } + "Microsoft.AspNet.Html.Abstractions": { }, + "Microsoft.Extensions.WebEncoders": { } } }, "Default": { // Rules to run for packages not listed in any other set. diff --git a/src/Microsoft.Extensions.WebEncoders/EncoderServiceCollectionExtensions.cs b/src/Microsoft.Extensions.WebEncoders/EncoderServiceCollectionExtensions.cs new file mode 100644 index 0000000000..80f1987c17 --- /dev/null +++ b/src/Microsoft.Extensions.WebEncoders/EncoderServiceCollectionExtensions.cs @@ -0,0 +1,64 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Text.Encodings.Web; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Options; +using Microsoft.Extensions.WebEncoders; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static class EncoderServiceCollectionExtensions + { + public static IServiceCollection AddWebEncoders(this IServiceCollection services) + { + if (services == null) + { + throw new ArgumentNullException(nameof(services)); + } + + return AddWebEncoders(services, configureOptions: null); + } + + public static IServiceCollection AddWebEncoders(this IServiceCollection services, Action configureOptions) + { + if (services == null) + { + throw new ArgumentNullException(nameof(services)); + } + + services.AddOptions(); + + // Register the default encoders + // We want to call the 'Default' property getters lazily since they perform static caching + services.TryAddSingleton( + CreateFactory(() => HtmlEncoder.Default, settings => HtmlEncoder.Create(settings))); + services.TryAddSingleton( + CreateFactory(() => JavaScriptEncoder.Default, settings => JavaScriptEncoder.Create(settings))); + services.TryAddSingleton( + CreateFactory(() => UrlEncoder.Default, settings => UrlEncoder.Create(settings))); + + if (configureOptions != null) + { + services.Configure(configureOptions); + } + + return services; + } + + private static Func CreateFactory( + Func defaultFactory, + Func customSettingsFactory) + { + return serviceProvider => + { + var settings = serviceProvider + ?.GetService>() + ?.Value + ?.TextEncoderSettings; + return (settings != null) ? customSettingsFactory(settings) : defaultFactory(); + }; + } + } +} diff --git a/src/Microsoft.Extensions.WebEncoders/EncoderServiceProviderExtensions.cs b/src/Microsoft.Extensions.WebEncoders/EncoderServiceProviderExtensions.cs new file mode 100644 index 0000000000..8d9d2da4e8 --- /dev/null +++ b/src/Microsoft.Extensions.WebEncoders/EncoderServiceProviderExtensions.cs @@ -0,0 +1,50 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Text.Encodings.Web; + +namespace Microsoft.Extensions.WebEncoders +{ + /// + /// Contains extension methods for fetching encoders from an . + /// + public static class EncoderServiceProviderExtensions + { + /// + /// Retrieves an from an . + /// + /// + /// This method is guaranteed never to return null. + /// It will return a default encoder instance if does not contain one or is null. + /// + public static HtmlEncoder GetHtmlEncoder(this IServiceProvider serviceProvider) + { + return (HtmlEncoder)serviceProvider?.GetService(typeof(HtmlEncoder)) ?? HtmlEncoder.Default; + } + + /// + /// Retrieves an from an . + /// + /// + /// This method is guaranteed never to return null. + /// It will return a default encoder instance if does not contain one or is null. + /// + public static JavaScriptEncoder GetJavaScriptEncoder(this IServiceProvider serviceProvider) + { + return (JavaScriptEncoder)serviceProvider?.GetService(typeof(JavaScriptEncoder)) ?? JavaScriptEncoder.Default; + } + + /// + /// Retrieves an from an . + /// + /// + /// This method is guaranteed never to return null. + /// It will return a default encoder instance if does not contain one or is null. + /// + public static UrlEncoder GetUrlEncoder(this IServiceProvider serviceProvider) + { + return (UrlEncoder)serviceProvider?.GetService(typeof(UrlEncoder)) ?? UrlEncoder.Default; + } + } +} diff --git a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.xproj b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.xproj new file mode 100644 index 0000000000..084e7901ea --- /dev/null +++ b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.xproj @@ -0,0 +1,17 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + dd2ce416-765e-4000-a03e-c2ff165da1b6 + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + 2.0 + + + \ No newline at end of file diff --git a/src/Microsoft.Extensions.WebEncoders/Properties/AssemblyInfo.cs b/src/Microsoft.Extensions.WebEncoders/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..b2437d9ad6 --- /dev/null +++ b/src/Microsoft.Extensions.WebEncoders/Properties/AssemblyInfo.cs @@ -0,0 +1,8 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Reflection; +using System.Resources; + +[assembly: AssemblyMetadata("Serviceable", "True")] +[assembly: NeutralResourcesLanguage("en-us")] \ No newline at end of file diff --git a/src/Microsoft.Extensions.WebEncoders/Testing/HtmlTestEncoder.cs b/src/Microsoft.Extensions.WebEncoders/Testing/HtmlTestEncoder.cs new file mode 100644 index 0000000000..162ce4f6c1 --- /dev/null +++ b/src/Microsoft.Extensions.WebEncoders/Testing/HtmlTestEncoder.cs @@ -0,0 +1,104 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Text.Encodings.Web; + +namespace Microsoft.Extensions.WebEncoders.Testing +{ + /// + /// Encoder used for unit testing. + /// + public sealed class HtmlTestEncoder : HtmlEncoder + { + public override int MaxOutputCharactersPerInputCharacter + { + get { return 1; } + } + + public override string Encode(string value) + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (value.Length == 0) + { + return string.Empty; + } + + return $"HtmlEncode[[{value}]]"; + } + + public override void Encode(TextWriter output, char[] value, int startIndex, int characterCount) + { + if (output == null) + { + throw new ArgumentNullException(nameof(output)); + } + + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (characterCount == 0) + { + return; + } + + output.Write("HtmlEncode[["); + output.Write(value, startIndex, characterCount); + output.Write("]]"); + } + + public override void Encode(TextWriter output, string value, int startIndex, int characterCount) + { + if (output == null) + { + throw new ArgumentNullException(nameof(output)); + } + + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (characterCount == 0) + { + return; + } + + output.Write("HtmlEncode[["); + output.Write(value.Substring(startIndex, characterCount)); + output.Write("]]"); + } + + public override bool WillEncode(int unicodeScalar) + { + return false; + } + + public override unsafe int FindFirstCharacterToEncode(char* text, int textLength) + { + return -1; + } + + public override unsafe bool TryEncodeUnicodeScalar( + int unicodeScalar, + char* buffer, + int bufferLength, + out int numberOfCharactersWritten) + { + if (buffer == null) + { + throw new ArgumentNullException(nameof(buffer)); + } + + numberOfCharactersWritten = 0; + return false; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.WebEncoders/Testing/JavaScriptTestEncoder.cs b/src/Microsoft.Extensions.WebEncoders/Testing/JavaScriptTestEncoder.cs new file mode 100644 index 0000000000..bef4461676 --- /dev/null +++ b/src/Microsoft.Extensions.WebEncoders/Testing/JavaScriptTestEncoder.cs @@ -0,0 +1,104 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Text.Encodings.Web; + +namespace Microsoft.Extensions.WebEncoders.Testing +{ + /// + /// Encoder used for unit testing. + /// + public class JavaScriptTestEncoder : JavaScriptEncoder + { + public override int MaxOutputCharactersPerInputCharacter + { + get { return 1; } + } + + public override string Encode(string value) + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (value.Length == 0) + { + return string.Empty; + } + + return $"JavaScriptEncode[[{value}]]"; + } + + public override void Encode(TextWriter output, char[] value, int startIndex, int characterCount) + { + if (output == null) + { + throw new ArgumentNullException(nameof(output)); + } + + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (characterCount == 0) + { + return; + } + + output.Write("JavaScriptEncode[["); + output.Write(value, startIndex, characterCount); + output.Write("]]"); + } + + public override void Encode(TextWriter output, string value, int startIndex, int characterCount) + { + if (output == null) + { + throw new ArgumentNullException(nameof(output)); + } + + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (characterCount == 0) + { + return; + } + + output.Write("JavaScriptEncode[["); + output.Write(value.Substring(startIndex, characterCount)); + output.Write("]]"); + } + + public override bool WillEncode(int unicodeScalar) + { + return false; + } + + public override unsafe int FindFirstCharacterToEncode(char* text, int textLength) + { + return -1; + } + + public override unsafe bool TryEncodeUnicodeScalar( + int unicodeScalar, + char* buffer, + int bufferLength, + out int numberOfCharactersWritten) + { + if (buffer == null) + { + throw new ArgumentNullException(nameof(buffer)); + } + + numberOfCharactersWritten = 0; + return false; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.WebEncoders/Testing/UrlTestEncoder.cs b/src/Microsoft.Extensions.WebEncoders/Testing/UrlTestEncoder.cs new file mode 100644 index 0000000000..295bda63e8 --- /dev/null +++ b/src/Microsoft.Extensions.WebEncoders/Testing/UrlTestEncoder.cs @@ -0,0 +1,104 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Text.Encodings.Web; + +namespace Microsoft.Extensions.WebEncoders.Testing +{ + /// + /// Encoder used for unit testing. + /// + public class UrlTestEncoder : UrlEncoder + { + public override int MaxOutputCharactersPerInputCharacter + { + get { return 1; } + } + + public override string Encode(string value) + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (value.Length == 0) + { + return string.Empty; + } + + return $"UrlEncode[[{value}]]"; + } + + public override void Encode(TextWriter output, char[] value, int startIndex, int characterCount) + { + if (output == null) + { + throw new ArgumentNullException(nameof(output)); + } + + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (characterCount == 0) + { + return; + } + + output.Write("UrlEncode[["); + output.Write(value, startIndex, characterCount); + output.Write("]]"); + } + + public override void Encode(TextWriter output, string value, int startIndex, int characterCount) + { + if (output == null) + { + throw new ArgumentNullException(nameof(output)); + } + + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (characterCount == 0) + { + return; + } + + output.Write("UrlEncode[["); + output.Write(value.Substring(startIndex, characterCount)); + output.Write("]]"); + } + + public override bool WillEncode(int unicodeScalar) + { + return false; + } + + public override unsafe int FindFirstCharacterToEncode(char* text, int textLength) + { + return -1; + } + + public override unsafe bool TryEncodeUnicodeScalar( + int unicodeScalar, + char* buffer, + int bufferLength, + out int numberOfCharactersWritten) + { + if (buffer == null) + { + throw new ArgumentNullException(nameof(buffer)); + } + + numberOfCharactersWritten = 0; + return false; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.WebEncoders/WebEncoderOptions.cs b/src/Microsoft.Extensions.WebEncoders/WebEncoderOptions.cs new file mode 100644 index 0000000000..2f5e770a0c --- /dev/null +++ b/src/Microsoft.Extensions.WebEncoders/WebEncoderOptions.cs @@ -0,0 +1,21 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Text.Encodings.Web; + +namespace Microsoft.Extensions.WebEncoders +{ + /// + /// Specifies options common to all three encoders (HtmlEncode, JavaScriptEncode, UrlEncode). + /// + public sealed class WebEncoderOptions + { + /// + /// Specifies which code points are allowed to be represented unescaped by the encoders. + /// + /// + /// If this property is null, then the encoders will use their default allow lists. + /// + public TextEncoderSettings TextEncoderSettings { get; set; } + } +} diff --git a/src/Microsoft.Extensions.WebEncoders/project.json b/src/Microsoft.Extensions.WebEncoders/project.json new file mode 100644 index 0000000000..0facfeeb8c --- /dev/null +++ b/src/Microsoft.Extensions.WebEncoders/project.json @@ -0,0 +1,27 @@ +{ + "version": "1.0.0-*", + "description": "Contains registration and configuration APIs for the core framework encoders.", + "repository": { + "type": "git", + "url": "git://github.com/aspnet/httpabstractions" + }, + "compilationOptions": { + "warningsAsErrors": true, + "allowUnsafe": true, + "keyFile": "../../tools/Key.snk" + }, + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "1.0.0-*", + "Microsoft.Extensions.Options": "1.0.0-*", + "System.Text.Encodings.Web": "4.0.0-*" + }, + "frameworks": { + "net451": { + "frameworkAssemblies": { + "System.IO": "", + "System.Runtime": "" + } + }, + "dotnet5.4": {} + } +} diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/EncoderServiceCollectionExtensionsTests.cs b/test/Microsoft.Extensions.WebEncoders.Tests/EncoderServiceCollectionExtensionsTests.cs new file mode 100644 index 0000000000..8e060102bb --- /dev/null +++ b/test/Microsoft.Extensions.WebEncoders.Tests/EncoderServiceCollectionExtensionsTests.cs @@ -0,0 +1,90 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Text.Encodings.Web; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.WebEncoders.Testing; +using Xunit; + +namespace Microsoft.Extensions.WebEncoders +{ + public class EncoderServiceCollectionExtensionsTests + { + [Fact] + public void AddWebEncoders_WithoutOptions_RegistersDefaultEncoders() + { + // Arrange + var serviceCollection = new ServiceCollection(); + + // Act + serviceCollection.AddWebEncoders(); + + // Assert + var serviceProvider = serviceCollection.BuildServiceProvider(); + Assert.Same(HtmlEncoder.Default, serviceProvider.GetRequiredService()); // default encoder + Assert.Same(HtmlEncoder.Default, serviceProvider.GetRequiredService()); // as singleton instance + Assert.Same(JavaScriptEncoder.Default, serviceProvider.GetRequiredService()); // default encoder + Assert.Same(JavaScriptEncoder.Default, serviceProvider.GetRequiredService()); // as singleton instance + Assert.Same(UrlEncoder.Default, serviceProvider.GetRequiredService()); // default encoder + Assert.Same(UrlEncoder.Default, serviceProvider.GetRequiredService()); // as singleton instance + } + + [Fact] + public void AddWebEncoders_WithOptions_RegistersEncodersWithCustomCodeFilter() + { + // Arrange + var serviceCollection = new ServiceCollection(); + + // Act + serviceCollection.AddWebEncoders(options => + { + options.TextEncoderSettings = new TextEncoderSettings(); + options.TextEncoderSettings.AllowCharacters("ace".ToCharArray()); // only these three chars are allowed + }); + + // Assert + var serviceProvider = serviceCollection.BuildServiceProvider(); + + var htmlEncoder = serviceProvider.GetRequiredService(); + Assert.Equal("abcde", htmlEncoder.Encode("abcde")); + Assert.Same(htmlEncoder, serviceProvider.GetRequiredService()); // as singleton instance + + var javaScriptEncoder = serviceProvider.GetRequiredService(); + Assert.Equal(@"a\u0062c\u0064e", javaScriptEncoder.Encode("abcde")); + Assert.Same(javaScriptEncoder, serviceProvider.GetRequiredService()); // as singleton instance + + var urlEncoder = serviceProvider.GetRequiredService(); + Assert.Equal("a%62c%64e", urlEncoder.Encode("abcde")); + Assert.Same(urlEncoder, serviceProvider.GetRequiredService()); // as singleton instance + } + + [Fact] + public void AddWebEncoders_DoesNotOverrideExistingRegisteredEncoders() + { + // Arrange + var serviceCollection = new ServiceCollection(); + + // Act + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + // we don't register an existing URL encoder + serviceCollection.AddWebEncoders(options => + { + options.TextEncoderSettings = new TextEncoderSettings(); + options.TextEncoderSettings.AllowCharacters("ace".ToCharArray()); // only these three chars are allowed + }); + + // Assert + var serviceProvider = serviceCollection.BuildServiceProvider(); + + var htmlEncoder = serviceProvider.GetHtmlEncoder(); + Assert.Equal("HtmlEncode[[abcde]]", htmlEncoder.Encode("abcde")); + + var javaScriptEncoder = serviceProvider.GetJavaScriptEncoder(); + Assert.Equal("JavaScriptEncode[[abcde]]", javaScriptEncoder.Encode("abcde")); + + var urlEncoder = serviceProvider.GetUrlEncoder(); + Assert.Equal("a%62c%64e", urlEncoder.Encode("abcde")); + } + } +} diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/EncoderServiceProviderExtensionsTests.cs b/test/Microsoft.Extensions.WebEncoders.Tests/EncoderServiceProviderExtensionsTests.cs new file mode 100644 index 0000000000..01492e759e --- /dev/null +++ b/test/Microsoft.Extensions.WebEncoders.Tests/EncoderServiceProviderExtensionsTests.cs @@ -0,0 +1,103 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Text.Encodings.Web; +using Xunit; + +namespace Microsoft.Extensions.WebEncoders +{ + public class EncoderServiceProviderExtensionsTests + { + [Fact] + public void GetHtmlEncoder_ServiceProviderDoesNotHaveEncoder_UsesDefault() + { + // Arrange + var serviceProvider = new TestServiceProvider(); + + // Act + var retVal = serviceProvider.GetHtmlEncoder(); + + // Assert + Assert.Same(HtmlEncoder.Default, retVal); + } + + [Fact] + public void GetHtmlEncoder_ServiceProviderHasEncoder_ReturnsRegisteredInstance() + { + // Arrange + var expectedEncoder = HtmlEncoder.Default; + var serviceProvider = new TestServiceProvider() { Service = expectedEncoder }; + + // Act + var retVal = serviceProvider.GetHtmlEncoder(); + + // Assert + Assert.Same(expectedEncoder, retVal); + } + + [Fact] + public void GetJavaScriptEncoder_ServiceProviderDoesNotHaveEncoder_UsesDefault() + { + // Arrange + var serviceProvider = new TestServiceProvider(); + + // Act + var retVal = serviceProvider.GetJavaScriptEncoder(); + + // Assert + Assert.Same(JavaScriptEncoder.Default, retVal); + } + + [Fact] + public void GetJavaScriptEncoder_ServiceProviderHasEncoder_ReturnsRegisteredInstance() + { + // Arrange + var expectedEncoder = JavaScriptEncoder.Default; + var serviceProvider = new TestServiceProvider() { Service = expectedEncoder }; + + // Act + var retVal = serviceProvider.GetJavaScriptEncoder(); + + // Assert + Assert.Same(expectedEncoder, retVal); + } + + [Fact] + public void GetUrlEncoder_ServiceProviderDoesNotHaveEncoder_UsesDefault() + { + // Arrange + var serviceProvider = new TestServiceProvider(); + + // Act + var retVal = serviceProvider.GetUrlEncoder(); + + // Assert + Assert.Same(UrlEncoder.Default, retVal); + } + + [Fact] + public void GetUrlEncoder_ServiceProviderHasEncoder_ReturnsRegisteredInstance() + { + // Arrange + var expectedEncoder = UrlEncoder.Default; + var serviceProvider = new TestServiceProvider() { Service = expectedEncoder }; + + // Act + var retVal = serviceProvider.GetUrlEncoder(); + + // Assert + Assert.Same(expectedEncoder, retVal); + } + + private class TestServiceProvider : IServiceProvider + { + public object Service { get; set; } + + public object GetService(Type serviceType) + { + return Service; + } + } + } +} diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/HtmlTestEncoderTest.cs b/test/Microsoft.Extensions.WebEncoders.Tests/HtmlTestEncoderTest.cs new file mode 100644 index 0000000000..baafedc4de --- /dev/null +++ b/test/Microsoft.Extensions.WebEncoders.Tests/HtmlTestEncoderTest.cs @@ -0,0 +1,26 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Xunit; + +namespace Microsoft.Extensions.WebEncoders.Testing +{ + public class HtmlTestEncoderTest + { + [Theory] + [InlineData("", "")] + [InlineData("abcd", "HtmlEncode[[abcd]]")] + [InlineData("<<''\"\">>", "HtmlEncode[[<<''\"\">>]]")] + public void StringEncode_EncodesAsExpected(string input, string expectedOutput) + { + // Arrange + var encoder = new HtmlTestEncoder(); + + // Act + var output = encoder.Encode(input); + + // Assert + Assert.Equal(expectedOutput, output); + } + } +} diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.xproj b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.xproj new file mode 100644 index 0000000000..9b0698e3cc --- /dev/null +++ b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.xproj @@ -0,0 +1,20 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 7ae2731d-43cd-4cf8-850a-4914de2ce930 + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + 2.0 + + + + + + \ No newline at end of file diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json new file mode 100644 index 0000000000..4d81779a7c --- /dev/null +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -0,0 +1,24 @@ +{ + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "1.0.0-*", + "Microsoft.Extensions.WebEncoders": "1.0.0-*", + "Newtonsoft.Json": "6.0.6", + "xunit.runner.aspnet": "2.0.0-aspnet-*" + }, + "commands": { + "test": "xunit.runner.aspnet" + }, + "compilationOptions": { + "allowUnsafe": true, + "warningsAsErrors": true, + "keyFile": "../../tools/Key.snk" + }, + "frameworks": { + "dnx451": { }, + "dnxcore50": { + "dependencies": { + "System.Text.Encoding.Extensions": "4.0.11-*" + } + } + } +} From 46f64dfa208ae29d4e4608343352286f54a6c4a8 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 29 Dec 2015 18:21:07 -0800 Subject: [PATCH 0057/1029] * Remove EncoderServiceProviderExtensions --- .../EncoderServiceCollectionExtensions.cs | 13 +++ .../EncoderServiceProviderExtensions.cs | 50 --------- ...EncoderServiceCollectionExtensionsTests.cs | 6 +- .../EncoderServiceProviderExtensionsTests.cs | 103 ------------------ .../project.json | 7 +- 5 files changed, 17 insertions(+), 162 deletions(-) delete mode 100644 src/Microsoft.Extensions.WebEncoders/EncoderServiceProviderExtensions.cs delete mode 100644 test/Microsoft.Extensions.WebEncoders.Tests/EncoderServiceProviderExtensionsTests.cs diff --git a/src/Microsoft.Extensions.WebEncoders/EncoderServiceCollectionExtensions.cs b/src/Microsoft.Extensions.WebEncoders/EncoderServiceCollectionExtensions.cs index 80f1987c17..df3946099c 100644 --- a/src/Microsoft.Extensions.WebEncoders/EncoderServiceCollectionExtensions.cs +++ b/src/Microsoft.Extensions.WebEncoders/EncoderServiceCollectionExtensions.cs @@ -11,6 +11,12 @@ namespace Microsoft.Extensions.DependencyInjection { public static class EncoderServiceCollectionExtensions { + /// + /// Adds , and + /// to the specified . + /// + /// The . + /// The instance after the encoders have been added. public static IServiceCollection AddWebEncoders(this IServiceCollection services) { if (services == null) @@ -21,6 +27,13 @@ namespace Microsoft.Extensions.DependencyInjection return AddWebEncoders(services, configureOptions: null); } + /// + /// Adds , and + /// to the specified . + /// + /// The . + /// A callback to configure . + /// The instance after the encoders have been added. public static IServiceCollection AddWebEncoders(this IServiceCollection services, Action configureOptions) { if (services == null) diff --git a/src/Microsoft.Extensions.WebEncoders/EncoderServiceProviderExtensions.cs b/src/Microsoft.Extensions.WebEncoders/EncoderServiceProviderExtensions.cs deleted file mode 100644 index 8d9d2da4e8..0000000000 --- a/src/Microsoft.Extensions.WebEncoders/EncoderServiceProviderExtensions.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Text.Encodings.Web; - -namespace Microsoft.Extensions.WebEncoders -{ - /// - /// Contains extension methods for fetching encoders from an . - /// - public static class EncoderServiceProviderExtensions - { - /// - /// Retrieves an from an . - /// - /// - /// This method is guaranteed never to return null. - /// It will return a default encoder instance if does not contain one or is null. - /// - public static HtmlEncoder GetHtmlEncoder(this IServiceProvider serviceProvider) - { - return (HtmlEncoder)serviceProvider?.GetService(typeof(HtmlEncoder)) ?? HtmlEncoder.Default; - } - - /// - /// Retrieves an from an . - /// - /// - /// This method is guaranteed never to return null. - /// It will return a default encoder instance if does not contain one or is null. - /// - public static JavaScriptEncoder GetJavaScriptEncoder(this IServiceProvider serviceProvider) - { - return (JavaScriptEncoder)serviceProvider?.GetService(typeof(JavaScriptEncoder)) ?? JavaScriptEncoder.Default; - } - - /// - /// Retrieves an from an . - /// - /// - /// This method is guaranteed never to return null. - /// It will return a default encoder instance if does not contain one or is null. - /// - public static UrlEncoder GetUrlEncoder(this IServiceProvider serviceProvider) - { - return (UrlEncoder)serviceProvider?.GetService(typeof(UrlEncoder)) ?? UrlEncoder.Default; - } - } -} diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/EncoderServiceCollectionExtensionsTests.cs b/test/Microsoft.Extensions.WebEncoders.Tests/EncoderServiceCollectionExtensionsTests.cs index 8e060102bb..0178bba2d5 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/EncoderServiceCollectionExtensionsTests.cs +++ b/test/Microsoft.Extensions.WebEncoders.Tests/EncoderServiceCollectionExtensionsTests.cs @@ -77,13 +77,13 @@ namespace Microsoft.Extensions.WebEncoders // Assert var serviceProvider = serviceCollection.BuildServiceProvider(); - var htmlEncoder = serviceProvider.GetHtmlEncoder(); + var htmlEncoder = serviceProvider.GetRequiredService(); Assert.Equal("HtmlEncode[[abcde]]", htmlEncoder.Encode("abcde")); - var javaScriptEncoder = serviceProvider.GetJavaScriptEncoder(); + var javaScriptEncoder = serviceProvider.GetRequiredService(); Assert.Equal("JavaScriptEncode[[abcde]]", javaScriptEncoder.Encode("abcde")); - var urlEncoder = serviceProvider.GetUrlEncoder(); + var urlEncoder = serviceProvider.GetRequiredService(); Assert.Equal("a%62c%64e", urlEncoder.Encode("abcde")); } } diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/EncoderServiceProviderExtensionsTests.cs b/test/Microsoft.Extensions.WebEncoders.Tests/EncoderServiceProviderExtensionsTests.cs deleted file mode 100644 index 01492e759e..0000000000 --- a/test/Microsoft.Extensions.WebEncoders.Tests/EncoderServiceProviderExtensionsTests.cs +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Text.Encodings.Web; -using Xunit; - -namespace Microsoft.Extensions.WebEncoders -{ - public class EncoderServiceProviderExtensionsTests - { - [Fact] - public void GetHtmlEncoder_ServiceProviderDoesNotHaveEncoder_UsesDefault() - { - // Arrange - var serviceProvider = new TestServiceProvider(); - - // Act - var retVal = serviceProvider.GetHtmlEncoder(); - - // Assert - Assert.Same(HtmlEncoder.Default, retVal); - } - - [Fact] - public void GetHtmlEncoder_ServiceProviderHasEncoder_ReturnsRegisteredInstance() - { - // Arrange - var expectedEncoder = HtmlEncoder.Default; - var serviceProvider = new TestServiceProvider() { Service = expectedEncoder }; - - // Act - var retVal = serviceProvider.GetHtmlEncoder(); - - // Assert - Assert.Same(expectedEncoder, retVal); - } - - [Fact] - public void GetJavaScriptEncoder_ServiceProviderDoesNotHaveEncoder_UsesDefault() - { - // Arrange - var serviceProvider = new TestServiceProvider(); - - // Act - var retVal = serviceProvider.GetJavaScriptEncoder(); - - // Assert - Assert.Same(JavaScriptEncoder.Default, retVal); - } - - [Fact] - public void GetJavaScriptEncoder_ServiceProviderHasEncoder_ReturnsRegisteredInstance() - { - // Arrange - var expectedEncoder = JavaScriptEncoder.Default; - var serviceProvider = new TestServiceProvider() { Service = expectedEncoder }; - - // Act - var retVal = serviceProvider.GetJavaScriptEncoder(); - - // Assert - Assert.Same(expectedEncoder, retVal); - } - - [Fact] - public void GetUrlEncoder_ServiceProviderDoesNotHaveEncoder_UsesDefault() - { - // Arrange - var serviceProvider = new TestServiceProvider(); - - // Act - var retVal = serviceProvider.GetUrlEncoder(); - - // Assert - Assert.Same(UrlEncoder.Default, retVal); - } - - [Fact] - public void GetUrlEncoder_ServiceProviderHasEncoder_ReturnsRegisteredInstance() - { - // Arrange - var expectedEncoder = UrlEncoder.Default; - var serviceProvider = new TestServiceProvider() { Service = expectedEncoder }; - - // Act - var retVal = serviceProvider.GetUrlEncoder(); - - // Assert - Assert.Same(expectedEncoder, retVal); - } - - private class TestServiceProvider : IServiceProvider - { - public object Service { get; set; } - - public object GetService(Type serviceType) - { - return Service; - } - } - } -} diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index 4d81779a7c..62fb30b458 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -2,7 +2,6 @@ "dependencies": { "Microsoft.Extensions.DependencyInjection": "1.0.0-*", "Microsoft.Extensions.WebEncoders": "1.0.0-*", - "Newtonsoft.Json": "6.0.6", "xunit.runner.aspnet": "2.0.0-aspnet-*" }, "commands": { @@ -15,10 +14,6 @@ }, "frameworks": { "dnx451": { }, - "dnxcore50": { - "dependencies": { - "System.Text.Encoding.Extensions": "4.0.11-*" - } - } + "dnxcore50": { } } } From 984fe02eb8a32c3e67592becd024acb527010930 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 31 Dec 2015 10:53:48 -0800 Subject: [PATCH 0058/1029] Rename IHtmlContentBuilder.Append(IHtmlContent) to IHtmlContentBuilder.AppendHtml(IHtmlContent) Fixes #4 --- .../HtmlContentBuilder.cs | 2 +- .../HtmlContentBuilderExtensions.cs | 16 ++++++++-------- .../IHtmlContentBuilder.cs | 2 +- .../HtmlContentBuilderExtensionsTest.cs | 2 +- .../HtmlContentBuilderTest.cs | 8 ++++---- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Microsoft.AspNet.Html.Abstractions/HtmlContentBuilder.cs b/src/Microsoft.AspNet.Html.Abstractions/HtmlContentBuilder.cs index 34e59d3318..10a50cb34d 100644 --- a/src/Microsoft.AspNet.Html.Abstractions/HtmlContentBuilder.cs +++ b/src/Microsoft.AspNet.Html.Abstractions/HtmlContentBuilder.cs @@ -67,7 +67,7 @@ namespace Microsoft.AspNet.Html } /// - public IHtmlContentBuilder Append(IHtmlContent htmlContent) + public IHtmlContentBuilder AppendHtml(IHtmlContent htmlContent) { if (htmlContent == null) { diff --git a/src/Microsoft.AspNet.Html.Abstractions/HtmlContentBuilderExtensions.cs b/src/Microsoft.AspNet.Html.Abstractions/HtmlContentBuilderExtensions.cs index 5d0b82dd5e..2ff745cdf3 100644 --- a/src/Microsoft.AspNet.Html.Abstractions/HtmlContentBuilderExtensions.cs +++ b/src/Microsoft.AspNet.Html.Abstractions/HtmlContentBuilderExtensions.cs @@ -48,7 +48,7 @@ namespace Microsoft.AspNet.Html throw new ArgumentNullException(nameof(args)); } - builder.Append(new HtmlFormatString(format, args)); + builder.AppendHtml(new HtmlFormatString(format, args)); return builder; } @@ -88,7 +88,7 @@ namespace Microsoft.AspNet.Html throw new ArgumentNullException(nameof(args)); } - builder.Append(new HtmlFormatString(formatProvider, format, args)); + builder.AppendHtml(new HtmlFormatString(formatProvider, format, args)); return builder; } @@ -104,7 +104,7 @@ namespace Microsoft.AspNet.Html throw new ArgumentNullException(nameof(builder)); } - builder.Append(HtmlEncodedString.NewLine); + builder.AppendHtml(HtmlEncodedString.NewLine); return builder; } @@ -123,7 +123,7 @@ namespace Microsoft.AspNet.Html } builder.Append(unencoded); - builder.Append(HtmlEncodedString.NewLine); + builder.AppendHtml(HtmlEncodedString.NewLine); return builder; } @@ -140,8 +140,8 @@ namespace Microsoft.AspNet.Html throw new ArgumentNullException(nameof(builder)); } - builder.Append(content); - builder.Append(HtmlEncodedString.NewLine); + builder.AppendHtml(content); + builder.AppendHtml(HtmlEncodedString.NewLine); return builder; } @@ -160,7 +160,7 @@ namespace Microsoft.AspNet.Html } builder.AppendHtml(encoded); - builder.Append(HtmlEncodedString.NewLine); + builder.AppendHtml(HtmlEncodedString.NewLine); return builder; } @@ -197,7 +197,7 @@ namespace Microsoft.AspNet.Html } builder.Clear(); - builder.Append(content); + builder.AppendHtml(content); return builder; } diff --git a/src/Microsoft.AspNet.Html.Abstractions/IHtmlContentBuilder.cs b/src/Microsoft.AspNet.Html.Abstractions/IHtmlContentBuilder.cs index de4b9ebd90..6b0a6d6571 100644 --- a/src/Microsoft.AspNet.Html.Abstractions/IHtmlContentBuilder.cs +++ b/src/Microsoft.AspNet.Html.Abstractions/IHtmlContentBuilder.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNet.Html /// /// The to append. /// The . - IHtmlContentBuilder Append(IHtmlContent content); + IHtmlContentBuilder AppendHtml(IHtmlContent content); /// /// Appends a value. The value is treated as unencoded as-provided, and will be HTML diff --git a/test/Microsoft.AspNet.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs b/test/Microsoft.AspNet.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs index 9355d507d3..ff201b494c 100644 --- a/test/Microsoft.AspNet.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs +++ b/test/Microsoft.AspNet.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs @@ -374,7 +374,7 @@ namespace Microsoft.AspNet.Html.Test return this; } - public IHtmlContentBuilder Append(IHtmlContent content) + public IHtmlContentBuilder AppendHtml(IHtmlContent content) { Entries.Add(content); return this; diff --git a/test/Microsoft.AspNet.Html.Abstractions.Test/HtmlContentBuilderTest.cs b/test/Microsoft.AspNet.Html.Abstractions.Test/HtmlContentBuilderTest.cs index 4eee28e219..c9eda50adc 100644 --- a/test/Microsoft.AspNet.Html.Abstractions.Test/HtmlContentBuilderTest.cs +++ b/test/Microsoft.AspNet.Html.Abstractions.Test/HtmlContentBuilderTest.cs @@ -65,7 +65,7 @@ namespace Microsoft.Extensions.Internal var writer = new StringWriter(); // Act - content.Append(new TestHtmlContent("Hello")); + content.AppendHtml(new TestHtmlContent("Hello")); // Assert var result = Assert.Single(content.Entries); @@ -81,7 +81,7 @@ namespace Microsoft.Extensions.Internal var content = new HtmlContentBuilder(); // Act - content.Append(new TestHtmlContent("hello")); + content.AppendHtml(new TestHtmlContent("hello")); content.Append("Test"); // Assert @@ -95,7 +95,7 @@ namespace Microsoft.Extensions.Internal { // Arrange var content = new HtmlContentBuilder(); - content.Append(new TestHtmlContent("hello")); + content.AppendHtml(new TestHtmlContent("hello")); content.Append("Test"); // Act @@ -111,7 +111,7 @@ namespace Microsoft.Extensions.Internal // Arrange var content = new HtmlContentBuilder(); var writer = new StringWriter(); - content.Append(new TestHtmlContent("Hello")); + content.AppendHtml(new TestHtmlContent("Hello")); content.Append("Test"); // Act From 54ae0b929655ddafc2922c038863a9c73892de77 Mon Sep 17 00:00:00 2001 From: Brennan Date: Wed, 6 Jan 2016 13:19:33 -0800 Subject: [PATCH 0059/1029] Unsource CommandLineUtils --- src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs | 2 +- src/Microsoft.Dnx.Watcher/Program.cs | 3 +-- src/Microsoft.Dnx.Watcher/project.json | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs b/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs index ca0763fdc1..a9bfe7d078 100644 --- a/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs +++ b/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.Dnx.Runtime.Common.CommandLine; +using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Logging; namespace Microsoft.Dnx.Watcher diff --git a/src/Microsoft.Dnx.Watcher/Program.cs b/src/Microsoft.Dnx.Watcher/Program.cs index 7faf51b813..e9e8d720ca 100644 --- a/src/Microsoft.Dnx.Watcher/Program.cs +++ b/src/Microsoft.Dnx.Watcher/Program.cs @@ -6,9 +6,8 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.Extensions.CompilationAbstractions; +using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.PlatformAbstractions; -using Microsoft.Dnx.Runtime.Common.CommandLine; using Microsoft.Dnx.Watcher.Core; using Microsoft.Extensions.Logging; diff --git a/src/Microsoft.Dnx.Watcher/project.json b/src/Microsoft.Dnx.Watcher/project.json index 2a32dcc292..cbd29d5335 100644 --- a/src/Microsoft.Dnx.Watcher/project.json +++ b/src/Microsoft.Dnx.Watcher/project.json @@ -7,7 +7,7 @@ }, "dependencies": { "Microsoft.Dnx.Watcher.Core": "1.0.0-*", - "Microsoft.Extensions.CommandLineUtils.Sources": { "version": "1.0.0-*", "type": "build" }, + "Microsoft.Extensions.CommandLineUtils": "1.0.0-*", "Microsoft.Extensions.Logging": "1.0.0-*", "Microsoft.Extensions.Logging.Console": "1.0.0-*" }, From d113f7edc97a23993c1f8324da7bf2577f709100 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Wed, 6 Jan 2016 14:49:54 -0800 Subject: [PATCH 0060/1029] Build with dotnet --- .gitattributes | 1 + .gitignore | 2 + .travis.yml | 8 ++- build.cmd | 68 +++++++++---------- build.sh | 47 +++++++------ .../project.json | 12 +++- .../project.json | 13 +++- 7 files changed, 88 insertions(+), 63 deletions(-) diff --git a/.gitattributes b/.gitattributes index bdaa5ba982..66abdf279e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -48,3 +48,4 @@ *.fsproj text=auto *.dbproj text=auto *.sln text=auto eol=crlf +*.sh eol=lf \ No newline at end of file diff --git a/.gitignore b/.gitignore index 329a307cda..980ee002d9 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,5 @@ nuget.exe node_modules **/[Cc]ompiler/[Rr]esources/**/*.js *launchSettings.json +.build/ +.testPublish/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index c0befaffcf..e8f77f0f14 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,9 +10,11 @@ addons: - libssl-dev - libunwind8 - zlib1g -env: - - KOREBUILD_DNU_RESTORE_CORECLR=true KOREBUILD_TEST_DNXCORE=true mono: - 4.0.5 +os: + - linux + - osx +osx_image: xcode7.1 script: - - ./build.sh --quiet verify + - ./build.sh --quiet verify \ No newline at end of file diff --git a/build.cmd b/build.cmd index 553e3929a0..65fb3e3353 100644 --- a/build.cmd +++ b/build.cmd @@ -1,40 +1,40 @@ -@echo off -cd %~dp0 - +@ECHO off SETLOCAL + +SET REPO_FOLDER=%~dp0 +CD "%REPO_FOLDER%" + +SET BUILD_FOLDER=.build +SET KOREBUILD_FOLDER=%BUILD_FOLDER%\KoreBuild-dotnet +SET KOREBUILD_VERSION= + +SET NUGET_PATH=%BUILD_FOLDER%\NuGet.exe SET NUGET_VERSION=latest SET CACHED_NUGET=%LocalAppData%\NuGet\nuget.%NUGET_VERSION%.exe -SET BUILDCMD_KOREBUILD_VERSION= -SET BUILDCMD_DNX_VERSION= -IF EXIST %CACHED_NUGET% goto copynuget -echo Downloading latest version of NuGet.exe... -IF NOT EXIST %LocalAppData%\NuGet md %LocalAppData%\NuGet -@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/%NUGET_VERSION%/nuget.exe' -OutFile '%CACHED_NUGET%'" - -:copynuget -IF EXIST .nuget\nuget.exe goto restore -md .nuget -copy %CACHED_NUGET% .nuget\nuget.exe > nul - -:restore -IF EXIST packages\Sake goto getdnx -IF "%BUILDCMD_KOREBUILD_VERSION%"=="" ( - .nuget\nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre -) ELSE ( - .nuget\nuget.exe install KoreBuild -version %BUILDCMD_KOREBUILD_VERSION% -ExcludeVersion -o packages -nocache -pre -) -.nuget\NuGet.exe install Sake -ExcludeVersion -Source https://www.nuget.org/api/v2/ -Out packages - -:getdnx -IF "%BUILDCMD_DNX_VERSION%"=="" ( - SET BUILDCMD_DNX_VERSION=latest -) -IF "%SKIP_DNX_INSTALL%"=="" ( - CALL packages\KoreBuild\build\dnvm install %BUILDCMD_DNX_VERSION% -runtime CoreCLR -arch x86 -alias default - CALL packages\KoreBuild\build\dnvm install default -runtime CLR -arch x86 -alias default -) ELSE ( - CALL packages\KoreBuild\build\dnvm use default -runtime CLR -arch x86 +IF NOT EXIST %BUILD_FOLDER% ( + md %BUILD_FOLDER% ) -packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %* +IF NOT EXIST %NUGET_PATH% ( + IF NOT EXIST %CACHED_NUGET% ( + echo Downloading latest version of NuGet.exe... + IF NOT EXIST %LocalAppData%\NuGet ( + md %LocalAppData%\NuGet + ) + @powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/%NUGET_VERSION%/nuget.exe' -OutFile '%CACHED_NUGET%'" + ) + + copy %CACHED_NUGET% %NUGET_PATH% > nul +) + +IF NOT EXIST %KOREBUILD_FOLDER% ( + SET KOREBUILD_DOWNLOAD_ARGS= + IF NOT "%KOREBUILD_VERSION%"=="" ( + SET KOREBUILD_DOWNLOAD_ARGS=-version %KOREBUILD_VERSION% + ) + + %BUILD_FOLDER%\nuget.exe install KoreBuild-dotnet -ExcludeVersion -o %BUILD_FOLDER% -nocache -pre %KOREBUILD_DOWNLOAD_ARGS% +) + +"%KOREBUILD_FOLDER%\build\KoreBuild.cmd" %* diff --git a/build.sh b/build.sh index da4e3fcd1c..7b5e25e3a8 100755 --- a/build.sh +++ b/build.sh @@ -1,5 +1,18 @@ #!/usr/bin/env bash +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located +done +repoFolder="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + +buildFolder=.build +koreBuildFolder=$buildFolder/KoreBuild-dotnet + +nugetPath=$buildFolder/nuget.exe + if test `uname` = Darwin; then cachedir=~/Library/Caches/KBuild else @@ -11,33 +24,25 @@ else fi mkdir -p $cachedir nugetVersion=latest -cachePath=$cachedir/nuget.$nugetVersion.exe +cacheNuget=$cachedir/nuget.$nugetVersion.exe -url=https://dist.nuget.org/win-x86-commandline/$nugetVersion/nuget.exe +nugetUrl=https://dist.nuget.org/win-x86-commandline/$nugetVersion/nuget.exe -if test ! -f $cachePath; then - wget -O $cachePath $url 2>/dev/null || curl -o $cachePath --location $url /dev/null +if test ! -d $buildFolder; then + mkdir $buildFolder fi -if test ! -e .nuget; then - mkdir .nuget - cp $cachePath .nuget/nuget.exe +if test ! -f $nugetPath; then + if test ! -f $cacheNuget; then + wget -O $cacheNuget $nugetUrl 2>/dev/null || curl -o $cacheNuget --location $nugetUrl /dev/null + fi + + cp $cacheNuget $nugetPath fi -if test ! -d packages/Sake; then - mono .nuget/nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre - mono .nuget/nuget.exe install Sake -ExcludeVersion -Source https://www.nuget.org/api/v2/ -Out packages +if test ! -d $koreBuildFolder; then + mono $nugetPath install KoreBuild-dotnet -ExcludeVersion -o $buildFolder -nocache -pre fi -if ! type dnvm > /dev/null 2>&1; then - source packages/KoreBuild/build/dnvm.sh -fi +source $koreBuildFolder/build/KoreBuild.sh -if ! type dnx > /dev/null 2>&1 || [ -z "$SKIP_DNX_INSTALL" ]; then - dnvm install latest -runtime coreclr -alias default - dnvm install default -runtime mono -alias default -else - dnvm use default -runtime mono -fi - -mono packages/Sake/tools/Sake.exe -I packages/KoreBuild/build -f makefile.shade "$@" diff --git a/test/Microsoft.AspNet.Html.Abstractions.Test/project.json b/test/Microsoft.AspNet.Html.Abstractions.Test/project.json index e3035cbf59..8adc45cf51 100644 --- a/test/Microsoft.AspNet.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNet.Html.Abstractions.Test/project.json @@ -7,16 +7,22 @@ "Microsoft.AspNet.Html.Abstractions": "1.0.0-*", "Microsoft.AspNet.Testing": "1.0.0-*", "Microsoft.Extensions.WebEncoders": "1.0.0-*", - "xunit.runner.aspnet": "2.0.0-aspnet-*" + "xunit": "2.1.0" }, + "testRunner": "xunit", "commands": { "test": "xunit.runner.aspnet" }, "frameworks": { - "dnx451": { }, + "dnx451": { + "dependencies": { + "xunit.runner.console": "2.1.0" + } + }, "dnxcore50": { "dependencies": { - "System.Runtime": "4.0.21-*" + "System.Runtime": "4.0.21-*", + "xunit.runner.aspnet": "2.0.0-aspnet-*" } } } diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index 62fb30b458..c588c7a29e 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -4,6 +4,7 @@ "Microsoft.Extensions.WebEncoders": "1.0.0-*", "xunit.runner.aspnet": "2.0.0-aspnet-*" }, + "testRunner": "xunit", "commands": { "test": "xunit.runner.aspnet" }, @@ -13,7 +14,15 @@ "keyFile": "../../tools/Key.snk" }, "frameworks": { - "dnx451": { }, - "dnxcore50": { } + "dnx451": { + "dependencies": { + "xunit.runner.console": "2.1.0" + } + }, + "dnxcore50": { + "dependencies": { + "xunit.runner.aspnet": "2.0.0-aspnet-*" + } + } } } From 1dba1cc6613faec1fe14a06aa445def8a0611e0b Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 13 Jan 2016 18:25:44 -0800 Subject: [PATCH 0061/1029] Bumping Json.Net version to 8.0.1 --- src/Microsoft.AspNet.JsonPatch/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.AspNet.JsonPatch/project.json b/src/Microsoft.AspNet.JsonPatch/project.json index 4bbe747d4b..d026fc5266 100644 --- a/src/Microsoft.AspNet.JsonPatch/project.json +++ b/src/Microsoft.AspNet.JsonPatch/project.json @@ -9,7 +9,7 @@ "url": "git://github.com/aspnet/mvc" }, "dependencies": { - "Newtonsoft.Json": "6.0.6" + "Newtonsoft.Json": "8.0.1" }, "frameworks": { "net451": {}, From 9ad62d796332572a5ddc4601b87687b08488c474 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 15 Jan 2016 15:36:29 -0800 Subject: [PATCH 0062/1029] Updating to Newtonsoft.Json 8.0.2 --- src/Microsoft.AspNet.JsonPatch/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.AspNet.JsonPatch/project.json b/src/Microsoft.AspNet.JsonPatch/project.json index d026fc5266..0b9789d9c2 100644 --- a/src/Microsoft.AspNet.JsonPatch/project.json +++ b/src/Microsoft.AspNet.JsonPatch/project.json @@ -9,7 +9,7 @@ "url": "git://github.com/aspnet/mvc" }, "dependencies": { - "Newtonsoft.Json": "8.0.1" + "Newtonsoft.Json": "8.0.2" }, "frameworks": { "net451": {}, From 9a05ea80c47bc6b61b1a85143eb4b3132b39102e Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 20 Jan 2016 20:47:18 -0800 Subject: [PATCH 0063/1029] Removing System.Runtime.Extensions --- src/Microsoft.Dnx.Watcher.Core/project.json | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Microsoft.Dnx.Watcher.Core/project.json b/src/Microsoft.Dnx.Watcher.Core/project.json index e88a593bb6..f723d1341c 100644 --- a/src/Microsoft.Dnx.Watcher.Core/project.json +++ b/src/Microsoft.Dnx.Watcher.Core/project.json @@ -27,7 +27,6 @@ "dependencies": { "System.Diagnostics.Process": "4.1.0-*", "System.Linq": "4.0.1-*", - "System.Runtime.Extensions": "4.0.11-*", "System.Threading.Thread": "4.0.0-*" } } From 40bbad426246962a4715747b641bf24996d204fa Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 20 Jan 2016 20:59:53 -0800 Subject: [PATCH 0064/1029] Reacting to CoreCLR package version change --- src/Microsoft.AspNet.JsonPatch/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.AspNet.JsonPatch/project.json b/src/Microsoft.AspNet.JsonPatch/project.json index 0b9789d9c2..4d1206eefb 100644 --- a/src/Microsoft.AspNet.JsonPatch/project.json +++ b/src/Microsoft.AspNet.JsonPatch/project.json @@ -21,7 +21,7 @@ "System.Globalization": "4.0.11-*", "System.Reflection.Extensions": "4.0.1-*", "System.Resources.ResourceManager": "4.0.1-*", - "System.Runtime.Extensions": "4.0.11-*", + "System.Runtime.Extensions": "4.1.0-*", "System.Text.Encoding.Extensions": "4.0.11-*" } } From d20b14d84645b071b502f737b09f22ebff9f8c1a Mon Sep 17 00:00:00 2001 From: Brennan Date: Thu, 21 Jan 2016 16:45:43 -0800 Subject: [PATCH 0065/1029] React to Fileproviders namespace changes --- src/Microsoft.Dnx.Watcher.Core/project.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Dnx.Watcher.Core/project.json b/src/Microsoft.Dnx.Watcher.Core/project.json index f723d1341c..c6c1c405d0 100644 --- a/src/Microsoft.Dnx.Watcher.Core/project.json +++ b/src/Microsoft.Dnx.Watcher.Core/project.json @@ -5,8 +5,8 @@ "keyFile": "../../tools/Key.snk" }, "dependencies": { - "Microsoft.AspNet.FileProviders.Abstractions": "1.0.0-*", - "Microsoft.AspNet.FileProviders.Physical": "1.0.0-*", + "Microsoft.Extensions.FileProviders.Abstractions": "1.0.0-*", + "Microsoft.Extensions.FileProviders.Physical": "1.0.0-*", "Microsoft.Extensions.PlatformAbstractions": "1.0.0-*", "Microsoft.Extensions.CompilationAbstractions": "1.0.0-*", "Microsoft.Extensions.JsonParser.Sources": { From 3e2798957a713a37e24b95344f07f75a86d65689 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Fri, 22 Jan 2016 11:42:34 -0800 Subject: [PATCH 0066/1029] Exit on change option --- src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs | 12 ++++++++++++ src/Microsoft.Dnx.Watcher/Program.cs | 9 ++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs b/src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs index e8f03f8e6b..b4a27a9afb 100644 --- a/src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs +++ b/src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs @@ -19,6 +19,8 @@ namespace Microsoft.Dnx.Watcher.Core private readonly ILogger _logger; + public bool ExitOnChange { get; set; } + public DnxWatcher( Func fileWatcherFactory, Func processWatcherFactory, @@ -88,6 +90,11 @@ namespace Microsoft.Dnx.Watcher.Core _logger.LogError($"dnx exit code: {dnxExitCode}"); } + if (ExitOnChange) + { + break; + } + _logger.LogInformation("Waiting for a file to change before restarting dnx..."); // Now wait for a file to change before restarting dnx await WaitForProjectFileToChangeAsync(project, cancellationToken); @@ -97,6 +104,11 @@ namespace Microsoft.Dnx.Watcher.Core // This is a file watcher task string changedFile = fileWatchingTask.Result; _logger.LogInformation($"File changed: {fileWatchingTask.Result}"); + + if (ExitOnChange) + { + break; + } } } } diff --git a/src/Microsoft.Dnx.Watcher/Program.cs b/src/Microsoft.Dnx.Watcher/Program.cs index e9e8d720ca..f2b2d9c104 100644 --- a/src/Microsoft.Dnx.Watcher/Program.cs +++ b/src/Microsoft.Dnx.Watcher/Program.cs @@ -77,10 +77,15 @@ namespace Microsoft.Dnx.Watcher CommandOptionType.SingleValue); var workingDirArg = app.Option( - "--workingDir ", + "--working-dir ", "The working directory for DNX. Defaults to the current directory.", CommandOptionType.SingleValue); + var exitOnChangeArg = app.Option( + "--exit-on-change", + "The watcher will exit when a file change is detected instead of restarting the process.", + CommandOptionType.NoValue); + // This option is here just to be displayed in help // it will not be parsed because it is removed before the code is executed app.Option( @@ -104,6 +109,8 @@ namespace Microsoft.Dnx.Watcher Directory.GetCurrentDirectory(); var watcher = DnxWatcher.CreateDefault(_loggerFactory); + watcher.ExitOnChange = exitOnChangeArg.HasValue(); + try { watcher.WatchAsync(projectToRun, dnxArgs, workingDir, cancellationToken).Wait(); From c564dfd20241e5f4eb81367ac5cc8ad494028773 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Fri, 22 Jan 2016 12:19:22 -0800 Subject: [PATCH 0067/1029] Rename AspNet 5 folders and files. See https://github.com/aspnet/Announcements/issues/144 for more information. --- .../HtmlContentBuilder.cs | 0 .../HtmlContentBuilderExtensions.cs | 0 .../HtmlEncodedString.cs | 0 .../HtmlTextWriter.cs | 0 .../IHtmlContent.cs | 0 .../IHtmlContentBuilder.cs | 0 .../Microsoft.AspNetCore.Html.Abstractions.xproj} | 0 .../Properties/AssemblyInfo.cs | 0 .../project.json | 0 .../HtmlContentBuilderExtensionsTest.cs | 0 .../HtmlContentBuilderTest.cs | 0 .../Microsoft.AspNetCore.Html.Abstractions.Test.xproj} | 0 .../project.json | 0 13 files changed, 0 insertions(+), 0 deletions(-) rename src/{Microsoft.AspNet.Html.Abstractions => Microsoft.AspNetCore.Html.Abstractions}/HtmlContentBuilder.cs (100%) rename src/{Microsoft.AspNet.Html.Abstractions => Microsoft.AspNetCore.Html.Abstractions}/HtmlContentBuilderExtensions.cs (100%) rename src/{Microsoft.AspNet.Html.Abstractions => Microsoft.AspNetCore.Html.Abstractions}/HtmlEncodedString.cs (100%) rename src/{Microsoft.AspNet.Html.Abstractions => Microsoft.AspNetCore.Html.Abstractions}/HtmlTextWriter.cs (100%) rename src/{Microsoft.AspNet.Html.Abstractions => Microsoft.AspNetCore.Html.Abstractions}/IHtmlContent.cs (100%) rename src/{Microsoft.AspNet.Html.Abstractions => Microsoft.AspNetCore.Html.Abstractions}/IHtmlContentBuilder.cs (100%) rename src/{Microsoft.AspNet.Html.Abstractions/Microsoft.AspNet.Html.Abstractions.xproj => Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.xproj} (100%) rename src/{Microsoft.AspNet.Html.Abstractions => Microsoft.AspNetCore.Html.Abstractions}/Properties/AssemblyInfo.cs (100%) rename src/{Microsoft.AspNet.Html.Abstractions => Microsoft.AspNetCore.Html.Abstractions}/project.json (100%) rename test/{Microsoft.AspNet.Html.Abstractions.Test => Microsoft.AspNetCore.Html.Abstractions.Test}/HtmlContentBuilderExtensionsTest.cs (100%) rename test/{Microsoft.AspNet.Html.Abstractions.Test => Microsoft.AspNetCore.Html.Abstractions.Test}/HtmlContentBuilderTest.cs (100%) rename test/{Microsoft.AspNet.Html.Abstractions.Test/Microsoft.AspNet.Html.Abstractions.Test.xproj => Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.xproj} (100%) rename test/{Microsoft.AspNet.Html.Abstractions.Test => Microsoft.AspNetCore.Html.Abstractions.Test}/project.json (100%) diff --git a/src/Microsoft.AspNet.Html.Abstractions/HtmlContentBuilder.cs b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilder.cs similarity index 100% rename from src/Microsoft.AspNet.Html.Abstractions/HtmlContentBuilder.cs rename to src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilder.cs diff --git a/src/Microsoft.AspNet.Html.Abstractions/HtmlContentBuilderExtensions.cs b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilderExtensions.cs similarity index 100% rename from src/Microsoft.AspNet.Html.Abstractions/HtmlContentBuilderExtensions.cs rename to src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilderExtensions.cs diff --git a/src/Microsoft.AspNet.Html.Abstractions/HtmlEncodedString.cs b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlEncodedString.cs similarity index 100% rename from src/Microsoft.AspNet.Html.Abstractions/HtmlEncodedString.cs rename to src/Microsoft.AspNetCore.Html.Abstractions/HtmlEncodedString.cs diff --git a/src/Microsoft.AspNet.Html.Abstractions/HtmlTextWriter.cs b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlTextWriter.cs similarity index 100% rename from src/Microsoft.AspNet.Html.Abstractions/HtmlTextWriter.cs rename to src/Microsoft.AspNetCore.Html.Abstractions/HtmlTextWriter.cs diff --git a/src/Microsoft.AspNet.Html.Abstractions/IHtmlContent.cs b/src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContent.cs similarity index 100% rename from src/Microsoft.AspNet.Html.Abstractions/IHtmlContent.cs rename to src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContent.cs diff --git a/src/Microsoft.AspNet.Html.Abstractions/IHtmlContentBuilder.cs b/src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContentBuilder.cs similarity index 100% rename from src/Microsoft.AspNet.Html.Abstractions/IHtmlContentBuilder.cs rename to src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContentBuilder.cs diff --git a/src/Microsoft.AspNet.Html.Abstractions/Microsoft.AspNet.Html.Abstractions.xproj b/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.xproj similarity index 100% rename from src/Microsoft.AspNet.Html.Abstractions/Microsoft.AspNet.Html.Abstractions.xproj rename to src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.xproj diff --git a/src/Microsoft.AspNet.Html.Abstractions/Properties/AssemblyInfo.cs b/src/Microsoft.AspNetCore.Html.Abstractions/Properties/AssemblyInfo.cs similarity index 100% rename from src/Microsoft.AspNet.Html.Abstractions/Properties/AssemblyInfo.cs rename to src/Microsoft.AspNetCore.Html.Abstractions/Properties/AssemblyInfo.cs diff --git a/src/Microsoft.AspNet.Html.Abstractions/project.json b/src/Microsoft.AspNetCore.Html.Abstractions/project.json similarity index 100% rename from src/Microsoft.AspNet.Html.Abstractions/project.json rename to src/Microsoft.AspNetCore.Html.Abstractions/project.json diff --git a/test/Microsoft.AspNet.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs b/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs similarity index 100% rename from test/Microsoft.AspNet.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs rename to test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs diff --git a/test/Microsoft.AspNet.Html.Abstractions.Test/HtmlContentBuilderTest.cs b/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderTest.cs similarity index 100% rename from test/Microsoft.AspNet.Html.Abstractions.Test/HtmlContentBuilderTest.cs rename to test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderTest.cs diff --git a/test/Microsoft.AspNet.Html.Abstractions.Test/Microsoft.AspNet.Html.Abstractions.Test.xproj b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.xproj similarity index 100% rename from test/Microsoft.AspNet.Html.Abstractions.Test/Microsoft.AspNet.Html.Abstractions.Test.xproj rename to test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.xproj diff --git a/test/Microsoft.AspNet.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json similarity index 100% rename from test/Microsoft.AspNet.Html.Abstractions.Test/project.json rename to test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json From 79558ae8d3633f1fd9045239bf21286e50159fe4 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Fri, 22 Jan 2016 12:19:23 -0800 Subject: [PATCH 0068/1029] Rename AspNet 5 file contents. See https://github.com/aspnet/Announcements/issues/144 for more information. --- HtmlAbstractions.sln | 4 ++-- NuGetPackageVerifier.json | 2 +- .../HtmlContentBuilder.cs | 4 ++-- .../HtmlContentBuilderExtensions.cs | 2 +- .../HtmlEncodedString.cs | 4 ++-- src/Microsoft.AspNetCore.Html.Abstractions/HtmlTextWriter.cs | 4 ++-- src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContent.cs | 2 +- .../IHtmlContentBuilder.cs | 4 ++-- .../Microsoft.AspNetCore.Html.Abstractions.xproj | 4 ++-- .../Properties/AssemblyInfo.cs | 2 +- .../HtmlContentBuilderExtensionsTest.cs | 4 ++-- .../HtmlContentBuilderTest.cs | 2 +- .../Microsoft.AspNetCore.Html.Abstractions.Test.xproj | 4 ++-- test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json | 4 ++-- 14 files changed, 23 insertions(+), 23 deletions(-) diff --git a/HtmlAbstractions.sln b/HtmlAbstractions.sln index a45f34a265..81189bb447 100644 --- a/HtmlAbstractions.sln +++ b/HtmlAbstractions.sln @@ -6,9 +6,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A5A15F1C-885 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F31FF137-390C-49BF-A3BD-7C6ED3597C21}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Html.Abstractions", "src\Microsoft.AspNet.Html.Abstractions\Microsoft.AspNet.Html.Abstractions.xproj", "{68A28E4A-3ADE-4187-9625-4FF185887CB3}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Html.Abstractions", "src\Microsoft.AspNetCore.Html.Abstractions\Microsoft.AspNetCore.Html.Abstractions.xproj", "{68A28E4A-3ADE-4187-9625-4FF185887CB3}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Html.Abstractions.Test", "test\Microsoft.AspNet.Html.Abstractions.Test\Microsoft.AspNet.Html.Abstractions.Test.xproj", "{2D187B88-94BD-4A39-AC97-F8F8B9363301}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Html.Abstractions.Test", "test\Microsoft.AspNetCore.Html.Abstractions.Test\Microsoft.AspNetCore.Html.Abstractions.Test.xproj", "{2D187B88-94BD-4A39-AC97-F8F8B9363301}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B4962A29-BE69-4A18-9B4F-B803EEE31EAA}" ProjectSection(SolutionItems) = preProject diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index 31f9437602..d9dea7c8ac 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -9,7 +9,7 @@ "StrictSemanticVersionValidationRule" ], "packages": { - "Microsoft.AspNet.Html.Abstractions": { }, + "Microsoft.AspNetCore.Html.Abstractions": { }, "Microsoft.Extensions.WebEncoders": { } } }, diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilder.cs b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilder.cs index 10a50cb34d..b79e400375 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilder.cs +++ b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilder.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.IO; using System.Text.Encodings.Web; -namespace Microsoft.AspNet.Html +namespace Microsoft.AspNetCore.Html { /// /// An implementation using an in memory list. diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilderExtensions.cs b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilderExtensions.cs index 2ff745cdf3..aaba4faefb 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilderExtensions.cs @@ -7,7 +7,7 @@ using System.Globalization; using System.IO; using System.Text.Encodings.Web; -namespace Microsoft.AspNet.Html +namespace Microsoft.AspNetCore.Html { /// /// Extension methods for . diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlEncodedString.cs b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlEncodedString.cs index e5c4ab5003..c50fba890c 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlEncodedString.cs +++ b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlEncodedString.cs @@ -1,11 +1,11 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.IO; using System.Text.Encodings.Web; -namespace Microsoft.AspNet.Html +namespace Microsoft.AspNetCore.Html { /// /// An implementation that wraps an HTML encoded . diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlTextWriter.cs b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlTextWriter.cs index 56633f527d..c9158b49b6 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlTextWriter.cs +++ b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlTextWriter.cs @@ -1,9 +1,9 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.IO; -namespace Microsoft.AspNet.Html +namespace Microsoft.AspNetCore.Html { /// /// A which supports special processing of . diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContent.cs b/src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContent.cs index 0e21889d54..2e9a0f19e2 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContent.cs +++ b/src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContent.cs @@ -4,7 +4,7 @@ using System.IO; using System.Text.Encodings.Web; -namespace Microsoft.AspNet.Html +namespace Microsoft.AspNetCore.Html { /// /// HTML content which can be written to a TextWriter. diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContentBuilder.cs b/src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContentBuilder.cs index 6b0a6d6571..978fedc03f 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContentBuilder.cs +++ b/src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContentBuilder.cs @@ -1,7 +1,7 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNet.Html +namespace Microsoft.AspNetCore.Html { /// /// A builder for HTML content. diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.xproj b/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.xproj index 564c800504..df229c75eb 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.xproj +++ b/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.xproj @@ -1,4 +1,4 @@ - + 14.0 @@ -7,7 +7,7 @@ 68a28e4a-3ade-4187-9625-4ff185887cb3 - Microsoft.AspNet.Html.Abstractions + Microsoft.AspNetCore.Html.Abstractions ..\..\artifacts\obj\$(MSBuildProjectName) ..\..\artifacts\bin\$(MSBuildProjectName)\ diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/Properties/AssemblyInfo.cs b/src/Microsoft.AspNetCore.Html.Abstractions/Properties/AssemblyInfo.cs index d310306c25..72210dd611 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/Properties/AssemblyInfo.cs +++ b/src/Microsoft.AspNetCore.Html.Abstractions/Properties/AssemblyInfo.cs @@ -7,4 +7,4 @@ using System.Runtime.CompilerServices; [assembly: AssemblyMetadata("Serviceable", "True")] [assembly: NeutralResourcesLanguage("en-us")] -[assembly: InternalsVisibleTo("Microsoft.AspNet.Html.Abstractions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] \ No newline at end of file +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Html.Abstractions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs b/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs index ff201b494c..6b4307f690 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs @@ -6,11 +6,11 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text.Encodings.Web; -using Microsoft.AspNet.Testing; +using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.WebEncoders.Testing; using Xunit; -namespace Microsoft.AspNet.Html.Test +namespace Microsoft.AspNetCore.Html.Test { public class HtmlContentBuilderExtensionsTest { diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderTest.cs b/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderTest.cs index c9eda50adc..901512fdad 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderTest.cs +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderTest.cs @@ -3,7 +3,7 @@ using System.IO; using System.Text.Encodings.Web; -using Microsoft.AspNet.Html; +using Microsoft.AspNetCore.Html; using Microsoft.Extensions.WebEncoders.Testing; using Xunit; diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.xproj b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.xproj index 4a03567677..f699a1c4dc 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.xproj +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.xproj @@ -1,4 +1,4 @@ - + 14.0 @@ -7,7 +7,7 @@ 2d187b88-94bd-4a39-ac97-f8f8b9363301 - Microsoft.AspNet.Html.Abstractions.Test + Microsoft.AspNetCore.Html.Abstractions.Test ..\..\artifacts\obj\$(MSBuildProjectName) ..\..\artifacts\bin\$(MSBuildProjectName)\ diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index 8adc45cf51..d796493c0a 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -4,8 +4,8 @@ "keyFile": "../../tools/Key.snk" }, "dependencies": { - "Microsoft.AspNet.Html.Abstractions": "1.0.0-*", - "Microsoft.AspNet.Testing": "1.0.0-*", + "Microsoft.AspNetCore.Html.Abstractions": "1.0.0-*", + "Microsoft.AspNetCore.Testing": "1.0.0-*", "Microsoft.Extensions.WebEncoders": "1.0.0-*", "xunit": "2.1.0" }, From 582e222c2bf4567d28cb224b78284439a6a34651 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Fri, 22 Jan 2016 12:20:54 -0800 Subject: [PATCH 0069/1029] Rename AspNet 5 folders and files. See https://github.com/aspnet/Announcements/issues/144 for more information. --- .../Adapters/IObjectAdapter.cs | 0 .../Adapters/ObjectAdapter.cs | 0 .../Converters/JsonPatchDocumentConverter.cs | 0 .../Converters/TypedJsonPatchDocumentConverter.cs | 0 .../Exceptions/JsonPatchException.cs | 0 .../Helpers/ActualPropertyPathResult.cs | 0 .../Helpers/ConversionResult.cs | 0 .../Helpers/ExpandoObjectDictionaryExtensions.cs | 0 .../Helpers/ExpressionHelpers.cs | 0 .../Helpers/GetValueResult.cs | 0 .../Helpers/JsonPatchProperty.cs | 0 .../Helpers/ObjectTreeAnalyisResult.cs | 0 .../Helpers/PathHelpers.cs | 0 .../Helpers/RemovedPropertyTypeResult.cs | 0 .../IJsonPatchDocument.cs | 0 .../JsonPatchDocument.cs | 0 .../JsonPatchDocumentOfT.cs | 0 .../JsonPatchError.cs | 0 .../Microsoft.AspNetCore.JsonPatch.xproj} | 0 .../Operations/Operation.cs | 0 .../Operations/OperationBase.cs | 0 .../Operations/OperationOfT.cs | 0 .../Operations/OperationType.cs | 0 .../Properties/AssemblyInfo.cs | 0 .../Properties/Resources.Designer.cs | 0 .../Resources.resx | 0 .../project.json | 0 .../Dynamic/AddOperationTests.cs | 0 .../Dynamic/AddTypedOperationTests.cs | 0 .../Dynamic/CopyOperationTests.cs | 0 .../Dynamic/CopyTypedOperationTests.cs | 0 .../Dynamic/MoveOperationTests.cs | 0 .../Dynamic/MoveTypedOperationTests.cs | 0 .../Dynamic/NestedDTO.cs | 0 .../Dynamic/PatchDocumentTests.cs | 0 .../Dynamic/RemoveOperationTests.cs | 0 .../Dynamic/RemoveTypedOperationTests.cs | 0 .../Dynamic/ReplaceOperationTests.cs | 0 .../Dynamic/ReplaceTypedOperationTests.cs | 0 .../Dynamic/SimpleDTO.cs | 0 .../Dynamic/SimpleDTOWithNestedDTO.cs | 0 .../Microsoft.AspNetCore.JsonPatch.Test.xproj} | 0 .../NestedDTO.cs | 0 .../NestedObjectTests.cs | 0 .../ObjectAdapterTests.cs | 0 .../SimpleDTO.cs | 0 .../SimpleDTOWithNestedDTO.cs | 0 .../TestErrorLogger.cs | 0 .../project.json | 0 49 files changed, 0 insertions(+), 0 deletions(-) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Adapters/IObjectAdapter.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Adapters/ObjectAdapter.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Converters/JsonPatchDocumentConverter.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Converters/TypedJsonPatchDocumentConverter.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Exceptions/JsonPatchException.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Helpers/ActualPropertyPathResult.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Helpers/ConversionResult.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Helpers/ExpandoObjectDictionaryExtensions.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Helpers/ExpressionHelpers.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Helpers/GetValueResult.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Helpers/JsonPatchProperty.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Helpers/ObjectTreeAnalyisResult.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Helpers/PathHelpers.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Helpers/RemovedPropertyTypeResult.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/IJsonPatchDocument.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/JsonPatchDocument.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/JsonPatchDocumentOfT.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/JsonPatchError.cs (100%) rename src/{Microsoft.AspNet.JsonPatch/Microsoft.AspNet.JsonPatch.xproj => Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.xproj} (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Operations/Operation.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Operations/OperationBase.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Operations/OperationOfT.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Operations/OperationType.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Properties/AssemblyInfo.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Properties/Resources.Designer.cs (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/Resources.resx (100%) rename src/{Microsoft.AspNet.JsonPatch => Microsoft.AspNetCore.JsonPatch}/project.json (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/Dynamic/AddOperationTests.cs (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/Dynamic/AddTypedOperationTests.cs (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/Dynamic/CopyOperationTests.cs (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/Dynamic/CopyTypedOperationTests.cs (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/Dynamic/MoveOperationTests.cs (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/Dynamic/MoveTypedOperationTests.cs (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/Dynamic/NestedDTO.cs (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/Dynamic/PatchDocumentTests.cs (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/Dynamic/RemoveOperationTests.cs (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/Dynamic/RemoveTypedOperationTests.cs (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/Dynamic/ReplaceOperationTests.cs (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/Dynamic/ReplaceTypedOperationTests.cs (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/Dynamic/SimpleDTO.cs (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/Dynamic/SimpleDTOWithNestedDTO.cs (100%) rename test/{Microsoft.AspNet.JsonPatch.Test/Microsoft.AspNet.JsonPatch.Test.xproj => Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.xproj} (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/NestedDTO.cs (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/NestedObjectTests.cs (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/ObjectAdapterTests.cs (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/SimpleDTO.cs (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/SimpleDTOWithNestedDTO.cs (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/TestErrorLogger.cs (100%) rename test/{Microsoft.AspNet.JsonPatch.Test => Microsoft.AspNetCore.JsonPatch.Test}/project.json (100%) diff --git a/src/Microsoft.AspNet.JsonPatch/Adapters/IObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/IObjectAdapter.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Adapters/IObjectAdapter.cs rename to src/Microsoft.AspNetCore.JsonPatch/Adapters/IObjectAdapter.cs diff --git a/src/Microsoft.AspNet.JsonPatch/Adapters/ObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Adapters/ObjectAdapter.cs rename to src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs diff --git a/src/Microsoft.AspNet.JsonPatch/Converters/JsonPatchDocumentConverter.cs b/src/Microsoft.AspNetCore.JsonPatch/Converters/JsonPatchDocumentConverter.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Converters/JsonPatchDocumentConverter.cs rename to src/Microsoft.AspNetCore.JsonPatch/Converters/JsonPatchDocumentConverter.cs diff --git a/src/Microsoft.AspNet.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs b/src/Microsoft.AspNetCore.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs rename to src/Microsoft.AspNetCore.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs diff --git a/src/Microsoft.AspNet.JsonPatch/Exceptions/JsonPatchException.cs b/src/Microsoft.AspNetCore.JsonPatch/Exceptions/JsonPatchException.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Exceptions/JsonPatchException.cs rename to src/Microsoft.AspNetCore.JsonPatch/Exceptions/JsonPatchException.cs diff --git a/src/Microsoft.AspNet.JsonPatch/Helpers/ActualPropertyPathResult.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ActualPropertyPathResult.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Helpers/ActualPropertyPathResult.cs rename to src/Microsoft.AspNetCore.JsonPatch/Helpers/ActualPropertyPathResult.cs diff --git a/src/Microsoft.AspNet.JsonPatch/Helpers/ConversionResult.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ConversionResult.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Helpers/ConversionResult.cs rename to src/Microsoft.AspNetCore.JsonPatch/Helpers/ConversionResult.cs diff --git a/src/Microsoft.AspNet.JsonPatch/Helpers/ExpandoObjectDictionaryExtensions.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpandoObjectDictionaryExtensions.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Helpers/ExpandoObjectDictionaryExtensions.cs rename to src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpandoObjectDictionaryExtensions.cs diff --git a/src/Microsoft.AspNet.JsonPatch/Helpers/ExpressionHelpers.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpressionHelpers.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Helpers/ExpressionHelpers.cs rename to src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpressionHelpers.cs diff --git a/src/Microsoft.AspNet.JsonPatch/Helpers/GetValueResult.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/GetValueResult.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Helpers/GetValueResult.cs rename to src/Microsoft.AspNetCore.JsonPatch/Helpers/GetValueResult.cs diff --git a/src/Microsoft.AspNet.JsonPatch/Helpers/JsonPatchProperty.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/JsonPatchProperty.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Helpers/JsonPatchProperty.cs rename to src/Microsoft.AspNetCore.JsonPatch/Helpers/JsonPatchProperty.cs diff --git a/src/Microsoft.AspNet.JsonPatch/Helpers/ObjectTreeAnalyisResult.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ObjectTreeAnalyisResult.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Helpers/ObjectTreeAnalyisResult.cs rename to src/Microsoft.AspNetCore.JsonPatch/Helpers/ObjectTreeAnalyisResult.cs diff --git a/src/Microsoft.AspNet.JsonPatch/Helpers/PathHelpers.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/PathHelpers.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Helpers/PathHelpers.cs rename to src/Microsoft.AspNetCore.JsonPatch/Helpers/PathHelpers.cs diff --git a/src/Microsoft.AspNet.JsonPatch/Helpers/RemovedPropertyTypeResult.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/RemovedPropertyTypeResult.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Helpers/RemovedPropertyTypeResult.cs rename to src/Microsoft.AspNetCore.JsonPatch/Helpers/RemovedPropertyTypeResult.cs diff --git a/src/Microsoft.AspNet.JsonPatch/IJsonPatchDocument.cs b/src/Microsoft.AspNetCore.JsonPatch/IJsonPatchDocument.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/IJsonPatchDocument.cs rename to src/Microsoft.AspNetCore.JsonPatch/IJsonPatchDocument.cs diff --git a/src/Microsoft.AspNet.JsonPatch/JsonPatchDocument.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/JsonPatchDocument.cs rename to src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs diff --git a/src/Microsoft.AspNet.JsonPatch/JsonPatchDocumentOfT.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/JsonPatchDocumentOfT.cs rename to src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs diff --git a/src/Microsoft.AspNet.JsonPatch/JsonPatchError.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchError.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/JsonPatchError.cs rename to src/Microsoft.AspNetCore.JsonPatch/JsonPatchError.cs diff --git a/src/Microsoft.AspNet.JsonPatch/Microsoft.AspNet.JsonPatch.xproj b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.xproj similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Microsoft.AspNet.JsonPatch.xproj rename to src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.xproj diff --git a/src/Microsoft.AspNet.JsonPatch/Operations/Operation.cs b/src/Microsoft.AspNetCore.JsonPatch/Operations/Operation.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Operations/Operation.cs rename to src/Microsoft.AspNetCore.JsonPatch/Operations/Operation.cs diff --git a/src/Microsoft.AspNet.JsonPatch/Operations/OperationBase.cs b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationBase.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Operations/OperationBase.cs rename to src/Microsoft.AspNetCore.JsonPatch/Operations/OperationBase.cs diff --git a/src/Microsoft.AspNet.JsonPatch/Operations/OperationOfT.cs b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationOfT.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Operations/OperationOfT.cs rename to src/Microsoft.AspNetCore.JsonPatch/Operations/OperationOfT.cs diff --git a/src/Microsoft.AspNet.JsonPatch/Operations/OperationType.cs b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationType.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Operations/OperationType.cs rename to src/Microsoft.AspNetCore.JsonPatch/Operations/OperationType.cs diff --git a/src/Microsoft.AspNet.JsonPatch/Properties/AssemblyInfo.cs b/src/Microsoft.AspNetCore.JsonPatch/Properties/AssemblyInfo.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Properties/AssemblyInfo.cs rename to src/Microsoft.AspNetCore.JsonPatch/Properties/AssemblyInfo.cs diff --git a/src/Microsoft.AspNet.JsonPatch/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Properties/Resources.Designer.cs rename to src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs diff --git a/src/Microsoft.AspNet.JsonPatch/Resources.resx b/src/Microsoft.AspNetCore.JsonPatch/Resources.resx similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/Resources.resx rename to src/Microsoft.AspNetCore.JsonPatch/Resources.resx diff --git a/src/Microsoft.AspNet.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json similarity index 100% rename from src/Microsoft.AspNet.JsonPatch/project.json rename to src/Microsoft.AspNetCore.JsonPatch/project.json diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/AddOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/Dynamic/AddOperationTests.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/CopyOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyOperationTests.cs similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/Dynamic/CopyOperationTests.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyOperationTests.cs diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/MoveOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveOperationTests.cs similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/Dynamic/MoveOperationTests.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveOperationTests.cs diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/NestedDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/NestedDTO.cs similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/Dynamic/NestedDTO.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/NestedDTO.cs diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/PatchDocumentTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/PatchDocumentTests.cs similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/Dynamic/PatchDocumentTests.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/PatchDocumentTests.cs diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/RemoveOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/Dynamic/RemoveOperationTests.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/ReplaceTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceTypedOperationTests.cs similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/Dynamic/ReplaceTypedOperationTests.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceTypedOperationTests.cs diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/SimpleDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleDTO.cs similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/Dynamic/SimpleDTO.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleDTO.cs diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Dynamic/SimpleDTOWithNestedDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleDTOWithNestedDTO.cs similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/Dynamic/SimpleDTOWithNestedDTO.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleDTOWithNestedDTO.cs diff --git a/test/Microsoft.AspNet.JsonPatch.Test/Microsoft.AspNet.JsonPatch.Test.xproj b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.xproj similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/Microsoft.AspNet.JsonPatch.Test.xproj rename to test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.xproj diff --git a/test/Microsoft.AspNet.JsonPatch.Test/NestedDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/NestedDTO.cs similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/NestedDTO.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/NestedDTO.cs diff --git a/test/Microsoft.AspNet.JsonPatch.Test/NestedObjectTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/NestedObjectTests.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs diff --git a/test/Microsoft.AspNet.JsonPatch.Test/ObjectAdapterTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/ObjectAdapterTests.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs diff --git a/test/Microsoft.AspNet.JsonPatch.Test/SimpleDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTO.cs similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/SimpleDTO.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTO.cs diff --git a/test/Microsoft.AspNet.JsonPatch.Test/SimpleDTOWithNestedDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTO.cs similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/SimpleDTOWithNestedDTO.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTO.cs diff --git a/test/Microsoft.AspNet.JsonPatch.Test/TestErrorLogger.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/TestErrorLogger.cs similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/TestErrorLogger.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/TestErrorLogger.cs diff --git a/test/Microsoft.AspNet.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json similarity index 100% rename from test/Microsoft.AspNet.JsonPatch.Test/project.json rename to test/Microsoft.AspNetCore.JsonPatch.Test/project.json From e2801d6c2065acfcb4b997901f13b474a3acbe57 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Fri, 22 Jan 2016 12:20:58 -0800 Subject: [PATCH 0070/1029] Rename AspNet 5 file contents. See https://github.com/aspnet/Announcements/issues/144 for more information. --- JsonPatch.sln | 6 +++--- NuGetPackageVerifier.json | 2 +- .../Adapters/IObjectAdapter.cs | 4 ++-- .../Adapters/ObjectAdapter.cs | 8 ++++---- .../Converters/JsonPatchDocumentConverter.cs | 8 ++++---- .../Converters/TypedJsonPatchDocumentConverter.cs | 6 +++--- .../Exceptions/JsonPatchException.cs | 4 ++-- .../Helpers/ActualPropertyPathResult.cs | 4 ++-- .../Helpers/ConversionResult.cs | 2 +- .../Helpers/ExpandoObjectDictionaryExtensions.cs | 4 ++-- .../Helpers/ExpressionHelpers.cs | 2 +- .../Helpers/GetValueResult.cs | 4 ++-- .../Helpers/JsonPatchProperty.cs | 2 +- .../Helpers/ObjectTreeAnalyisResult.cs | 4 ++-- .../Helpers/PathHelpers.cs | 6 +++--- .../Helpers/RemovedPropertyTypeResult.cs | 4 ++-- .../IJsonPatchDocument.cs | 4 ++-- .../JsonPatchDocument.cs | 10 +++++----- .../JsonPatchDocumentOfT.cs | 10 +++++----- src/Microsoft.AspNetCore.JsonPatch/JsonPatchError.cs | 4 ++-- .../Operations/Operation.cs | 4 ++-- .../Operations/OperationBase.cs | 2 +- .../Operations/OperationOfT.cs | 4 ++-- .../Operations/OperationType.cs | 2 +- .../Properties/Resources.Designer.cs | 4 ++-- .../Dynamic/AddOperationTests.cs | 6 +++--- .../Dynamic/AddTypedOperationTests.cs | 6 +++--- .../Dynamic/CopyOperationTests.cs | 4 ++-- .../Dynamic/CopyTypedOperationTests.cs | 4 ++-- .../Dynamic/MoveOperationTests.cs | 4 ++-- .../Dynamic/MoveTypedOperationTests.cs | 4 ++-- .../Dynamic/NestedDTO.cs | 4 ++-- .../Dynamic/PatchDocumentTests.cs | 6 +++--- .../Dynamic/RemoveOperationTests.cs | 6 +++--- .../Dynamic/RemoveTypedOperationTests.cs | 6 +++--- .../Dynamic/ReplaceOperationTests.cs | 4 ++-- .../Dynamic/ReplaceTypedOperationTests.cs | 4 ++-- .../Dynamic/SimpleDTO.cs | 4 ++-- .../Dynamic/SimpleDTOWithNestedDTO.cs | 4 ++-- test/Microsoft.AspNetCore.JsonPatch.Test/NestedDTO.cs | 2 +- .../NestedObjectTests.cs | 4 ++-- .../ObjectAdapterTests.cs | 4 ++-- test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTO.cs | 2 +- .../SimpleDTOWithNestedDTO.cs | 2 +- .../TestErrorLogger.cs | 2 +- test/Microsoft.AspNetCore.JsonPatch.Test/project.json | 4 ++-- 46 files changed, 100 insertions(+), 100 deletions(-) diff --git a/JsonPatch.sln b/JsonPatch.sln index 01e02f3125..7149fc4551 100644 --- a/JsonPatch.sln +++ b/JsonPatch.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 VisualStudioVersion = 14.0.23107.0 @@ -7,9 +7,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{430B59ED-F96 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{36CD6341-AB44-44EB-B3AA-BF98C89FECDD}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.JsonPatch", "src\Microsoft.AspNet.JsonPatch\Microsoft.AspNet.JsonPatch.xproj", "{4D55F4D8-633B-462F-A5B1-FEB84BD2D534}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.JsonPatch", "src\Microsoft.AspNetCore.JsonPatch\Microsoft.AspNetCore.JsonPatch.xproj", "{4D55F4D8-633B-462F-A5B1-FEB84BD2D534}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.JsonPatch.Test", "test\Microsoft.AspNet.JsonPatch.Test\Microsoft.AspNet.JsonPatch.Test.xproj", "{81C20848-E063-4E12-AC40-0B55A532C16C}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.JsonPatch.Test", "test\Microsoft.AspNetCore.JsonPatch.Test\Microsoft.AspNetCore.JsonPatch.Test.xproj", "{81C20848-E063-4E12-AC40-0B55A532C16C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index a45e74c44d..e95640a3d3 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -9,7 +9,7 @@ "StrictSemanticVersionValidationRule" ], "packages": { - "Microsoft.AspNet.JsonPatch": { } + "Microsoft.AspNetCore.JsonPatch": { } } }, "Default": { // Rules to run for packages not listed in any other set. diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/IObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/IObjectAdapter.cs index 724dfe3f79..f699755ed4 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Adapters/IObjectAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/IObjectAdapter.cs @@ -1,9 +1,9 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Microsoft.AspNet.JsonPatch.Operations; +using Microsoft.AspNetCore.JsonPatch.Operations; -namespace Microsoft.AspNet.JsonPatch.Adapters +namespace Microsoft.AspNetCore.JsonPatch.Adapters { /// /// Defines the operations that can be performed on a JSON patch document. diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs index 4640e97039..aeae454fa9 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs @@ -5,13 +5,13 @@ using System; using System.Collections; using System.Collections.Generic; using System.Reflection; -using Microsoft.AspNet.JsonPatch.Exceptions; -using Microsoft.AspNet.JsonPatch.Helpers; -using Microsoft.AspNet.JsonPatch.Operations; +using Microsoft.AspNetCore.JsonPatch.Exceptions; +using Microsoft.AspNetCore.JsonPatch.Helpers; +using Microsoft.AspNetCore.JsonPatch.Operations; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; -namespace Microsoft.AspNet.JsonPatch.Adapters +namespace Microsoft.AspNetCore.JsonPatch.Adapters { /// public class ObjectAdapter : IObjectAdapter diff --git a/src/Microsoft.AspNetCore.JsonPatch/Converters/JsonPatchDocumentConverter.cs b/src/Microsoft.AspNetCore.JsonPatch/Converters/JsonPatchDocumentConverter.cs index 4551f64043..e93e84e12a 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Converters/JsonPatchDocumentConverter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Converters/JsonPatchDocumentConverter.cs @@ -1,15 +1,15 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; -using Microsoft.AspNet.JsonPatch.Exceptions; -using Microsoft.AspNet.JsonPatch.Operations; +using Microsoft.AspNetCore.JsonPatch.Exceptions; +using Microsoft.AspNetCore.JsonPatch.Operations; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; -namespace Microsoft.AspNet.JsonPatch.Converters +namespace Microsoft.AspNetCore.JsonPatch.Converters { public class JsonPatchDocumentConverter : JsonConverter { diff --git a/src/Microsoft.AspNetCore.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs b/src/Microsoft.AspNetCore.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs index 7b6bb77e17..a150bd0478 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs @@ -4,13 +4,13 @@ using System; using System.Collections.Generic; using System.Reflection; -using Microsoft.AspNet.JsonPatch.Exceptions; -using Microsoft.AspNet.JsonPatch.Operations; +using Microsoft.AspNetCore.JsonPatch.Exceptions; +using Microsoft.AspNetCore.JsonPatch.Operations; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; -namespace Microsoft.AspNet.JsonPatch.Converters +namespace Microsoft.AspNetCore.JsonPatch.Converters { public class TypedJsonPatchDocumentConverter : JsonPatchDocumentConverter { diff --git a/src/Microsoft.AspNetCore.JsonPatch/Exceptions/JsonPatchException.cs b/src/Microsoft.AspNetCore.JsonPatch/Exceptions/JsonPatchException.cs index ac5222a2bb..90e080575a 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Exceptions/JsonPatchException.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Exceptions/JsonPatchException.cs @@ -2,9 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.AspNet.JsonPatch.Operations; +using Microsoft.AspNetCore.JsonPatch.Operations; -namespace Microsoft.AspNet.JsonPatch.Exceptions +namespace Microsoft.AspNetCore.JsonPatch.Exceptions { public class JsonPatchException : Exception { diff --git a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ActualPropertyPathResult.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ActualPropertyPathResult.cs index d22d1bf830..1967bf6d90 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ActualPropertyPathResult.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ActualPropertyPathResult.cs @@ -1,7 +1,7 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNet.JsonPatch.Helpers +namespace Microsoft.AspNetCore.JsonPatch.Helpers { internal class ActualPropertyPathResult { diff --git a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ConversionResult.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ConversionResult.cs index aba4913f2d..00a7513d44 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ConversionResult.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ConversionResult.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNet.JsonPatch.Helpers +namespace Microsoft.AspNetCore.JsonPatch.Helpers { internal class ConversionResult { diff --git a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpandoObjectDictionaryExtensions.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpandoObjectDictionaryExtensions.cs index a5911dded2..aa9fa2158b 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpandoObjectDictionaryExtensions.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpandoObjectDictionaryExtensions.cs @@ -1,10 +1,10 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; -namespace Microsoft.AspNet.JsonPatch.Helpers +namespace Microsoft.AspNetCore.JsonPatch.Helpers { // Helper methods to allow case-insensitive key search internal static class ExpandoObjectDictionaryExtensions diff --git a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpressionHelpers.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpressionHelpers.cs index 6a0279876c..92880eb0e1 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpressionHelpers.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpressionHelpers.cs @@ -5,7 +5,7 @@ using System; using System.Globalization; using System.Linq.Expressions; -namespace Microsoft.AspNet.JsonPatch.Helpers +namespace Microsoft.AspNetCore.JsonPatch.Helpers { internal static class ExpressionHelpers { diff --git a/src/Microsoft.AspNetCore.JsonPatch/Helpers/GetValueResult.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/GetValueResult.cs index 89b7c93520..e2e739a027 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Helpers/GetValueResult.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Helpers/GetValueResult.cs @@ -1,7 +1,7 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNet.JsonPatch.Helpers +namespace Microsoft.AspNetCore.JsonPatch.Helpers { /// /// Return value for the helper method used by Copy/Move. Needed to ensure we can make a different diff --git a/src/Microsoft.AspNetCore.JsonPatch/Helpers/JsonPatchProperty.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/JsonPatchProperty.cs index 0539d230a3..041b0104ac 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Helpers/JsonPatchProperty.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Helpers/JsonPatchProperty.cs @@ -4,7 +4,7 @@ using System; using Newtonsoft.Json.Serialization; -namespace Microsoft.AspNet.JsonPatch +namespace Microsoft.AspNetCore.JsonPatch { /// /// Metadata for JsonProperty. diff --git a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ObjectTreeAnalyisResult.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ObjectTreeAnalyisResult.cs index 91d5ee129d..4d083bd073 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ObjectTreeAnalyisResult.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ObjectTreeAnalyisResult.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -7,7 +7,7 @@ using System.Collections.Generic; using System.Linq; using Newtonsoft.Json.Serialization; -namespace Microsoft.AspNet.JsonPatch.Helpers +namespace Microsoft.AspNetCore.JsonPatch.Helpers { internal class ObjectTreeAnalysisResult { diff --git a/src/Microsoft.AspNetCore.JsonPatch/Helpers/PathHelpers.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/PathHelpers.cs index 28683e7c98..99bb2f1536 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Helpers/PathHelpers.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Helpers/PathHelpers.cs @@ -1,9 +1,9 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Microsoft.AspNet.JsonPatch.Exceptions; +using Microsoft.AspNetCore.JsonPatch.Exceptions; -namespace Microsoft.AspNet.JsonPatch.Helpers +namespace Microsoft.AspNetCore.JsonPatch.Helpers { internal static class PathHelpers { diff --git a/src/Microsoft.AspNetCore.JsonPatch/Helpers/RemovedPropertyTypeResult.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/RemovedPropertyTypeResult.cs index 9f5b97a868..c548f55c6e 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Helpers/RemovedPropertyTypeResult.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Helpers/RemovedPropertyTypeResult.cs @@ -1,9 +1,9 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -namespace Microsoft.AspNet.JsonPatch.Helpers +namespace Microsoft.AspNetCore.JsonPatch.Helpers { /// /// Return value for Remove operation. The combination tells us what to do next (if this operation diff --git a/src/Microsoft.AspNetCore.JsonPatch/IJsonPatchDocument.cs b/src/Microsoft.AspNetCore.JsonPatch/IJsonPatchDocument.cs index 18033e82f0..fc5f5bd4d1 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/IJsonPatchDocument.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/IJsonPatchDocument.cs @@ -1,11 +1,11 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Microsoft.AspNet.JsonPatch.Operations; +using Microsoft.AspNetCore.JsonPatch.Operations; using System.Collections.Generic; using Newtonsoft.Json.Serialization; -namespace Microsoft.AspNet.JsonPatch +namespace Microsoft.AspNetCore.JsonPatch { public interface IJsonPatchDocument { diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs index fc2e73030a..c9c34459a9 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs @@ -3,14 +3,14 @@ using System; using System.Collections.Generic; -using Microsoft.AspNet.JsonPatch.Adapters; -using Microsoft.AspNet.JsonPatch.Converters; -using Microsoft.AspNet.JsonPatch.Helpers; -using Microsoft.AspNet.JsonPatch.Operations; +using Microsoft.AspNetCore.JsonPatch.Adapters; +using Microsoft.AspNetCore.JsonPatch.Converters; +using Microsoft.AspNetCore.JsonPatch.Helpers; +using Microsoft.AspNetCore.JsonPatch.Operations; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; -namespace Microsoft.AspNet.JsonPatch +namespace Microsoft.AspNetCore.JsonPatch { // Implementation details: the purpose of this type of patch document is to allow creation of such // documents for cases where there's no class/DTO to work on. Typical use case: backend not built in diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs index 7b03f1644c..530b414060 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs @@ -4,14 +4,14 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; -using Microsoft.AspNet.JsonPatch.Adapters; -using Microsoft.AspNet.JsonPatch.Converters; -using Microsoft.AspNet.JsonPatch.Helpers; -using Microsoft.AspNet.JsonPatch.Operations; +using Microsoft.AspNetCore.JsonPatch.Adapters; +using Microsoft.AspNetCore.JsonPatch.Converters; +using Microsoft.AspNetCore.JsonPatch.Helpers; +using Microsoft.AspNetCore.JsonPatch.Operations; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; -namespace Microsoft.AspNet.JsonPatch +namespace Microsoft.AspNetCore.JsonPatch { // Implementation details: the purpose of this type of patch document is to ensure we can do type-checking // when producing a JsonPatchDocument. However, we cannot send this "typed" over the wire, as that would require diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchError.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchError.cs index a140f0d4c1..a49af7a4e2 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchError.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchError.cs @@ -2,9 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.AspNet.JsonPatch.Operations; +using Microsoft.AspNetCore.JsonPatch.Operations; -namespace Microsoft.AspNet.JsonPatch +namespace Microsoft.AspNetCore.JsonPatch { /// /// Captures error message and the related entity and the operation that caused it. diff --git a/src/Microsoft.AspNetCore.JsonPatch/Operations/Operation.cs b/src/Microsoft.AspNetCore.JsonPatch/Operations/Operation.cs index 7f056f41bf..ea81b0c668 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Operations/Operation.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Operations/Operation.cs @@ -2,10 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.AspNet.JsonPatch.Adapters; +using Microsoft.AspNetCore.JsonPatch.Adapters; using Newtonsoft.Json; -namespace Microsoft.AspNet.JsonPatch.Operations +namespace Microsoft.AspNetCore.JsonPatch.Operations { public class Operation : OperationBase { diff --git a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationBase.cs b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationBase.cs index 17455f75e8..5f421f41c7 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationBase.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationBase.cs @@ -4,7 +4,7 @@ using System; using Newtonsoft.Json; -namespace Microsoft.AspNet.JsonPatch.Operations +namespace Microsoft.AspNetCore.JsonPatch.Operations { public class OperationBase { diff --git a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationOfT.cs b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationOfT.cs index 63663f70d9..c41454b7ef 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationOfT.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationOfT.cs @@ -2,9 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.AspNet.JsonPatch.Adapters; +using Microsoft.AspNetCore.JsonPatch.Adapters; -namespace Microsoft.AspNet.JsonPatch.Operations +namespace Microsoft.AspNetCore.JsonPatch.Operations { public class Operation : Operation where TModel : class { diff --git a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationType.cs b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationType.cs index a4d006bc51..846b07019f 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationType.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationType.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNet.JsonPatch.Operations +namespace Microsoft.AspNetCore.JsonPatch.Operations { public enum OperationType { diff --git a/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs index f0ee7f2439..70f76f1fa3 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs @@ -1,5 +1,5 @@ // -namespace Microsoft.AspNet.JsonPatch +namespace Microsoft.AspNetCore.JsonPatch { using System.Globalization; using System.Reflection; @@ -8,7 +8,7 @@ namespace Microsoft.AspNet.JsonPatch internal static class Resources { private static readonly ResourceManager _resourceManager - = new ResourceManager("Microsoft.AspNet.JsonPatch.Resources", typeof(Resources).GetTypeInfo().Assembly); + = new ResourceManager("Microsoft.AspNetCore.JsonPatch.Resources", typeof(Resources).GetTypeInfo().Assembly); /// /// The type of the property at path '{0}' could not be determined. diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs index f5a3c384ef..cb5f090d0f 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs @@ -1,14 +1,14 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; using System.Dynamic; -using Microsoft.AspNet.JsonPatch.Exceptions; +using Microsoft.AspNetCore.JsonPatch.Exceptions; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic { public class AddOperationTests { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs index 7913541514..098e97d850 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs @@ -1,12 +1,12 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; -using Microsoft.AspNet.JsonPatch.Exceptions; +using Microsoft.AspNetCore.JsonPatch.Exceptions; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic { public class AddTypedOperationTests { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyOperationTests.cs index 3fa546faac..87f221bc15 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyOperationTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; @@ -6,7 +6,7 @@ using System.Dynamic; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic { public class CopyOperationTests { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs index 5b015416ac..3a51556013 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs @@ -1,11 +1,11 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic { public class CopyTypedOperationTests { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveOperationTests.cs index dea2b6ee32..ed367848b7 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveOperationTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; @@ -6,7 +6,7 @@ using System.Dynamic; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic { public class MoveOperationTests { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs index 3d356a3401..cd4124d564 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs @@ -1,11 +1,11 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic { public class MoveTypedOperationTests { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/NestedDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/NestedDTO.cs index 4d30cf60f2..f94ad05d97 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/NestedDTO.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/NestedDTO.cs @@ -1,7 +1,7 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic { public class NestedDTO { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/PatchDocumentTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/PatchDocumentTests.cs index 8b14c3448b..e7e6f665a5 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/PatchDocumentTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/PatchDocumentTests.cs @@ -1,11 +1,11 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Microsoft.AspNet.JsonPatch.Exceptions; +using Microsoft.AspNetCore.JsonPatch.Exceptions; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic { public class PatchDocumentTests { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs index 9ecb520b38..b436bb4d23 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs @@ -1,13 +1,13 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; using System.Dynamic; -using Microsoft.AspNet.JsonPatch.Exceptions; +using Microsoft.AspNetCore.JsonPatch.Exceptions; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic { public class RemoveOperationTests { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs index 802fb27e40..d716dafe9a 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs @@ -1,12 +1,12 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; -using Microsoft.AspNet.JsonPatch.Exceptions; +using Microsoft.AspNetCore.JsonPatch.Exceptions; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic { public class RemoveTypedOperationTests { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs index c7573c0286..8dff9b6a98 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -8,7 +8,7 @@ using System.Dynamic; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic { public class ReplaceOperationTests { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceTypedOperationTests.cs index ccdd86f1a7..589e86e03a 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceTypedOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceTypedOperationTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -8,7 +8,7 @@ using System.Linq; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic { public class ReplaceTypedOperationTests { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleDTO.cs index a6938dd992..d4bf19f75a 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleDTO.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleDTO.cs @@ -1,10 +1,10 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; -namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic { public class SimpleDTO { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleDTOWithNestedDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleDTOWithNestedDTO.cs index 03c74f8a1b..f8af4bb390 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleDTOWithNestedDTO.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleDTOWithNestedDTO.cs @@ -1,9 +1,9 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; -namespace Microsoft.AspNet.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic { public class SimpleDTOWithNestedDTO { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/NestedDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/NestedDTO.cs index 6dd5ce8852..aa767557c3 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/NestedDTO.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/NestedDTO.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNet.JsonPatch.Test +namespace Microsoft.AspNetCore.JsonPatch.Test { public class NestedDTO { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs index e736373ed8..6215da6bcd 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs @@ -3,11 +3,11 @@ using System.Collections.Generic; using System.Collections.ObjectModel; -using Microsoft.AspNet.JsonPatch.Exceptions; +using Microsoft.AspNetCore.JsonPatch.Exceptions; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNet.JsonPatch.Test +namespace Microsoft.AspNetCore.JsonPatch.Test { public class NestedObjectTests { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs index 85d9404e6d..98a72e1bf8 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs @@ -4,11 +4,11 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using Microsoft.AspNet.JsonPatch.Exceptions; +using Microsoft.AspNetCore.JsonPatch.Exceptions; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNet.JsonPatch.Test +namespace Microsoft.AspNetCore.JsonPatch.Test { public class ObjectAdapterTests { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTO.cs index b1177bc5ce..1206cd108f 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTO.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTO.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; -namespace Microsoft.AspNet.JsonPatch.Test +namespace Microsoft.AspNetCore.JsonPatch.Test { public class SimpleDTO { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTO.cs index 81aa38e682..dbded242ee 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTO.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTO.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; -namespace Microsoft.AspNet.JsonPatch.Test +namespace Microsoft.AspNetCore.JsonPatch.Test { public class SimpleDTOWithNestedDTO { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/TestErrorLogger.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/TestErrorLogger.cs index 525321cfb3..6db8a42684 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/TestErrorLogger.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/TestErrorLogger.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNet.JsonPatch.Test +namespace Microsoft.AspNetCore.JsonPatch.Test { public class TestErrorLogger where T : class { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index 8b97af645a..7699879f8f 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -3,8 +3,8 @@ "warningsAsErrors": true }, "dependencies": { - "Microsoft.AspNet.JsonPatch": "1.0.0-*", - "Microsoft.AspNet.Testing": "1.0.0-*", + "Microsoft.AspNetCore.JsonPatch": "1.0.0-*", + "Microsoft.AspNetCore.Testing": "1.0.0-*", "Newtonsoft.Json": "6.0.6", "xunit.runner.aspnet": "2.0.0-aspnet-*" }, From 3fce15bc6a0d05287aca2233a53f784968073dd0 Mon Sep 17 00:00:00 2001 From: Brennan Date: Thu, 21 Jan 2016 09:42:54 -0800 Subject: [PATCH 0071/1029] React to Logging API changes --- src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs b/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs index a9bfe7d078..59b329d0d1 100644 --- a/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs +++ b/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs @@ -38,7 +38,7 @@ namespace Microsoft.Dnx.Watcher return true; } - public void Log(LogLevel logLevel, int eventId, object state, Exception exception, Func formatter) + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) { if (IsEnabled(logLevel)) { From 8d19947ada81d6458e6ddf0a48f2cbb12492c9a1 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 28 Jan 2016 11:03:22 -0800 Subject: [PATCH 0072/1029] Updating to dotnet-cli build Fixes #9 --- .gitattributes | 52 ++++++++++++++ .gitignore | 15 ++-- .travis.yml | 8 ++- appveyor.yml | 2 +- build.cmd | 68 +++++++++---------- build.sh | 42 ++++++------ .../project.json | 10 +-- 7 files changed, 125 insertions(+), 72 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..d4ee1cb7f3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,52 @@ +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain + +*.jpg binary +*.png binary +*.gif binary + +*.cs text=auto diff=csharp +*.vb text=auto +*.resx text=auto +*.c text=auto +*.cpp text=auto +*.cxx text=auto +*.h text=auto +*.hxx text=auto +*.py text=auto +*.rb text=auto +*.java text=auto +*.html text=auto +*.htm text=auto +*.css text=auto +*.scss text=auto +*.sass text=auto +*.less text=auto +*.js text=auto +*.lisp text=auto +*.clj text=auto +*.sql text=auto +*.php text=auto +*.lua text=auto +*.m text=auto +*.asm text=auto +*.erl text=auto +*.fs text=auto +*.fsx text=auto +*.hs text=auto + +*.csproj text=auto +*.vbproj text=auto +*.fsproj text=auto +*.dbproj text=auto +*.sln text=auto eol=crlf + +*.sh eol=lf diff --git a/.gitignore b/.gitignore index 8a9bbc3a43..2e4b2d6b5d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,23 +2,21 @@ [Bb]in/ TestResults/ .nuget/ +.build/ +.testPublish/ *.sln.ide/ _ReSharper.*/ packages/ artifacts/ +.build/ PublishProfiles/ -.vs/ -bower_components/ -node_modules/ -**/wwwroot/lib/ -debugSettings.json -project.lock.json *.user *.suo *.cache *.docstates _ReSharper.* nuget.exe +project.lock.json *net45.csproj *net451.csproj *k10.csproj @@ -30,7 +28,4 @@ nuget.exe *.ncrunchsolution *.*sdf *.ipch -.settings -*.sln.ide -node_modules -**/[Cc]ompiler/[Rr]esources/**/*.js +.build/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index c0befaffcf..e8f77f0f14 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,9 +10,11 @@ addons: - libssl-dev - libunwind8 - zlib1g -env: - - KOREBUILD_DNU_RESTORE_CORECLR=true KOREBUILD_TEST_DNXCORE=true mono: - 4.0.5 +os: + - linux + - osx +osx_image: xcode7.1 script: - - ./build.sh --quiet verify + - ./build.sh --quiet verify \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index 58a3e1bc22..636a7618d3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,7 @@ init: - git config --global core.autocrlf true build_script: - - build.cmd --quiet --parallel verify + - build.cmd --quiet verify clone_depth: 1 test: off deploy: off \ No newline at end of file diff --git a/build.cmd b/build.cmd index 553e3929a0..65fb3e3353 100644 --- a/build.cmd +++ b/build.cmd @@ -1,40 +1,40 @@ -@echo off -cd %~dp0 - +@ECHO off SETLOCAL + +SET REPO_FOLDER=%~dp0 +CD "%REPO_FOLDER%" + +SET BUILD_FOLDER=.build +SET KOREBUILD_FOLDER=%BUILD_FOLDER%\KoreBuild-dotnet +SET KOREBUILD_VERSION= + +SET NUGET_PATH=%BUILD_FOLDER%\NuGet.exe SET NUGET_VERSION=latest SET CACHED_NUGET=%LocalAppData%\NuGet\nuget.%NUGET_VERSION%.exe -SET BUILDCMD_KOREBUILD_VERSION= -SET BUILDCMD_DNX_VERSION= -IF EXIST %CACHED_NUGET% goto copynuget -echo Downloading latest version of NuGet.exe... -IF NOT EXIST %LocalAppData%\NuGet md %LocalAppData%\NuGet -@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/%NUGET_VERSION%/nuget.exe' -OutFile '%CACHED_NUGET%'" - -:copynuget -IF EXIST .nuget\nuget.exe goto restore -md .nuget -copy %CACHED_NUGET% .nuget\nuget.exe > nul - -:restore -IF EXIST packages\Sake goto getdnx -IF "%BUILDCMD_KOREBUILD_VERSION%"=="" ( - .nuget\nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre -) ELSE ( - .nuget\nuget.exe install KoreBuild -version %BUILDCMD_KOREBUILD_VERSION% -ExcludeVersion -o packages -nocache -pre -) -.nuget\NuGet.exe install Sake -ExcludeVersion -Source https://www.nuget.org/api/v2/ -Out packages - -:getdnx -IF "%BUILDCMD_DNX_VERSION%"=="" ( - SET BUILDCMD_DNX_VERSION=latest -) -IF "%SKIP_DNX_INSTALL%"=="" ( - CALL packages\KoreBuild\build\dnvm install %BUILDCMD_DNX_VERSION% -runtime CoreCLR -arch x86 -alias default - CALL packages\KoreBuild\build\dnvm install default -runtime CLR -arch x86 -alias default -) ELSE ( - CALL packages\KoreBuild\build\dnvm use default -runtime CLR -arch x86 +IF NOT EXIST %BUILD_FOLDER% ( + md %BUILD_FOLDER% ) -packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %* +IF NOT EXIST %NUGET_PATH% ( + IF NOT EXIST %CACHED_NUGET% ( + echo Downloading latest version of NuGet.exe... + IF NOT EXIST %LocalAppData%\NuGet ( + md %LocalAppData%\NuGet + ) + @powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/%NUGET_VERSION%/nuget.exe' -OutFile '%CACHED_NUGET%'" + ) + + copy %CACHED_NUGET% %NUGET_PATH% > nul +) + +IF NOT EXIST %KOREBUILD_FOLDER% ( + SET KOREBUILD_DOWNLOAD_ARGS= + IF NOT "%KOREBUILD_VERSION%"=="" ( + SET KOREBUILD_DOWNLOAD_ARGS=-version %KOREBUILD_VERSION% + ) + + %BUILD_FOLDER%\nuget.exe install KoreBuild-dotnet -ExcludeVersion -o %BUILD_FOLDER% -nocache -pre %KOREBUILD_DOWNLOAD_ARGS% +) + +"%KOREBUILD_FOLDER%\build\KoreBuild.cmd" %* diff --git a/build.sh b/build.sh index da4e3fcd1c..263fb667a8 100755 --- a/build.sh +++ b/build.sh @@ -1,5 +1,10 @@ #!/usr/bin/env bash +buildFolder=.build +koreBuildFolder=$buildFolder/KoreBuild-dotnet + +nugetPath=$buildFolder/nuget.exe + if test `uname` = Darwin; then cachedir=~/Library/Caches/KBuild else @@ -11,33 +16,30 @@ else fi mkdir -p $cachedir nugetVersion=latest -cachePath=$cachedir/nuget.$nugetVersion.exe +cacheNuget=$cachedir/nuget.$nugetVersion.exe -url=https://dist.nuget.org/win-x86-commandline/$nugetVersion/nuget.exe +nugetUrl=https://dist.nuget.org/win-x86-commandline/$nugetVersion/nuget.exe -if test ! -f $cachePath; then - wget -O $cachePath $url 2>/dev/null || curl -o $cachePath --location $url /dev/null +if test ! -d $buildFolder; then + mkdir $buildFolder fi -if test ! -e .nuget; then - mkdir .nuget - cp $cachePath .nuget/nuget.exe +if test ! -f $nugetPath; then + if test ! -f $cacheNuget; then + wget -O $cacheNuget $nugetUrl 2>/dev/null || curl -o $cacheNuget --location $nugetUrl /dev/null + fi + + cp $cacheNuget $nugetPath fi -if test ! -d packages/Sake; then - mono .nuget/nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre - mono .nuget/nuget.exe install Sake -ExcludeVersion -Source https://www.nuget.org/api/v2/ -Out packages +if test ! -d $koreBuildFolder; then + mono $nugetPath install KoreBuild-dotnet -ExcludeVersion -o $buildFolder -nocache -pre + chmod +x $koreBuildFolder/build/KoreBuild.sh fi -if ! type dnvm > /dev/null 2>&1; then - source packages/KoreBuild/build/dnvm.sh +makeFile=makefile.shade +if [ ! -e $makeFile ]; then + makeFile=$koreBuildFolder/build/makefile.shade fi -if ! type dnx > /dev/null 2>&1 || [ -z "$SKIP_DNX_INSTALL" ]; then - dnvm install latest -runtime coreclr -alias default - dnvm install default -runtime mono -alias default -else - dnvm use default -runtime mono -fi - -mono packages/Sake/tools/Sake.exe -I packages/KoreBuild/build -f makefile.shade "$@" +./$koreBuildFolder/build/KoreBuild.sh -n $nugetPath -m $makeFile "$@" diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index 7699879f8f..963a3eff63 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -5,21 +5,23 @@ "dependencies": { "Microsoft.AspNetCore.JsonPatch": "1.0.0-*", "Microsoft.AspNetCore.Testing": "1.0.0-*", - "Newtonsoft.Json": "6.0.6", - "xunit.runner.aspnet": "2.0.0-aspnet-*" + "xunit": "2.1.0" }, "commands": { "test": "xunit.runner.aspnet" }, + "testRunner": "xunit", "frameworks": { "dnx451": { "dependencies": { - "Moq": "4.2.1312.1622" + "Moq": "4.2.1312.1622", + "xunit.runner.console": "2.1.0" } }, "dnxcore50": { "dependencies": { - "moq.netcore": "4.4.0-beta8" + "moq.netcore": "4.4.0-beta8", + "xunit.runner.aspnet": "2.0.0-aspnet-*" } } } From 690c42c199e20ed8f7388a497e8672477a4b8594 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 28 Jan 2016 11:12:36 -0800 Subject: [PATCH 0073/1029] Add dependency on System.Runtime.Serialization.Primitives to make up for JSON.NET not including it Fixes https://github.com/aspnet/Mvc/issues/3946 --- src/Microsoft.AspNetCore.JsonPatch/project.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index 4d1206eefb..e654aecf23 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -22,6 +22,7 @@ "System.Reflection.Extensions": "4.0.1-*", "System.Resources.ResourceManager": "4.0.1-*", "System.Runtime.Extensions": "4.1.0-*", + "System.Runtime.Serialization.Primitives": "4.1.0-*", "System.Text.Encoding.Extensions": "4.0.11-*" } } From 20ed43fd686f86c9be96d7f456864cdc6fa80762 Mon Sep 17 00:00:00 2001 From: John Luo Date: Mon, 1 Feb 2016 14:48:27 -0800 Subject: [PATCH 0074/1029] Updating to new CLI --- src/Microsoft.AspNetCore.JsonPatch/project.json | 7 +++++-- test/Microsoft.AspNetCore.JsonPatch.Test/project.json | 6 ++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index e654aecf23..2a3d61af5e 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -9,7 +9,8 @@ "url": "git://github.com/aspnet/mvc" }, "dependencies": { - "Newtonsoft.Json": "8.0.2" + "Newtonsoft.Json": "8.0.2", + "Microsoft.NETCore.Platforms": "1.0.1-*" }, "frameworks": { "net451": {}, @@ -21,10 +22,12 @@ "System.Globalization": "4.0.11-*", "System.Reflection.Extensions": "4.0.1-*", "System.Resources.ResourceManager": "4.0.1-*", + "System.Runtime": "4.0.21-*", "System.Runtime.Extensions": "4.1.0-*", "System.Runtime.Serialization.Primitives": "4.1.0-*", "System.Text.Encoding.Extensions": "4.0.11-*" - } + }, + "imports": "portable-net451+win8" } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index 963a3eff63..ff30cfb346 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -5,7 +5,8 @@ "dependencies": { "Microsoft.AspNetCore.JsonPatch": "1.0.0-*", "Microsoft.AspNetCore.Testing": "1.0.0-*", - "xunit": "2.1.0" + "xunit": "2.1.0", + "Microsoft.NETCore.Platforms": "1.0.1-*" }, "commands": { "test": "xunit.runner.aspnet" @@ -22,7 +23,8 @@ "dependencies": { "moq.netcore": "4.4.0-beta8", "xunit.runner.aspnet": "2.0.0-aspnet-*" - } + }, + "imports": "portable-net451+win8" } } } \ No newline at end of file From 33629c5fc07604227d251e5ddcae55f49ae14219 Mon Sep 17 00:00:00 2001 From: John Luo Date: Mon, 1 Feb 2016 17:04:37 -0800 Subject: [PATCH 0075/1029] Updating to new CLI --- src/Microsoft.AspNetCore.Html.Abstractions/project.json | 6 ++++-- src/Microsoft.Extensions.WebEncoders/project.json | 5 ++++- .../project.json | 3 ++- test/Microsoft.Extensions.WebEncoders.Tests/project.json | 3 ++- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/project.json b/src/Microsoft.AspNetCore.Html.Abstractions/project.json index 55cc30d9b1..03334e45aa 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/project.json +++ b/src/Microsoft.AspNetCore.Html.Abstractions/project.json @@ -10,7 +10,8 @@ "keyFile": "../../tools/Key.snk" }, "dependencies": { - "System.Text.Encodings.Web": "4.0.0-*" + "System.Text.Encodings.Web": "4.0.0-*", + "Microsoft.NETCore.Platforms": "1.0.1-*" }, "frameworks": { "net451": { @@ -23,7 +24,8 @@ "dependencies": { "System.Collections": "4.0.11-*", "System.Resources.ResourceManager": "4.0.1-*" - } + }, + "imports": "portable-net451+win8" } } } diff --git a/src/Microsoft.Extensions.WebEncoders/project.json b/src/Microsoft.Extensions.WebEncoders/project.json index 0facfeeb8c..f56cd3d4b6 100644 --- a/src/Microsoft.Extensions.WebEncoders/project.json +++ b/src/Microsoft.Extensions.WebEncoders/project.json @@ -13,6 +13,7 @@ "dependencies": { "Microsoft.Extensions.DependencyInjection.Abstractions": "1.0.0-*", "Microsoft.Extensions.Options": "1.0.0-*", + "Microsoft.NETCore.Platforms": "1.0.1-*", "System.Text.Encodings.Web": "4.0.0-*" }, "frameworks": { @@ -22,6 +23,8 @@ "System.Runtime": "" } }, - "dotnet5.4": {} + "dotnet5.4": { + "imports": "portable-net451+win8" + } } } diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index d796493c0a..7e104bae8d 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -23,7 +23,8 @@ "dependencies": { "System.Runtime": "4.0.21-*", "xunit.runner.aspnet": "2.0.0-aspnet-*" - } + }, + "imports": "portable-net451+win8" } } } diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index c588c7a29e..ebfb18cf96 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -22,7 +22,8 @@ "dnxcore50": { "dependencies": { "xunit.runner.aspnet": "2.0.0-aspnet-*" - } + }, + "imports": "portable-net451+win8" } } } From 82e17ce2b69a6bfdcdb631a93b6066a6c74ad47c Mon Sep 17 00:00:00 2001 From: John Luo Date: Mon, 1 Feb 2016 17:58:41 -0800 Subject: [PATCH 0076/1029] Removing redundant dependencies --- src/Microsoft.AspNetCore.JsonPatch/project.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index 2a3d61af5e..072386b843 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -9,8 +9,7 @@ "url": "git://github.com/aspnet/mvc" }, "dependencies": { - "Newtonsoft.Json": "8.0.2", - "Microsoft.NETCore.Platforms": "1.0.1-*" + "Newtonsoft.Json": "8.0.2" }, "frameworks": { "net451": {}, From 2fd1490c4acb6017e0811bad655e601782575d57 Mon Sep 17 00:00:00 2001 From: John Luo Date: Mon, 1 Feb 2016 18:33:21 -0800 Subject: [PATCH 0077/1029] Relocating dependencies --- src/Microsoft.AspNetCore.Html.Abstractions/project.json | 6 ++---- src/Microsoft.Extensions.WebEncoders/project.json | 5 +---- .../project.json | 1 + test/Microsoft.Extensions.WebEncoders.Tests/project.json | 1 + 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/project.json b/src/Microsoft.AspNetCore.Html.Abstractions/project.json index 03334e45aa..55cc30d9b1 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/project.json +++ b/src/Microsoft.AspNetCore.Html.Abstractions/project.json @@ -10,8 +10,7 @@ "keyFile": "../../tools/Key.snk" }, "dependencies": { - "System.Text.Encodings.Web": "4.0.0-*", - "Microsoft.NETCore.Platforms": "1.0.1-*" + "System.Text.Encodings.Web": "4.0.0-*" }, "frameworks": { "net451": { @@ -24,8 +23,7 @@ "dependencies": { "System.Collections": "4.0.11-*", "System.Resources.ResourceManager": "4.0.1-*" - }, - "imports": "portable-net451+win8" + } } } } diff --git a/src/Microsoft.Extensions.WebEncoders/project.json b/src/Microsoft.Extensions.WebEncoders/project.json index f56cd3d4b6..0facfeeb8c 100644 --- a/src/Microsoft.Extensions.WebEncoders/project.json +++ b/src/Microsoft.Extensions.WebEncoders/project.json @@ -13,7 +13,6 @@ "dependencies": { "Microsoft.Extensions.DependencyInjection.Abstractions": "1.0.0-*", "Microsoft.Extensions.Options": "1.0.0-*", - "Microsoft.NETCore.Platforms": "1.0.1-*", "System.Text.Encodings.Web": "4.0.0-*" }, "frameworks": { @@ -23,8 +22,6 @@ "System.Runtime": "" } }, - "dotnet5.4": { - "imports": "portable-net451+win8" - } + "dotnet5.4": {} } } diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index 7e104bae8d..2d2e1345d4 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -7,6 +7,7 @@ "Microsoft.AspNetCore.Html.Abstractions": "1.0.0-*", "Microsoft.AspNetCore.Testing": "1.0.0-*", "Microsoft.Extensions.WebEncoders": "1.0.0-*", + "Microsoft.NETCore.Platforms": "1.0.1-*", "xunit": "2.1.0" }, "testRunner": "xunit", diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index ebfb18cf96..62a6a59ec0 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -2,6 +2,7 @@ "dependencies": { "Microsoft.Extensions.DependencyInjection": "1.0.0-*", "Microsoft.Extensions.WebEncoders": "1.0.0-*", + "Microsoft.NETCore.Platforms": "1.0.1-*", "xunit.runner.aspnet": "2.0.0-aspnet-*" }, "testRunner": "xunit", From f452597452c3c0b359bb5cffc795429328268325 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Tue, 2 Feb 2016 12:44:07 -0800 Subject: [PATCH 0078/1029] Add Microsoft.NETCore.Platforms to the projects that have to be built with dnu --- src/Microsoft.Dnx.Watcher.Core/project.json | 3 ++- src/Microsoft.Dnx.Watcher/project.json | 3 ++- test/Microsoft.Dnx.Watcher.Tests/project.json | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Dnx.Watcher.Core/project.json b/src/Microsoft.Dnx.Watcher.Core/project.json index c6c1c405d0..6decafd5c3 100644 --- a/src/Microsoft.Dnx.Watcher.Core/project.json +++ b/src/Microsoft.Dnx.Watcher.Core/project.json @@ -14,7 +14,8 @@ "version": "1.0.0-*" }, "Microsoft.Extensions.Logging.Abstractions": "1.0.0-*", - "Microsoft.Extensions.FileSystemGlobbing": "1.0.0-*" + "Microsoft.Extensions.FileSystemGlobbing": "1.0.0-*", + "Microsoft.NETCore.Platforms": "1.0.1-*" }, "frameworks": { "dnx451": { diff --git a/src/Microsoft.Dnx.Watcher/project.json b/src/Microsoft.Dnx.Watcher/project.json index cbd29d5335..c8fc4080ac 100644 --- a/src/Microsoft.Dnx.Watcher/project.json +++ b/src/Microsoft.Dnx.Watcher/project.json @@ -9,7 +9,8 @@ "Microsoft.Dnx.Watcher.Core": "1.0.0-*", "Microsoft.Extensions.CommandLineUtils": "1.0.0-*", "Microsoft.Extensions.Logging": "1.0.0-*", - "Microsoft.Extensions.Logging.Console": "1.0.0-*" + "Microsoft.Extensions.Logging.Console": "1.0.0-*", + "Microsoft.NETCore.Platforms": "1.0.1-*" }, "frameworks": { "dnx451": { }, diff --git a/test/Microsoft.Dnx.Watcher.Tests/project.json b/test/Microsoft.Dnx.Watcher.Tests/project.json index 5cc6a0c054..f613c1cefc 100644 --- a/test/Microsoft.Dnx.Watcher.Tests/project.json +++ b/test/Microsoft.Dnx.Watcher.Tests/project.json @@ -6,6 +6,7 @@ "dependencies": { "Microsoft.Extensions.PlatformAbstractions": "1.0.0-*", "Microsoft.Dnx.Watcher": "1.0.0-*", + "Microsoft.NETCore.Platforms": "1.0.1-*", "xunit.runner.aspnet": "2.0.0-aspnet-*" }, "frameworks": { From 9959601c4b07bd5e170975b900293bd3beb13e2a Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Fri, 5 Feb 2016 17:20:53 -0800 Subject: [PATCH 0079/1029] Update project.json to remove redundant System.Runtime dependency. - This package is pulled in transitively. --- test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json | 1 - 1 file changed, 1 deletion(-) diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index 2d2e1345d4..f27a4cd094 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -22,7 +22,6 @@ }, "dnxcore50": { "dependencies": { - "System.Runtime": "4.0.21-*", "xunit.runner.aspnet": "2.0.0-aspnet-*" }, "imports": "portable-net451+win8" From e0fbc6e2c218849a04e16e1792ae472d31952f4c Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Fri, 5 Feb 2016 17:22:05 -0800 Subject: [PATCH 0080/1029] Update project.json to remove redundant System.Runtime dependency. - This package is pulled in transitively. --- src/Microsoft.AspNetCore.JsonPatch/project.json | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index 072386b843..bae136cbbc 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -21,7 +21,6 @@ "System.Globalization": "4.0.11-*", "System.Reflection.Extensions": "4.0.1-*", "System.Resources.ResourceManager": "4.0.1-*", - "System.Runtime": "4.0.21-*", "System.Runtime.Extensions": "4.1.0-*", "System.Runtime.Serialization.Primitives": "4.1.0-*", "System.Text.Encoding.Extensions": "4.0.11-*" From 4bef698f3bc77e071601a67fbd9a3fb857215c3a Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 8 Feb 2016 09:33:43 -0800 Subject: [PATCH 0081/1029] Reacting to CoreCLR package version changes --- src/Microsoft.Dnx.Watcher.Core/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Dnx.Watcher.Core/project.json b/src/Microsoft.Dnx.Watcher.Core/project.json index 6decafd5c3..b0b659a01b 100644 --- a/src/Microsoft.Dnx.Watcher.Core/project.json +++ b/src/Microsoft.Dnx.Watcher.Core/project.json @@ -27,7 +27,7 @@ "dnxcore50": { "dependencies": { "System.Diagnostics.Process": "4.1.0-*", - "System.Linq": "4.0.1-*", + "System.Linq": "4.0.2-*", "System.Threading.Thread": "4.0.0-*" } } From 76c20aa01032064f8c7a4e6baa92007b1302bf0a Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 8 Feb 2016 09:33:46 -0800 Subject: [PATCH 0082/1029] Reacting to CoreCLR package version changes --- src/Microsoft.AspNetCore.JsonPatch/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index bae136cbbc..ec303724f5 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -16,7 +16,7 @@ "dotnet5.4": { "dependencies": { "Microsoft.CSharp": "4.0.1-*", - "System.Collections.Concurrent": "4.0.11-*", + "System.Collections.Concurrent": "4.0.12-*", "System.ComponentModel.TypeConverter": "4.0.1-*", "System.Globalization": "4.0.11-*", "System.Reflection.Extensions": "4.0.1-*", From 3fa76b26c89190d818974b6112b914dd8aae2477 Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Tue, 9 Feb 2016 22:23:47 -0800 Subject: [PATCH 0083/1029] Enable tests to run using dotnet xunit runner --- .../project.json | 15 ++++++--------- .../project.json | 17 +++++++---------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index f27a4cd094..ff91514fd4 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -11,20 +11,17 @@ "xunit": "2.1.0" }, "testRunner": "xunit", - "commands": { - "test": "xunit.runner.aspnet" - }, "frameworks": { - "dnx451": { - "dependencies": { - "xunit.runner.console": "2.1.0" - } - }, "dnxcore50": { "dependencies": { - "xunit.runner.aspnet": "2.0.0-aspnet-*" + "dotnet-test-xunit": "1.0.0-dev-*" }, "imports": "portable-net451+win8" + }, + "dnx451": { + "dependencies": { + "xunit.runner.console": "2.1.0" } } } +} \ No newline at end of file diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index 62a6a59ec0..bcd52ff6ee 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -6,25 +6,22 @@ "xunit.runner.aspnet": "2.0.0-aspnet-*" }, "testRunner": "xunit", - "commands": { - "test": "xunit.runner.aspnet" - }, "compilationOptions": { "allowUnsafe": true, "warningsAsErrors": true, "keyFile": "../../tools/Key.snk" }, "frameworks": { + "dnxcore50": { + "dependencies": { + "dotnet-test-xunit": "1.0.0-dev-*" + }, + "imports": "portable-net451+win8" + }, "dnx451": { "dependencies": { "xunit.runner.console": "2.1.0" } - }, - "dnxcore50": { - "dependencies": { - "xunit.runner.aspnet": "2.0.0-aspnet-*" - }, - "imports": "portable-net451+win8" } } -} +} \ No newline at end of file From de419e26ce4eadcd0073ae4d74d66d11f2885a25 Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Tue, 9 Feb 2016 22:27:25 -0800 Subject: [PATCH 0084/1029] Enable tests to run using dotnet xunit runner --- .../project.json | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index ff30cfb346..07a2b3511c 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -8,23 +8,20 @@ "xunit": "2.1.0", "Microsoft.NETCore.Platforms": "1.0.1-*" }, - "commands": { - "test": "xunit.runner.aspnet" - }, "testRunner": "xunit", "frameworks": { + "dnxcore50": { + "dependencies": { + "moq.netcore": "4.4.0-beta8", + "dotnet-test-xunit": "1.0.0-dev-*" + }, + "imports": "portable-net451+win8" + }, "dnx451": { "dependencies": { "Moq": "4.2.1312.1622", "xunit.runner.console": "2.1.0" } - }, - "dnxcore50": { - "dependencies": { - "moq.netcore": "4.4.0-beta8", - "xunit.runner.aspnet": "2.0.0-aspnet-*" - }, - "imports": "portable-net451+win8" } } } \ No newline at end of file From 2bbb7a69e9ba3b98c53d2a8c70b38b43599a7309 Mon Sep 17 00:00:00 2001 From: Brennan Date: Thu, 11 Feb 2016 09:45:54 -0800 Subject: [PATCH 0085/1029] Update dependencies --- test/Microsoft.AspNetCore.JsonPatch.Test/project.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index 07a2b3511c..cb87b096e9 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -18,6 +18,10 @@ "imports": "portable-net451+win8" }, "dnx451": { + "frameworkAssemblies": { + "System.Runtime": "", + "System.Threading.Tasks": "" + }, "dependencies": { "Moq": "4.2.1312.1622", "xunit.runner.console": "2.1.0" From 59cb4fe65ab50371f7632c0dd738d3fb0de49a1d Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Tue, 2 Feb 2016 12:24:33 -0800 Subject: [PATCH 0086/1029] dnx-watch -> dotnet-watch --- .gitattributes | 2 + .gitignore | 2 + .travis.yml | 7 +- NuGet.config | 4 +- build.cmd | 68 ++-- build.sh | 42 +-- dnx-watch.sln => dotnet-watch.sln | 13 +- .../External/Runtime/Constants.cs | 34 -- .../External/Runtime/FileFormatException.cs | 123 ------- .../External/Runtime/LockFile.cs | 16 - .../Runtime/LockFileProjectLibrary.cs | 12 - .../External/Runtime/LockFileReader.cs | 218 ------------ .../External/Runtime/NamedResourceReader.cs | 75 ---- .../External/Runtime/PackIncludeEntry.cs | 45 --- .../External/Runtime/PathUtility.cs | 196 ----------- .../External/Runtime/PatternGroup.cs | 125 ------- .../Runtime/PatternsCollectionHelper.cs | 107 ------ .../External/Runtime/Project.cs | 125 ------- .../Runtime/ProjectFilesCollection.cs | 200 ----------- .../External/Runtime/ProjectReader.cs | 145 -------- .../Runtime/RuntimeEnvironmentHelper.cs | 50 --- .../External/Runtime/SemanticVersion.cs | 330 ------------------ src/Microsoft.Dnx.Watcher/Program.cs | 133 ------- .../Properties/AssemblyInfo.cs | 10 - .../Abstractions/IFileWatcher.cs | 2 +- .../Abstractions/IProcessWatcher.cs | 3 +- .../Abstractions/IProject.cs | 2 +- .../Abstractions/IProjectProvider.cs | 2 +- .../DictionaryExtensions.cs | 0 .../DotNetWatcher.cs} | 84 +++-- .../FileSystem/FileSystemWatcherRoot.cs | 2 +- .../FileSystem/FileWatcher.cs | 2 +- .../FileSystem/IWatcherRoot.cs | 2 +- .../Impl/ProcessWatcher.cs | 61 ++-- .../Impl/Project.cs | 14 +- .../Impl/ProjectProvider.cs | 10 +- .../Microsoft.DotNet.Watcher.Core.xproj} | 0 .../Properties/AssemblyInfo.cs | 0 .../project.json | 13 +- .../CommandOutputLogger.cs | 2 +- .../CommandOutputProvider.cs | 2 +- src/dotnet-watch/Program.cs | 139 ++++++++ src/dotnet-watch/Properties/AssemblyInfo.cs | 10 + .../dotnet-watch.xproj} | 0 .../project.json | 16 +- .../CommandLineParsingTests.cs | 48 --- .../Microsoft.Dnx.Watcher.Tests.xproj | 21 -- test/Microsoft.Dnx.Watcher.Tests/project.json | 20 -- 48 files changed, 331 insertions(+), 2206 deletions(-) rename dnx-watch.sln => dotnet-watch.sln (64%) delete mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/Constants.cs delete mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/FileFormatException.cs delete mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFile.cs delete mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFileProjectLibrary.cs delete mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFileReader.cs delete mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/NamedResourceReader.cs delete mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/PackIncludeEntry.cs delete mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/PathUtility.cs delete mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs delete mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternsCollectionHelper.cs delete mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/Project.cs delete mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectFilesCollection.cs delete mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectReader.cs delete mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/RuntimeEnvironmentHelper.cs delete mode 100644 src/Microsoft.Dnx.Watcher.Core/External/Runtime/SemanticVersion.cs delete mode 100644 src/Microsoft.Dnx.Watcher/Program.cs delete mode 100644 src/Microsoft.Dnx.Watcher/Properties/AssemblyInfo.cs rename src/{Microsoft.Dnx.Watcher.Core => Microsoft.DotNet.Watcher.Core}/Abstractions/IFileWatcher.cs (91%) rename src/{Microsoft.Dnx.Watcher.Core => Microsoft.DotNet.Watcher.Core}/Abstractions/IProcessWatcher.cs (88%) rename src/{Microsoft.Dnx.Watcher.Core => Microsoft.DotNet.Watcher.Core}/Abstractions/IProject.cs (90%) rename src/{Microsoft.Dnx.Watcher.Core => Microsoft.DotNet.Watcher.Core}/Abstractions/IProjectProvider.cs (88%) rename src/{Microsoft.Dnx.Watcher.Core => Microsoft.DotNet.Watcher.Core}/DictionaryExtensions.cs (100%) rename src/{Microsoft.Dnx.Watcher.Core/DnxWatcher.cs => Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs} (71%) rename src/{Microsoft.Dnx.Watcher.Core => Microsoft.DotNet.Watcher.Core}/FileSystem/FileSystemWatcherRoot.cs (93%) rename src/{Microsoft.Dnx.Watcher.Core => Microsoft.DotNet.Watcher.Core}/FileSystem/FileWatcher.cs (99%) rename src/{Microsoft.Dnx.Watcher.Core => Microsoft.DotNet.Watcher.Core}/FileSystem/IWatcherRoot.cs (87%) rename src/{Microsoft.Dnx.Watcher.Core => Microsoft.DotNet.Watcher.Core}/Impl/ProcessWatcher.cs (55%) rename src/{Microsoft.Dnx.Watcher.Core => Microsoft.DotNet.Watcher.Core}/Impl/Project.cs (82%) rename src/{Microsoft.Dnx.Watcher.Core => Microsoft.DotNet.Watcher.Core}/Impl/ProjectProvider.cs (87%) rename src/{Microsoft.Dnx.Watcher.Core/Microsoft.Dnx.Watcher.Core.xproj => Microsoft.DotNet.Watcher.Core/Microsoft.DotNet.Watcher.Core.xproj} (100%) rename src/{Microsoft.Dnx.Watcher.Core => Microsoft.DotNet.Watcher.Core}/Properties/AssemblyInfo.cs (100%) rename src/{Microsoft.Dnx.Watcher.Core => Microsoft.DotNet.Watcher.Core}/project.json (71%) rename src/{Microsoft.Dnx.Watcher => dotnet-watch}/CommandOutputLogger.cs (98%) rename src/{Microsoft.Dnx.Watcher => dotnet-watch}/CommandOutputProvider.cs (95%) create mode 100644 src/dotnet-watch/Program.cs create mode 100644 src/dotnet-watch/Properties/AssemblyInfo.cs rename src/{Microsoft.Dnx.Watcher/Microsoft.Dnx.Watcher.xproj => dotnet-watch/dotnet-watch.xproj} (100%) rename src/{Microsoft.Dnx.Watcher => dotnet-watch}/project.json (66%) delete mode 100644 test/Microsoft.Dnx.Watcher.Tests/CommandLineParsingTests.cs delete mode 100644 test/Microsoft.Dnx.Watcher.Tests/Microsoft.Dnx.Watcher.Tests.xproj delete mode 100644 test/Microsoft.Dnx.Watcher.Tests/project.json diff --git a/.gitattributes b/.gitattributes index bdaa5ba982..c2f0f84273 100644 --- a/.gitattributes +++ b/.gitattributes @@ -48,3 +48,5 @@ *.fsproj text=auto *.dbproj text=auto *.sln text=auto eol=crlf + +*.sh eol=lf \ No newline at end of file diff --git a/.gitignore b/.gitignore index ac82da7568..10779cb569 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,5 @@ nuget.exe *.ipch *.sln.ide project.lock.json +.testPublish/ +.build/ diff --git a/.travis.yml b/.travis.yml index 2019384e19..e8f77f0f14 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,14 +10,11 @@ addons: - libssl-dev - libunwind8 - zlib1g -before_install: - - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install icu4c; fi -env: - - KOREBUILD_DNU_RESTORE_CORECLR=true MONO_THREADS_PER_CPU=2000 mono: - 4.0.5 os: - linux - osx +osx_image: xcode7.1 script: - - ./build.sh --quiet verify + - ./build.sh --quiet verify \ No newline at end of file diff --git a/NuGet.config b/NuGet.config index 03704957e8..52bf414192 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + - \ No newline at end of file + diff --git a/build.cmd b/build.cmd index 553e3929a0..65fb3e3353 100644 --- a/build.cmd +++ b/build.cmd @@ -1,40 +1,40 @@ -@echo off -cd %~dp0 - +@ECHO off SETLOCAL + +SET REPO_FOLDER=%~dp0 +CD "%REPO_FOLDER%" + +SET BUILD_FOLDER=.build +SET KOREBUILD_FOLDER=%BUILD_FOLDER%\KoreBuild-dotnet +SET KOREBUILD_VERSION= + +SET NUGET_PATH=%BUILD_FOLDER%\NuGet.exe SET NUGET_VERSION=latest SET CACHED_NUGET=%LocalAppData%\NuGet\nuget.%NUGET_VERSION%.exe -SET BUILDCMD_KOREBUILD_VERSION= -SET BUILDCMD_DNX_VERSION= -IF EXIST %CACHED_NUGET% goto copynuget -echo Downloading latest version of NuGet.exe... -IF NOT EXIST %LocalAppData%\NuGet md %LocalAppData%\NuGet -@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/%NUGET_VERSION%/nuget.exe' -OutFile '%CACHED_NUGET%'" - -:copynuget -IF EXIST .nuget\nuget.exe goto restore -md .nuget -copy %CACHED_NUGET% .nuget\nuget.exe > nul - -:restore -IF EXIST packages\Sake goto getdnx -IF "%BUILDCMD_KOREBUILD_VERSION%"=="" ( - .nuget\nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre -) ELSE ( - .nuget\nuget.exe install KoreBuild -version %BUILDCMD_KOREBUILD_VERSION% -ExcludeVersion -o packages -nocache -pre -) -.nuget\NuGet.exe install Sake -ExcludeVersion -Source https://www.nuget.org/api/v2/ -Out packages - -:getdnx -IF "%BUILDCMD_DNX_VERSION%"=="" ( - SET BUILDCMD_DNX_VERSION=latest -) -IF "%SKIP_DNX_INSTALL%"=="" ( - CALL packages\KoreBuild\build\dnvm install %BUILDCMD_DNX_VERSION% -runtime CoreCLR -arch x86 -alias default - CALL packages\KoreBuild\build\dnvm install default -runtime CLR -arch x86 -alias default -) ELSE ( - CALL packages\KoreBuild\build\dnvm use default -runtime CLR -arch x86 +IF NOT EXIST %BUILD_FOLDER% ( + md %BUILD_FOLDER% ) -packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %* +IF NOT EXIST %NUGET_PATH% ( + IF NOT EXIST %CACHED_NUGET% ( + echo Downloading latest version of NuGet.exe... + IF NOT EXIST %LocalAppData%\NuGet ( + md %LocalAppData%\NuGet + ) + @powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/%NUGET_VERSION%/nuget.exe' -OutFile '%CACHED_NUGET%'" + ) + + copy %CACHED_NUGET% %NUGET_PATH% > nul +) + +IF NOT EXIST %KOREBUILD_FOLDER% ( + SET KOREBUILD_DOWNLOAD_ARGS= + IF NOT "%KOREBUILD_VERSION%"=="" ( + SET KOREBUILD_DOWNLOAD_ARGS=-version %KOREBUILD_VERSION% + ) + + %BUILD_FOLDER%\nuget.exe install KoreBuild-dotnet -ExcludeVersion -o %BUILD_FOLDER% -nocache -pre %KOREBUILD_DOWNLOAD_ARGS% +) + +"%KOREBUILD_FOLDER%\build\KoreBuild.cmd" %* diff --git a/build.sh b/build.sh index da4e3fcd1c..263fb667a8 100755 --- a/build.sh +++ b/build.sh @@ -1,5 +1,10 @@ #!/usr/bin/env bash +buildFolder=.build +koreBuildFolder=$buildFolder/KoreBuild-dotnet + +nugetPath=$buildFolder/nuget.exe + if test `uname` = Darwin; then cachedir=~/Library/Caches/KBuild else @@ -11,33 +16,30 @@ else fi mkdir -p $cachedir nugetVersion=latest -cachePath=$cachedir/nuget.$nugetVersion.exe +cacheNuget=$cachedir/nuget.$nugetVersion.exe -url=https://dist.nuget.org/win-x86-commandline/$nugetVersion/nuget.exe +nugetUrl=https://dist.nuget.org/win-x86-commandline/$nugetVersion/nuget.exe -if test ! -f $cachePath; then - wget -O $cachePath $url 2>/dev/null || curl -o $cachePath --location $url /dev/null +if test ! -d $buildFolder; then + mkdir $buildFolder fi -if test ! -e .nuget; then - mkdir .nuget - cp $cachePath .nuget/nuget.exe +if test ! -f $nugetPath; then + if test ! -f $cacheNuget; then + wget -O $cacheNuget $nugetUrl 2>/dev/null || curl -o $cacheNuget --location $nugetUrl /dev/null + fi + + cp $cacheNuget $nugetPath fi -if test ! -d packages/Sake; then - mono .nuget/nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre - mono .nuget/nuget.exe install Sake -ExcludeVersion -Source https://www.nuget.org/api/v2/ -Out packages +if test ! -d $koreBuildFolder; then + mono $nugetPath install KoreBuild-dotnet -ExcludeVersion -o $buildFolder -nocache -pre + chmod +x $koreBuildFolder/build/KoreBuild.sh fi -if ! type dnvm > /dev/null 2>&1; then - source packages/KoreBuild/build/dnvm.sh +makeFile=makefile.shade +if [ ! -e $makeFile ]; then + makeFile=$koreBuildFolder/build/makefile.shade fi -if ! type dnx > /dev/null 2>&1 || [ -z "$SKIP_DNX_INSTALL" ]; then - dnvm install latest -runtime coreclr -alias default - dnvm install default -runtime mono -alias default -else - dnvm use default -runtime mono -fi - -mono packages/Sake/tools/Sake.exe -I packages/KoreBuild/build -f makefile.shade "$@" +./$koreBuildFolder/build/KoreBuild.sh -n $nugetPath -m $makeFile "$@" diff --git a/dnx-watch.sln b/dotnet-watch.sln similarity index 64% rename from dnx-watch.sln rename to dotnet-watch.sln index 6b01701d71..3c8e1e6bbb 100644 --- a/dnx-watch.sln +++ b/dotnet-watch.sln @@ -5,9 +5,9 @@ VisualStudioVersion = 14.0.23107.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66517987-2A5A-4330-B130-207039378FD4}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Dnx.Watcher", "src\Microsoft.Dnx.Watcher\Microsoft.Dnx.Watcher.xproj", "{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-watch", "src\dotnet-watch\dotnet-watch.xproj", "{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Dnx.Watcher.Core", "src\Microsoft.Dnx.Watcher.Core\Microsoft.Dnx.Watcher.Core.xproj", "{D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Watcher.Core", "src\Microsoft.DotNet.Watcher.Core\Microsoft.DotNet.Watcher.Core.xproj", "{D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8321E0D1-9A47-4D2F-AED8-3AE636D44E35}" ProjectSection(SolutionItems) = preProject @@ -15,10 +15,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution NuGet.Config = NuGet.Config EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{442A6A17-4C5A-4E11-B547-A554063FD338}" -EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Dnx.Watcher.Tests", "test\Microsoft.Dnx.Watcher.Tests\Microsoft.Dnx.Watcher.Tests.xproj", "{640D190B-26DB-4DDE-88EE-55814C86C43E}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -33,10 +29,6 @@ Global {D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}.Debug|Any CPU.Build.0 = Debug|Any CPU {D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}.Release|Any CPU.ActiveCfg = Release|Any CPU {D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}.Release|Any CPU.Build.0 = Release|Any CPU - {640D190B-26DB-4DDE-88EE-55814C86C43E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {640D190B-26DB-4DDE-88EE-55814C86C43E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {640D190B-26DB-4DDE-88EE-55814C86C43E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {640D190B-26DB-4DDE-88EE-55814C86C43E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -44,6 +36,5 @@ Global GlobalSection(NestedProjects) = preSolution {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46} = {66517987-2A5A-4330-B130-207039378FD4} {D3DA3BBB-E206-404F-AEE6-17FB9B6F1221} = {66517987-2A5A-4330-B130-207039378FD4} - {640D190B-26DB-4DDE-88EE-55814C86C43E} = {442A6A17-4C5A-4E11-B547-A554063FD338} EndGlobalSection EndGlobal diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/Constants.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/Constants.cs deleted file mode 100644 index 9c2e502b02..0000000000 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/Constants.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; - -namespace Microsoft.Dnx.Runtime -{ - internal static class Constants - { - public const string BootstrapperExeName = "dnx"; - public const string BootstrapperFullName = "Microsoft .NET Execution environment"; - public const string DefaultLocalRuntimeHomeDir = ".dnx"; - public const string RuntimeShortName = "dnx"; - public const string RuntimeLongName = "Microsoft DNX"; - public const string RuntimeNamePrefix = RuntimeShortName + "-"; - public const string WebConfigRuntimeVersion = RuntimeNamePrefix + "version"; - public const string WebConfigRuntimeFlavor = RuntimeNamePrefix + "clr"; - public const string WebConfigRuntimeAppBase = RuntimeNamePrefix + "app-base"; - public const string WebConfigBootstrapperVersion = "bootstrapper-version"; - public const string WebConfigRuntimePath = "runtime-path"; - public const string BootstrapperHostName = RuntimeShortName + ".host"; - public const string BootstrapperClrName = RuntimeShortName + ".clr"; - - public const int LockFileVersion = 2; - - public static readonly TimeSpan RegexMatchTimeout = TimeSpan.FromSeconds(10); - public static readonly string AppConfigurationFileName = "app.config"; - - public static readonly Version Version35 = new Version(3, 5); - public static readonly Version Version40 = new Version(4, 0); - public static readonly Version Version50 = new Version(5, 0); - public static readonly Version Version10_0 = new Version(10, 0); - } -} diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/FileFormatException.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/FileFormatException.cs deleted file mode 100644 index 0efa1871d1..0000000000 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/FileFormatException.cs +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.Extensions.JsonParser.Sources; - -namespace Microsoft.Dnx.Runtime -{ - internal sealed class FileFormatException : Exception - { - private FileFormatException(string message) : - base(message) - { - } - - private FileFormatException(string message, Exception innerException) : - base(message, innerException) - { - } - - public string Path { get; private set; } - public int Line { get; private set; } - public int Column { get; private set; } - - public override string ToString() - { - return $"{Path}({Line},{Column}): Error: {base.ToString()}"; - } - - internal static FileFormatException Create(Exception exception, string filePath) - { - if (exception is JsonDeserializerException) - { - return new FileFormatException(exception.Message, exception) - .WithFilePath(filePath) - .WithLineInfo((JsonDeserializerException)exception); - } - else - { - return new FileFormatException(exception.Message, exception) - .WithFilePath(filePath); - } - } - - internal static FileFormatException Create(Exception exception, JsonValue jsonValue, string filePath) - { - var result = Create(exception, jsonValue) - .WithFilePath(filePath); - - return result; - } - - internal static FileFormatException Create(Exception exception, JsonValue jsonValue) - { - var result = new FileFormatException(exception.Message, exception) - .WithLineInfo(jsonValue); - - return result; - } - - internal static FileFormatException Create(string message, JsonValue jsonValue, string filePath) - { - var result = Create(message, jsonValue) - .WithFilePath(filePath); - - return result; - } - - internal static FileFormatException Create(string message, string filePath) - { - var result = new FileFormatException(message) - .WithFilePath(filePath); - - return result; - } - - internal static FileFormatException Create(string message, JsonValue jsonValue) - { - var result = new FileFormatException(message) - .WithLineInfo(jsonValue); - - return result; - } - - internal FileFormatException WithFilePath(string path) - { - if (path == null) - { - throw new ArgumentNullException(nameof(path)); - } - - Path = path; - - return this; - } - - private FileFormatException WithLineInfo(JsonValue value) - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - Line = value.Line; - Column = value.Column; - - return this; - } - - private FileFormatException WithLineInfo(JsonDeserializerException exception) - { - if (exception == null) - { - throw new ArgumentNullException(nameof(exception)); - } - - Line = exception.Line; - Column = exception.Column; - - return this; - } - } -} \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFile.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFile.cs deleted file mode 100644 index 8f07a5f54c..0000000000 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFile.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Microsoft.Dnx.Runtime -{ - public class LockFile - { - public int Version { get; set; } - - public IList ProjectLibraries { get; set; } = new List(); - } -} \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFileProjectLibrary.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFileProjectLibrary.cs deleted file mode 100644 index a131fa32ce..0000000000 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFileProjectLibrary.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.Dnx.Runtime -{ - public class LockFileProjectLibrary - { - public string Name { get; set; } - - public string Path { get; set; } - } -} \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFileReader.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFileReader.cs deleted file mode 100644 index 5cc3821fd9..0000000000 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/LockFileReader.cs +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading; -using Microsoft.Extensions.JsonParser.Sources; -using NuGet; - -namespace Microsoft.Dnx.Runtime -{ - internal class LockFileReader - { - public const string LockFileName = "project.lock.json"; - - public LockFile Read(string filePath) - { - using (var stream = OpenFileStream(filePath)) - { - try - { - return Read(stream); - } - catch (FileFormatException ex) - { - throw ex.WithFilePath(filePath); - } - catch (Exception ex) - { - throw FileFormatException.Create(ex, filePath); - } - } - } - - private static FileStream OpenFileStream(string filePath) - { - // Retry 3 times before re-throw the exception. - // It mitigates the race condition when DTH read lock file while VS is restoring projects. - - int retry = 3; - while (true) - { - try - { - return new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); - } - catch (Exception) - { - if (retry > 0) - { - retry--; - Thread.Sleep(100); - } - else - { - throw; - } - } - } - - } - - internal LockFile Read(Stream stream) - { - try - { - var reader = new StreamReader(stream); - var jobject = JsonDeserializer.Deserialize(reader) as JsonObject; - - if (jobject != null) - { - return ReadLockFile(jobject); - } - else - { - throw new InvalidDataException(); - } - } - catch - { - // Ran into parsing errors, mark it as unlocked and out-of-date - return new LockFile - { - Version = int.MinValue - }; - } - } - - private LockFile ReadLockFile(JsonObject cursor) - { - var lockFile = new LockFile(); - lockFile.Version = ReadInt(cursor, "version", defaultValue: int.MinValue); - ReadLibrary(cursor.ValueAsJsonObject("libraries"), lockFile); - - return lockFile; - } - - private void ReadLibrary(JsonObject json, LockFile lockFile) - { - if (json == null) - { - return; - } - - foreach (var key in json.Keys) - { - var value = json.ValueAsJsonObject(key); - if (value == null) - { - throw FileFormatException.Create("The value type is not object.", json.Value(key)); - } - - var parts = key.Split(new[] { '/' }, 2); - var name = parts[0]; - var version = parts.Length == 2 ? SemanticVersion.Parse(parts[1]) : null; - - var type = value.ValueAsString("type")?.Value; - - if (type == "project") - { - lockFile.ProjectLibraries.Add(new LockFileProjectLibrary - { - Name = name, - Path = ReadString(value.Value("path")) - }); - } - } - } - - private string ReadFrameworkAssemblyReference(JsonValue json) - { - return ReadString(json); - } - - private IList ReadArray(JsonValue json, Func readItem) - { - if (json == null) - { - return new List(); - } - - var jarray = json as JsonArray; - if (jarray == null) - { - throw FileFormatException.Create("The value type is not array.", json); - } - - var items = new List(); - for (int i = 0; i < jarray.Length; ++i) - { - items.Add(readItem(jarray[i])); - } - return items; - } - - private IList ReadObject(JsonObject json, Func readItem) - { - if (json == null) - { - return new List(); - } - var items = new List(); - foreach (var childKey in json.Keys) - { - items.Add(readItem(childKey, json.Value(childKey))); - } - return items; - } - - private bool ReadBool(JsonObject cursor, string property, bool defaultValue) - { - var valueToken = cursor.Value(property) as JsonBoolean; - if (valueToken == null) - { - return defaultValue; - } - - return valueToken.Value; - } - - private int ReadInt(JsonObject cursor, string property, int defaultValue) - { - var number = cursor.Value(property) as JsonNumber; - if (number == null) - { - return defaultValue; - } - - try - { - var resultInInt = Convert.ToInt32(number.Raw); - return resultInInt; - } - catch (Exception ex) - { - // FormatException or OverflowException - throw FileFormatException.Create(ex, cursor); - } - } - - private string ReadString(JsonValue json) - { - if (json is JsonString) - { - return (json as JsonString).Value; - } - else if (json is JsonNull) - { - return null; - } - else - { - throw FileFormatException.Create("The value type is not string.", json); - } - } - } -} \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/NamedResourceReader.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/NamedResourceReader.cs deleted file mode 100644 index 54bfed296b..0000000000 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/NamedResourceReader.cs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using System.IO; -using Microsoft.Extensions.JsonParser.Sources; - -namespace Microsoft.Dnx.Runtime -{ - internal static class NamedResourceReader - { - public static IDictionary ReadNamedResources(JsonObject rawProject, string projectFilePath) - { - if (!rawProject.Keys.Contains("namedResource")) - { - return new Dictionary(); - } - - var namedResourceToken = rawProject.ValueAsJsonObject("namedResource"); - if (namedResourceToken == null) - { - throw FileFormatException.Create("Value must be object.", rawProject.Value("namedResource"), projectFilePath); - } - - var namedResources = new Dictionary(); - - foreach (var namedResourceKey in namedResourceToken.Keys) - { - var resourcePath = namedResourceToken.ValueAsString(namedResourceKey); - if (resourcePath == null) - { - throw FileFormatException.Create("Value must be string.", namedResourceToken.Value(namedResourceKey), projectFilePath); - } - - if (resourcePath.Value.Contains("*")) - { - throw FileFormatException.Create("Value cannot contain wildcards.", resourcePath, projectFilePath); - } - - var resourceFileFullPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(projectFilePath), resourcePath)); - - if (namedResources.ContainsKey(namedResourceKey)) - { - throw FileFormatException.Create( - string.Format("The named resource {0} already exists.", namedResourceKey), - resourcePath, - projectFilePath); - } - - namedResources.Add( - namedResourceKey, - resourceFileFullPath); - } - - return namedResources; - } - - public static void ApplyNamedResources(IDictionary namedResources, IDictionary resources) - { - foreach (var namedResource in namedResources) - { - // The named resources dictionary is like the project file - // key = name, value = path to resource - if (resources.ContainsKey(namedResource.Value)) - { - resources[namedResource.Value] = namedResource.Key; - } - else - { - resources.Add(namedResource.Value, namedResource.Key); - } - } - } - } -} \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PackIncludeEntry.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PackIncludeEntry.cs deleted file mode 100644 index 8ba9c19515..0000000000 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PackIncludeEntry.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Linq; -using Microsoft.Extensions.JsonParser.Sources; - -namespace Microsoft.Dnx.Runtime -{ - public class PackIncludeEntry - { - public string Target { get; } - public string[] SourceGlobs { get; } - public int Line { get; } - public int Column { get; } - - internal PackIncludeEntry(string target, JsonValue json) - : this(target, ExtractValues(json), json.Line, json.Column) - { - } - - public PackIncludeEntry(string target, string[] sourceGlobs, int line, int column) - { - Target = target; - SourceGlobs = sourceGlobs; - Line = line; - Column = column; - } - - private static string[] ExtractValues(JsonValue json) - { - var valueAsString = json as JsonString; - if (valueAsString != null) - { - return new string[] { valueAsString.Value }; - } - - var valueAsArray = json as JsonArray; - if(valueAsArray != null) - { - return valueAsArray.Values.Select(v => v.ToString()).ToArray(); - } - return new string[0]; - } - } -} \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PathUtility.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PathUtility.cs deleted file mode 100644 index 9546881690..0000000000 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PathUtility.cs +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; - -namespace NuGet -{ - internal static class PathUtility - { - public static bool IsChildOfDirectory(string dir, string candidate) - { - if (dir == null) - { - throw new ArgumentNullException(nameof(dir)); - } - if (candidate == null) - { - throw new ArgumentNullException(nameof(candidate)); - } - dir = Path.GetFullPath(dir); - dir = EnsureTrailingSlash(dir); - candidate = Path.GetFullPath(candidate); - return candidate.StartsWith(dir, StringComparison.OrdinalIgnoreCase); - } - - public static string EnsureTrailingSlash(string path) - { - return EnsureTrailingCharacter(path, Path.DirectorySeparatorChar); - } - - public static string EnsureTrailingForwardSlash(string path) - { - return EnsureTrailingCharacter(path, '/'); - } - - private static string EnsureTrailingCharacter(string path, char trailingCharacter) - { - if (path == null) - { - throw new ArgumentNullException(nameof(path)); - } - - // if the path is empty, we want to return the original string instead of a single trailing character. - if (path.Length == 0 || path[path.Length - 1] == trailingCharacter) - { - return path; - } - - return path + trailingCharacter; - } - - public static void EnsureParentDirectory(string filePath) - { - string directory = Path.GetDirectoryName(filePath); - if (!Directory.Exists(directory)) - { - Directory.CreateDirectory(directory); - } - } - - /// - /// Returns path2 relative to path1, with Path.DirectorySeparatorChar as separator - /// - public static string GetRelativePath(string path1, string path2) - { - return GetRelativePath(path1, path2, Path.DirectorySeparatorChar); - } - - /// - /// Returns path2 relative to path1, with given path separator - /// - public static string GetRelativePath(string path1, string path2, char separator) - { - if (string.IsNullOrEmpty(path1)) - { - throw new ArgumentException("Path must have a value", nameof(path1)); - } - - if (string.IsNullOrEmpty(path2)) - { - throw new ArgumentException("Path must have a value", nameof(path2)); - } - - StringComparison compare; - if (Microsoft.Dnx.Runtime.RuntimeEnvironmentHelper.IsWindows) - { - compare = StringComparison.OrdinalIgnoreCase; - // check if paths are on the same volume - if (!string.Equals(Path.GetPathRoot(path1), Path.GetPathRoot(path2))) - { - // on different volumes, "relative" path is just path2 - return path2; - } - } - else - { - compare = StringComparison.Ordinal; - } - - var index = 0; - var path1Segments = path1.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); - var path2Segments = path2.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); - // if path1 does not end with / it is assumed the end is not a directory - // we will assume that is isn't a directory by ignoring the last split - var len1 = path1Segments.Length - 1; - var len2 = path2Segments.Length; - - // find largest common absolute path between both paths - var min = Math.Min(len1, len2); - while (min > index) - { - if (!string.Equals(path1Segments[index], path2Segments[index], compare)) - { - break; - } - // Handle scenarios where folder and file have same name (only if os supports same name for file and directory) - // e.g. /file/name /file/name/app - else if ((len1 == index && len2 > index + 1) || (len1 > index && len2 == index + 1)) - { - break; - } - ++index; - } - - var path = ""; - - // check if path2 ends with a non-directory separator and if path1 has the same non-directory at the end - if (len1 + 1 == len2 && !string.IsNullOrEmpty(path1Segments[index]) && - string.Equals(path1Segments[index], path2Segments[index], compare)) - { - return path; - } - - for (var i = index; len1 > i; ++i) - { - path += ".." + separator; - } - for (var i = index; len2 - 1 > i; ++i) - { - path += path2Segments[i] + separator; - } - // if path2 doesn't end with an empty string it means it ended with a non-directory name, so we add it back - if (!string.IsNullOrEmpty(path2Segments[len2 - 1])) - { - path += path2Segments[len2 - 1]; - } - - return path; - } - - public static string GetAbsolutePath(string basePath, string relativePath) - { - if (basePath == null) - { - throw new ArgumentNullException(nameof(basePath)); - } - - if (relativePath == null) - { - throw new ArgumentNullException(nameof(relativePath)); - } - - Uri resultUri = new Uri(new Uri(basePath), new Uri(relativePath, UriKind.Relative)); - return resultUri.LocalPath; - } - - public static string GetDirectoryName(string path) - { - path = path.TrimEnd(Path.DirectorySeparatorChar); - return path.Substring(Path.GetDirectoryName(path).Length).Trim(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); - } - - public static string GetPathWithForwardSlashes(string path) - { - return path.Replace('\\', '/'); - } - - public static string GetPathWithBackSlashes(string path) - { - return path.Replace('/', '\\'); - } - - public static string GetPathWithDirectorySeparator(string path) - { - if (Path.DirectorySeparatorChar == '/') - { - return GetPathWithForwardSlashes(path); - } - else - { - return GetPathWithBackSlashes(path); - } - } - } -} \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs deleted file mode 100644 index b7abecd809..0000000000 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternGroup.cs +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Microsoft.Extensions.CompilationAbstractions; -using Microsoft.Extensions.FileSystemGlobbing; -using Microsoft.Extensions.JsonParser.Sources; - -namespace Microsoft.Dnx.Runtime -{ - public class PatternGroup - { - private readonly List _excludeGroups = new List(); - private readonly Matcher _matcher = new Matcher(); - - internal PatternGroup(IEnumerable includePatterns) - { - IncludeLiterals = Enumerable.Empty(); - IncludePatterns = includePatterns; - ExcludePatterns = Enumerable.Empty(); - _matcher.AddIncludePatterns(IncludePatterns); - } - - internal PatternGroup(IEnumerable includePatterns, IEnumerable excludePatterns, IEnumerable includeLiterals) - { - IncludeLiterals = includeLiterals; - IncludePatterns = includePatterns; - ExcludePatterns = excludePatterns; - - _matcher.AddIncludePatterns(IncludePatterns); - _matcher.AddExcludePatterns(ExcludePatterns); - } - - internal static PatternGroup Build( - JsonObject rawProject, - string projectDirectory, - string projectFilePath, - string name, - IEnumerable fallbackIncluding = null, - IEnumerable additionalIncluding = null, - IEnumerable additionalExcluding = null, - bool includePatternsOnly = false, - ICollection warnings = null) - { - string includePropertyName = name; - additionalIncluding = additionalIncluding ?? Enumerable.Empty(); - var includePatterns = PatternsCollectionHelper.GetPatternsCollection(rawProject, projectDirectory, projectFilePath, includePropertyName, defaultPatterns: fallbackIncluding) - .Concat(additionalIncluding) - .Distinct(); - - if (includePatternsOnly) - { - return new PatternGroup(includePatterns); - } - - additionalExcluding = additionalExcluding ?? Enumerable.Empty(); - var excludePatterns = PatternsCollectionHelper.GetPatternsCollection(rawProject, projectDirectory, projectFilePath, propertyName: name + "Exclude") - .Concat(additionalExcluding) - .Distinct(); - - var includeLiterals = PatternsCollectionHelper.GetPatternsCollection(rawProject, projectDirectory, projectFilePath, propertyName: name + "Files", literalPath: true) - .Distinct(); - - return new PatternGroup(includePatterns, excludePatterns, includeLiterals); - } - - public IEnumerable IncludeLiterals { get; } - - public IEnumerable IncludePatterns { get; } - - public IEnumerable ExcludePatterns { get; } - - public IEnumerable ExcludePatternsGroup { get { return _excludeGroups; } } - - public PatternGroup ExcludeGroup(PatternGroup group) - { - _excludeGroups.Add(group); - - return this; - } - - public IEnumerable SearchFiles(string rootPath) - { - // literal included files are added at the last, but the search happens early - // so as to make the process fail early in case there is missing file. fail early - // helps to avoid unnecessary globing for performance optimization - var literalIncludedFiles = new List(); - foreach (var literalRelativePath in IncludeLiterals) - { - var fullPath = Path.GetFullPath(Path.Combine(rootPath, literalRelativePath)); - - if (!File.Exists(fullPath)) - { - throw new InvalidOperationException(string.Format("Can't find file {0}", literalRelativePath)); - } - - // TODO: extract utility like NuGet.PathUtility.GetPathWithForwardSlashes() - literalIncludedFiles.Add(fullPath.Replace('\\', '/')); - } - - // globing files - var globbingResults = _matcher.GetResultsInFullPath(rootPath); - - // if there is no results generated in globing, skip excluding other groups - // for performance optimization. - if (globbingResults.Any()) - { - foreach (var group in _excludeGroups) - { - globbingResults = globbingResults.Except(group.SearchFiles(rootPath)); - } - } - - return globbingResults.Concat(literalIncludedFiles).Distinct(); - } - - public override string ToString() - { - return string.Format("Pattern group: Literals [{0}] Includes [{1}] Excludes [{2}]", string.Join(", ", IncludeLiterals), string.Join(", ", IncludePatterns), string.Join(", ", ExcludePatterns)); - } - } -} \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternsCollectionHelper.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternsCollectionHelper.cs deleted file mode 100644 index ed3bb607b3..0000000000 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/PatternsCollectionHelper.cs +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Microsoft.Extensions.JsonParser.Sources; - -namespace Microsoft.Dnx.Runtime -{ - internal static class PatternsCollectionHelper - { - private static readonly char[] PatternSeparator = new[] { ';' }; - - public static IEnumerable GetPatternsCollection( - JsonObject rawProject, - string projectDirectory, - string projectFilePath, - string propertyName, - IEnumerable defaultPatterns = null, - bool literalPath = false) - { - defaultPatterns = defaultPatterns ?? Enumerable.Empty(); - - try - { - if (!rawProject.Keys.Contains(propertyName)) - { - return CreateCollection(projectDirectory, propertyName, defaultPatterns, literalPath); - } - - var valueInString = rawProject.ValueAsString(propertyName); - if (valueInString != null) - { - return CreateCollection(projectDirectory, propertyName, new string[] { valueInString }, literalPath); - } - - var valuesInArray = rawProject.ValueAsStringArray(propertyName); - if (valuesInArray != null) - { - return CreateCollection(projectDirectory, propertyName, valuesInArray.Select(s => s.ToString()), literalPath); - } - } - catch (Exception ex) - { - throw FileFormatException.Create(ex, rawProject.Value(propertyName), projectFilePath); - } - - throw FileFormatException.Create("Value must be either string or array.", rawProject.Value(propertyName), projectFilePath); - } - - private static IEnumerable CreateCollection(string projectDirectory, string propertyName, IEnumerable patternsStrings, bool literalPath) - { - var patterns = patternsStrings.SelectMany(patternsString => GetSourcesSplit(patternsString)) - .Select(patternString => patternString.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar)); - - foreach (var pattern in patterns) - { - if (Path.IsPathRooted(pattern)) - { - throw new InvalidOperationException($"The '{propertyName}' property cannot be a rooted path."); - } - - if (literalPath && pattern.Contains('*')) - { - throw new InvalidOperationException($"The '{propertyName}' property cannot contain wildcard characters."); - } - } - - return new List(patterns.Select(pattern => FolderToPattern(pattern, projectDirectory))); - } - - private static IEnumerable GetSourcesSplit(string sourceDescription) - { - if (string.IsNullOrEmpty(sourceDescription)) - { - return Enumerable.Empty(); - } - - return sourceDescription.Split(PatternSeparator, StringSplitOptions.RemoveEmptyEntries); - } - - private static string FolderToPattern(string candidate, string projectDir) - { - // This conversion is needed to support current template - - // If it's already a pattern, no change is needed - if (candidate.Contains('*')) - { - return candidate; - } - - // If the given string ends with a path separator, or it is an existing directory - // we convert this folder name to a pattern matching all files in the folder - if (candidate.EndsWith(@"\") || - candidate.EndsWith("/") || - Directory.Exists(Path.Combine(projectDir, candidate))) - { - return Path.Combine(candidate, "**", "*"); - } - - // Otherwise, it represents a single file - return candidate; - } - } -} diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/Project.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/Project.cs deleted file mode 100644 index 1b8ddd07d5..0000000000 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/Project.cs +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using Microsoft.Extensions.CompilationAbstractions; -using NuGet; - -namespace Microsoft.Dnx.Runtime -{ - public class Project - { - public const string ProjectFileName = "project.json"; - - public Project() - { - } - - public string ProjectFilePath { get; set; } - - public string ProjectDirectory - { - get - { - return Path.GetDirectoryName(ProjectFilePath); - } - } - - public string Name { get; set; } - - public string Title { get; set; } - - public string Description { get; set; } - - public string Copyright { get; set; } - - public string Summary { get; set; } - - public string Language { get; set; } - - public string ReleaseNotes { get; set; } - - public string[] Authors { get; set; } - - public string[] Owners { get; set; } - - public bool EmbedInteropTypes { get; set; } - - public Version AssemblyFileVersion { get; set; } - public string WebRoot { get; set; } - - public string EntryPoint { get; set; } - - public string ProjectUrl { get; set; } - - public string LicenseUrl { get; set; } - - public string IconUrl { get; set; } - - public bool RequireLicenseAcceptance { get; set; } - - public string[] Tags { get; set; } - - public bool IsLoadable { get; set; } - - public ProjectFilesCollection Files { get; set; } - - public IDictionary Commands { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase); - - public IDictionary> Scripts { get; } = new Dictionary>(StringComparer.OrdinalIgnoreCase); - - public static bool HasProjectFile(string path) - { - string projectPath = Path.Combine(path, ProjectFileName); - - return File.Exists(projectPath); - } - - public static bool TryGetProject(string path, out Project project, ICollection diagnostics = null) - { - project = null; - - string projectPath = null; - - if (string.Equals(Path.GetFileName(path), ProjectFileName, StringComparison.OrdinalIgnoreCase)) - { - projectPath = path; - path = Path.GetDirectoryName(path); - } - else if (!HasProjectFile(path)) - { - return false; - } - else - { - projectPath = Path.Combine(path, ProjectFileName); - } - - // Assume the directory name is the project name if none was specified - var projectName = PathUtility.GetDirectoryName(path); - projectPath = Path.GetFullPath(projectPath); - - if (!File.Exists(projectPath)) - { - return false; - } - - try - { - using (var stream = File.OpenRead(projectPath)) - { - var reader = new ProjectReader(); - project = reader.ReadProject(stream, projectName, projectPath, diagnostics); - } - } - catch (Exception ex) - { - throw FileFormatException.Create(ex, projectPath); - } - - return true; - } - } -} diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectFilesCollection.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectFilesCollection.cs deleted file mode 100644 index 2fe99407b3..0000000000 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectFilesCollection.cs +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using System.Linq; -using Microsoft.Extensions.JsonParser.Sources; - -namespace Microsoft.Dnx.Runtime -{ - public class ProjectFilesCollection - { - public static readonly string[] DefaultCompileBuiltInPatterns = new[] { @"**/*.cs" }; - public static readonly string[] DefaultPublishExcludePatterns = new[] { @"obj/**/*.*", @"bin/**/*.*", @"**/.*/**", @"**/global.json" }; - public static readonly string[] DefaultPreprocessPatterns = new[] { @"compiler/preprocess/**/*.cs" }; - public static readonly string[] DefaultSharedPatterns = new[] { @"compiler/shared/**/*.cs" }; - public static readonly string[] DefaultResourcesBuiltInPatterns = new[] { @"compiler/resources/**/*", "**/*.resx" }; - public static readonly string[] DefaultContentsBuiltInPatterns = new[] { @"**/*" }; - - public static readonly string[] DefaultBuiltInExcludePatterns = new[] { "bin/**", "obj/**", "**/*.xproj" }; - - public static readonly string PackIncludePropertyName = "packInclude"; - - private PatternGroup _sharedPatternsGroup; - private PatternGroup _resourcePatternsGroup; - private PatternGroup _preprocessPatternsGroup; - private PatternGroup _compilePatternsGroup; - private PatternGroup _contentPatternsGroup; - private IDictionary _namedResources; - private IEnumerable _publishExcludePatterns; - private IEnumerable _packInclude; - - private readonly string _projectDirectory; - private readonly string _projectFilePath; - - private JsonObject _rawProject; - private bool _initialized; - - internal ProjectFilesCollection(JsonObject rawProject, string projectDirectory, string projectFilePath) - { - _projectDirectory = projectDirectory; - _projectFilePath = projectFilePath; - _rawProject = rawProject; - } - - internal void EnsureInitialized() - { - if (_initialized) - { - return; - } - - var excludeBuiltIns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "excludeBuiltIn", DefaultBuiltInExcludePatterns); - var excludePatterns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "exclude") - .Concat(excludeBuiltIns); - var contentBuiltIns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "contentBuiltIn", DefaultContentsBuiltInPatterns); - var compileBuiltIns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "compileBuiltIn", DefaultCompileBuiltInPatterns); - var resourceBuiltIns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "resourceBuiltIn", DefaultResourcesBuiltInPatterns); - - _publishExcludePatterns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "publishExclude", DefaultPublishExcludePatterns); - - _sharedPatternsGroup = PatternGroup.Build(_rawProject, _projectDirectory, _projectFilePath, "shared", fallbackIncluding: DefaultSharedPatterns, additionalExcluding: excludePatterns); - - _resourcePatternsGroup = PatternGroup.Build(_rawProject, _projectDirectory, _projectFilePath, "resource", additionalIncluding: resourceBuiltIns, additionalExcluding: excludePatterns); - - _preprocessPatternsGroup = PatternGroup.Build(_rawProject, _projectDirectory, _projectFilePath, "preprocess", fallbackIncluding: DefaultPreprocessPatterns, additionalExcluding: excludePatterns) - .ExcludeGroup(_sharedPatternsGroup) - .ExcludeGroup(_resourcePatternsGroup); - - _compilePatternsGroup = PatternGroup.Build(_rawProject, _projectDirectory, _projectFilePath, "compile", additionalIncluding: compileBuiltIns, additionalExcluding: excludePatterns) - .ExcludeGroup(_sharedPatternsGroup) - .ExcludeGroup(_preprocessPatternsGroup) - .ExcludeGroup(_resourcePatternsGroup); - - _contentPatternsGroup = PatternGroup.Build(_rawProject, _projectDirectory, _projectFilePath, "content", additionalIncluding: contentBuiltIns, additionalExcluding: excludePatterns.Concat(_publishExcludePatterns)) - .ExcludeGroup(_compilePatternsGroup) - .ExcludeGroup(_preprocessPatternsGroup) - .ExcludeGroup(_sharedPatternsGroup) - .ExcludeGroup(_resourcePatternsGroup); - - _namedResources = NamedResourceReader.ReadNamedResources(_rawProject, _projectFilePath); - - // Files to be packed along with the project - var packIncludeJson = _rawProject.ValueAsJsonObject(PackIncludePropertyName); - if (packIncludeJson != null) - { - _packInclude = packIncludeJson - .Keys - .Select(k => new PackIncludeEntry(k, packIncludeJson.Value(k))) - .ToList(); - } - else - { - _packInclude = new List(); - } - - _initialized = true; - _rawProject = null; - } - - public IEnumerable PackInclude - { - get - { - EnsureInitialized(); - return _packInclude; - } - } - - public IEnumerable SourceFiles - { - get { return CompilePatternsGroup.SearchFiles(_projectDirectory).Distinct(); } - } - - public IEnumerable PreprocessSourceFiles - { - get { return PreprocessPatternsGroup.SearchFiles(_projectDirectory).Distinct(); } - } - - public IDictionary ResourceFiles - { - get - { - var resources = ResourcePatternsGroup - .SearchFiles(_projectDirectory) - .Distinct() - .ToDictionary(res => res, res => (string)null); - - NamedResourceReader.ApplyNamedResources(_namedResources, resources); - - return resources; - } - } - - public IEnumerable SharedFiles - { - get { return SharedPatternsGroup.SearchFiles(_projectDirectory).Distinct(); } - } - - public IEnumerable GetFilesForBundling(bool includeSource, IEnumerable additionalExcludePatterns) - { - var patternGroup = new PatternGroup(ContentPatternsGroup.IncludePatterns, - ContentPatternsGroup.ExcludePatterns.Concat(additionalExcludePatterns), - ContentPatternsGroup.IncludeLiterals); - if (!includeSource) - { - foreach (var excludedGroup in ContentPatternsGroup.ExcludePatternsGroup) - { - patternGroup.ExcludeGroup(excludedGroup); - } - } - - return patternGroup.SearchFiles(_projectDirectory); - } - - internal PatternGroup CompilePatternsGroup - { - get - { - EnsureInitialized(); - return _compilePatternsGroup; - } - } - - internal PatternGroup SharedPatternsGroup - { - get - { - EnsureInitialized(); - return _sharedPatternsGroup; - } - } - - internal PatternGroup ResourcePatternsGroup - { - get - { - EnsureInitialized(); - return _resourcePatternsGroup; - } - } - - internal PatternGroup PreprocessPatternsGroup - { - get - { - EnsureInitialized(); - return _preprocessPatternsGroup; - } - } - - internal PatternGroup ContentPatternsGroup - { - get - { - EnsureInitialized(); - return _contentPatternsGroup; - } - } - } -} diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectReader.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectReader.cs deleted file mode 100644 index 1eafcc90a9..0000000000 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/ProjectReader.cs +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Microsoft.Extensions.CompilationAbstractions; -using Microsoft.Extensions.JsonParser.Sources; -using NuGet; - -namespace Microsoft.Dnx.Runtime -{ - public class ProjectReader - { - public Project ReadProject(Stream stream, string projectName, string projectPath, ICollection diagnostics) - { - var project = new Project(); - - var reader = new StreamReader(stream); - var rawProject = JsonDeserializer.Deserialize(reader) as JsonObject; - if (rawProject == null) - { - throw FileFormatException.Create( - "The JSON file can't be deserialized to a JSON object.", - projectPath); - } - - // Meta-data properties - project.Name = projectName; - project.ProjectFilePath = Path.GetFullPath(projectPath); - - var version = rawProject.Value("version") as JsonString; - - project.Description = rawProject.ValueAsString("description"); - project.Summary = rawProject.ValueAsString("summary"); - project.Copyright = rawProject.ValueAsString("copyright"); - project.Title = rawProject.ValueAsString("title"); - project.WebRoot = rawProject.ValueAsString("webroot"); - project.EntryPoint = rawProject.ValueAsString("entryPoint"); - project.ProjectUrl = rawProject.ValueAsString("projectUrl"); - project.LicenseUrl = rawProject.ValueAsString("licenseUrl"); - project.IconUrl = rawProject.ValueAsString("iconUrl"); - - project.Authors = rawProject.ValueAsStringArray("authors") ?? new string[] { }; - project.Owners = rawProject.ValueAsStringArray("owners") ?? new string[] { }; - project.Tags = rawProject.ValueAsStringArray("tags") ?? new string[] { }; - - project.Language = rawProject.ValueAsString("language"); - project.ReleaseNotes = rawProject.ValueAsString("releaseNotes"); - - project.RequireLicenseAcceptance = rawProject.ValueAsBoolean("requireLicenseAcceptance", defaultValue: false); - project.IsLoadable = rawProject.ValueAsBoolean("loadable", defaultValue: true); - // TODO: Move this to the dependencies node - project.EmbedInteropTypes = rawProject.ValueAsBoolean("embedInteropTypes", defaultValue: false); - - // Project files - project.Files = new ProjectFilesCollection(rawProject, project.ProjectDirectory, project.ProjectFilePath); - - var commands = rawProject.Value("commands") as JsonObject; - if (commands != null) - { - foreach (var key in commands.Keys) - { - var value = commands.ValueAsString(key); - if (value != null) - { - project.Commands[key] = value; - } - } - } - - var scripts = rawProject.Value("scripts") as JsonObject; - if (scripts != null) - { - foreach (var key in scripts.Keys) - { - var stringValue = scripts.ValueAsString(key); - if (stringValue != null) - { - project.Scripts[key] = new string[] { stringValue }; - continue; - } - - var arrayValue = scripts.ValueAsStringArray(key); - if (arrayValue != null) - { - project.Scripts[key] = arrayValue; - continue; - } - - throw FileFormatException.Create( - string.Format("The value of a script in {0} can only be a string or an array of strings", Project.ProjectFileName), - scripts.Value(key), - project.ProjectFilePath); - } - } - - return project; - } - - private static SemanticVersion SpecifySnapshot(string version, string snapshotValue) - { - if (version.EndsWith("-*")) - { - if (string.IsNullOrEmpty(snapshotValue)) - { - version = version.Substring(0, version.Length - 2); - } - else - { - version = version.Substring(0, version.Length - 1) + snapshotValue; - } - } - - return new SemanticVersion(version); - } - - private static bool TryGetStringEnumerable(JsonObject parent, string property, out IEnumerable result) - { - var collection = new List(); - var valueInString = parent.ValueAsString(property); - if (valueInString != null) - { - collection.Add(valueInString); - } - else - { - var valueInArray = parent.ValueAsStringArray(property); - if (valueInArray != null) - { - collection.AddRange(valueInArray); - } - else - { - result = null; - return false; - } - } - - result = collection.SelectMany(value => value.Split(new[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries)); - return true; - } - } -} diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/RuntimeEnvironmentHelper.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/RuntimeEnvironmentHelper.cs deleted file mode 100644 index 27ea21b458..0000000000 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/RuntimeEnvironmentHelper.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.Extensions.PlatformAbstractions; - -namespace Microsoft.Dnx.Runtime -{ - internal static class RuntimeEnvironmentHelper - { - private static Lazy _isMono = new Lazy(() => - _runtimeEnv.Value.RuntimeType == "Mono"); - - private static Lazy _isWindows = new Lazy(() => - _runtimeEnv.Value.OperatingSystem == "Windows"); - - private static Lazy _runtimeEnv = new Lazy(() => - GetRuntimeEnvironment()); - - private static IRuntimeEnvironment GetRuntimeEnvironment() - { - var environment = PlatformServices.Default.Runtime; - - if (environment == null) - { - throw new InvalidOperationException("Failed to resolve IRuntimeEnvironment"); - } - - return environment; - } - - public static IRuntimeEnvironment RuntimeEnvironment - { - get - { - return _runtimeEnv.Value; - } - } - - public static bool IsWindows - { - get { return _isWindows.Value; } - } - - public static bool IsMono - { - get { return _isMono.Value; } - } - } -} diff --git a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/SemanticVersion.cs b/src/Microsoft.Dnx.Watcher.Core/External/Runtime/SemanticVersion.cs deleted file mode 100644 index 59846a2cf9..0000000000 --- a/src/Microsoft.Dnx.Watcher.Core/External/Runtime/SemanticVersion.cs +++ /dev/null @@ -1,330 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Text; - -namespace NuGet -{ - /// - /// A hybrid implementation of SemVer that supports semantic versioning as described at http://semver.org while not strictly enforcing it to - /// allow older 4-digit versioning schemes to continue working. - /// - internal sealed class SemanticVersion : IComparable, IComparable, IEquatable - { - private string _normalizedVersionString; - - public SemanticVersion(string version) - : this(Parse(version)) - { - } - - public SemanticVersion(int major, int minor, int build, int revision) - : this(new Version(major, minor, build, revision)) - { - } - - public SemanticVersion(int major, int minor, int build, string specialVersion) - : this(new Version(major, minor, build), specialVersion) - { - } - - public SemanticVersion(Version version) - : this(version, string.Empty) - { - } - - public SemanticVersion(Version version, string specialVersion) - { - if (version == null) - { - throw new ArgumentNullException(nameof(version)); - } - Version = NormalizeVersionValue(version); - SpecialVersion = specialVersion ?? string.Empty; - } - - internal SemanticVersion(SemanticVersion semVer) - { - Version = semVer.Version; - SpecialVersion = semVer.SpecialVersion; - } - - /// - /// Gets the normalized version portion. - /// - public Version Version - { - get; - private set; - } - - /// - /// Gets the optional special version. - /// - public string SpecialVersion - { - get; - private set; - } - - private static string[] SplitAndPadVersionString(string version) - { - string[] a = version.Split('.'); - if (a.Length == 4) - { - return a; - } - else - { - // if 'a' has less than 4 elements, we pad the '0' at the end - // to make it 4. - var b = new string[4] { "0", "0", "0", "0" }; - Array.Copy(a, 0, b, 0, a.Length); - return b; - } - } - - /// - /// Parses a version string using loose semantic versioning rules that allows 2-4 version components followed by an optional special version. - /// - public static SemanticVersion Parse(string version) - { - if (string.IsNullOrEmpty(version)) - { - throw new ArgumentNullException(nameof(version)); - } - - SemanticVersion semVer; - if (!TryParse(version, out semVer)) - { - throw new ArgumentException(nameof(version)); - } - return semVer; - } - - /// - /// Parses a version string using loose semantic versioning rules that allows 2-4 version components followed by an optional special version. - /// - public static bool TryParse(string version, out SemanticVersion value) - { - return TryParseInternal(version, strict: false, semVer: out value); - } - - /// - /// Parses a version string using strict semantic versioning rules that allows exactly 3 components and an optional special version. - /// - public static bool TryParseStrict(string version, out SemanticVersion value) - { - return TryParseInternal(version, strict: true, semVer: out value); - } - - private static bool TryParseInternal(string version, bool strict, out SemanticVersion semVer) - { - semVer = null; - if (string.IsNullOrEmpty(version)) - { - return false; - } - - version = version.Trim(); - var versionPart = version; - - string specialVersion = string.Empty; - if (version.IndexOf('-') != -1) - { - var parts = version.Split(new char[] { '-' }, 2, StringSplitOptions.RemoveEmptyEntries); - if (parts.Length != 2) - { - return false; - } - - versionPart = parts[0]; - specialVersion = parts[1]; - } - - Version versionValue; - if (!Version.TryParse(versionPart, out versionValue)) - { - return false; - } - - if (strict) - { - // Must have major, minor and build only. - if (versionValue.Major == -1 || - versionValue.Minor == -1 || - versionValue.Build == -1 || - versionValue.Revision != -1) - { - return false; - } - } - - semVer = new SemanticVersion(NormalizeVersionValue(versionValue), specialVersion); - return true; - } - - /// - /// Attempts to parse the version token as a SemanticVersion. - /// - /// An instance of SemanticVersion if it parses correctly, null otherwise. - public static SemanticVersion ParseOptionalVersion(string version) - { - SemanticVersion semVer; - TryParse(version, out semVer); - return semVer; - } - - private static Version NormalizeVersionValue(Version version) - { - return new Version(version.Major, - version.Minor, - Math.Max(version.Build, 0), - Math.Max(version.Revision, 0)); - } - - public int CompareTo(object obj) - { - if (Object.ReferenceEquals(obj, null)) - { - return 1; - } - SemanticVersion other = obj as SemanticVersion; - if (other == null) - { - throw new ArgumentException(nameof(obj)); - } - return CompareTo(other); - } - - public int CompareTo(SemanticVersion other) - { - if (Object.ReferenceEquals(other, null)) - { - return 1; - } - - int result = Version.CompareTo(other.Version); - - if (result != 0) - { - return result; - } - - bool empty = string.IsNullOrEmpty(SpecialVersion); - bool otherEmpty = string.IsNullOrEmpty(other.SpecialVersion); - if (empty && otherEmpty) - { - return 0; - } - else if (empty) - { - return 1; - } - else if (otherEmpty) - { - return -1; - } - return StringComparer.OrdinalIgnoreCase.Compare(SpecialVersion, other.SpecialVersion); - } - - public static bool operator ==(SemanticVersion version1, SemanticVersion version2) - { - if (Object.ReferenceEquals(version1, null)) - { - return Object.ReferenceEquals(version2, null); - } - return version1.Equals(version2); - } - - public static bool operator !=(SemanticVersion version1, SemanticVersion version2) - { - return !(version1 == version2); - } - - public static bool operator <(SemanticVersion version1, SemanticVersion version2) - { - if (version1 == null) - { - throw new ArgumentNullException(nameof(version1)); - } - return version1.CompareTo(version2) < 0; - } - - public static bool operator <=(SemanticVersion version1, SemanticVersion version2) - { - return (version1 == version2) || (version1 < version2); - } - - public static bool operator >(SemanticVersion version1, SemanticVersion version2) - { - if (version1 == null) - { - throw new ArgumentNullException(nameof(version1)); - } - return version2 < version1; - } - - public static bool operator >=(SemanticVersion version1, SemanticVersion version2) - { - return (version1 == version2) || (version1 > version2); - } - - public override string ToString() - { - if (_normalizedVersionString == null) - { - var builder = new StringBuilder(); - builder - .Append(Version.Major) - .Append('.') - .Append(Version.Minor) - .Append('.') - .Append(Math.Max(0, Version.Build)); - - if (Version.Revision > 0) - { - builder - .Append('.') - .Append(Version.Revision); - } - - if (!string.IsNullOrEmpty(SpecialVersion)) - { - builder - .Append('-') - .Append(SpecialVersion); - } - - _normalizedVersionString = builder.ToString(); - } - - return _normalizedVersionString; - } - - public bool Equals(SemanticVersion other) - { - return !Object.ReferenceEquals(null, other) && - Version.Equals(other.Version) && - SpecialVersion.Equals(other.SpecialVersion, StringComparison.OrdinalIgnoreCase); - } - - public override bool Equals(object obj) - { - SemanticVersion semVer = obj as SemanticVersion; - return !Object.ReferenceEquals(null, semVer) && Equals(semVer); - } - - public override int GetHashCode() - { - int hashCode = Version.GetHashCode(); - if (SpecialVersion != null) - { - hashCode = hashCode * 4567 + SpecialVersion.GetHashCode(); - } - - return hashCode; - } - } -} diff --git a/src/Microsoft.Dnx.Watcher/Program.cs b/src/Microsoft.Dnx.Watcher/Program.cs deleted file mode 100644 index f2b2d9c104..0000000000 --- a/src/Microsoft.Dnx.Watcher/Program.cs +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.CommandLineUtils; -using Microsoft.Extensions.PlatformAbstractions; -using Microsoft.Dnx.Watcher.Core; -using Microsoft.Extensions.Logging; - -namespace Microsoft.Dnx.Watcher -{ - public class Program - { - private const string DnxWatchArgumentSeparator = "--dnx-args"; - - private readonly ILoggerFactory _loggerFactory; - - public Program() - { - _loggerFactory = new LoggerFactory(); - - var commandProvider = new CommandOutputProvider(PlatformServices.Default.Runtime); - _loggerFactory.AddProvider(commandProvider); - } - - public static int Main(string[] args) - { - using (CancellationTokenSource ctrlCTokenSource = new CancellationTokenSource()) - { - Console.CancelKeyPress += (sender, ev) => - { - ctrlCTokenSource.Cancel(); - ev.Cancel = false; - }; - - string[] watchArgs, dnxArgs; - SeparateWatchArguments(args, out watchArgs, out dnxArgs); - - return new Program().MainInternal(watchArgs, dnxArgs, ctrlCTokenSource.Token); - } - } - - internal static void SeparateWatchArguments(string[] args, out string[] watchArgs, out string[] dnxArgs) - { - int argsIndex = -1; - watchArgs = args.TakeWhile((arg, idx) => - { - argsIndex = idx; - return !string.Equals(arg, DnxWatchArgumentSeparator, StringComparison.OrdinalIgnoreCase); - }).ToArray(); - - dnxArgs = args.Skip(argsIndex + 1).ToArray(); - - if (dnxArgs.Length == 0) - { - // If no explicit dnx arguments then all arguments get passed to dnx - dnxArgs = watchArgs; - watchArgs = new string[0]; - } - } - - private int MainInternal(string[] watchArgs, string[] dnxArgs, CancellationToken cancellationToken) - { - var app = new CommandLineApplication(); - app.Name = "dnx-watch"; - app.FullName = "Microsoft .NET DNX File Watcher"; - - app.HelpOption("-?|-h|--help"); - - var projectArg = app.Option( - "--project ", - "Path to the project.json file or the application folder. Defaults to the current folder if not provided. Will be passed to DNX.", - CommandOptionType.SingleValue); - - var workingDirArg = app.Option( - "--working-dir ", - "The working directory for DNX. Defaults to the current directory.", - CommandOptionType.SingleValue); - - var exitOnChangeArg = app.Option( - "--exit-on-change", - "The watcher will exit when a file change is detected instead of restarting the process.", - CommandOptionType.NoValue); - - // This option is here just to be displayed in help - // it will not be parsed because it is removed before the code is executed - app.Option( - $"{DnxWatchArgumentSeparator} ", - "Marks the arguments that will be passed to DNX. Anything following this option is passed. If not specified, all the arguments are passed to DNX.", - CommandOptionType.SingleValue); - - app.OnExecute(() => - { - var projectToRun = projectArg.HasValue() ? - projectArg.Value() : - Directory.GetCurrentDirectory(); - - if (!projectToRun.EndsWith("project.json", StringComparison.Ordinal)) - { - projectToRun = Path.Combine(projectToRun, "project.json"); - } - - var workingDir = workingDirArg.HasValue() ? - workingDirArg.Value() : - Directory.GetCurrentDirectory(); - - var watcher = DnxWatcher.CreateDefault(_loggerFactory); - watcher.ExitOnChange = exitOnChangeArg.HasValue(); - - try - { - watcher.WatchAsync(projectToRun, dnxArgs, workingDir, cancellationToken).Wait(); - } - catch (AggregateException ex) - { - if (ex.InnerExceptions.Count != 1 || !(ex.InnerException is TaskCanceledException)) - { - throw; - } - } - - - return 1; - }); - - return app.Execute(watchArgs); - } - } -} diff --git a/src/Microsoft.Dnx.Watcher/Properties/AssemblyInfo.cs b/src/Microsoft.Dnx.Watcher/Properties/AssemblyInfo.cs deleted file mode 100644 index 64dbfc69d0..0000000000 --- a/src/Microsoft.Dnx.Watcher/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Reflection; -using System.Resources; -using System.Runtime.CompilerServices; - -[assembly:InternalsVisibleTo("Microsoft.Dnx.Watcher.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] -[assembly: AssemblyMetadata("Serviceable", "True")] -[assembly: NeutralResourcesLanguage("en-US")] diff --git a/src/Microsoft.Dnx.Watcher.Core/Abstractions/IFileWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Abstractions/IFileWatcher.cs similarity index 91% rename from src/Microsoft.Dnx.Watcher.Core/Abstractions/IFileWatcher.cs rename to src/Microsoft.DotNet.Watcher.Core/Abstractions/IFileWatcher.cs index 8dfd44f1e5..c5f01a6399 100644 --- a/src/Microsoft.Dnx.Watcher.Core/Abstractions/IFileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Abstractions/IFileWatcher.cs @@ -3,7 +3,7 @@ using System; -namespace Microsoft.Dnx.Watcher.Core +namespace Microsoft.DotNet.Watcher.Core { public interface IFileWatcher : IDisposable { diff --git a/src/Microsoft.Dnx.Watcher.Core/Abstractions/IProcessWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Abstractions/IProcessWatcher.cs similarity index 88% rename from src/Microsoft.Dnx.Watcher.Core/Abstractions/IProcessWatcher.cs rename to src/Microsoft.DotNet.Watcher.Core/Abstractions/IProcessWatcher.cs index d075bd519a..ad975f3a12 100644 --- a/src/Microsoft.Dnx.Watcher.Core/Abstractions/IProcessWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Abstractions/IProcessWatcher.cs @@ -1,10 +1,11 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Threading; using System.Threading.Tasks; -namespace Microsoft.Dnx.Watcher.Core +namespace Microsoft.DotNet.Watcher.Core { public interface IProcessWatcher { diff --git a/src/Microsoft.Dnx.Watcher.Core/Abstractions/IProject.cs b/src/Microsoft.DotNet.Watcher.Core/Abstractions/IProject.cs similarity index 90% rename from src/Microsoft.Dnx.Watcher.Core/Abstractions/IProject.cs rename to src/Microsoft.DotNet.Watcher.Core/Abstractions/IProject.cs index cad54e0997..fc4556c570 100644 --- a/src/Microsoft.Dnx.Watcher.Core/Abstractions/IProject.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Abstractions/IProject.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; -namespace Microsoft.Dnx.Watcher.Core +namespace Microsoft.DotNet.Watcher.Core { public interface IProject { diff --git a/src/Microsoft.Dnx.Watcher.Core/Abstractions/IProjectProvider.cs b/src/Microsoft.DotNet.Watcher.Core/Abstractions/IProjectProvider.cs similarity index 88% rename from src/Microsoft.Dnx.Watcher.Core/Abstractions/IProjectProvider.cs rename to src/Microsoft.DotNet.Watcher.Core/Abstractions/IProjectProvider.cs index 77abc7bbb1..44e46cd91e 100644 --- a/src/Microsoft.Dnx.Watcher.Core/Abstractions/IProjectProvider.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Abstractions/IProjectProvider.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.Dnx.Watcher.Core +namespace Microsoft.DotNet.Watcher.Core { public interface IProjectProvider { diff --git a/src/Microsoft.Dnx.Watcher.Core/DictionaryExtensions.cs b/src/Microsoft.DotNet.Watcher.Core/DictionaryExtensions.cs similarity index 100% rename from src/Microsoft.Dnx.Watcher.Core/DictionaryExtensions.cs rename to src/Microsoft.DotNet.Watcher.Core/DictionaryExtensions.cs diff --git a/src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs similarity index 71% rename from src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs rename to src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs index b4a27a9afb..f105727329 100644 --- a/src/Microsoft.Dnx.Watcher.Core/DnxWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs @@ -8,9 +8,9 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; -namespace Microsoft.Dnx.Watcher.Core +namespace Microsoft.DotNet.Watcher.Core { - public class DnxWatcher + public class DotNetWatcher { private readonly Func _fileWatcherFactory; private readonly Func _processWatcherFactory; @@ -21,7 +21,7 @@ namespace Microsoft.Dnx.Watcher.Core public bool ExitOnChange { get; set; } - public DnxWatcher( + public DotNetWatcher( Func fileWatcherFactory, Func processWatcherFactory, IProjectProvider projectProvider, @@ -32,12 +32,44 @@ namespace Microsoft.Dnx.Watcher.Core _projectProvider = projectProvider; _loggerFactory = loggerFactory; - _logger = _loggerFactory.CreateLogger(nameof(DnxWatcher)); + _logger = _loggerFactory.CreateLogger(nameof(DotNetWatcher)); } - public async Task WatchAsync(string projectFile, string[] dnxArguments, string workingDir, CancellationToken cancellationToken) + + public async Task WatchAsync(string projectFile, string command, string[] dotnetArguments, string workingDir, CancellationToken cancellationToken) { - dnxArguments = new string[] { "--project", projectFile } - .Concat(dnxArguments) + if (string.IsNullOrEmpty(projectFile)) + { + throw new ArgumentNullException(nameof(projectFile)); + } + if (string.IsNullOrEmpty(command)) + { + throw new ArgumentNullException(nameof(command)); + } + if (dotnetArguments == null) + { + throw new ArgumentNullException(nameof(dotnetArguments)); + } + if (string.IsNullOrEmpty(workingDir)) + { + throw new ArgumentNullException(nameof(workingDir)); + } + if (cancellationToken == null) + { + throw new ArgumentNullException(nameof(cancellationToken)); + } + + if (dotnetArguments.Length > 0) + { + dotnetArguments = new string[] { command, "--" } + .Concat(dotnetArguments) + .ToArray(); + } + else + { + dotnetArguments = new string[] { command }; + } + + dotnetArguments = dotnetArguments .Select(arg => { // If the argument has spaces, make sure we quote it @@ -50,7 +82,7 @@ namespace Microsoft.Dnx.Watcher.Core }) .ToArray(); - var dnxArgumentsAsString = string.Join(" ", dnxArguments); + var dotnetArgumentsAsString = string.Join(" ", dotnetArguments); while (true) { @@ -63,14 +95,14 @@ namespace Microsoft.Dnx.Watcher.Core currentRunCancellationSource.Token)) { var fileWatchingTask = WaitForProjectFileToChangeAsync(project, combinedCancellationSource.Token); - var dnxTask = WaitForDnxToExitAsync(dnxArgumentsAsString, workingDir, combinedCancellationSource.Token); + var dotnetTask = WaitForDotnetToExitAsync(dotnetArgumentsAsString, workingDir, combinedCancellationSource.Token); - var tasksToWait = new Task[] { dnxTask, fileWatchingTask }; + var tasksToWait = new Task[] { dotnetTask, fileWatchingTask }; int finishedTaskIndex = Task.WaitAny(tasksToWait, cancellationToken); // Regardless of the outcome, make sure everything is cancelled - // and wait for dnx to exit. We don't want orphan processes + // and wait for dotnet to exit. We don't want orphan processes currentRunCancellationSource.Cancel(); Task.WaitAll(tasksToWait); @@ -78,16 +110,16 @@ namespace Microsoft.Dnx.Watcher.Core if (finishedTaskIndex == 0) { - // This is the dnx task - var dnxExitCode = dnxTask.Result; + // This is the dotnet task + var dotnetExitCode = dotnetTask.Result; - if (dnxExitCode == 0) + if (dotnetExitCode == 0) { - _logger.LogInformation($"dnx exit code: {dnxExitCode}"); + _logger.LogInformation($"dotnet exit code: {dotnetExitCode}"); } else { - _logger.LogError($"dnx exit code: {dnxExitCode}"); + _logger.LogError($"dotnet exit code: {dotnetExitCode}"); } if (ExitOnChange) @@ -95,8 +127,8 @@ namespace Microsoft.Dnx.Watcher.Core break; } - _logger.LogInformation("Waiting for a file to change before restarting dnx..."); - // Now wait for a file to change before restarting dnx + _logger.LogInformation("Waiting for a file to change before restarting dotnet..."); + // Now wait for a file to change before restarting dotnet await WaitForProjectFileToChangeAsync(project, cancellationToken); } else @@ -123,15 +155,15 @@ namespace Microsoft.Dnx.Watcher.Core } } - private Task WaitForDnxToExitAsync(string dnxArguments, string workingDir, CancellationToken cancellationToken) + private Task WaitForDotnetToExitAsync(string dotnetArguments, string workingDir, CancellationToken cancellationToken) { - _logger.LogInformation($"Running dnx with the following arguments: {dnxArguments}"); + _logger.LogInformation($"Running dotnet with the following arguments: {dotnetArguments}"); - var dnxWatcher = _processWatcherFactory(); - int dnxProcessId = dnxWatcher.Start("dnx", dnxArguments, workingDir); - _logger.LogInformation($"dnx process id: {dnxProcessId}"); + var dotnetWatcher = _processWatcherFactory(); + int dotnetProcessId = dotnetWatcher.Start("dotnet", dotnetArguments, workingDir); + _logger.LogInformation($"dotnet run process id: {dotnetProcessId}"); - return dnxWatcher.WaitForExitAsync(cancellationToken); + return dotnetWatcher.WaitForExitAsync(cancellationToken); } private async Task WaitForValidProjectJsonAsync(string projectFile, CancellationToken cancellationToken) @@ -219,9 +251,9 @@ namespace Microsoft.Dnx.Watcher.Core return changedPath; } - public static DnxWatcher CreateDefault(ILoggerFactory loggerFactory) + public static DotNetWatcher CreateDefault(ILoggerFactory loggerFactory) { - return new DnxWatcher( + return new DotNetWatcher( fileWatcherFactory: root => new FileWatcher(root), processWatcherFactory: () => new ProcessWatcher(), projectProvider: new ProjectProvider(), diff --git a/src/Microsoft.Dnx.Watcher.Core/FileSystem/FileSystemWatcherRoot.cs b/src/Microsoft.DotNet.Watcher.Core/FileSystem/FileSystemWatcherRoot.cs similarity index 93% rename from src/Microsoft.Dnx.Watcher.Core/FileSystem/FileSystemWatcherRoot.cs rename to src/Microsoft.DotNet.Watcher.Core/FileSystem/FileSystemWatcherRoot.cs index 3c4fb517c1..ff8534bc37 100644 --- a/src/Microsoft.Dnx.Watcher.Core/FileSystem/FileSystemWatcherRoot.cs +++ b/src/Microsoft.DotNet.Watcher.Core/FileSystem/FileSystemWatcherRoot.cs @@ -3,7 +3,7 @@ using System.IO; -namespace Microsoft.Dnx.Watcher.Core +namespace Microsoft.DotNet.Watcher.Core { internal class FileSystemWatcherRoot : IWatcherRoot { diff --git a/src/Microsoft.Dnx.Watcher.Core/FileSystem/FileWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/FileSystem/FileWatcher.cs similarity index 99% rename from src/Microsoft.Dnx.Watcher.Core/FileSystem/FileWatcher.cs rename to src/Microsoft.DotNet.Watcher.Core/FileSystem/FileWatcher.cs index fe9921336e..e3d3abd442 100644 --- a/src/Microsoft.Dnx.Watcher.Core/FileSystem/FileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/FileSystem/FileWatcher.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.IO; -namespace Microsoft.Dnx.Watcher.Core +namespace Microsoft.DotNet.Watcher.Core { public class FileWatcher : IFileWatcher { diff --git a/src/Microsoft.Dnx.Watcher.Core/FileSystem/IWatcherRoot.cs b/src/Microsoft.DotNet.Watcher.Core/FileSystem/IWatcherRoot.cs similarity index 87% rename from src/Microsoft.Dnx.Watcher.Core/FileSystem/IWatcherRoot.cs rename to src/Microsoft.DotNet.Watcher.Core/FileSystem/IWatcherRoot.cs index ffc7a86f6b..eaf0e66bd0 100644 --- a/src/Microsoft.Dnx.Watcher.Core/FileSystem/IWatcherRoot.cs +++ b/src/Microsoft.DotNet.Watcher.Core/FileSystem/IWatcherRoot.cs @@ -3,7 +3,7 @@ using System; -namespace Microsoft.Dnx.Watcher.Core +namespace Microsoft.DotNet.Watcher.Core { internal interface IWatcherRoot : IDisposable { diff --git a/src/Microsoft.Dnx.Watcher.Core/Impl/ProcessWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Impl/ProcessWatcher.cs similarity index 55% rename from src/Microsoft.Dnx.Watcher.Core/Impl/ProcessWatcher.cs rename to src/Microsoft.DotNet.Watcher.Core/Impl/ProcessWatcher.cs index 153979d659..91e7d72653 100644 --- a/src/Microsoft.Dnx.Watcher.Core/Impl/ProcessWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Impl/ProcessWatcher.cs @@ -3,14 +3,16 @@ using System; using System.Diagnostics; -using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.PlatformAbstractions; -namespace Microsoft.Dnx.Watcher.Core +namespace Microsoft.DotNet.Watcher.Core { public class ProcessWatcher : IProcessWatcher { + private static readonly bool _isWindows = PlatformServices.Default.Runtime.OperatingSystem.Equals("Windows", StringComparison.OrdinalIgnoreCase); + private Process _runningProcess; public int Start(string executable, string arguments, string workingDir) @@ -30,8 +32,6 @@ namespace Microsoft.Dnx.Watcher.Core WorkingDirectory = workingDir }; - RemoveCompilationPortEnvironmentVariable(_runningProcess.StartInfo); - _runningProcess.Start(); return _runningProcess.Id; @@ -39,9 +39,9 @@ namespace Microsoft.Dnx.Watcher.Core public Task WaitForExitAsync(CancellationToken cancellationToken) { - cancellationToken.Register(() => _runningProcess?.Kill()); - - return Task.Run(() => + cancellationToken.Register(() => KillProcess(_runningProcess?.Id)); + + return Task.Run(() => { _runningProcess.WaitForExit(); @@ -52,32 +52,33 @@ namespace Microsoft.Dnx.Watcher.Core }); } - private static void RemoveCompilationPortEnvironmentVariable(ProcessStartInfo procStartInfo) + private void KillProcess(int? processId) { - string[] _environmentVariablesToRemove = new string[] + if (processId == null) { - "DNX_COMPILATION_SERVER_PORT", - }; - -#if DNX451 - var environmentVariables = procStartInfo.EnvironmentVariables.Keys.Cast(); -#else - var environmentVariables = procStartInfo.Environment.Keys; -#endif - - var envVarsToRemove = environmentVariables - .Where(envVar => _environmentVariablesToRemove.Contains(envVar, StringComparer.OrdinalIgnoreCase)) - .ToArray(); - - // Workaround for the DNX start issue (it passes some environment variables that it shouldn't) - foreach (var envVar in envVarsToRemove) - { -#if DNX451 - procStartInfo.EnvironmentVariables.Remove(envVar); -#else - procStartInfo.Environment.Remove(envVar); -#endif + return; } + + ProcessStartInfo startInfo; + + if (_isWindows) + { + startInfo = new ProcessStartInfo() + { + FileName = "taskkill", + Arguments = $"/T /F /PID {processId}", + }; + } + else + { + startInfo = new ProcessStartInfo() + { + FileName = "pkill", + Arguments = $"-TERM -P {processId}", + }; + } + var killProcess = Process.Start(startInfo); + killProcess.WaitForExit(); } } } \ No newline at end of file diff --git a/src/Microsoft.Dnx.Watcher.Core/Impl/Project.cs b/src/Microsoft.DotNet.Watcher.Core/Impl/Project.cs similarity index 82% rename from src/Microsoft.Dnx.Watcher.Core/Impl/Project.cs rename to src/Microsoft.DotNet.Watcher.Core/Impl/Project.cs index 04d667c95a..a4e2423206 100644 --- a/src/Microsoft.Dnx.Watcher.Core/Impl/Project.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Impl/Project.cs @@ -4,14 +4,13 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using Microsoft.Dnx.Runtime; -using Microsoft.Extensions.CompilationAbstractions; +using Microsoft.DotNet.ProjectModel.Graph; -namespace Microsoft.Dnx.Watcher.Core +namespace Microsoft.DotNet.Watcher.Core { internal class Project : IProject { - public Project(Runtime.Project runtimeProject) + public Project(ProjectModel.Project runtimeProject) { ProjectFile = runtimeProject.ProjectFilePath; ProjectDirectory = runtimeProject.ProjectDirectory; @@ -23,12 +22,11 @@ namespace Microsoft.Dnx.Watcher.Core new string[] { runtimeProject.ProjectFilePath }) .ToList(); - var projectLockJsonPath = Path.Combine(runtimeProject.ProjectDirectory, LockFileReader.LockFileName); - var lockFileReader = new LockFileReader(); - + var projectLockJsonPath = Path.Combine(runtimeProject.ProjectDirectory, "project.lock.json"); + if (File.Exists(projectLockJsonPath)) { - var lockFile = lockFileReader.Read(projectLockJsonPath); + var lockFile = LockFileReader.Read(projectLockJsonPath); ProjectDependencies = lockFile.ProjectLibraries.Select(dep => GetProjectRelativeFullPath(dep.Path)).ToList(); } else diff --git a/src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs b/src/Microsoft.DotNet.Watcher.Core/Impl/ProjectProvider.cs similarity index 87% rename from src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs rename to src/Microsoft.DotNet.Watcher.Core/Impl/ProjectProvider.cs index 73005c5d15..1336f50829 100644 --- a/src/Microsoft.Dnx.Watcher.Core/Impl/ProjectProvider.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Impl/ProjectProvider.cs @@ -5,9 +5,9 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; -using Microsoft.Extensions.CompilationAbstractions; +using Microsoft.DotNet.ProjectModel; -namespace Microsoft.Dnx.Watcher.Core +namespace Microsoft.DotNet.Watcher.Core { public class ProjectProvider : IProjectProvider { @@ -16,7 +16,7 @@ namespace Microsoft.Dnx.Watcher.Core errors = null; project = null; - Runtime.Project runtimeProject; + ProjectModel.Project runtimeProject; if (!TryGetProject(projectFile, out runtimeProject, out errors)) { return false; @@ -36,12 +36,12 @@ namespace Microsoft.Dnx.Watcher.Core } // Same as TryGetProject but it doesn't throw - private bool TryGetProject(string projectFile, out Runtime.Project project, out string errorMessage) + private bool TryGetProject(string projectFile, out ProjectModel.Project project, out string errorMessage) { try { var errors = new List(); - if (!Runtime.Project.TryGetProject(projectFile, out project, errors)) + if (!ProjectReader.TryGetProject(projectFile, out project, errors)) { errorMessage = string.Join(Environment.NewLine, errors.Select(e => e.ToString())); } diff --git a/src/Microsoft.Dnx.Watcher.Core/Microsoft.Dnx.Watcher.Core.xproj b/src/Microsoft.DotNet.Watcher.Core/Microsoft.DotNet.Watcher.Core.xproj similarity index 100% rename from src/Microsoft.Dnx.Watcher.Core/Microsoft.Dnx.Watcher.Core.xproj rename to src/Microsoft.DotNet.Watcher.Core/Microsoft.DotNet.Watcher.Core.xproj diff --git a/src/Microsoft.Dnx.Watcher.Core/Properties/AssemblyInfo.cs b/src/Microsoft.DotNet.Watcher.Core/Properties/AssemblyInfo.cs similarity index 100% rename from src/Microsoft.Dnx.Watcher.Core/Properties/AssemblyInfo.cs rename to src/Microsoft.DotNet.Watcher.Core/Properties/AssemblyInfo.cs diff --git a/src/Microsoft.Dnx.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json similarity index 71% rename from src/Microsoft.Dnx.Watcher.Core/project.json rename to src/Microsoft.DotNet.Watcher.Core/project.json index b0b659a01b..cb07bfea11 100644 --- a/src/Microsoft.Dnx.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -5,6 +5,7 @@ "keyFile": "../../tools/Key.snk" }, "dependencies": { + "Microsoft.DotNet.ProjectModel": "1.0.0-*", "Microsoft.Extensions.FileProviders.Abstractions": "1.0.0-*", "Microsoft.Extensions.FileProviders.Physical": "1.0.0-*", "Microsoft.Extensions.PlatformAbstractions": "1.0.0-*", @@ -18,18 +19,8 @@ "Microsoft.NETCore.Platforms": "1.0.1-*" }, "frameworks": { - "dnx451": { - "frameworkAssemblies": { - "System.Collections": "", - "System.Runtime": "" - } - }, "dnxcore50": { - "dependencies": { - "System.Diagnostics.Process": "4.1.0-*", - "System.Linq": "4.0.2-*", - "System.Threading.Thread": "4.0.0-*" - } + "imports": "portable-net451+win8" } } } diff --git a/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs b/src/dotnet-watch/CommandOutputLogger.cs similarity index 98% rename from src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs rename to src/dotnet-watch/CommandOutputLogger.cs index 59b329d0d1..673f7ee8d8 100644 --- a/src/Microsoft.Dnx.Watcher/CommandOutputLogger.cs +++ b/src/dotnet-watch/CommandOutputLogger.cs @@ -5,7 +5,7 @@ using System; using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Logging; -namespace Microsoft.Dnx.Watcher +namespace Microsoft.DotNet.Watcher { /// /// Logger to print formatted command output. diff --git a/src/Microsoft.Dnx.Watcher/CommandOutputProvider.cs b/src/dotnet-watch/CommandOutputProvider.cs similarity index 95% rename from src/Microsoft.Dnx.Watcher/CommandOutputProvider.cs rename to src/dotnet-watch/CommandOutputProvider.cs index ea8fec48dd..fd4945a078 100644 --- a/src/Microsoft.Dnx.Watcher/CommandOutputProvider.cs +++ b/src/dotnet-watch/CommandOutputProvider.cs @@ -5,7 +5,7 @@ using System; using Microsoft.Extensions.PlatformAbstractions; using Microsoft.Extensions.Logging; -namespace Microsoft.Dnx.Watcher +namespace Microsoft.DotNet.Watcher { public class CommandOutputProvider : ILoggerProvider { diff --git a/src/dotnet-watch/Program.cs b/src/dotnet-watch/Program.cs new file mode 100644 index 0000000000..7f5c0ac257 --- /dev/null +++ b/src/dotnet-watch/Program.cs @@ -0,0 +1,139 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.CommandLineUtils; +using Microsoft.Extensions.PlatformAbstractions; +using Microsoft.DotNet.Watcher.Core; +using Microsoft.Extensions.Logging; + +namespace Microsoft.DotNet.Watcher +{ + public class Program + { + private const string AppArgumentSeparator = "--"; + + private readonly ILoggerFactory _loggerFactory; + + public Program() + { + _loggerFactory = new LoggerFactory(); + + var commandProvider = new CommandOutputProvider(PlatformServices.Default.Runtime); + _loggerFactory.AddProvider(commandProvider); + } + + public static int Main(string[] args) + { + using (CancellationTokenSource ctrlCTokenSource = new CancellationTokenSource()) + { + Console.CancelKeyPress += (sender, ev) => + { + ctrlCTokenSource.Cancel(); + ev.Cancel = false; + }; + + string[] watchArgs, appArgs; + SeparateWatchArguments(args, out watchArgs, out appArgs); + + return new Program().MainInternal(watchArgs, appArgs, ctrlCTokenSource.Token); + } + } + + // The argument separation rules are: if no "--" is encountered, all arguments are passed to the app being watched. + // Unless, the argument is "--help", in which case the help for the watcher is being invoked and everything else is discarded. + // To pass arguments to both the watcher and the app use "--" as separator. + // To pass "--help" to the app being watched, you must use "--": dotnet watch -- --help + internal static void SeparateWatchArguments(string[] args, out string[] watchArgs, out string[] appArgs) + { + // Special case "--help" + if (args.Length > 0 && ( + args[0].Equals("--help", StringComparison.OrdinalIgnoreCase) || + args[0].Equals("-h", StringComparison.OrdinalIgnoreCase) || + args[0].Equals("-?", StringComparison.OrdinalIgnoreCase))) + { + watchArgs = new string[] { args[0] }; + appArgs = new string[0]; + return; + } + + int argsIndex = -1; + watchArgs = args.TakeWhile((arg, idx) => + { + argsIndex = idx; + return !string.Equals(arg, AppArgumentSeparator, StringComparison.OrdinalIgnoreCase); + }).ToArray(); + + appArgs = args.Skip(argsIndex + 1).ToArray(); + + if (appArgs.Length == 0) + { + // If no explicit watcher arguments then all arguments get passed to the app being watched + appArgs = watchArgs; + watchArgs = new string[0]; + } + } + + private int MainInternal(string[] watchArgs, string[] appArgs, CancellationToken cancellationToken) + { + var app = new CommandLineApplication(); + app.Name = "dotnet-watch"; + app.FullName = "Microsoft dotnet File Watcher"; + + app.HelpOption("-?|-h|--help"); + + var commandArg = app.Option( + "--command ", + "Optional. The dotnet command to run. Default: 'run'.", + CommandOptionType.SingleValue); + + var workingDirArg = app.Option( + "--working-dir ", + "Optional. The working directory. Default: project's directory.", + CommandOptionType.SingleValue); + + var exitOnChangeArg = app.Option( + "--exit-on-change", + "Optional. The watcher will exit when a file change is detected instead of restarting the process. Default: not set.", + CommandOptionType.NoValue); + + + app.OnExecute(() => + { + var projectToWatch = Path.Combine(Directory.GetCurrentDirectory(), ProjectModel.Project.FileName); + + var workingDir = workingDirArg.HasValue() ? + workingDirArg.Value() : + Path.GetDirectoryName(projectToWatch); + + var command = commandArg.HasValue() ? + commandArg.Value() : + "run"; + + var watcher = DotNetWatcher.CreateDefault(_loggerFactory); + watcher.ExitOnChange = exitOnChangeArg.HasValue(); + + try + { + watcher.WatchAsync(projectToWatch, command, appArgs, workingDir, cancellationToken).Wait(); + } + catch (AggregateException ex) + { + if (ex.InnerExceptions.Count != 1 || !(ex.InnerException is TaskCanceledException)) + { + throw; + } + } + + + return 1; + }); + + return app.Execute(watchArgs); + } + } +} diff --git a/src/dotnet-watch/Properties/AssemblyInfo.cs b/src/dotnet-watch/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..a78f66dc06 --- /dev/null +++ b/src/dotnet-watch/Properties/AssemblyInfo.cs @@ -0,0 +1,10 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; + +[assembly:InternalsVisibleTo("dotnet-watch.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: AssemblyMetadata("Serviceable", "True")] +[assembly: NeutralResourcesLanguage("en-US")] diff --git a/src/Microsoft.Dnx.Watcher/Microsoft.Dnx.Watcher.xproj b/src/dotnet-watch/dotnet-watch.xproj similarity index 100% rename from src/Microsoft.Dnx.Watcher/Microsoft.Dnx.Watcher.xproj rename to src/dotnet-watch/dotnet-watch.xproj diff --git a/src/Microsoft.Dnx.Watcher/project.json b/src/dotnet-watch/project.json similarity index 66% rename from src/Microsoft.Dnx.Watcher/project.json rename to src/dotnet-watch/project.json index c8fc4080ac..dbe7a7ec35 100644 --- a/src/Microsoft.Dnx.Watcher/project.json +++ b/src/dotnet-watch/project.json @@ -6,23 +6,15 @@ "keyFile": "../../tools/Key.snk" }, "dependencies": { - "Microsoft.Dnx.Watcher.Core": "1.0.0-*", + "Microsoft.DotNet.Watcher.Core": "1.0.0-*", "Microsoft.Extensions.CommandLineUtils": "1.0.0-*", "Microsoft.Extensions.Logging": "1.0.0-*", "Microsoft.Extensions.Logging.Console": "1.0.0-*", "Microsoft.NETCore.Platforms": "1.0.1-*" }, "frameworks": { - "dnx451": { }, - "dnxcore50": { } - }, - - "commands": { - "dnx-watch": "Microsoft.Dnx.Watcher" - }, - - "scripts": { - "postbuild": [ - ] + "dnxcore50": { + "imports": "portable-net451+win8" + } } } diff --git a/test/Microsoft.Dnx.Watcher.Tests/CommandLineParsingTests.cs b/test/Microsoft.Dnx.Watcher.Tests/CommandLineParsingTests.cs deleted file mode 100644 index c4ac14008b..0000000000 --- a/test/Microsoft.Dnx.Watcher.Tests/CommandLineParsingTests.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Xunit; - -namespace Microsoft.Dnx.Watcher.Tests -{ - // This project can output the Class library as a NuGet Package. - // To enable this option, right-click on the project and select the Properties menu item. In the Build tab select "Produce outputs on build". - public class CommandLineParsingTests - { - [Fact] - public void NoWatcherArgs() - { - var args = "--arg1 v1 --arg2 v2".Split(' '); - - string[] watcherArgs, dnxArgs; - Program.SeparateWatchArguments(args, out watcherArgs, out dnxArgs); - - Assert.Empty(watcherArgs); - Assert.Equal(args, dnxArgs); - } - - [Fact] - public void ArgsForBothDnxAndWatcher() - { - var args = "--arg1 v1 --arg2 v2 --dnx-args --arg3 --arg4 v4".Split(' '); - - string[] watcherArgs, dnxArgs; - Program.SeparateWatchArguments(args, out watcherArgs, out dnxArgs); - - Assert.Equal(new string[] {"--arg1", "v1", "--arg2", "v2" }, watcherArgs); - Assert.Equal(new string[] { "--arg3", "--arg4", "v4" }, dnxArgs); - } - - [Fact] - public void MultipleSeparators() - { - var args = "--arg1 v1 --arg2 v2 --dnx-args --arg3 --dnxArgs --arg4 v4".Split(' '); - - string[] watcherArgs, dnxArgs; - Program.SeparateWatchArguments(args, out watcherArgs, out dnxArgs); - - Assert.Equal(new string[] { "--arg1", "v1", "--arg2", "v2" }, watcherArgs); - Assert.Equal(new string[] { "--arg3", "--dnxArgs", "--arg4", "v4" }, dnxArgs); - } - } -} diff --git a/test/Microsoft.Dnx.Watcher.Tests/Microsoft.Dnx.Watcher.Tests.xproj b/test/Microsoft.Dnx.Watcher.Tests/Microsoft.Dnx.Watcher.Tests.xproj deleted file mode 100644 index 7c8ac87ba2..0000000000 --- a/test/Microsoft.Dnx.Watcher.Tests/Microsoft.Dnx.Watcher.Tests.xproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 640d190b-26db-4dde-88ee-55814c86c43e - Microsoft.Dnx.Watcher.Tests - ..\artifacts\obj\$(MSBuildProjectName) - ..\artifacts\bin\$(MSBuildProjectName)\ - - - 2.0 - - - - - - \ No newline at end of file diff --git a/test/Microsoft.Dnx.Watcher.Tests/project.json b/test/Microsoft.Dnx.Watcher.Tests/project.json deleted file mode 100644 index f613c1cefc..0000000000 --- a/test/Microsoft.Dnx.Watcher.Tests/project.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilationOptions": { - "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk" - }, - "dependencies": { - "Microsoft.Extensions.PlatformAbstractions": "1.0.0-*", - "Microsoft.Dnx.Watcher": "1.0.0-*", - "Microsoft.NETCore.Platforms": "1.0.1-*", - "xunit.runner.aspnet": "2.0.0-aspnet-*" - }, - "frameworks": { - "dnx451": { }, - "dnxcore50": { } - }, - "commands": { - "test": "xunit.runner.aspnet" - } -} - From f1e696d865a5b7478b1fe9f6604276fcdfa40f01 Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Thu, 18 Feb 2016 12:39:01 -0800 Subject: [PATCH 0087/1029] Enabled xml doc generation --- NuGetPackageVerifier.json | 14 ++------------ .../project.json | 4 +++- src/Microsoft.Extensions.WebEncoders/project.json | 4 +++- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index d9dea7c8ac..8df495e3e0 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -1,12 +1,7 @@ { "adx": { // Packages written by the ADX team and that ship on NuGet.org "rules": [ - "AssemblyHasDocumentFileRule", - "AssemblyHasVersionAttributesRule", - "AssemblyHasServicingAttributeRule", - "AssemblyHasNeutralResourcesLanguageAttributeRule", - "SatellitePackageRule", - "StrictSemanticVersionValidationRule" + "AdxVerificationCompositeRule" ], "packages": { "Microsoft.AspNetCore.Html.Abstractions": { }, @@ -15,12 +10,7 @@ }, "Default": { // Rules to run for packages not listed in any other set. "rules": [ - "AssemblyHasDocumentFileRule", - "AssemblyHasVersionAttributesRule", - "AssemblyHasServicingAttributeRule", - "AssemblyHasNeutralResourcesLanguageAttributeRule", - "SatellitePackageRule", - "StrictSemanticVersionValidationRule" + "DefaultCompositeRule" ] } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/project.json b/src/Microsoft.AspNetCore.Html.Abstractions/project.json index 55cc30d9b1..7b5fcb40a1 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/project.json +++ b/src/Microsoft.AspNetCore.Html.Abstractions/project.json @@ -7,7 +7,9 @@ }, "compilationOptions": { "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk" + "keyFile": "../../tools/Key.snk", + "nowarn": [ "CS1591" ], + "xmlDoc": true }, "dependencies": { "System.Text.Encodings.Web": "4.0.0-*" diff --git a/src/Microsoft.Extensions.WebEncoders/project.json b/src/Microsoft.Extensions.WebEncoders/project.json index 0facfeeb8c..a777ff4d9b 100644 --- a/src/Microsoft.Extensions.WebEncoders/project.json +++ b/src/Microsoft.Extensions.WebEncoders/project.json @@ -8,7 +8,9 @@ "compilationOptions": { "warningsAsErrors": true, "allowUnsafe": true, - "keyFile": "../../tools/Key.snk" + "keyFile": "../../tools/Key.snk", + "nowarn": [ "CS1591" ], + "xmlDoc": true }, "dependencies": { "Microsoft.Extensions.DependencyInjection.Abstractions": "1.0.0-*", From 4e5e6b3891bd9e6ff22e2cd5a0e435cfad961c57 Mon Sep 17 00:00:00 2001 From: John Luo Date: Thu, 18 Feb 2016 14:46:26 -0800 Subject: [PATCH 0088/1029] Updating test TFMs for custom test discovery --- test/Microsoft.AspNetCore.JsonPatch.Test/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index cb87b096e9..cd04e92bb2 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -17,7 +17,7 @@ }, "imports": "portable-net451+win8" }, - "dnx451": { + "net451": { "frameworkAssemblies": { "System.Runtime": "", "System.Threading.Tasks": "" From 42d913b3ba8a7e82867f1cd4749277338071bca7 Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Thu, 18 Feb 2016 16:20:51 -0800 Subject: [PATCH 0089/1029] Enabled xml doc generation --- NuGetPackageVerifier.json | 14 ++------------ src/Microsoft.AspNetCore.JsonPatch/project.json | 4 +++- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index e95640a3d3..f68002830f 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -1,12 +1,7 @@ { "adx": { // Packages written by the ADX team and that ship on NuGet.org "rules": [ - "AssemblyHasDocumentFileRule", - "AssemblyHasVersionAttributesRule", - "AssemblyHasServicingAttributeRule", - "AssemblyHasNeutralResourcesLanguageAttributeRule", - "SatellitePackageRule", - "StrictSemanticVersionValidationRule" + "AdxVerificationCompositeRule" ], "packages": { "Microsoft.AspNetCore.JsonPatch": { } @@ -14,12 +9,7 @@ }, "Default": { // Rules to run for packages not listed in any other set. "rules": [ - "AssemblyHasDocumentFileRule", - "AssemblyHasVersionAttributesRule", - "AssemblyHasServicingAttributeRule", - "AssemblyHasNeutralResourcesLanguageAttributeRule", - "SatellitePackageRule", - "StrictSemanticVersionValidationRule" + "DefaultCompositeRule" ] } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index ec303724f5..91adf85b87 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -2,7 +2,9 @@ "version": "1.0.0-*", "compilationOptions": { "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk" + "keyFile": "../../tools/Key.snk", + "nowarn": [ "CS1591" ], + "xmlDoc": true }, "repository": { "type": "git", From 397cda382b24fc1f3ded028dd368a6f091618ed2 Mon Sep 17 00:00:00 2001 From: John Luo Date: Thu, 18 Feb 2016 17:08:28 -0800 Subject: [PATCH 0090/1029] Updating test TFMs for custom test discovery --- test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json | 4 ++-- test/Microsoft.Extensions.WebEncoders.Tests/project.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index ff91514fd4..35c576a3c2 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -18,10 +18,10 @@ }, "imports": "portable-net451+win8" }, - "dnx451": { + "net451": { "dependencies": { "xunit.runner.console": "2.1.0" + } } } -} } \ No newline at end of file diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index bcd52ff6ee..074b939a6d 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -3,7 +3,7 @@ "Microsoft.Extensions.DependencyInjection": "1.0.0-*", "Microsoft.Extensions.WebEncoders": "1.0.0-*", "Microsoft.NETCore.Platforms": "1.0.1-*", - "xunit.runner.aspnet": "2.0.0-aspnet-*" + "xunit": "2.1.0" }, "testRunner": "xunit", "compilationOptions": { @@ -18,7 +18,7 @@ }, "imports": "portable-net451+win8" }, - "dnx451": { + "net451": { "dependencies": { "xunit.runner.console": "2.1.0" } From 58525b0369a559d1f4f0cdb8e89c520476b5e66e Mon Sep 17 00:00:00 2001 From: John Luo Date: Fri, 19 Feb 2016 16:55:51 -0800 Subject: [PATCH 0091/1029] Ignore .vs/ --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 10779cb569..d9e70ea3c8 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,5 @@ nuget.exe project.lock.json .testPublish/ .build/ +/.vs/ + From 5de08352fa103ba937c85bdc7c0c3155ae9d2817 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Wed, 24 Feb 2016 09:37:41 -0800 Subject: [PATCH 0092/1029] Update `build.sh` to match other repos - currently attempts to `source KoreBuild.sh` --- build.sh | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/build.sh b/build.sh index 7b5e25e3a8..263fb667a8 100755 --- a/build.sh +++ b/build.sh @@ -1,13 +1,5 @@ #!/usr/bin/env bash -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -repoFolder="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - buildFolder=.build koreBuildFolder=$buildFolder/KoreBuild-dotnet @@ -42,7 +34,12 @@ fi if test ! -d $koreBuildFolder; then mono $nugetPath install KoreBuild-dotnet -ExcludeVersion -o $buildFolder -nocache -pre + chmod +x $koreBuildFolder/build/KoreBuild.sh fi -source $koreBuildFolder/build/KoreBuild.sh +makeFile=makefile.shade +if [ ! -e $makeFile ]; then + makeFile=$koreBuildFolder/build/makefile.shade +fi +./$koreBuildFolder/build/KoreBuild.sh -n $nugetPath -m $makeFile "$@" From 24d4c027b11148bc83b15f8d87b964835f503f71 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Wed, 24 Feb 2016 12:37:07 -0800 Subject: [PATCH 0093/1029] Update `build.cmd` to match latest template - aspnet/Universe#347 - `%KOREBUILD_VERSION%` doesn't work without this fix --- build.cmd | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/build.cmd b/build.cmd index 65fb3e3353..95b049cf63 100644 --- a/build.cmd +++ b/build.cmd @@ -28,12 +28,11 @@ IF NOT EXIST %NUGET_PATH% ( copy %CACHED_NUGET% %NUGET_PATH% > nul ) +SET KOREBUILD_DOWNLOAD_ARGS= +IF NOT "%KOREBUILD_VERSION%"=="" ( + SET KOREBUILD_DOWNLOAD_ARGS=-version %KOREBUILD_VERSION% +) IF NOT EXIST %KOREBUILD_FOLDER% ( - SET KOREBUILD_DOWNLOAD_ARGS= - IF NOT "%KOREBUILD_VERSION%"=="" ( - SET KOREBUILD_DOWNLOAD_ARGS=-version %KOREBUILD_VERSION% - ) - %BUILD_FOLDER%\nuget.exe install KoreBuild-dotnet -ExcludeVersion -o %BUILD_FOLDER% -nocache -pre %KOREBUILD_DOWNLOAD_ARGS% ) From 05b2b8e7d84a2cf7cd77f070f9aa4091e6a60aaf Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Wed, 24 Feb 2016 12:44:10 -0800 Subject: [PATCH 0094/1029] Update `build.cmd` to match latest template - aspnet/Universe#347 - `%KOREBUILD_VERSION%` doesn't work without this fix --- build.cmd | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/build.cmd b/build.cmd index 65fb3e3353..95b049cf63 100644 --- a/build.cmd +++ b/build.cmd @@ -28,12 +28,11 @@ IF NOT EXIST %NUGET_PATH% ( copy %CACHED_NUGET% %NUGET_PATH% > nul ) +SET KOREBUILD_DOWNLOAD_ARGS= +IF NOT "%KOREBUILD_VERSION%"=="" ( + SET KOREBUILD_DOWNLOAD_ARGS=-version %KOREBUILD_VERSION% +) IF NOT EXIST %KOREBUILD_FOLDER% ( - SET KOREBUILD_DOWNLOAD_ARGS= - IF NOT "%KOREBUILD_VERSION%"=="" ( - SET KOREBUILD_DOWNLOAD_ARGS=-version %KOREBUILD_VERSION% - ) - %BUILD_FOLDER%\nuget.exe install KoreBuild-dotnet -ExcludeVersion -o %BUILD_FOLDER% -nocache -pre %KOREBUILD_DOWNLOAD_ARGS% ) From 34c0c208518badb6658806ebbb5f9c13895c186b Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Wed, 24 Feb 2016 12:47:22 -0800 Subject: [PATCH 0095/1029] Update `build.cmd` to match latest template - aspnet/Universe#347 - `%KOREBUILD_VERSION%` doesn't work without this fix --- build.cmd | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/build.cmd b/build.cmd index 65fb3e3353..95b049cf63 100644 --- a/build.cmd +++ b/build.cmd @@ -28,12 +28,11 @@ IF NOT EXIST %NUGET_PATH% ( copy %CACHED_NUGET% %NUGET_PATH% > nul ) +SET KOREBUILD_DOWNLOAD_ARGS= +IF NOT "%KOREBUILD_VERSION%"=="" ( + SET KOREBUILD_DOWNLOAD_ARGS=-version %KOREBUILD_VERSION% +) IF NOT EXIST %KOREBUILD_FOLDER% ( - SET KOREBUILD_DOWNLOAD_ARGS= - IF NOT "%KOREBUILD_VERSION%"=="" ( - SET KOREBUILD_DOWNLOAD_ARGS=-version %KOREBUILD_VERSION% - ) - %BUILD_FOLDER%\nuget.exe install KoreBuild-dotnet -ExcludeVersion -o %BUILD_FOLDER% -nocache -pre %KOREBUILD_DOWNLOAD_ARGS% ) From 82d3269b45db242e79edf6d2c9c34cb531c9f884 Mon Sep 17 00:00:00 2001 From: John Luo Date: Fri, 26 Feb 2016 16:51:53 -0800 Subject: [PATCH 0096/1029] Fixed how processes are killed on Linux --- .../Impl/ProcessWatcher.cs | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/Impl/ProcessWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Impl/ProcessWatcher.cs index 91e7d72653..3fc42a5304 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Impl/ProcessWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Impl/ProcessWatcher.cs @@ -59,26 +59,34 @@ namespace Microsoft.DotNet.Watcher.Core return; } - ProcessStartInfo startInfo; - if (_isWindows) { - startInfo = new ProcessStartInfo() + var startInfo = new ProcessStartInfo() { FileName = "taskkill", Arguments = $"/T /F /PID {processId}", }; + var killProcess = Process.Start(startInfo); + killProcess.WaitForExit(); } else { - startInfo = new ProcessStartInfo() + var killSubProcessStartInfo = new ProcessStartInfo { FileName = "pkill", Arguments = $"-TERM -P {processId}", }; + var killSubProcess = Process.Start(killSubProcessStartInfo); + killSubProcess.WaitForExit(); + + var killProcessStartInfo = new ProcessStartInfo + { + FileName = "kill", + Arguments = $"-TERM {processId}", + }; + var killProcess = Process.Start(killProcessStartInfo); + killProcess.WaitForExit(); } - var killProcess = Process.Start(startInfo); - killProcess.WaitForExit(); } } } \ No newline at end of file From 2e84cc5aac4d40a24cf56c49e837598271c48da5 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Sat, 27 Feb 2016 12:51:06 -0800 Subject: [PATCH 0097/1029] Update the build scripts --- build.cmd | 41 ++----------------------------------- build.ps1 | 36 +++++++++++++++++++++++++++++++++ build.sh | 60 +++++++++++++++++++++++-------------------------------- 3 files changed, 63 insertions(+), 74 deletions(-) create mode 100644 build.ps1 diff --git a/build.cmd b/build.cmd index 95b049cf63..2fa024b15e 100644 --- a/build.cmd +++ b/build.cmd @@ -1,39 +1,2 @@ -@ECHO off -SETLOCAL - -SET REPO_FOLDER=%~dp0 -CD "%REPO_FOLDER%" - -SET BUILD_FOLDER=.build -SET KOREBUILD_FOLDER=%BUILD_FOLDER%\KoreBuild-dotnet -SET KOREBUILD_VERSION= - -SET NUGET_PATH=%BUILD_FOLDER%\NuGet.exe -SET NUGET_VERSION=latest -SET CACHED_NUGET=%LocalAppData%\NuGet\nuget.%NUGET_VERSION%.exe - -IF NOT EXIST %BUILD_FOLDER% ( - md %BUILD_FOLDER% -) - -IF NOT EXIST %NUGET_PATH% ( - IF NOT EXIST %CACHED_NUGET% ( - echo Downloading latest version of NuGet.exe... - IF NOT EXIST %LocalAppData%\NuGet ( - md %LocalAppData%\NuGet - ) - @powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/%NUGET_VERSION%/nuget.exe' -OutFile '%CACHED_NUGET%'" - ) - - copy %CACHED_NUGET% %NUGET_PATH% > nul -) - -SET KOREBUILD_DOWNLOAD_ARGS= -IF NOT "%KOREBUILD_VERSION%"=="" ( - SET KOREBUILD_DOWNLOAD_ARGS=-version %KOREBUILD_VERSION% -) -IF NOT EXIST %KOREBUILD_FOLDER% ( - %BUILD_FOLDER%\nuget.exe install KoreBuild-dotnet -ExcludeVersion -o %BUILD_FOLDER% -nocache -pre %KOREBUILD_DOWNLOAD_ARGS% -) - -"%KOREBUILD_FOLDER%\build\KoreBuild.cmd" %* +@ECHO OFF +PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*" \ No newline at end of file diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000000..4fd24a30d5 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,36 @@ +cd $PSScriptRoot + +$repoFolder = $PSScriptRoot +$env:REPO_FOLDER = $repoFolder + +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +if ($env:KOREBUILD_ZIP) +{ + $koreBuildZip=$env:KOREBUILD_ZIP +} + +$buildFolder = ".build" +$buildFile="$buildFolder\KoreBuild.ps1" + +if (!(Test-Path $buildFolder)) { + Write-Host "Downloading KoreBuild from $koreBuildZip" + + $tempFolder=$env:TEMP + "\KoreBuild-" + [guid]::NewGuid() + New-Item -Path "$tempFolder" -Type directory | Out-Null + + $localZipFile="$tempFolder\korebuild.zip" + + Invoke-WebRequest $koreBuildZip -OutFile $localZipFile + Add-Type -AssemblyName System.IO.Compression.FileSystem + [System.IO.Compression.ZipFile]::ExtractToDirectory($localZipFile, $tempFolder) + + New-Item -Path "$buildFolder" -Type directory | Out-Null + copy-item "$tempFolder\**\build\*" $buildFolder -Recurse + + # Cleanup + if (Test-Path $tempFolder) { + Remove-Item -Recurse -Force $tempFolder + } +} + +&"$buildFile" $args \ No newline at end of file diff --git a/build.sh b/build.sh index 263fb667a8..79638d06b6 100755 --- a/build.sh +++ b/build.sh @@ -1,45 +1,35 @@ #!/usr/bin/env bash +repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd $repoFolder -buildFolder=.build -koreBuildFolder=$buildFolder/KoreBuild-dotnet - -nugetPath=$buildFolder/nuget.exe - -if test `uname` = Darwin; then - cachedir=~/Library/Caches/KBuild -else - if [ -z $XDG_DATA_HOME ]; then - cachedir=$HOME/.local/share - else - cachedir=$XDG_DATA_HOME; - fi +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +if [ ! -z $KOREBUILD_ZIP ]; then + koreBuildZip=$KOREBUILD_ZIP fi -mkdir -p $cachedir -nugetVersion=latest -cacheNuget=$cachedir/nuget.$nugetVersion.exe -nugetUrl=https://dist.nuget.org/win-x86-commandline/$nugetVersion/nuget.exe +buildFolder=".build" +buildFile="$buildFolder/KoreBuild.sh" if test ! -d $buildFolder; then + echo "Downloading KoreBuild from $koreBuildZip" + + tempFolder="/tmp/KoreBuild-$(uuidgen)" + mkdir $tempFolder + + localZipFile="$tempFolder/korebuild.zip" + + wget -O $localZipFile $koreBuildZip 2>/dev/null || curl -o $localZipFile --location $koreBuildZip /dev/null + unzip -q -d $tempFolder $localZipFile + mkdir $buildFolder -fi - -if test ! -f $nugetPath; then - if test ! -f $cacheNuget; then - wget -O $cacheNuget $nugetUrl 2>/dev/null || curl -o $cacheNuget --location $nugetUrl /dev/null + cp -r $tempFolder/**/build/** $buildFolder + + chmod +x $buildFile + + # Cleanup + if test ! -d $tempFolder; then + rm -rf $tempFolder fi - - cp $cacheNuget $nugetPath fi -if test ! -d $koreBuildFolder; then - mono $nugetPath install KoreBuild-dotnet -ExcludeVersion -o $buildFolder -nocache -pre - chmod +x $koreBuildFolder/build/KoreBuild.sh -fi - -makeFile=makefile.shade -if [ ! -e $makeFile ]; then - makeFile=$koreBuildFolder/build/makefile.shade -fi - -./$koreBuildFolder/build/KoreBuild.sh -n $nugetPath -m $makeFile "$@" +$buildFile -r $repoFolder "$@" From c6e3cf30d3ab9ba2e1793fcdc42652823ed0614a Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Sat, 27 Feb 2016 12:51:10 -0800 Subject: [PATCH 0098/1029] Update the build scripts --- build.cmd | 41 ++----------------------------------- build.ps1 | 36 +++++++++++++++++++++++++++++++++ build.sh | 60 +++++++++++++++++++++++-------------------------------- 3 files changed, 63 insertions(+), 74 deletions(-) create mode 100644 build.ps1 diff --git a/build.cmd b/build.cmd index 95b049cf63..2fa024b15e 100644 --- a/build.cmd +++ b/build.cmd @@ -1,39 +1,2 @@ -@ECHO off -SETLOCAL - -SET REPO_FOLDER=%~dp0 -CD "%REPO_FOLDER%" - -SET BUILD_FOLDER=.build -SET KOREBUILD_FOLDER=%BUILD_FOLDER%\KoreBuild-dotnet -SET KOREBUILD_VERSION= - -SET NUGET_PATH=%BUILD_FOLDER%\NuGet.exe -SET NUGET_VERSION=latest -SET CACHED_NUGET=%LocalAppData%\NuGet\nuget.%NUGET_VERSION%.exe - -IF NOT EXIST %BUILD_FOLDER% ( - md %BUILD_FOLDER% -) - -IF NOT EXIST %NUGET_PATH% ( - IF NOT EXIST %CACHED_NUGET% ( - echo Downloading latest version of NuGet.exe... - IF NOT EXIST %LocalAppData%\NuGet ( - md %LocalAppData%\NuGet - ) - @powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/%NUGET_VERSION%/nuget.exe' -OutFile '%CACHED_NUGET%'" - ) - - copy %CACHED_NUGET% %NUGET_PATH% > nul -) - -SET KOREBUILD_DOWNLOAD_ARGS= -IF NOT "%KOREBUILD_VERSION%"=="" ( - SET KOREBUILD_DOWNLOAD_ARGS=-version %KOREBUILD_VERSION% -) -IF NOT EXIST %KOREBUILD_FOLDER% ( - %BUILD_FOLDER%\nuget.exe install KoreBuild-dotnet -ExcludeVersion -o %BUILD_FOLDER% -nocache -pre %KOREBUILD_DOWNLOAD_ARGS% -) - -"%KOREBUILD_FOLDER%\build\KoreBuild.cmd" %* +@ECHO OFF +PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*" \ No newline at end of file diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000000..4fd24a30d5 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,36 @@ +cd $PSScriptRoot + +$repoFolder = $PSScriptRoot +$env:REPO_FOLDER = $repoFolder + +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +if ($env:KOREBUILD_ZIP) +{ + $koreBuildZip=$env:KOREBUILD_ZIP +} + +$buildFolder = ".build" +$buildFile="$buildFolder\KoreBuild.ps1" + +if (!(Test-Path $buildFolder)) { + Write-Host "Downloading KoreBuild from $koreBuildZip" + + $tempFolder=$env:TEMP + "\KoreBuild-" + [guid]::NewGuid() + New-Item -Path "$tempFolder" -Type directory | Out-Null + + $localZipFile="$tempFolder\korebuild.zip" + + Invoke-WebRequest $koreBuildZip -OutFile $localZipFile + Add-Type -AssemblyName System.IO.Compression.FileSystem + [System.IO.Compression.ZipFile]::ExtractToDirectory($localZipFile, $tempFolder) + + New-Item -Path "$buildFolder" -Type directory | Out-Null + copy-item "$tempFolder\**\build\*" $buildFolder -Recurse + + # Cleanup + if (Test-Path $tempFolder) { + Remove-Item -Recurse -Force $tempFolder + } +} + +&"$buildFile" $args \ No newline at end of file diff --git a/build.sh b/build.sh index 263fb667a8..79638d06b6 100755 --- a/build.sh +++ b/build.sh @@ -1,45 +1,35 @@ #!/usr/bin/env bash +repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd $repoFolder -buildFolder=.build -koreBuildFolder=$buildFolder/KoreBuild-dotnet - -nugetPath=$buildFolder/nuget.exe - -if test `uname` = Darwin; then - cachedir=~/Library/Caches/KBuild -else - if [ -z $XDG_DATA_HOME ]; then - cachedir=$HOME/.local/share - else - cachedir=$XDG_DATA_HOME; - fi +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +if [ ! -z $KOREBUILD_ZIP ]; then + koreBuildZip=$KOREBUILD_ZIP fi -mkdir -p $cachedir -nugetVersion=latest -cacheNuget=$cachedir/nuget.$nugetVersion.exe -nugetUrl=https://dist.nuget.org/win-x86-commandline/$nugetVersion/nuget.exe +buildFolder=".build" +buildFile="$buildFolder/KoreBuild.sh" if test ! -d $buildFolder; then + echo "Downloading KoreBuild from $koreBuildZip" + + tempFolder="/tmp/KoreBuild-$(uuidgen)" + mkdir $tempFolder + + localZipFile="$tempFolder/korebuild.zip" + + wget -O $localZipFile $koreBuildZip 2>/dev/null || curl -o $localZipFile --location $koreBuildZip /dev/null + unzip -q -d $tempFolder $localZipFile + mkdir $buildFolder -fi - -if test ! -f $nugetPath; then - if test ! -f $cacheNuget; then - wget -O $cacheNuget $nugetUrl 2>/dev/null || curl -o $cacheNuget --location $nugetUrl /dev/null + cp -r $tempFolder/**/build/** $buildFolder + + chmod +x $buildFile + + # Cleanup + if test ! -d $tempFolder; then + rm -rf $tempFolder fi - - cp $cacheNuget $nugetPath fi -if test ! -d $koreBuildFolder; then - mono $nugetPath install KoreBuild-dotnet -ExcludeVersion -o $buildFolder -nocache -pre - chmod +x $koreBuildFolder/build/KoreBuild.sh -fi - -makeFile=makefile.shade -if [ ! -e $makeFile ]; then - makeFile=$koreBuildFolder/build/makefile.shade -fi - -./$koreBuildFolder/build/KoreBuild.sh -n $nugetPath -m $makeFile "$@" +$buildFile -r $repoFolder "$@" From e4e39b686f4a9fe246bd2c056eb2ccf29d6cbdae Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Sat, 27 Feb 2016 12:51:17 -0800 Subject: [PATCH 0099/1029] Update the build scripts --- build.cmd | 41 ++----------------------------------- build.ps1 | 36 +++++++++++++++++++++++++++++++++ build.sh | 60 +++++++++++++++++++++++-------------------------------- 3 files changed, 63 insertions(+), 74 deletions(-) create mode 100644 build.ps1 diff --git a/build.cmd b/build.cmd index 95b049cf63..2fa024b15e 100644 --- a/build.cmd +++ b/build.cmd @@ -1,39 +1,2 @@ -@ECHO off -SETLOCAL - -SET REPO_FOLDER=%~dp0 -CD "%REPO_FOLDER%" - -SET BUILD_FOLDER=.build -SET KOREBUILD_FOLDER=%BUILD_FOLDER%\KoreBuild-dotnet -SET KOREBUILD_VERSION= - -SET NUGET_PATH=%BUILD_FOLDER%\NuGet.exe -SET NUGET_VERSION=latest -SET CACHED_NUGET=%LocalAppData%\NuGet\nuget.%NUGET_VERSION%.exe - -IF NOT EXIST %BUILD_FOLDER% ( - md %BUILD_FOLDER% -) - -IF NOT EXIST %NUGET_PATH% ( - IF NOT EXIST %CACHED_NUGET% ( - echo Downloading latest version of NuGet.exe... - IF NOT EXIST %LocalAppData%\NuGet ( - md %LocalAppData%\NuGet - ) - @powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/%NUGET_VERSION%/nuget.exe' -OutFile '%CACHED_NUGET%'" - ) - - copy %CACHED_NUGET% %NUGET_PATH% > nul -) - -SET KOREBUILD_DOWNLOAD_ARGS= -IF NOT "%KOREBUILD_VERSION%"=="" ( - SET KOREBUILD_DOWNLOAD_ARGS=-version %KOREBUILD_VERSION% -) -IF NOT EXIST %KOREBUILD_FOLDER% ( - %BUILD_FOLDER%\nuget.exe install KoreBuild-dotnet -ExcludeVersion -o %BUILD_FOLDER% -nocache -pre %KOREBUILD_DOWNLOAD_ARGS% -) - -"%KOREBUILD_FOLDER%\build\KoreBuild.cmd" %* +@ECHO OFF +PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*" \ No newline at end of file diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000000..4fd24a30d5 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,36 @@ +cd $PSScriptRoot + +$repoFolder = $PSScriptRoot +$env:REPO_FOLDER = $repoFolder + +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +if ($env:KOREBUILD_ZIP) +{ + $koreBuildZip=$env:KOREBUILD_ZIP +} + +$buildFolder = ".build" +$buildFile="$buildFolder\KoreBuild.ps1" + +if (!(Test-Path $buildFolder)) { + Write-Host "Downloading KoreBuild from $koreBuildZip" + + $tempFolder=$env:TEMP + "\KoreBuild-" + [guid]::NewGuid() + New-Item -Path "$tempFolder" -Type directory | Out-Null + + $localZipFile="$tempFolder\korebuild.zip" + + Invoke-WebRequest $koreBuildZip -OutFile $localZipFile + Add-Type -AssemblyName System.IO.Compression.FileSystem + [System.IO.Compression.ZipFile]::ExtractToDirectory($localZipFile, $tempFolder) + + New-Item -Path "$buildFolder" -Type directory | Out-Null + copy-item "$tempFolder\**\build\*" $buildFolder -Recurse + + # Cleanup + if (Test-Path $tempFolder) { + Remove-Item -Recurse -Force $tempFolder + } +} + +&"$buildFile" $args \ No newline at end of file diff --git a/build.sh b/build.sh index 263fb667a8..79638d06b6 100755 --- a/build.sh +++ b/build.sh @@ -1,45 +1,35 @@ #!/usr/bin/env bash +repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd $repoFolder -buildFolder=.build -koreBuildFolder=$buildFolder/KoreBuild-dotnet - -nugetPath=$buildFolder/nuget.exe - -if test `uname` = Darwin; then - cachedir=~/Library/Caches/KBuild -else - if [ -z $XDG_DATA_HOME ]; then - cachedir=$HOME/.local/share - else - cachedir=$XDG_DATA_HOME; - fi +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +if [ ! -z $KOREBUILD_ZIP ]; then + koreBuildZip=$KOREBUILD_ZIP fi -mkdir -p $cachedir -nugetVersion=latest -cacheNuget=$cachedir/nuget.$nugetVersion.exe -nugetUrl=https://dist.nuget.org/win-x86-commandline/$nugetVersion/nuget.exe +buildFolder=".build" +buildFile="$buildFolder/KoreBuild.sh" if test ! -d $buildFolder; then + echo "Downloading KoreBuild from $koreBuildZip" + + tempFolder="/tmp/KoreBuild-$(uuidgen)" + mkdir $tempFolder + + localZipFile="$tempFolder/korebuild.zip" + + wget -O $localZipFile $koreBuildZip 2>/dev/null || curl -o $localZipFile --location $koreBuildZip /dev/null + unzip -q -d $tempFolder $localZipFile + mkdir $buildFolder -fi - -if test ! -f $nugetPath; then - if test ! -f $cacheNuget; then - wget -O $cacheNuget $nugetUrl 2>/dev/null || curl -o $cacheNuget --location $nugetUrl /dev/null + cp -r $tempFolder/**/build/** $buildFolder + + chmod +x $buildFile + + # Cleanup + if test ! -d $tempFolder; then + rm -rf $tempFolder fi - - cp $cacheNuget $nugetPath fi -if test ! -d $koreBuildFolder; then - mono $nugetPath install KoreBuild-dotnet -ExcludeVersion -o $buildFolder -nocache -pre - chmod +x $koreBuildFolder/build/KoreBuild.sh -fi - -makeFile=makefile.shade -if [ ! -e $makeFile ]; then - makeFile=$koreBuildFolder/build/makefile.shade -fi - -./$koreBuildFolder/build/KoreBuild.sh -n $nugetPath -m $makeFile "$@" +$buildFile -r $repoFolder "$@" From ed2529edced330be83302b97eb70b75aa6068850 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Sun, 28 Feb 2016 10:12:09 -0800 Subject: [PATCH 0100/1029] Return the error code from build.cmd --- build.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.cmd b/build.cmd index 2fa024b15e..7d4894cb4a 100644 --- a/build.cmd +++ b/build.cmd @@ -1,2 +1,2 @@ @ECHO OFF -PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*" \ No newline at end of file +PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*; exit $LASTEXITCODE" \ No newline at end of file From 39af4735ac70102f05fe8b4a895d3fed8f7c6934 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Sun, 28 Feb 2016 10:12:13 -0800 Subject: [PATCH 0101/1029] Return the error code from build.cmd --- build.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.cmd b/build.cmd index 2fa024b15e..7d4894cb4a 100644 --- a/build.cmd +++ b/build.cmd @@ -1,2 +1,2 @@ @ECHO OFF -PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*" \ No newline at end of file +PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*; exit $LASTEXITCODE" \ No newline at end of file From b64b30b02d62459440ffa1e91f3291e0f6f4134a Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Sun, 28 Feb 2016 10:12:21 -0800 Subject: [PATCH 0102/1029] Return the error code from build.cmd --- build.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.cmd b/build.cmd index 2fa024b15e..7d4894cb4a 100644 --- a/build.cmd +++ b/build.cmd @@ -1,2 +1,2 @@ @ECHO OFF -PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*" \ No newline at end of file +PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*; exit $LASTEXITCODE" \ No newline at end of file From e8f642df19281a3a3059c0ddd51e9eb865519a02 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Tue, 1 Mar 2016 13:29:45 -0800 Subject: [PATCH 0103/1029] Transition to netstandard. - dotnet5.X => netstandard1.y (where y = x-1). - DNXCore50 => netstandardapp1.5. - Applied the same changes to ifdefs. --- .../project.json | 13 +++++++++---- src/Microsoft.Extensions.WebEncoders/project.json | 12 +++++++++--- .../project.json | 7 +++++-- .../project.json | 7 +++++-- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/project.json b/src/Microsoft.AspNetCore.Html.Abstractions/project.json index 7b5fcb40a1..921349d93f 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/project.json +++ b/src/Microsoft.AspNetCore.Html.Abstractions/project.json @@ -8,7 +8,9 @@ "compilationOptions": { "warningsAsErrors": true, "keyFile": "../../tools/Key.snk", - "nowarn": [ "CS1591" ], + "nowarn": [ + "CS1591" + ], "xmlDoc": true }, "dependencies": { @@ -21,11 +23,14 @@ "System.Runtime": "" } }, - "dotnet5.4": { + "netstandard1.3": { "dependencies": { "System.Collections": "4.0.11-*", "System.Resources.ResourceManager": "4.0.1-*" - } + }, + "imports": [ + "dotnet5.4" + ] } } -} +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.WebEncoders/project.json b/src/Microsoft.Extensions.WebEncoders/project.json index a777ff4d9b..1c0e609f4c 100644 --- a/src/Microsoft.Extensions.WebEncoders/project.json +++ b/src/Microsoft.Extensions.WebEncoders/project.json @@ -9,7 +9,9 @@ "warningsAsErrors": true, "allowUnsafe": true, "keyFile": "../../tools/Key.snk", - "nowarn": [ "CS1591" ], + "nowarn": [ + "CS1591" + ], "xmlDoc": true }, "dependencies": { @@ -24,6 +26,10 @@ "System.Runtime": "" } }, - "dotnet5.4": {} + "netstandard1.3": { + "imports": [ + "dotnet5.4" + ] + } } -} +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index 35c576a3c2..a2b85b5cfe 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -12,11 +12,14 @@ }, "testRunner": "xunit", "frameworks": { - "dnxcore50": { + "netstandardapp1.5": { "dependencies": { "dotnet-test-xunit": "1.0.0-dev-*" }, - "imports": "portable-net451+win8" + "imports": [ + "dnxcore50", + "portable-net451+win8" + ] }, "net451": { "dependencies": { diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index 074b939a6d..0e0c77023b 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -12,11 +12,14 @@ "keyFile": "../../tools/Key.snk" }, "frameworks": { - "dnxcore50": { + "netstandardapp1.5": { "dependencies": { "dotnet-test-xunit": "1.0.0-dev-*" }, - "imports": "portable-net451+win8" + "imports": [ + "dnxcore50", + "portable-net451+win8" + ] }, "net451": { "dependencies": { From 8c293934e874addfcdcfc3859592dc1ac3de210d Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Tue, 1 Mar 2016 13:32:25 -0800 Subject: [PATCH 0104/1029] Transition to netstandard. - dotnet5.X => netstandard1.y (where y = x-1). - DNXCore50 => netstandardapp1.5. - Applied the same changes to ifdefs. --- src/Microsoft.AspNetCore.JsonPatch/project.json | 13 +++++++++---- .../project.json | 7 +++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index 91adf85b87..6e66884725 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -3,7 +3,9 @@ "compilationOptions": { "warningsAsErrors": true, "keyFile": "../../tools/Key.snk", - "nowarn": [ "CS1591" ], + "nowarn": [ + "CS1591" + ], "xmlDoc": true }, "repository": { @@ -15,7 +17,7 @@ }, "frameworks": { "net451": {}, - "dotnet5.4": { + "netstandard1.3": { "dependencies": { "Microsoft.CSharp": "4.0.1-*", "System.Collections.Concurrent": "4.0.12-*", @@ -27,7 +29,10 @@ "System.Runtime.Serialization.Primitives": "4.1.0-*", "System.Text.Encoding.Extensions": "4.0.11-*" }, - "imports": "portable-net451+win8" + "imports": [ + "dotnet5.4", + "portable-net451+win8" + ] } } -} +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index cd04e92bb2..6bfaeafb67 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -10,12 +10,15 @@ }, "testRunner": "xunit", "frameworks": { - "dnxcore50": { + "netstandardapp1.5": { "dependencies": { "moq.netcore": "4.4.0-beta8", "dotnet-test-xunit": "1.0.0-dev-*" }, - "imports": "portable-net451+win8" + "imports": [ + "dnxcore50", + "portable-net451+win8" + ] }, "net451": { "frameworkAssemblies": { From 5f2f4340349a2eba1cb88e97a49b58d376d2a4ec Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Tue, 1 Mar 2016 13:40:42 -0800 Subject: [PATCH 0105/1029] Transition to netstandard. - dotnet5.X => netstandard1.y (where y = x-1). - DNXCore50 => netstandardapp1.5. - Applied the same changes to ifdefs. --- .../project.json | 9 +++-- src/dotnet-watch/project.json | 39 ++++++++++--------- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index cb07bfea11..5173d391fc 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -19,8 +19,11 @@ "Microsoft.NETCore.Platforms": "1.0.1-*" }, "frameworks": { - "dnxcore50": { - "imports": "portable-net451+win8" + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net451+win8" + ] } } -} +} \ No newline at end of file diff --git a/src/dotnet-watch/project.json b/src/dotnet-watch/project.json index dbe7a7ec35..63233488f7 100644 --- a/src/dotnet-watch/project.json +++ b/src/dotnet-watch/project.json @@ -1,20 +1,23 @@ { - "version": "1.0.0-*", - "compilationOptions": { - "warningsAsErrors": true, - "emitEntryPoint": true, - "keyFile": "../../tools/Key.snk" - }, - "dependencies": { - "Microsoft.DotNet.Watcher.Core": "1.0.0-*", - "Microsoft.Extensions.CommandLineUtils": "1.0.0-*", - "Microsoft.Extensions.Logging": "1.0.0-*", - "Microsoft.Extensions.Logging.Console": "1.0.0-*", - "Microsoft.NETCore.Platforms": "1.0.1-*" - }, - "frameworks": { - "dnxcore50": { - "imports": "portable-net451+win8" - } + "version": "1.0.0-*", + "compilationOptions": { + "warningsAsErrors": true, + "emitEntryPoint": true, + "keyFile": "../../tools/Key.snk" + }, + "dependencies": { + "Microsoft.DotNet.Watcher.Core": "1.0.0-*", + "Microsoft.Extensions.CommandLineUtils": "1.0.0-*", + "Microsoft.Extensions.Logging": "1.0.0-*", + "Microsoft.Extensions.Logging.Console": "1.0.0-*", + "Microsoft.NETCore.Platforms": "1.0.1-*" + }, + "frameworks": { + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net451+win8" + ] } -} + } +} \ No newline at end of file From b2b623816b6c6dabf535e7d924b191e69c091009 Mon Sep 17 00:00:00 2001 From: jacalvar Date: Wed, 24 Feb 2016 23:20:35 -0800 Subject: [PATCH 0106/1029] Make ServiceCollectionExtensions consistent --- .../EncoderServiceCollectionExtensions.cs | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/src/Microsoft.Extensions.WebEncoders/EncoderServiceCollectionExtensions.cs b/src/Microsoft.Extensions.WebEncoders/EncoderServiceCollectionExtensions.cs index df3946099c..317d88f99d 100644 --- a/src/Microsoft.Extensions.WebEncoders/EncoderServiceCollectionExtensions.cs +++ b/src/Microsoft.Extensions.WebEncoders/EncoderServiceCollectionExtensions.cs @@ -9,6 +9,9 @@ using Microsoft.Extensions.WebEncoders; namespace Microsoft.Extensions.DependencyInjection { + /// + /// Extension methods for setting up web encoding services in an . + /// public static class EncoderServiceCollectionExtensions { /// @@ -17,24 +20,7 @@ namespace Microsoft.Extensions.DependencyInjection /// /// The . /// The instance after the encoders have been added. - public static IServiceCollection AddWebEncoders(this IServiceCollection services) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - return AddWebEncoders(services, configureOptions: null); - } - - /// - /// Adds , and - /// to the specified . - /// - /// The . - /// A callback to configure . - /// The instance after the encoders have been added. - public static IServiceCollection AddWebEncoders(this IServiceCollection services, Action configureOptions) + public static void AddWebEncoders(this IServiceCollection services) { if (services == null) { @@ -51,13 +37,28 @@ namespace Microsoft.Extensions.DependencyInjection CreateFactory(() => JavaScriptEncoder.Default, settings => JavaScriptEncoder.Create(settings))); services.TryAddSingleton( CreateFactory(() => UrlEncoder.Default, settings => UrlEncoder.Create(settings))); + } - if (configureOptions != null) + /// + /// Adds , and + /// to the specified . + /// + /// The . + /// An to configure the provided . + public static void AddWebEncoders(this IServiceCollection services, Action setupAction) + { + if (services == null) { - services.Configure(configureOptions); + throw new ArgumentNullException(nameof(services)); } - return services; + if (setupAction == null) + { + throw new ArgumentNullException(nameof(setupAction)); + } + + services.AddWebEncoders(); + services.Configure(setupAction); } private static Func CreateFactory( From e5c6f5ed14e0a5fdc56ea5be1e3d8e4f025305c6 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Wed, 2 Mar 2016 09:57:58 -0800 Subject: [PATCH 0107/1029] Revert "Transition to netstandard." This reverts commit 5f2f4340349a2eba1cb88e97a49b58d376d2a4ec. --- .../project.json | 9 ++--- src/dotnet-watch/project.json | 39 +++++++++---------- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index 5173d391fc..cb07bfea11 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -19,11 +19,8 @@ "Microsoft.NETCore.Platforms": "1.0.1-*" }, "frameworks": { - "netstandardapp1.5": { - "imports": [ - "dnxcore50", - "portable-net451+win8" - ] + "dnxcore50": { + "imports": "portable-net451+win8" } } -} \ No newline at end of file +} diff --git a/src/dotnet-watch/project.json b/src/dotnet-watch/project.json index 63233488f7..dbe7a7ec35 100644 --- a/src/dotnet-watch/project.json +++ b/src/dotnet-watch/project.json @@ -1,23 +1,20 @@ { - "version": "1.0.0-*", - "compilationOptions": { - "warningsAsErrors": true, - "emitEntryPoint": true, - "keyFile": "../../tools/Key.snk" - }, - "dependencies": { - "Microsoft.DotNet.Watcher.Core": "1.0.0-*", - "Microsoft.Extensions.CommandLineUtils": "1.0.0-*", - "Microsoft.Extensions.Logging": "1.0.0-*", - "Microsoft.Extensions.Logging.Console": "1.0.0-*", - "Microsoft.NETCore.Platforms": "1.0.1-*" - }, - "frameworks": { - "netstandardapp1.5": { - "imports": [ - "dnxcore50", - "portable-net451+win8" - ] + "version": "1.0.0-*", + "compilationOptions": { + "warningsAsErrors": true, + "emitEntryPoint": true, + "keyFile": "../../tools/Key.snk" + }, + "dependencies": { + "Microsoft.DotNet.Watcher.Core": "1.0.0-*", + "Microsoft.Extensions.CommandLineUtils": "1.0.0-*", + "Microsoft.Extensions.Logging": "1.0.0-*", + "Microsoft.Extensions.Logging.Console": "1.0.0-*", + "Microsoft.NETCore.Platforms": "1.0.1-*" + }, + "frameworks": { + "dnxcore50": { + "imports": "portable-net451+win8" + } } - } -} \ No newline at end of file +} From 5f153686e99ec473faf020f627b7258ab2048d97 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Wed, 2 Mar 2016 18:37:40 -0800 Subject: [PATCH 0108/1029] Remove project name from output path - aspnet/Coherence-Signed#187 - remove `` settings but maintain other unique aspects e.g. `` - in a few cases, standardize on VS version `14.0` and not something more specific --- .../Microsoft.DotNet.Watcher.Core.xproj | 7 ++----- src/dotnet-watch/dotnet-watch.xproj | 7 ++----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/Microsoft.DotNet.Watcher.Core.xproj b/src/Microsoft.DotNet.Watcher.Core/Microsoft.DotNet.Watcher.Core.xproj index 27b8206579..1467ed1975 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Microsoft.DotNet.Watcher.Core.xproj +++ b/src/Microsoft.DotNet.Watcher.Core/Microsoft.DotNet.Watcher.Core.xproj @@ -4,17 +4,14 @@ 14.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - d3da3bbb-e206-404f-aee6-17fb9b6f1221 - Microsoft.Dnx.Watcher.Core ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin\ - 2.0 - + \ No newline at end of file diff --git a/src/dotnet-watch/dotnet-watch.xproj b/src/dotnet-watch/dotnet-watch.xproj index c3c42491f3..bc07d744ea 100644 --- a/src/dotnet-watch/dotnet-watch.xproj +++ b/src/dotnet-watch/dotnet-watch.xproj @@ -4,17 +4,14 @@ 14.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - 8a8ceabc-ac47-43ff-a5df-69224f7e1f46 - Microsoft.Dnx.Watcher ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin\ - 2.0 - + \ No newline at end of file From 67c1dfc43d14109906d3c2e236d5cdb4d2332b32 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Wed, 2 Mar 2016 18:50:26 -0800 Subject: [PATCH 0109/1029] Remove project name from output path - aspnet/Coherence-Signed#187 - remove `` settings but maintain other unique aspects e.g. `` - in a few cases, standardize on VS version `14.0` and not something more specific --- .../Microsoft.AspNetCore.Html.Abstractions.xproj | 6 ++---- .../Microsoft.Extensions.WebEncoders.xproj | 2 +- .../Microsoft.AspNetCore.Html.Abstractions.Test.xproj | 5 ++--- .../Microsoft.Extensions.WebEncoders.Tests.xproj | 2 +- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.xproj b/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.xproj index df229c75eb..7a3801b2b1 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.xproj +++ b/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.xproj @@ -1,4 +1,4 @@ - + 14.0 @@ -7,11 +7,9 @@ 68a28e4a-3ade-4187-9625-4ff185887cb3 - Microsoft.AspNetCore.Html.Abstractions ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin\ - 2.0 diff --git a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.xproj b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.xproj index 084e7901ea..0f278d6c98 100644 --- a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.xproj +++ b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.xproj @@ -8,7 +8,7 @@ dd2ce416-765e-4000-a03e-c2ff165da1b6 ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin\ 2.0 diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.xproj b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.xproj index f699a1c4dc..20389ad4bf 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.xproj +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.xproj @@ -1,4 +1,4 @@ - + 14.0 @@ -7,9 +7,8 @@ 2d187b88-94bd-4a39-ac97-f8f8b9363301 - Microsoft.AspNetCore.Html.Abstractions.Test ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin\ 2.0 diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.xproj b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.xproj index 9b0698e3cc..9ad3cb3d4f 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.xproj +++ b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.xproj @@ -8,7 +8,7 @@ 7ae2731d-43cd-4cf8-850a-4914de2ce930 ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin\ 2.0 From 404a3144cf8c2cb609f79c51d94c3053491db04c Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Wed, 2 Mar 2016 18:55:57 -0800 Subject: [PATCH 0110/1029] Remove project name from output path - aspnet/Coherence-Signed#187 - remove `` settings but maintain other unique aspects e.g. `` - in a few cases, standardize on VS version `14.0` and not something more specific --- .../Microsoft.AspNetCore.JsonPatch.xproj | 2 +- .../Microsoft.AspNetCore.JsonPatch.Test.xproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.xproj b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.xproj index f9fb187ecd..d11d600744 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.xproj +++ b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.xproj @@ -8,7 +8,7 @@ 4d55f4d8-633b-462f-a5b1-feb84bd2d534 ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin\ 2.0 diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.xproj b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.xproj index 74e0fef687..0b71c5d301 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.xproj +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.xproj @@ -8,7 +8,7 @@ 81c20848-e063-4e12-ac40-0b55a532c16c ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + ..\..\artifacts\bin\ 2.0 From b62d90d7dc0cf8bc0c09c8c3cf4cf19a73d4035b Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Thu, 3 Mar 2016 12:15:50 -0800 Subject: [PATCH 0111/1029] Enabled xml doc generation --- NuGetPackageVerifier.json | 18 +++------- .../project.json | 4 ++- src/dotnet-watch/project.json | 36 ++++++++++--------- 3 files changed, 26 insertions(+), 32 deletions(-) diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index c989ccf13a..d80b811540 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -1,26 +1,16 @@ { "adx": { // Packages written by the ADX team and that ship on NuGet.org "rules": [ - "AssemblyHasDocumentFileRule", - "AssemblyHasVersionAttributesRule", - "AssemblyHasServicingAttributeRule", - "AssemblyHasNeutralResourcesLanguageAttributeRule", - "SatellitePackageRule", - "StrictSemanticVersionValidationRule" + "AdxVerificationCompositeRule" ], "packages": { - "Microsoft.Dnx.Watcher": { }, - "Microsoft.Dnx.Watcher.Core": { } + "dotnet-watch": { }, + "Microsoft.DotNet.Watcher.Core": { } } }, "Default": { // Rules to run for packages not listed in any other set. "rules": [ - "AssemblyHasDocumentFileRule", - "AssemblyHasVersionAttributesRule", - "AssemblyHasServicingAttributeRule", - "AssemblyHasNeutralResourcesLanguageAttributeRule", - "SatellitePackageRule", - "StrictSemanticVersionValidationRule" + "DefaultCompositeRule" ] } } \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index cb07bfea11..abf92233e7 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -2,7 +2,9 @@ "version": "1.0.0-*", "compilationOptions": { "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk" + "keyFile": "../../tools/Key.snk", + "nowarn": [ "CS1591" ], + "xmlDoc": true }, "dependencies": { "Microsoft.DotNet.ProjectModel": "1.0.0-*", diff --git a/src/dotnet-watch/project.json b/src/dotnet-watch/project.json index dbe7a7ec35..1c46b27251 100644 --- a/src/dotnet-watch/project.json +++ b/src/dotnet-watch/project.json @@ -1,20 +1,22 @@ { - "version": "1.0.0-*", - "compilationOptions": { - "warningsAsErrors": true, - "emitEntryPoint": true, - "keyFile": "../../tools/Key.snk" - }, - "dependencies": { - "Microsoft.DotNet.Watcher.Core": "1.0.0-*", - "Microsoft.Extensions.CommandLineUtils": "1.0.0-*", - "Microsoft.Extensions.Logging": "1.0.0-*", - "Microsoft.Extensions.Logging.Console": "1.0.0-*", - "Microsoft.NETCore.Platforms": "1.0.1-*" - }, - "frameworks": { - "dnxcore50": { - "imports": "portable-net451+win8" - } + "version": "1.0.0-*", + "compilationOptions": { + "warningsAsErrors": true, + "emitEntryPoint": true, + "keyFile": "../../tools/Key.snk", + "nowarn": [ "CS1591" ], + "xmlDoc": true + }, + "dependencies": { + "Microsoft.DotNet.Watcher.Core": "1.0.0-*", + "Microsoft.Extensions.CommandLineUtils": "1.0.0-*", + "Microsoft.Extensions.Logging": "1.0.0-*", + "Microsoft.Extensions.Logging.Console": "1.0.0-*", + "Microsoft.NETCore.Platforms": "1.0.1-*" + }, + "frameworks": { + "dnxcore50": { + "imports": "portable-net451+win8" } + } } From c43c37e7f9aa4c61512d7ba8015da94e010511aa Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Fri, 19 Feb 2016 14:51:08 -0800 Subject: [PATCH 0112/1029] - E2E test - File watcher that takes the globbing patterns into account - A big rewrite of the core algorithm --- dotnet-watch.sln | 40 ++++ .../DictionaryExtensions.cs | 23 -- .../DotNetWatcher.cs | 91 ++------ .../FileSystem/FileSystemWatcherRoot.cs | 30 --- .../FileSystem/FileWatcher.cs | 217 ------------------ .../FileSystem/IWatcherRoot.cs | 12 - .../IFileWatcher.cs | 10 +- .../IProcessWatcher.cs | 2 +- .../{Abstractions => Internal}/IProject.cs | 2 +- .../IProjectProvider.cs | 2 +- .../Internal/Implementation/FileWatcher.cs | 111 +++++++++ .../Implementation}/ProcessWatcher.cs | 48 +--- .../Implementation}/Project.cs | 2 +- .../Implementation}/ProjectProvider.cs | 2 +- .../Internal/ProcessExtensions.cs | 113 +++++++++ .../Internal/ProjectWatcher.cs | 119 ++++++++++ .../project.json | 3 +- test/TestApps/AppWithDeps/AppWithDeps.xproj | 19 ++ test/TestApps/AppWithDeps/Program.cs | 23 ++ test/TestApps/AppWithDeps/project.json | 20 ++ test/TestApps/Dependency/Dependency.xproj | 19 ++ test/TestApps/Dependency/Foo.cs | 9 + test/TestApps/Dependency/project.json | 18 ++ test/TestApps/GlobbingApp/GlobbingApp.xproj | 19 ++ test/TestApps/GlobbingApp/Program.cs | 23 ++ test/TestApps/GlobbingApp/exclude/Baz.cs | 10 + test/TestApps/GlobbingApp/include/Foo.cs | 9 + test/TestApps/GlobbingApp/project.json | 27 +++ test/TestApps/NoDepsApp/NoDepsApp.xproj | 19 ++ test/TestApps/NoDepsApp/Program.cs | 27 +++ test/TestApps/NoDepsApp/project.json | 21 ++ .../AppWithDepsTests.cs | 74 ++++++ .../GlobbingAppTests.cs | 168 ++++++++++++++ .../NoDepsAppTests.cs | 158 +++++++++++++ .../Scenario/DotNetWatchScenario.cs | 67 ++++++ .../Scenario/ProjectToolScenario.cs | 150 ++++++++++++ .../WaitForFileToChange.cs | 52 +++++ test/dotnet-watch.FunctionalTests/Waiters.cs | 67 ++++++ .../dotnet-watch.FunctionalTests.xproj | 20 ++ .../dotnet-watch.FunctionalTests/project.json | 23 ++ 40 files changed, 1463 insertions(+), 406 deletions(-) delete mode 100644 src/Microsoft.DotNet.Watcher.Core/DictionaryExtensions.cs delete mode 100644 src/Microsoft.DotNet.Watcher.Core/FileSystem/FileSystemWatcherRoot.cs delete mode 100644 src/Microsoft.DotNet.Watcher.Core/FileSystem/FileWatcher.cs delete mode 100644 src/Microsoft.DotNet.Watcher.Core/FileSystem/IWatcherRoot.cs rename src/Microsoft.DotNet.Watcher.Core/{Abstractions => Internal}/IFileWatcher.cs (53%) rename src/Microsoft.DotNet.Watcher.Core/{Abstractions => Internal}/IProcessWatcher.cs (90%) rename src/Microsoft.DotNet.Watcher.Core/{Abstractions => Internal}/IProject.cs (88%) rename src/Microsoft.DotNet.Watcher.Core/{Abstractions => Internal}/IProjectProvider.cs (86%) create mode 100644 src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs rename src/Microsoft.DotNet.Watcher.Core/{Impl => Internal/Implementation}/ProcessWatcher.cs (51%) rename src/Microsoft.DotNet.Watcher.Core/{Impl => Internal/Implementation}/Project.cs (97%) rename src/Microsoft.DotNet.Watcher.Core/{Impl => Internal/Implementation}/ProjectProvider.cs (98%) create mode 100644 src/Microsoft.DotNet.Watcher.Core/Internal/ProcessExtensions.cs create mode 100644 src/Microsoft.DotNet.Watcher.Core/Internal/ProjectWatcher.cs create mode 100644 test/TestApps/AppWithDeps/AppWithDeps.xproj create mode 100644 test/TestApps/AppWithDeps/Program.cs create mode 100644 test/TestApps/AppWithDeps/project.json create mode 100644 test/TestApps/Dependency/Dependency.xproj create mode 100644 test/TestApps/Dependency/Foo.cs create mode 100644 test/TestApps/Dependency/project.json create mode 100644 test/TestApps/GlobbingApp/GlobbingApp.xproj create mode 100644 test/TestApps/GlobbingApp/Program.cs create mode 100644 test/TestApps/GlobbingApp/exclude/Baz.cs create mode 100644 test/TestApps/GlobbingApp/include/Foo.cs create mode 100644 test/TestApps/GlobbingApp/project.json create mode 100644 test/TestApps/NoDepsApp/NoDepsApp.xproj create mode 100644 test/TestApps/NoDepsApp/Program.cs create mode 100644 test/TestApps/NoDepsApp/project.json create mode 100644 test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs create mode 100644 test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs create mode 100644 test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs create mode 100644 test/dotnet-watch.FunctionalTests/Scenario/DotNetWatchScenario.cs create mode 100644 test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs create mode 100644 test/dotnet-watch.FunctionalTests/WaitForFileToChange.cs create mode 100644 test/dotnet-watch.FunctionalTests/Waiters.cs create mode 100644 test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.xproj create mode 100644 test/dotnet-watch.FunctionalTests/project.json diff --git a/dotnet-watch.sln b/dotnet-watch.sln index 3c8e1e6bbb..c35ff1f2d6 100644 --- a/dotnet-watch.sln +++ b/dotnet-watch.sln @@ -15,6 +15,20 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution NuGet.Config = NuGet.Config EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F5B382BC-258F-46E1-AC3D-10E5CCD55134}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-watch.FunctionalTests", "test\dotnet-watch.FunctionalTests\dotnet-watch.FunctionalTests.xproj", "{16BADE2F-1184-4518-8A70-B68A19D0805B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestApps", "TestApps", "{2876B12E-5841-4792-85A8-2929AEE11885}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NoDepsApp", "test\TestApps\NoDepsApp\NoDepsApp.xproj", "{4F0D8A80-221F-4BCB-822E-44A0655F537E}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "GlobbingApp", "test\TestApps\GlobbingApp\GlobbingApp.xproj", "{2AB1A28B-2022-49EA-AF77-AC8A875915CC}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AppWithDeps", "test\TestApps\AppWithDeps\AppWithDeps.xproj", "{F7734E61-F510-41E0-AD15-301A64081CD1}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Dependency", "test\TestApps\Dependency\Dependency.xproj", "{2F48041A-F7D1-478F-9C38-D41F0F05E8CA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -29,6 +43,26 @@ Global {D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}.Debug|Any CPU.Build.0 = Debug|Any CPU {D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}.Release|Any CPU.ActiveCfg = Release|Any CPU {D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}.Release|Any CPU.Build.0 = Release|Any CPU + {16BADE2F-1184-4518-8A70-B68A19D0805B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {16BADE2F-1184-4518-8A70-B68A19D0805B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.Build.0 = Release|Any CPU + {4F0D8A80-221F-4BCB-822E-44A0655F537E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F0D8A80-221F-4BCB-822E-44A0655F537E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F0D8A80-221F-4BCB-822E-44A0655F537E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F0D8A80-221F-4BCB-822E-44A0655F537E}.Release|Any CPU.Build.0 = Release|Any CPU + {2AB1A28B-2022-49EA-AF77-AC8A875915CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2AB1A28B-2022-49EA-AF77-AC8A875915CC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2AB1A28B-2022-49EA-AF77-AC8A875915CC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2AB1A28B-2022-49EA-AF77-AC8A875915CC}.Release|Any CPU.Build.0 = Release|Any CPU + {F7734E61-F510-41E0-AD15-301A64081CD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F7734E61-F510-41E0-AD15-301A64081CD1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F7734E61-F510-41E0-AD15-301A64081CD1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F7734E61-F510-41E0-AD15-301A64081CD1}.Release|Any CPU.Build.0 = Release|Any CPU + {2F48041A-F7D1-478F-9C38-D41F0F05E8CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2F48041A-F7D1-478F-9C38-D41F0F05E8CA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2F48041A-F7D1-478F-9C38-D41F0F05E8CA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2F48041A-F7D1-478F-9C38-D41F0F05E8CA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -36,5 +70,11 @@ Global GlobalSection(NestedProjects) = preSolution {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46} = {66517987-2A5A-4330-B130-207039378FD4} {D3DA3BBB-E206-404F-AEE6-17FB9B6F1221} = {66517987-2A5A-4330-B130-207039378FD4} + {16BADE2F-1184-4518-8A70-B68A19D0805B} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} + {2876B12E-5841-4792-85A8-2929AEE11885} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} + {4F0D8A80-221F-4BCB-822E-44A0655F537E} = {2876B12E-5841-4792-85A8-2929AEE11885} + {2AB1A28B-2022-49EA-AF77-AC8A875915CC} = {2876B12E-5841-4792-85A8-2929AEE11885} + {F7734E61-F510-41E0-AD15-301A64081CD1} = {2876B12E-5841-4792-85A8-2929AEE11885} + {2F48041A-F7D1-478F-9C38-D41F0F05E8CA} = {2876B12E-5841-4792-85A8-2929AEE11885} EndGlobalSection EndGlobal diff --git a/src/Microsoft.DotNet.Watcher.Core/DictionaryExtensions.cs b/src/Microsoft.DotNet.Watcher.Core/DictionaryExtensions.cs deleted file mode 100644 index 0b318da824..0000000000 --- a/src/Microsoft.DotNet.Watcher.Core/DictionaryExtensions.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace System.Collections.Generic -{ - internal static class DictionaryExtensions - { - public static TValue GetOrAdd(this IDictionary dictionary, TKey key, Func factory) - { - lock (dictionary) - { - TValue value; - if (!dictionary.TryGetValue(key, out value)) - { - value = factory(key); - dictionary[key] = value; - } - - return value; - } - } - } -} diff --git a/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs index f105727329..9ef05d2eb0 100644 --- a/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs @@ -2,17 +2,17 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.DotNet.Watcher.Core.Internal; using Microsoft.Extensions.Logging; namespace Microsoft.DotNet.Watcher.Core { public class DotNetWatcher { - private readonly Func _fileWatcherFactory; + private readonly Func _fileWatcherFactory; private readonly Func _processWatcherFactory; private readonly IProjectProvider _projectProvider; private readonly ILoggerFactory _loggerFactory; @@ -22,7 +22,7 @@ namespace Microsoft.DotNet.Watcher.Core public bool ExitOnChange { get; set; } public DotNetWatcher( - Func fileWatcherFactory, + Func fileWatcherFactory, Func processWatcherFactory, IProjectProvider projectProvider, ILoggerFactory loggerFactory) @@ -86,7 +86,7 @@ namespace Microsoft.DotNet.Watcher.Core while (true) { - var project = await WaitForValidProjectJsonAsync(projectFile, cancellationToken); + await WaitForValidProjectJsonAsync(projectFile, cancellationToken); cancellationToken.ThrowIfCancellationRequested(); using (var currentRunCancellationSource = new CancellationTokenSource()) @@ -94,7 +94,7 @@ namespace Microsoft.DotNet.Watcher.Core cancellationToken, currentRunCancellationSource.Token)) { - var fileWatchingTask = WaitForProjectFileToChangeAsync(project, combinedCancellationSource.Token); + var fileWatchingTask = WaitForProjectFileToChangeAsync(projectFile, combinedCancellationSource.Token); var dotnetTask = WaitForDotnetToExitAsync(dotnetArgumentsAsString, workingDir, combinedCancellationSource.Token); var tasksToWait = new Task[] { dotnetTask, fileWatchingTask }; @@ -129,7 +129,7 @@ namespace Microsoft.DotNet.Watcher.Core _logger.LogInformation("Waiting for a file to change before restarting dotnet..."); // Now wait for a file to change before restarting dotnet - await WaitForProjectFileToChangeAsync(project, cancellationToken); + await WaitForProjectFileToChangeAsync(projectFile, cancellationToken); } else { @@ -146,12 +146,11 @@ namespace Microsoft.DotNet.Watcher.Core } } - private async Task WaitForProjectFileToChangeAsync(IProject project, CancellationToken cancellationToken) + private async Task WaitForProjectFileToChangeAsync(string projectFile, CancellationToken cancellationToken) { - using (var fileWatcher = _fileWatcherFactory(Path.GetDirectoryName(project.ProjectFile))) + using (var projectWatcher = CreateProjectWatcher(projectFile, watchProjectJsonOnly: false)) { - AddProjectAndDependeciesToWatcher(project, fileWatcher); - return await WatchForFileChangeAsync(fileWatcher, cancellationToken); + return await projectWatcher.WaitForChangeAsync(cancellationToken); } } @@ -161,37 +160,33 @@ namespace Microsoft.DotNet.Watcher.Core var dotnetWatcher = _processWatcherFactory(); int dotnetProcessId = dotnetWatcher.Start("dotnet", dotnetArguments, workingDir); - _logger.LogInformation($"dotnet run process id: {dotnetProcessId}"); + _logger.LogInformation($"dotnet process id: {dotnetProcessId}"); return dotnetWatcher.WaitForExitAsync(cancellationToken); } - private async Task WaitForValidProjectJsonAsync(string projectFile, CancellationToken cancellationToken) + private async Task WaitForValidProjectJsonAsync(string projectFile, CancellationToken cancellationToken) { - IProject project = null; - while (true) { + IProject project; string errors; if (_projectProvider.TryReadProject(projectFile, out project, out errors)) { - return project; + return; } _logger.LogError($"Error(s) reading project file '{projectFile}': "); _logger.LogError(errors); _logger.LogInformation("Fix the error to continue."); - using (var fileWatcher = _fileWatcherFactory(Path.GetDirectoryName(projectFile))) + using (var projectWatcher = CreateProjectWatcher(projectFile, watchProjectJsonOnly: true)) { - fileWatcher.WatchFile(projectFile); - fileWatcher.WatchProject(projectFile); - - await WatchForFileChangeAsync(fileWatcher, cancellationToken); + await projectWatcher.WaitForChangeAsync(cancellationToken); if (cancellationToken.IsCancellationRequested) { - return null; + return; } _logger.LogInformation($"File changed: {projectFile}"); @@ -199,66 +194,18 @@ namespace Microsoft.DotNet.Watcher.Core } } - private void AddProjectAndDependeciesToWatcher(string projectFile, IFileWatcher fileWatcher) + private ProjectWatcher CreateProjectWatcher(string projectFile, bool watchProjectJsonOnly) { - IProject project; - string errors; - - if (_projectProvider.TryReadProject(projectFile, out project, out errors)) - { - AddProjectAndDependeciesToWatcher(project, fileWatcher); - } - } - - private void AddProjectAndDependeciesToWatcher(IProject project, IFileWatcher fileWatcher) - { - foreach (var file in project.Files) - { - if (!string.IsNullOrEmpty(file)) - { - fileWatcher.WatchDirectory( - Path.GetDirectoryName(file), - Path.GetExtension(file)); - } - } - - fileWatcher.WatchProject(project.ProjectFile); - - foreach (var projFile in project.ProjectDependencies) - { - AddProjectAndDependeciesToWatcher(projFile, fileWatcher); - } - } - - private async Task WatchForFileChangeAsync(IFileWatcher fileWatcher, CancellationToken cancellationToken) - { - var tcs = new TaskCompletionSource(); - - cancellationToken.Register(() => tcs.TrySetResult(null)); - - Action callback = path => - { - tcs.TrySetResult(path); - }; - - fileWatcher.OnChanged += callback; - - var changedPath = await tcs.Task; - - // Don't need to listen anymore - fileWatcher.OnChanged -= callback; - - return changedPath; + return new ProjectWatcher(projectFile, watchProjectJsonOnly, _fileWatcherFactory, _projectProvider); } public static DotNetWatcher CreateDefault(ILoggerFactory loggerFactory) { return new DotNetWatcher( - fileWatcherFactory: root => new FileWatcher(root), + fileWatcherFactory: () => new FileWatcher(), processWatcherFactory: () => new ProcessWatcher(), projectProvider: new ProjectProvider(), loggerFactory: loggerFactory); } - } } diff --git a/src/Microsoft.DotNet.Watcher.Core/FileSystem/FileSystemWatcherRoot.cs b/src/Microsoft.DotNet.Watcher.Core/FileSystem/FileSystemWatcherRoot.cs deleted file mode 100644 index ff8534bc37..0000000000 --- a/src/Microsoft.DotNet.Watcher.Core/FileSystem/FileSystemWatcherRoot.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.IO; - -namespace Microsoft.DotNet.Watcher.Core -{ - internal class FileSystemWatcherRoot : IWatcherRoot - { - private readonly FileSystemWatcher _watcher; - - public FileSystemWatcherRoot(FileSystemWatcher watcher) - { - _watcher = watcher; - } - - public string Path - { - get - { - return _watcher.Path; - } - } - - public void Dispose() - { - _watcher.Dispose(); - } - } -} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Core/FileSystem/FileWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/FileSystem/FileWatcher.cs deleted file mode 100644 index e3d3abd442..0000000000 --- a/src/Microsoft.DotNet.Watcher.Core/FileSystem/FileWatcher.cs +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; - -namespace Microsoft.DotNet.Watcher.Core -{ - public class FileWatcher : IFileWatcher - { - private readonly HashSet _files = new HashSet(StringComparer.OrdinalIgnoreCase); - private readonly Dictionary> _directories = new Dictionary>(StringComparer.OrdinalIgnoreCase); - - private readonly List _watchers = new List(); - - internal FileWatcher() - { - } - - public FileWatcher(string path) - { - AddWatcher(path); - } - - public event Action OnChanged; - - public void WatchDirectory(string path, string extension) - { - var extensions = _directories.GetOrAdd(path, _ => new HashSet(StringComparer.OrdinalIgnoreCase)); - - extensions.Add(extension); - } - - public bool WatchFile(string path) - { - return _files.Add(path); - } - - public void WatchProject(string projectPath) - { - if (string.IsNullOrEmpty(projectPath)) - { - return; - } - - // If any watchers already handle this path then noop - if (!IsAlreadyWatched(projectPath)) - { - // To reduce the number of watchers we have we add a watcher to the root - // of this project so that we'll be notified if anything we care - // about changes - var rootPath = ResolveRootDirectory(projectPath); - AddWatcher(rootPath); - } - } - - // For testing - internal bool IsAlreadyWatched(string projectPath) - { - if (string.IsNullOrEmpty(projectPath)) - { - return false; - } - - bool anyWatchers = false; - - foreach (var watcher in _watchers) - { - // REVIEW: This needs to work x-platform, should this be case - // sensitive? - if (EnsureTrailingSlash(projectPath).StartsWith(EnsureTrailingSlash(watcher.Path), StringComparison.OrdinalIgnoreCase)) - { - anyWatchers = true; - } - } - - return anyWatchers; - } - - public void Dispose() - { - foreach (var w in _watchers) - { - w.Dispose(); - } - - _watchers.Clear(); - } - - public bool ReportChange(string newPath, WatcherChangeTypes changeType) - { - return ReportChange(oldPath: null, newPath: newPath, changeType: changeType); - } - - public bool ReportChange(string oldPath, string newPath, WatcherChangeTypes changeType) - { - if (HasChanged(oldPath, newPath, changeType)) - { - if (OnChanged != null) - { - OnChanged(oldPath ?? newPath); - } - - return true; - } - - return false; - } - - private static string EnsureTrailingSlash(string path) - { - if (string.IsNullOrEmpty(path)) - { - return path; - } - - if (path[path.Length - 1] != Path.DirectorySeparatorChar) - { - return path + Path.DirectorySeparatorChar; - } - - return path; - } - - // For testing only - internal void AddWatcher(IWatcherRoot watcherRoot) - { - _watchers.Add(watcherRoot); - } - - private void AddWatcher(string path) - { - var watcher = new FileSystemWatcher(path); - watcher.IncludeSubdirectories = true; - watcher.EnableRaisingEvents = true; - - watcher.Changed += OnWatcherChanged; - watcher.Renamed += OnRenamed; - watcher.Deleted += OnWatcherChanged; - watcher.Created += OnWatcherChanged; - - _watchers.Add(new FileSystemWatcherRoot(watcher)); - } - - private void OnRenamed(object sender, RenamedEventArgs e) - { - ReportChange(e.OldFullPath, e.FullPath, e.ChangeType); - } - - private void OnWatcherChanged(object sender, FileSystemEventArgs e) - { - ReportChange(e.FullPath, e.ChangeType); - } - - private bool HasChanged(string oldPath, string newPath, WatcherChangeTypes changeType) - { - // File changes - if (_files.Contains(newPath) || - (oldPath != null && _files.Contains(oldPath))) - { - return true; - } - - HashSet extensions; - if (_directories.TryGetValue(newPath, out extensions) || - _directories.TryGetValue(Path.GetDirectoryName(newPath), out extensions)) - { - string extension = Path.GetExtension(newPath); - - if (String.IsNullOrEmpty(extension)) - { - // Assume it's a directory - if (changeType == WatcherChangeTypes.Created || - changeType == WatcherChangeTypes.Renamed) - { - foreach (var e in extensions) - { - WatchDirectory(newPath, e); - } - } - else if (changeType == WatcherChangeTypes.Deleted) - { - return true; - } - - // Ignore anything else - return false; - } - - return extensions.Contains(extension); - } - - return false; - } - - private static string ResolveRootDirectory(string projectPath) - { - var di = new DirectoryInfo(projectPath); - - while (di.Parent != null) - { - var globalJsonPath = Path.Combine(di.FullName, "global.json"); - - if (File.Exists(globalJsonPath)) - { - return di.FullName; - } - - di = di.Parent; - } - - // If we don't find any files then make the project folder the root - return projectPath; - } - } -} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Core/FileSystem/IWatcherRoot.cs b/src/Microsoft.DotNet.Watcher.Core/FileSystem/IWatcherRoot.cs deleted file mode 100644 index eaf0e66bd0..0000000000 --- a/src/Microsoft.DotNet.Watcher.Core/FileSystem/IWatcherRoot.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; - -namespace Microsoft.DotNet.Watcher.Core -{ - internal interface IWatcherRoot : IDisposable - { - string Path { get; } - } -} diff --git a/src/Microsoft.DotNet.Watcher.Core/Abstractions/IFileWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/IFileWatcher.cs similarity index 53% rename from src/Microsoft.DotNet.Watcher.Core/Abstractions/IFileWatcher.cs rename to src/Microsoft.DotNet.Watcher.Core/Internal/IFileWatcher.cs index c5f01a6399..ab1f255003 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Abstractions/IFileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/IFileWatcher.cs @@ -3,16 +3,12 @@ using System; -namespace Microsoft.DotNet.Watcher.Core +namespace Microsoft.DotNet.Watcher.Core.Internal { public interface IFileWatcher : IDisposable { - event Action OnChanged; + event Action OnFileChange; - void WatchDirectory(string path, string extension); - - bool WatchFile(string path); - - void WatchProject(string path); + void WatchDirectory(string directory); } } diff --git a/src/Microsoft.DotNet.Watcher.Core/Abstractions/IProcessWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/IProcessWatcher.cs similarity index 90% rename from src/Microsoft.DotNet.Watcher.Core/Abstractions/IProcessWatcher.cs rename to src/Microsoft.DotNet.Watcher.Core/Internal/IProcessWatcher.cs index ad975f3a12..86960b28b3 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Abstractions/IProcessWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/IProcessWatcher.cs @@ -5,7 +5,7 @@ using System; using System.Threading; using System.Threading.Tasks; -namespace Microsoft.DotNet.Watcher.Core +namespace Microsoft.DotNet.Watcher.Core.Internal { public interface IProcessWatcher { diff --git a/src/Microsoft.DotNet.Watcher.Core/Abstractions/IProject.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/IProject.cs similarity index 88% rename from src/Microsoft.DotNet.Watcher.Core/Abstractions/IProject.cs rename to src/Microsoft.DotNet.Watcher.Core/Internal/IProject.cs index fc4556c570..a2a2389f06 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Abstractions/IProject.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/IProject.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; -namespace Microsoft.DotNet.Watcher.Core +namespace Microsoft.DotNet.Watcher.Core.Internal { public interface IProject { diff --git a/src/Microsoft.DotNet.Watcher.Core/Abstractions/IProjectProvider.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/IProjectProvider.cs similarity index 86% rename from src/Microsoft.DotNet.Watcher.Core/Abstractions/IProjectProvider.cs rename to src/Microsoft.DotNet.Watcher.Core/Internal/IProjectProvider.cs index 44e46cd91e..bcbf63aaae 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Abstractions/IProjectProvider.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/IProjectProvider.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.DotNet.Watcher.Core +namespace Microsoft.DotNet.Watcher.Core.Internal { public interface IProjectProvider { diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs new file mode 100644 index 0000000000..48f13534f5 --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs @@ -0,0 +1,111 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Microsoft.DotNet.Watcher.Core.Internal +{ + public class FileWatcher : IFileWatcher + { + private bool _disposed; + + private readonly IDictionary _watchers = new Dictionary(); + + public event Action OnFileChange; + + public void WatchDirectory(string directory) + { + EnsureNotDisposed(); + AddDirectoryWatcher(directory); + } + + public void Dispose() + { + if (_disposed) + { + return; + } + + _disposed = true; + + foreach (var watcher in _watchers) + { + watcher.Value.Dispose(); + } + _watchers.Clear(); + } + + private void AddDirectoryWatcher(string directory) + { + var alreadyWatched = _watchers + .Where(d => directory.StartsWith(d.Key)) + .Any(); + + if (alreadyWatched) + { + return; + } + + var redundantWatchers = _watchers + .Where(d => d.Key.StartsWith(directory)) + .Select(d => d.Key) + .ToList(); + + if (redundantWatchers.Any()) + { + foreach (var watcher in redundantWatchers) + { + DisposeWatcher(watcher); + } + } + + var newWatcher = new FileSystemWatcher(directory); + newWatcher.IncludeSubdirectories = true; + + newWatcher.Changed += WatcherChangedHandler; + newWatcher.Created += WatcherChangedHandler; + newWatcher.Deleted += WatcherChangedHandler; + newWatcher.Renamed += WatcherRenamedHandler; + + newWatcher.EnableRaisingEvents = true; + + _watchers.Add(directory, newWatcher); + } + + private void WatcherRenamedHandler(object sender, RenamedEventArgs e) + { + NotifyChange(e.OldFullPath); + NotifyChange(e.FullPath); + } + + private void WatcherChangedHandler(object sender, FileSystemEventArgs e) + { + NotifyChange(e.FullPath); + } + + private void NotifyChange(string path) + { + if (OnFileChange != null) + { + OnFileChange(path); + } + } + + private void DisposeWatcher(string directory) + { + _watchers[directory].Dispose(); + _watchers.Remove(directory); + } + + private void EnsureNotDisposed() + { + if (_disposed) + { + throw new ObjectDisposedException(nameof(FileWatcher)); + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Core/Impl/ProcessWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/ProcessWatcher.cs similarity index 51% rename from src/Microsoft.DotNet.Watcher.Core/Impl/ProcessWatcher.cs rename to src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/ProcessWatcher.cs index 3fc42a5304..0524284ba2 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Impl/ProcessWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/ProcessWatcher.cs @@ -7,11 +7,11 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.PlatformAbstractions; -namespace Microsoft.DotNet.Watcher.Core +namespace Microsoft.DotNet.Watcher.Core.Internal { public class ProcessWatcher : IProcessWatcher { - private static readonly bool _isWindows = PlatformServices.Default.Runtime.OperatingSystem.Equals("Windows", StringComparison.OrdinalIgnoreCase); + private static readonly TimeSpan _processKillTimeout = TimeSpan.FromSeconds(30); private Process _runningProcess; @@ -39,7 +39,13 @@ namespace Microsoft.DotNet.Watcher.Core public Task WaitForExitAsync(CancellationToken cancellationToken) { - cancellationToken.Register(() => KillProcess(_runningProcess?.Id)); + cancellationToken.Register(() => + { + if (_runningProcess != null) + { + _runningProcess.KillTree(_processKillTimeout); + } + }); return Task.Run(() => { @@ -52,41 +58,5 @@ namespace Microsoft.DotNet.Watcher.Core }); } - private void KillProcess(int? processId) - { - if (processId == null) - { - return; - } - - if (_isWindows) - { - var startInfo = new ProcessStartInfo() - { - FileName = "taskkill", - Arguments = $"/T /F /PID {processId}", - }; - var killProcess = Process.Start(startInfo); - killProcess.WaitForExit(); - } - else - { - var killSubProcessStartInfo = new ProcessStartInfo - { - FileName = "pkill", - Arguments = $"-TERM -P {processId}", - }; - var killSubProcess = Process.Start(killSubProcessStartInfo); - killSubProcess.WaitForExit(); - - var killProcessStartInfo = new ProcessStartInfo - { - FileName = "kill", - Arguments = $"-TERM {processId}", - }; - var killProcess = Process.Start(killProcessStartInfo); - killProcess.WaitForExit(); - } - } } } \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Core/Impl/Project.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs similarity index 97% rename from src/Microsoft.DotNet.Watcher.Core/Impl/Project.cs rename to src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs index a4e2423206..655308066e 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Impl/Project.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs @@ -6,7 +6,7 @@ using System.IO; using System.Linq; using Microsoft.DotNet.ProjectModel.Graph; -namespace Microsoft.DotNet.Watcher.Core +namespace Microsoft.DotNet.Watcher.Core.Internal { internal class Project : IProject { diff --git a/src/Microsoft.DotNet.Watcher.Core/Impl/ProjectProvider.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/ProjectProvider.cs similarity index 98% rename from src/Microsoft.DotNet.Watcher.Core/Impl/ProjectProvider.cs rename to src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/ProjectProvider.cs index 1336f50829..fc41f81888 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Impl/ProjectProvider.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/ProjectProvider.cs @@ -7,7 +7,7 @@ using System.Linq; using System.Text; using Microsoft.DotNet.ProjectModel; -namespace Microsoft.DotNet.Watcher.Core +namespace Microsoft.DotNet.Watcher.Core.Internal { public class ProjectProvider : IProjectProvider { diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/ProcessExtensions.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/ProcessExtensions.cs new file mode 100644 index 0000000000..56744e87c7 --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/ProcessExtensions.cs @@ -0,0 +1,113 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using Microsoft.Extensions.PlatformAbstractions; + +namespace Microsoft.DotNet.Watcher.Core.Internal +{ + public static class ProcessExtensions + { + private static readonly bool _isWindows = PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows; + + public static void KillTree(this Process process, TimeSpan timeout) + { + string stdout; + if (_isWindows) + { + RunProcessAndWaitForExit( + "taskkill", + $"/T /F /PID {process.Id}", + timeout, + out stdout); + } + else + { + var children = GetAllChildIdsUnix(process, timeout); + foreach (var childId in children) + { + KillProcessUnix(childId, timeout); + } + KillProcessUnix(process.Id, timeout); + } + } + + private static IEnumerable GetAllChildIdsUnix(Process process, TimeSpan timeout) + { + var children = new HashSet(); + GetAllChildIdsUnix(process.Id, children, timeout); + return children; + } + + private static void GetAllChildIdsUnix(int parentId, ISet children, TimeSpan timeout) + { + string stdout; + var exitCode = RunProcessAndWaitForExit( + "pgrep", + $"-P {parentId}", + timeout, + out stdout); + + if (exitCode == 0 && !string.IsNullOrEmpty(stdout)) + { + using (var reader = new StringReader(stdout)) + { + while (true) + { + var text = reader.ReadLine(); + if (text == null) + { + return; + } + + int id; + if (int.TryParse(text, out id)) + { + children.Add(id); + // Recursively get the children + GetAllChildIdsUnix(id, children, timeout); + } + } + } + } + } + + private static void KillProcessUnix(int processId, TimeSpan timeout) + { + string stdout; + RunProcessAndWaitForExit( + "kill", + $"-TERM {processId}", + timeout, + out stdout); + } + + private static int RunProcessAndWaitForExit(string fileName, string arguments, TimeSpan timeout, out string stdout) + { + var startInfo = new ProcessStartInfo + { + FileName = fileName, + Arguments = arguments, + RedirectStandardOutput = true, + UseShellExecute = false + }; + + var process = Process.Start(startInfo); + + stdout = null; + if (process.WaitForExit((int)timeout.TotalMilliseconds)) + { + stdout = process.StandardOutput.ReadToEnd(); + } + else + { + process.Kill(); + } + + return process.ExitCode; + } + } +} diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/ProjectWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/ProjectWatcher.cs new file mode 100644 index 0000000000..e94afb7dd4 --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/ProjectWatcher.cs @@ -0,0 +1,119 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.DotNet.Watcher.Core.Internal +{ + public class ProjectWatcher : IDisposable + { + private readonly IProjectProvider _projectProvider; + private readonly IFileWatcher _fileWatcher; + + private readonly string _rootProject; + private readonly bool _watchProjectJsonOnly; + + private ISet _watchedFiles; + + public ProjectWatcher( + string projectToWatch, + bool watchProjectJsonOnly, + Func fileWatcherFactory, + IProjectProvider projectProvider) + { + _projectProvider = projectProvider; + _fileWatcher = fileWatcherFactory(); + + _rootProject = projectToWatch; + _watchProjectJsonOnly = watchProjectJsonOnly; + } + + public async Task WaitForChangeAsync(CancellationToken cancellationToken) + { + _watchedFiles = GetProjectFilesClosure(_rootProject); + + foreach (var file in _watchedFiles) + { + _fileWatcher.WatchDirectory(Path.GetDirectoryName(file)); + } + + var tcs = new TaskCompletionSource(); + cancellationToken.Register(() => tcs.TrySetResult(null)); + + Action callback = path => + { + // If perf becomes a problem, this could be a good starting point + // because it reparses the project on every change + // Maybe it could time-buffer the changes in case there are a lot + // of files changed at the same time + if (IsFileInTheWatchedSet(path)) + { + tcs.TrySetResult(path); + } + }; + + _fileWatcher.OnFileChange += callback; + var changedFile = await tcs.Task; + _fileWatcher.OnFileChange -= callback; + + return changedFile; + } + + public void Dispose() + { + _fileWatcher?.Dispose(); + } + + private bool IsFileInTheWatchedSet(string file) + { + // If the file was already watched + // or if the new project file closure determined + // by file globbing patterns contains the new file + // Note, we cannot simply rebuild the closure every time because it wouldn't + // detect renamed files that have the new name outside of the closure + return + _watchedFiles.Contains(file) || + GetProjectFilesClosure(_rootProject).Contains(file); + } + + private ISet GetProjectFilesClosure(string projectFile) + { + var closure = new HashSet(); + + if (_watchProjectJsonOnly) + { + closure.Add(projectFile); + } + else + { + GetProjectFilesClosure(projectFile, closure); + } + return closure; + } + + private void GetProjectFilesClosure(string projectFile, ISet closure) + { + closure.Add(projectFile); + + IProject project; + string errors; + + if (_projectProvider.TryReadProject(projectFile, out project, out errors)) + { + foreach (var file in project.Files) + { + closure.Add(file); + } + + foreach (var dependency in project.ProjectDependencies) + { + GetProjectFilesClosure(dependency, closure); + } + } + } + } +} diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index abf92233e7..a84beb6964 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -18,7 +18,8 @@ }, "Microsoft.Extensions.Logging.Abstractions": "1.0.0-*", "Microsoft.Extensions.FileSystemGlobbing": "1.0.0-*", - "Microsoft.NETCore.Platforms": "1.0.1-*" + "Microsoft.NETCore.Platforms": "1.0.1-*", + "System.Diagnostics.Process": "4.1.0-*" }, "frameworks": { "dnxcore50": { diff --git a/test/TestApps/AppWithDeps/AppWithDeps.xproj b/test/TestApps/AppWithDeps/AppWithDeps.xproj new file mode 100644 index 0000000000..289874a39b --- /dev/null +++ b/test/TestApps/AppWithDeps/AppWithDeps.xproj @@ -0,0 +1,19 @@ + + + + 14.0.23107 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + f7734e61-f510-41e0-ad15-301a64081cd1 + AppWithDeps + ..\..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + \ No newline at end of file diff --git a/test/TestApps/AppWithDeps/Program.cs b/test/TestApps/AppWithDeps/Program.cs new file mode 100644 index 0000000000..6c67ed0901 --- /dev/null +++ b/test/TestApps/AppWithDeps/Program.cs @@ -0,0 +1,23 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.IO; + +namespace ConsoleApplication +{ + public class Program + { + public static void Main(string[] args) + { + Console.WriteLine("AppWithDeps started."); + + var processId = Process.GetCurrentProcess().Id; + File.AppendAllLines(args[0], new string[] { $"{processId}" }); + + File.WriteAllText(args[0] + ".started", ""); + Console.ReadLine(); + } + } +} diff --git a/test/TestApps/AppWithDeps/project.json b/test/TestApps/AppWithDeps/project.json new file mode 100644 index 0000000000..c9ce3f74a3 --- /dev/null +++ b/test/TestApps/AppWithDeps/project.json @@ -0,0 +1,20 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true + }, + "dependencies": { + "Dependency": "1.0.0", + "NETStandard.Library": "1.0.0-*" + }, + "frameworks": { + "dnxcore50": { + "dependencies": { + "System.Console": "4.0.0-*", + "System.Diagnostics.Process": "4.1.0-*", + "System.IO": "4.0.11-*", + "System.IO.FileSystem": "4.0.1-*" + } + } + } +} \ No newline at end of file diff --git a/test/TestApps/Dependency/Dependency.xproj b/test/TestApps/Dependency/Dependency.xproj new file mode 100644 index 0000000000..d1edb4ad06 --- /dev/null +++ b/test/TestApps/Dependency/Dependency.xproj @@ -0,0 +1,19 @@ + + + + 14.0.23107 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 2f48041a-f7d1-478f-9c38-d41f0f05e8ca + Dependency + ..\..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + \ No newline at end of file diff --git a/test/TestApps/Dependency/Foo.cs b/test/TestApps/Dependency/Foo.cs new file mode 100644 index 0000000000..3441304e2f --- /dev/null +++ b/test/TestApps/Dependency/Foo.cs @@ -0,0 +1,9 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Dependency +{ + public class Foo + { + } +} diff --git a/test/TestApps/Dependency/project.json b/test/TestApps/Dependency/project.json new file mode 100644 index 0000000000..89004d9d47 --- /dev/null +++ b/test/TestApps/Dependency/project.json @@ -0,0 +1,18 @@ +{ + "version": "1.0.0-*", + + "dependencies": { + "NETStandard.Library": "1.0.0-*" + }, + + "frameworks": { + "dnxcore50": { + "dependencies": { + "System.Console": "4.0.0-*", + "System.Diagnostics.Process": "4.1.0-*", + "System.IO": "4.0.11-*", + "System.IO.FileSystem": "4.0.1-*" + } + } + } +} diff --git a/test/TestApps/GlobbingApp/GlobbingApp.xproj b/test/TestApps/GlobbingApp/GlobbingApp.xproj new file mode 100644 index 0000000000..791e441f8f --- /dev/null +++ b/test/TestApps/GlobbingApp/GlobbingApp.xproj @@ -0,0 +1,19 @@ + + + + 14.0.23107 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 2ab1a28b-2022-49ea-af77-ac8a875915cc + GlobbingApp + ..\..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + \ No newline at end of file diff --git a/test/TestApps/GlobbingApp/Program.cs b/test/TestApps/GlobbingApp/Program.cs new file mode 100644 index 0000000000..ae996205d5 --- /dev/null +++ b/test/TestApps/GlobbingApp/Program.cs @@ -0,0 +1,23 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.IO; + +namespace ConsoleApplication +{ + public class Program + { + public static void Main(string[] args) + { + Console.WriteLine("GlobbingApp started."); + + var processId = Process.GetCurrentProcess().Id; + File.AppendAllLines(args[0], new string[] { $"{processId}" }); + + File.WriteAllText(args[0] + ".started", ""); + Console.ReadLine(); + } + } +} diff --git a/test/TestApps/GlobbingApp/exclude/Baz.cs b/test/TestApps/GlobbingApp/exclude/Baz.cs new file mode 100644 index 0000000000..fdaebd7201 --- /dev/null +++ b/test/TestApps/GlobbingApp/exclude/Baz.cs @@ -0,0 +1,10 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace GlobbingApp.exclude +{ + public class Baz + { + "THIS FILE SHOULD NOT BE INCLUDED IN COMPILATION" + } +} diff --git a/test/TestApps/GlobbingApp/include/Foo.cs b/test/TestApps/GlobbingApp/include/Foo.cs new file mode 100644 index 0000000000..d1afb658fc --- /dev/null +++ b/test/TestApps/GlobbingApp/include/Foo.cs @@ -0,0 +1,9 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace GlobbingApp.include +{ + public class Foo + { + } +} diff --git a/test/TestApps/GlobbingApp/project.json b/test/TestApps/GlobbingApp/project.json new file mode 100644 index 0000000000..1a6b3da081 --- /dev/null +++ b/test/TestApps/GlobbingApp/project.json @@ -0,0 +1,27 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true + }, + "compile": [ + "Program.cs", + "include/*.cs" + ], + "exclude": [ + "exclude/*" + ], + "dependencies": { + "NETStandard.Library": "1.0.0-*" + }, + + "frameworks": { + "dnxcore50": { + "dependencies": { + "System.Console": "4.0.0-*", + "System.Diagnostics.Process": "4.1.0-*", + "System.IO": "4.0.11-*", + "System.IO.FileSystem": "4.0.1-*" + } + } + } +} diff --git a/test/TestApps/NoDepsApp/NoDepsApp.xproj b/test/TestApps/NoDepsApp/NoDepsApp.xproj new file mode 100644 index 0000000000..959a38dc0e --- /dev/null +++ b/test/TestApps/NoDepsApp/NoDepsApp.xproj @@ -0,0 +1,19 @@ + + + + 14.0.23107 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 4f0d8a80-221f-4bcb-822e-44a0655f537e + NoDepsApp + ..\..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + \ No newline at end of file diff --git a/test/TestApps/NoDepsApp/Program.cs b/test/TestApps/NoDepsApp/Program.cs new file mode 100644 index 0000000000..2309fabd26 --- /dev/null +++ b/test/TestApps/NoDepsApp/Program.cs @@ -0,0 +1,27 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.IO; + +namespace ConsoleApplication +{ + public class Program + { + public static void Main(string[] args) + { + Console.WriteLine("NoDepsApp started."); + + var processId = Process.GetCurrentProcess().Id; + File.AppendAllLines(args[0], new string[] { $"{processId}" }); + + File.WriteAllText(args[0] + ".started", ""); + + if (args.Length > 1 && args[1] == "--no-exit") + { + Console.ReadLine(); + } + } + } +} diff --git a/test/TestApps/NoDepsApp/project.json b/test/TestApps/NoDepsApp/project.json new file mode 100644 index 0000000000..380a03bc97 --- /dev/null +++ b/test/TestApps/NoDepsApp/project.json @@ -0,0 +1,21 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true + }, + + "dependencies": { + "NETStandard.Library": "1.0.0-*" + }, + + "frameworks": { + "dnxcore50": { + "dependencies": { + "System.Console": "4.0.0-*", + "System.Diagnostics.Process": "4.1.0-*", + "System.IO": "4.0.11-*", + "System.IO.FileSystem": "4.0.1-*" + } + } + } +} diff --git a/test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs b/test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs new file mode 100644 index 0000000000..0b6144b1aa --- /dev/null +++ b/test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs @@ -0,0 +1,74 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.IO; +using Xunit; + +namespace Microsoft.DotNet.Watcher.FunctionalTests +{ + public class AppWithDepsTests + { + private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30); + + // Change a file included in compilation + [Fact] + public void ChangeFileInDependency() + { + using (var scenario = new AppWithDepsScenario()) + using (var wait = new WaitForFileToChange(scenario.StartedFile)) + { + var fileToChange = Path.Combine(scenario.DependencyFolder, "Foo.cs"); + var programCs = File.ReadAllText(fileToChange); + File.WriteAllText(fileToChange, programCs); + + wait.Wait(_defaultTimeout, + expectedToChange: true, + errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); + } + } + + + private class AppWithDepsScenario : DotNetWatchScenario + { + private const string AppWithDeps = "AppWithDeps"; + private const string Dependency = "Dependency"; + + private static readonly string _appWithDepsFolder = Path.Combine(_repositoryRoot, "test", "TestApps", AppWithDeps); + private static readonly string _dependencyFolder = Path.Combine(_repositoryRoot, "test", "TestApps", Dependency); + + public AppWithDepsScenario() + { + StatusFile = Path.Combine(_scenario.TempFolder, "status"); + StartedFile = StatusFile + ".started"; + + _scenario.AddProject(_appWithDepsFolder); + _scenario.AddProject(_dependencyFolder); + + _scenario.AddToolToProject(AppWithDeps, DotnetWatch); + _scenario.Restore(); + + AppWithDepsFolder = Path.Combine(_scenario.WorkFolder, AppWithDeps); + DependencyFolder = Path.Combine(_scenario.WorkFolder, Dependency); + + // Wait for the process to start + using (var wait = new WaitForFileToChange(StatusFile)) + { + RunDotNetWatch(StatusFile, Path.Combine(_scenario.WorkFolder, AppWithDeps)); + + wait.Wait(_defaultTimeout, + expectedToChange: true, + errorMessage: $"File not created: {StatusFile}"); + } + + Waiters.WaitForFileToBeReadable(StatusFile, _defaultTimeout); + } + + public string StatusFile { get; private set; } + public string StartedFile { get; private set; } + public string AppWithDepsFolder { get; private set; } + public string DependencyFolder { get; private set; } + } + } +} diff --git a/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs b/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs new file mode 100644 index 0000000000..3188706b0e --- /dev/null +++ b/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs @@ -0,0 +1,168 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.IO; +using System.Threading; +using Xunit; + +namespace Microsoft.DotNet.Watcher.FunctionalTests +{ + public class GlobbingAppTests + { + private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30); + + private static readonly TimeSpan _negativeTestWaitTime = TimeSpan.FromSeconds(10); + + // Change a file included in compilation + [Fact] + public void ChangeCompiledFile() + { + using (var scenario = new GlobbingAppScenario()) + using (var wait = new WaitForFileToChange(scenario.StartedFile)) + { + var fileToChange = Path.Combine(scenario.TestAppFolder, "include", "Foo.cs"); + var programCs = File.ReadAllText(fileToChange); + File.WriteAllText(fileToChange, programCs); + + wait.Wait(_defaultTimeout, + expectedToChange: true, + errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); + } + + } + + // Add a file to a folder included in compilation + [Fact] + public void AddCompiledFile() + { + // Add a file in a folder that's included in compilation + using (var scenario = new GlobbingAppScenario()) + using (var wait = new WaitForFileToChange(scenario.StartedFile)) + { + var fileToChange = Path.Combine(scenario.TestAppFolder, "include", "Bar.cs"); + File.WriteAllText(fileToChange, ""); + + wait.Wait(_defaultTimeout, + expectedToChange: true, + errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); + } + } + + // Delete a file included in compilation + [Fact] + public void DeleteCompiledFile() + { + using (var scenario = new GlobbingAppScenario()) + using (var wait = new WaitForFileToChange(scenario.StartedFile)) + { + var fileToChange = Path.Combine(scenario.TestAppFolder, "include", "Foo.cs"); + File.Delete(fileToChange); + + wait.Wait(_defaultTimeout, + expectedToChange: true, + errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); + } + } + + // Rename a file included in compilation + [Fact] + public void RenameCompiledFile() + { + using (var scenario = new GlobbingAppScenario()) + + using (var wait = new WaitForFileToChange(scenario.StatusFile)) + { + var oldFile = Path.Combine(scenario.TestAppFolder, "include", "Foo.cs"); + var newFile = Path.Combine(scenario.TestAppFolder, "include", "Foo_new.cs"); + File.Move(oldFile, newFile); + + wait.Wait(_defaultTimeout, + expectedToChange: true, + errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); + } + } + + // Add a file that's in a included folder but not matching the globbing pattern + [Fact] + public void ChangeNonCompiledFile() + { + using (var scenario = new GlobbingAppScenario()) + using (var wait = new WaitForFileToChange(scenario.StartedFile)) + { + var ids = File.ReadAllLines(scenario.StatusFile); + var procId = int.Parse(ids[0]); + + var changedFile = Path.Combine(scenario.TestAppFolder, "include", "not_compiled.css"); + File.WriteAllText(changedFile, ""); + + Console.WriteLine($"Waiting {_negativeTestWaitTime} seconds to see if the app restarts"); + Waiters.WaitForProcessToStop( + procId, + _negativeTestWaitTime, + expectedToStop: false, + errorMessage: "Test app restarted"); + } + } + + // Change a file that's in an excluded folder + [Fact] + public void ChangeExcludedFile() + { + using (var scenario = new GlobbingAppScenario()) + { + // Then wait for it to restart when we change a file that's included in the compilation files + using (var wait = new WaitForFileToChange(scenario.StartedFile)) + { + var ids = File.ReadAllLines(scenario.StatusFile); + var procId = int.Parse(ids[0]); + + var changedFile = Path.Combine(scenario.TestAppFolder, "exclude", "Baz.cs"); + File.WriteAllText(changedFile, ""); + + Console.WriteLine($"Waiting {_negativeTestWaitTime} seconds to see if the app restarts"); + Waiters.WaitForProcessToStop( + procId, + _negativeTestWaitTime, + expectedToStop: false, + errorMessage: "Test app restarted"); + } + } + } + + private class GlobbingAppScenario : DotNetWatchScenario + { + private const string TestAppName = "GlobbingApp"; + private static readonly string _testAppFolder = Path.Combine(_repositoryRoot, "test", "TestApps", TestAppName); + + public GlobbingAppScenario() + { + StatusFile = Path.Combine(_scenario.TempFolder, "status"); + StartedFile = StatusFile + ".started"; + + _scenario.AddProject(_testAppFolder); + _scenario.AddToolToProject(TestAppName, DotnetWatch); + _scenario.Restore(); + + TestAppFolder = Path.Combine(_scenario.WorkFolder, TestAppName); + + // Wait for the process to start + using (var wait = new WaitForFileToChange(StartedFile)) + { + RunDotNetWatch(StatusFile, Path.Combine(_scenario.WorkFolder, TestAppName)); + + wait.Wait(_defaultTimeout, + expectedToChange: true, + errorMessage: $"File not created: {StartedFile}"); + } + + Waiters.WaitForFileToBeReadable(StartedFile, _defaultTimeout); + } + + public string StatusFile { get; private set; } + public string StartedFile { get; private set; } + public string TestAppFolder { get; private set; } + } + } +} diff --git a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs new file mode 100644 index 0000000000..418fe53fe1 --- /dev/null +++ b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs @@ -0,0 +1,158 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.IO; +using Xunit; + +namespace Microsoft.DotNet.Watcher.FunctionalTests +{ + public class NoDepsAppTests + { + private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30); + + [Fact] + public void RestartProcessOnFileChange() + { + using (var scenario = new NoDepsAppScenario()) + { + // Wait for the process to start + using (var wait = new WaitForFileToChange(scenario.StartedFile)) + { + scenario.RunDotNetWatch($"{scenario.StatusFile} --no-exit"); + + wait.Wait(_defaultTimeout, + expectedToChange: true, + errorMessage: $"File not created: {scenario.StartedFile}"); + } + + // Then wait for it to restart when we change a file + using (var wait = new WaitForFileToChange(scenario.StartedFile)) + { + var fileToChange = Path.Combine(scenario.TestAppFolder, "Program.cs"); + var programCs = File.ReadAllText(fileToChange); + File.WriteAllText(fileToChange, programCs); + + wait.Wait(_defaultTimeout, + expectedToChange: true, + errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); + } + + // Check that the first child process is no longer running + Waiters.WaitForFileToBeReadable(scenario.StatusFile, _defaultTimeout); + var ids = File.ReadAllLines(scenario.StatusFile); + var firstProcessId = int.Parse(ids[0]); + Waiters.WaitForProcessToStop( + firstProcessId, + TimeSpan.FromSeconds(1), + expectedToStop: true, + errorMessage: $"PID: {firstProcessId} is still alive"); + } + } + + [Fact] + public void RestartProcessThatTerminatesAfterFileChange() + { + using (var scenario = new NoDepsAppScenario()) + { + // Wait for the process to start + using (var wait = new WaitForFileToChange(scenario.StartedFile)) + { + scenario.RunDotNetWatch(scenario.StatusFile); + + wait.Wait(_defaultTimeout, + expectedToChange: true, + errorMessage: $"File not created: {scenario.StartedFile}"); + } + + // Then wait for the app to exit + Waiters.WaitForFileToBeReadable(scenario.StartedFile, _defaultTimeout); + var ids = File.ReadAllLines(scenario.StatusFile); + var procId = int.Parse(ids[0]); + Waiters.WaitForProcessToStop( + procId, + _defaultTimeout, + expectedToStop: true, + errorMessage: "Test app did not exit"); + + // Then wait for it to restart when we change a file + using (var wait = new WaitForFileToChange(scenario.StartedFile)) + { + var fileToChange = Path.Combine(scenario.TestAppFolder, "Program.cs"); + var programCs = File.ReadAllText(fileToChange); + File.WriteAllText(fileToChange, programCs); + + wait.Wait(_defaultTimeout, + expectedToChange: true, + errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); + } + } + } + + + [Fact] + public void ExitOnChange() + { + using (var scenario = new NoDepsAppScenario()) + { + // Wait for the process to start + using (var wait = new WaitForFileToChange(scenario.StartedFile)) + { + scenario.RunDotNetWatch($"--exit-on-change -- {scenario.StatusFile} --no-exit"); + + wait.Wait(_defaultTimeout, + expectedToChange: true, + errorMessage: $"File not created: {scenario.StartedFile}"); + } + + // Change a file + var fileToChange = Path.Combine(scenario.TestAppFolder, "Program.cs"); + var programCs = File.ReadAllText(fileToChange); + File.WriteAllText(fileToChange, programCs); + + Waiters.WaitForProcessToStop( + scenario.WatcherProcess.Id, + _defaultTimeout, + expectedToStop: true, + errorMessage: "The watcher did not stop"); + + // Check that the first child process is no longer running + var ids = File.ReadAllLines(scenario.StatusFile); + var firstProcessId = int.Parse(ids[0]); + Waiters.WaitForProcessToStop( + firstProcessId, + TimeSpan.FromSeconds(1), + expectedToStop: true, + errorMessage: $"PID: {firstProcessId} is still alive"); + } + } + + private class NoDepsAppScenario : DotNetWatchScenario + { + private const string TestAppName = "NoDepsApp"; + private static readonly string _testAppFolder = Path.Combine(_repositoryRoot, "test", "TestApps", TestAppName); + + public NoDepsAppScenario() + { + StatusFile = Path.Combine(_scenario.TempFolder, "status"); + StartedFile = StatusFile + ".started"; + + _scenario.AddProject(_testAppFolder); + _scenario.AddToolToProject(TestAppName, DotnetWatch); + _scenario.Restore(); + + TestAppFolder = Path.Combine(_scenario.WorkFolder, TestAppName); + } + + public string StatusFile { get; private set; } + public string StartedFile { get; private set; } + public string TestAppFolder { get; private set; } + + public void RunDotNetWatch(string args) + { + RunDotNetWatch(args, Path.Combine(_scenario.WorkFolder, TestAppName)); + } + } + } +} diff --git a/test/dotnet-watch.FunctionalTests/Scenario/DotNetWatchScenario.cs b/test/dotnet-watch.FunctionalTests/Scenario/DotNetWatchScenario.cs new file mode 100644 index 0000000000..ebcdebc00d --- /dev/null +++ b/test/dotnet-watch.FunctionalTests/Scenario/DotNetWatchScenario.cs @@ -0,0 +1,67 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.IO; +using Microsoft.DotNet.Watcher.Core.Internal; + +namespace Microsoft.DotNet.Watcher.FunctionalTests +{ + public class DotNetWatchScenario : IDisposable + { + private static readonly TimeSpan _processKillTimeout = TimeSpan.FromSeconds(30); + + protected const string DotnetWatch = "dotnet-watch"; + + protected static readonly string _repositoryRoot = FindRepoRoot(); + protected static readonly string _artifactsFolder = Path.Combine(_repositoryRoot, "artifacts", "build"); + + protected ProjectToolScenario _scenario; + + public DotNetWatchScenario() + { + _scenario = new ProjectToolScenario(); + _scenario.AddNugetFeed(DotnetWatch, _artifactsFolder); + } + + public Process WatcherProcess { get; private set; } + + protected void RunDotNetWatch(string arguments, string workingFolder) + { + WatcherProcess = _scenario.ExecuteDotnet("watch " + arguments, workingFolder); + } + + public virtual void Dispose() + { + if (WatcherProcess != null) + { + if (!WatcherProcess.HasExited) + { + WatcherProcess.KillTree(_processKillTimeout); + } + WatcherProcess.Dispose(); + } + _scenario.Dispose(); + } + + private static string FindRepoRoot() + { + var di = new DirectoryInfo(Directory.GetCurrentDirectory()); + + while (di.Parent != null) + { + var globalJsonFile = Path.Combine(di.FullName, "global.json"); + + if (File.Exists(globalJsonFile)) + { + return di.FullName; + } + + di = di.Parent; + } + + return null; + } + } +} diff --git a/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs new file mode 100644 index 0000000000..41ee122cb1 --- /dev/null +++ b/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -0,0 +1,150 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Threading; +using System.Xml.Linq; +using Newtonsoft.Json.Linq; + +namespace Microsoft.DotNet.Watcher.FunctionalTests +{ + public class ProjectToolScenario: IDisposable + { + private const string NugetConfigFileName = "NuGet.config"; + + public ProjectToolScenario() + { + Console.WriteLine($"The temporary test folder is {TempFolder}"); + + WorkFolder = Path.Combine(TempFolder, "work"); + PackagesFolder = Path.Combine(TempFolder, "packages"); + + CreateTestDirectory(); + } + + public string TempFolder { get; } = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + + public string WorkFolder { get; } + + public string PackagesFolder { get; } + + public void AddProject(string projectFolder) + { + var destinationFolder = Path.Combine(WorkFolder, Path.GetFileName(projectFolder)); + Console.WriteLine($"Copying project {projectFolder} to {destinationFolder}"); + + Directory.CreateDirectory(destinationFolder); + + foreach (var directory in Directory.GetDirectories(projectFolder, "*", SearchOption.AllDirectories)) + { + Directory.CreateDirectory(directory.Replace(projectFolder, destinationFolder)); + } + + foreach (var file in Directory.GetFiles(projectFolder, "*.*", SearchOption.AllDirectories)) + { + File.Copy(file, file.Replace(projectFolder, destinationFolder), true); + } + } + + public void AddNugetFeed(string feedName, string feed) + { + var tempNugetConfigFile = Path.Combine(WorkFolder, NugetConfigFileName); + + var nugetConfig = XDocument.Load(tempNugetConfigFile); + var packageSource = nugetConfig.Element("configuration").Element("packageSources"); + packageSource.Add(new XElement("add", new XAttribute("key", feedName), new XAttribute("value", feed))); + using (var stream = File.OpenWrite(tempNugetConfigFile)) + { + nugetConfig.Save(stream); + } + } + + public void AddToolToProject(string projectName, string toolName) + { + var projectFile = Path.Combine(WorkFolder, projectName, "project.json"); + Console.WriteLine($"Adding {toolName} to {projectFile}"); + + var projectJson = JObject.Parse(File.ReadAllText(projectFile)); + projectJson.Add("tools", new JObject(new JProperty(toolName, "1.0.0-*"))); + File.WriteAllText(projectFile, projectJson.ToString()); + } + + public void Restore(string project = null) + { + if (project == null) + { + project = WorkFolder; + } + else + { + project = Path.Combine(WorkFolder, project); + } + + var restore = ExecuteDotnet($"restore -v Minimal", project); + restore.WaitForExit(); + + if (restore.ExitCode != 0) + { + throw new Exception($"Exit code {restore.ExitCode}"); + } + } + + private void CreateTestDirectory() + { + Directory.CreateDirectory(WorkFolder); + var nugetConfigFilePath = FindNugetConfig(); + + var tempNugetConfigFile = Path.Combine(WorkFolder, NugetConfigFileName); + File.Copy(nugetConfigFilePath, tempNugetConfigFile); + } + + public Process ExecuteDotnet(string arguments, string workDir) + { + Console.WriteLine($"Running dotnet {arguments} in {workDir}"); + + var psi = new ProcessStartInfo("dotnet", arguments) + { + UseShellExecute = false, + WorkingDirectory = workDir + }; + + return Process.Start(psi); + } + + private string FindNugetConfig() + { + var currentDirPath = Directory.GetCurrentDirectory(); + + string nugetConfigFile; + while (true) + { + nugetConfigFile = Directory.GetFiles(currentDirPath).SingleOrDefault(f => Path.GetFileName(f).Equals(NugetConfigFileName, StringComparison.Ordinal)); + if (!string.IsNullOrEmpty(nugetConfigFile)) + { + break; + } + + currentDirPath = Path.GetDirectoryName(currentDirPath); + } + + return nugetConfigFile; + } + + public void Dispose() + { + try + { + Directory.Delete(TempFolder, recursive: true); + } + catch + { + Console.WriteLine($"Failed to delete {TempFolder}. Retrying..."); + Thread.Sleep(TimeSpan.FromSeconds(5)); + Directory.Delete(TempFolder, recursive: true); + } + } + } +} diff --git a/test/dotnet-watch.FunctionalTests/WaitForFileToChange.cs b/test/dotnet-watch.FunctionalTests/WaitForFileToChange.cs new file mode 100644 index 0000000000..0105b74e8b --- /dev/null +++ b/test/dotnet-watch.FunctionalTests/WaitForFileToChange.cs @@ -0,0 +1,52 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Threading; + +namespace Microsoft.DotNet.Watcher.FunctionalTests +{ + public class WaitForFileToChange : IDisposable + { + private readonly FileSystemWatcher _watcher; + private readonly string _expectedFile; + + private readonly ManualResetEvent _changed = new ManualResetEvent(false); + + public WaitForFileToChange(string file) + { + _watcher = new FileSystemWatcher(Path.GetDirectoryName(file), "*" + Path.GetExtension(file)); + _expectedFile = file; + + _watcher.Changed += WatcherEvent; + _watcher.Created += WatcherEvent; + + _watcher.EnableRaisingEvents = true; + } + + private void WatcherEvent(object sender, FileSystemEventArgs e) + { + if (e.FullPath.Equals(_expectedFile, StringComparison.Ordinal)) + { + Waiters.WaitForFileToBeReadable(_expectedFile, TimeSpan.FromSeconds(10)); + _changed.Set(); + } + } + + public void Wait(TimeSpan timeout, bool expectedToChange, string errorMessage) + { + var changed = _changed.WaitOne(timeout); + if (changed != expectedToChange) + { + throw new Exception(errorMessage); + } + } + + public void Dispose() + { + _watcher.Dispose(); + _changed.Dispose(); + } + } +} diff --git a/test/dotnet-watch.FunctionalTests/Waiters.cs b/test/dotnet-watch.FunctionalTests/Waiters.cs new file mode 100644 index 0000000000..b24a11e054 --- /dev/null +++ b/test/dotnet-watch.FunctionalTests/Waiters.cs @@ -0,0 +1,67 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.IO; +using System.Threading; + +namespace Microsoft.DotNet.Watcher.FunctionalTests +{ + public static class Waiters + { + public static void WaitForFileToBeReadable(string file, TimeSpan timeout) + { + var watch = new Stopwatch(); + + watch.Start(); + while (watch.Elapsed < timeout) + { + try + { + File.ReadAllText(file); + watch.Stop(); + return; + } + catch + { + } + Thread.Sleep(500); + } + watch.Stop(); + + throw new Exception($"{file} is not readable."); + } + + public static void WaitForProcessToStop(int processId, TimeSpan timeout, bool expectedToStop, string errorMessage) + { + Process process = null; + + try + { + process = Process.GetProcessById(processId); + } + catch + { + } + + var watch = new Stopwatch(); + watch.Start(); + while (watch.Elapsed < timeout) + { + if (process == null || process.HasExited) + { + break; + } + Thread.Sleep(500); + } + watch.Stop(); + + bool isStopped = process == null || process.HasExited; + if (isStopped != expectedToStop) + { + throw new Exception(errorMessage); + } + } + } +} diff --git a/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.xproj b/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.xproj new file mode 100644 index 0000000000..7fd8ef1ab9 --- /dev/null +++ b/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.xproj @@ -0,0 +1,20 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 16bade2f-1184-4518-8a70-b68a19d0805b + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + 2.0 + + + + + + \ No newline at end of file diff --git a/test/dotnet-watch.FunctionalTests/project.json b/test/dotnet-watch.FunctionalTests/project.json new file mode 100644 index 0000000000..70c64e32c6 --- /dev/null +++ b/test/dotnet-watch.FunctionalTests/project.json @@ -0,0 +1,23 @@ +{ + "compilationOptions": { + "warningsAsErrors": true, + "keyFile": "../../tools/Key.snk" + }, + "dependencies": { + "dotnet-test-xunit": "1.0.0-dev-*", + "Microsoft.Extensions.DependencyInjection": "1.0.0-*", + "Microsoft.DotNet.Watcher.Core": "1.0.0-*", + "Microsoft.NETCore.Platforms": "1.0.1-*", + "Newtonsoft.Json": "8.0.2", + "xunit": "2.1.0", + "System.Diagnostics.Process": "4.1.0-*", + "System.IO.FileSystem.Watcher": "4.0.0-*", + "System.Xml.XDocument": "4.0.10-*" + }, + "frameworks": { + "dnxcore50": { + "imports": "portable-net451+win8" + } + }, + "testRunner": "xunit" +} \ No newline at end of file From e95ed5d204956a60a1b8ebe992aa25d4b862181b Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Thu, 3 Mar 2016 17:31:17 -0800 Subject: [PATCH 0113/1029] Added Company, Copyright and Product attributes to AssemblyInfo --- .../Properties/AssemblyInfo.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Properties/AssemblyInfo.cs b/src/Microsoft.AspNetCore.JsonPatch/Properties/AssemblyInfo.cs index b2437d9ad6..76feceeff0 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Properties/AssemblyInfo.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Properties/AssemblyInfo.cs @@ -5,4 +5,7 @@ using System.Reflection; using System.Resources; [assembly: AssemblyMetadata("Serviceable", "True")] -[assembly: NeutralResourcesLanguage("en-us")] \ No newline at end of file +[assembly: NeutralResourcesLanguage("en-us")] +[assembly: AssemblyCompany("Microsoft Corporation.")] +[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] +[assembly: AssemblyProduct("Microsoft ASP.NET Core")] From b9d2dc89aae71e648b2d19721730d4f023a2f1f5 Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Thu, 3 Mar 2016 17:31:53 -0800 Subject: [PATCH 0114/1029] Added Company, Copyright and Product attributes to AssemblyInfo --- .../Properties/AssemblyInfo.cs | 5 ++++- .../Properties/AssemblyInfo.cs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/Properties/AssemblyInfo.cs b/src/Microsoft.AspNetCore.Html.Abstractions/Properties/AssemblyInfo.cs index 72210dd611..403f0e3c52 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/Properties/AssemblyInfo.cs +++ b/src/Microsoft.AspNetCore.Html.Abstractions/Properties/AssemblyInfo.cs @@ -7,4 +7,7 @@ using System.Runtime.CompilerServices; [assembly: AssemblyMetadata("Serviceable", "True")] [assembly: NeutralResourcesLanguage("en-us")] -[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Html.Abstractions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] \ No newline at end of file +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Html.Abstractions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: AssemblyCompany("Microsoft Corporation.")] +[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] +[assembly: AssemblyProduct("Microsoft ASP.NET Core")] diff --git a/src/Microsoft.Extensions.WebEncoders/Properties/AssemblyInfo.cs b/src/Microsoft.Extensions.WebEncoders/Properties/AssemblyInfo.cs index b2437d9ad6..8d8d88195c 100644 --- a/src/Microsoft.Extensions.WebEncoders/Properties/AssemblyInfo.cs +++ b/src/Microsoft.Extensions.WebEncoders/Properties/AssemblyInfo.cs @@ -5,4 +5,7 @@ using System.Reflection; using System.Resources; [assembly: AssemblyMetadata("Serviceable", "True")] -[assembly: NeutralResourcesLanguage("en-us")] \ No newline at end of file +[assembly: NeutralResourcesLanguage("en-us")] +[assembly: AssemblyCompany("Microsoft Corporation.")] +[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] +[assembly: AssemblyProduct("Microsoft .NET Extensions")] From 467e520b35878fe180b237854bd291573ee3a3fc Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Thu, 3 Mar 2016 17:54:13 -0800 Subject: [PATCH 0115/1029] Added Company, Copyright and Product attributes to AssemblyInfo --- src/Microsoft.DotNet.Watcher.Core/Properties/AssemblyInfo.cs | 3 +++ src/dotnet-watch/Properties/AssemblyInfo.cs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/Microsoft.DotNet.Watcher.Core/Properties/AssemblyInfo.cs b/src/Microsoft.DotNet.Watcher.Core/Properties/AssemblyInfo.cs index 9cb7b1f01b..540e9029bc 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Properties/AssemblyInfo.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Properties/AssemblyInfo.cs @@ -6,3 +6,6 @@ using System.Resources; [assembly: AssemblyMetadata("Serviceable", "True")] [assembly: NeutralResourcesLanguage("en-US")] +[assembly: AssemblyCompany("Microsoft Corporation.")] +[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] +[assembly: AssemblyProduct("Microsoft .NET")] \ No newline at end of file diff --git a/src/dotnet-watch/Properties/AssemblyInfo.cs b/src/dotnet-watch/Properties/AssemblyInfo.cs index a78f66dc06..43612c95ba 100644 --- a/src/dotnet-watch/Properties/AssemblyInfo.cs +++ b/src/dotnet-watch/Properties/AssemblyInfo.cs @@ -8,3 +8,6 @@ using System.Runtime.CompilerServices; [assembly:InternalsVisibleTo("dotnet-watch.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: AssemblyMetadata("Serviceable", "True")] [assembly: NeutralResourcesLanguage("en-US")] +[assembly: AssemblyCompany("Microsoft Corporation.")] +[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] +[assembly: AssemblyProduct("Microsoft .NET")] \ No newline at end of file From 2705510508b08f6c50007c87e35fd32951208811 Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Fri, 12 Feb 2016 18:11:48 -0800 Subject: [PATCH 0116/1029] Add Copy/Move for content - Remove HtmlTextWriter Currently we overload the definition of WriteTo on IHtmlContent implementation classes to either represent a "real" write or a "flatten" by checking if the writer inherits HtmlText writer. This overloading is a bit of an odd fit and hides the real semantic we want for flattening. Additionally, we want to gradually make the concept of a pooled backing-buffer for IHtmlContent first-class - using pooled buffers dictates that we support move-semantics to some degree. This change makes the work that we do for flattening into pooled buffers explicit rather than hidden. --- .../HtmlContentBuilder.cs | 64 +++++++++ .../HtmlEncodedString.cs | 13 +- .../HtmlTextWriter.cs | 49 ------- .../IHtmlContentBuilder.cs | 2 +- .../IHtmlContentContainer.cs | 30 +++++ .../HtmlContentBuilderExtensionsTest.cs | 14 ++ .../HtmlContentBuilderTest.cs | 124 +++++++++++++++++- 7 files changed, 240 insertions(+), 56 deletions(-) delete mode 100644 src/Microsoft.AspNetCore.Html.Abstractions/HtmlTextWriter.cs create mode 100644 src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContentContainer.cs diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilder.cs b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilder.cs index b79e400375..be218244b0 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilder.cs +++ b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilder.cs @@ -96,6 +96,70 @@ namespace Microsoft.AspNetCore.Html return this; } + /// + public void CopyTo(IHtmlContentBuilder destination) + { + if (destination == null) + { + throw new ArgumentNullException(nameof(destination)); + } + + for (var i = 0; i < Entries.Count; i++) + { + var entry = Entries[i]; + + string entryAsString; + IHtmlContentContainer entryAsContainer; + if ((entryAsString = entry as string) != null) + { + destination.Append(entryAsString); + } + else if ((entryAsContainer = entry as IHtmlContentContainer) != null) + { + // Since we're copying, do a deep flatten. + entryAsContainer.CopyTo(destination); + } + else + { + // Only string, IHtmlContent values can be added to the buffer. + destination.AppendHtml((IHtmlContent)entry); + } + } + } + + /// + public void MoveTo(IHtmlContentBuilder destination) + { + if (destination == null) + { + throw new ArgumentNullException(nameof(destination)); + } + + for (var i = 0; i < Entries.Count; i++) + { + var entry = Entries[i]; + + string entryAsString; + IHtmlContentContainer entryAsContainer; + if ((entryAsString = entry as string) != null) + { + destination.Append(entryAsString); + } + else if ((entryAsContainer = entry as IHtmlContentContainer) != null) + { + // Since we're moving, do a deep flatten. + entryAsContainer.MoveTo(destination); + } + else + { + // Only string, IHtmlContent values can be added to the buffer. + destination.AppendHtml((IHtmlContent)entry); + } + } + + Entries.Clear(); + } + /// public void WriteTo(TextWriter writer, HtmlEncoder encoder) { diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlEncodedString.cs b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlEncodedString.cs index c50fba890c..bf38ac3682 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlEncodedString.cs +++ b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlEncodedString.cs @@ -17,17 +17,20 @@ namespace Microsoft.AspNetCore.Html /// public static readonly IHtmlContent NewLine = new HtmlEncodedString(Environment.NewLine); - private readonly string _value; - /// /// Creates a new . /// /// The HTML encoded value. public HtmlEncodedString(string value) { - _value = value; + Value = value; } + /// + /// Gets the HTML encoded value. + /// + public string Value { get; } + /// public void WriteTo(TextWriter writer, HtmlEncoder encoder) { @@ -41,13 +44,13 @@ namespace Microsoft.AspNetCore.Html throw new ArgumentNullException(nameof(encoder)); } - writer.Write(_value); + writer.Write(Value); } /// public override string ToString() { - return _value ?? string.Empty; + return Value ?? string.Empty; } } } diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlTextWriter.cs b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlTextWriter.cs deleted file mode 100644 index c9158b49b6..0000000000 --- a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlTextWriter.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.IO; - -namespace Microsoft.AspNetCore.Html -{ - /// - /// A which supports special processing of . - /// - public abstract class HtmlTextWriter : TextWriter - { - /// - /// Writes an value. - /// - /// The value. - public abstract void Write(IHtmlContent value); - - /// - public override void Write(object value) - { - var htmlContent = value as IHtmlContent; - if (htmlContent == null) - { - base.Write(value); - } - else - { - Write(htmlContent); - } - } - - /// - public override void WriteLine(object value) - { - var htmlContent = value as IHtmlContent; - if (htmlContent == null) - { - base.Write(value); - } - else - { - Write(htmlContent); - } - - base.WriteLine(); - } - } -} diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContentBuilder.cs b/src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContentBuilder.cs index 978fedc03f..912fe442aa 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContentBuilder.cs +++ b/src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContentBuilder.cs @@ -6,7 +6,7 @@ namespace Microsoft.AspNetCore.Html /// /// A builder for HTML content. /// - public interface IHtmlContentBuilder : IHtmlContent + public interface IHtmlContentBuilder : IHtmlContentContainer { /// /// Appends an instance. diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContentContainer.cs b/src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContentContainer.cs new file mode 100644 index 0000000000..f17811433c --- /dev/null +++ b/src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContentContainer.cs @@ -0,0 +1,30 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.AspNetCore.Html +{ + /// + /// Defines a contract for instances made up of several components which + /// can be copied into an . + /// + public interface IHtmlContentContainer : IHtmlContent + { + /// + /// Copies the contained content of this into . + /// + /// The . + void CopyTo(IHtmlContentBuilder builder); + + /// + /// + /// Moves the contained content of this into . + /// + /// + /// After is called, this instance should be left + /// in an empty state. + /// + /// + /// The . + void MoveTo(IHtmlContentBuilder builder); + } +} diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs b/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs index 6b4307f690..08151b3675 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs @@ -392,6 +392,20 @@ namespace Microsoft.AspNetCore.Html.Test return this; } + public void CopyTo(IHtmlContentBuilder destination) + { + foreach (var entry in Entries) + { + destination.AppendHtml(entry); + } + } + + public void MoveTo(IHtmlContentBuilder destination) + { + CopyTo(destination); + Clear(); + } + public void WriteTo(TextWriter writer, HtmlEncoder encoder) { foreach (var entry in Entries) diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderTest.cs b/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderTest.cs index 901512fdad..40219b19f7 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderTest.cs +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderTest.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.IO; using System.Text.Encodings.Web; using Microsoft.AspNetCore.Html; @@ -105,6 +106,106 @@ namespace Microsoft.Extensions.Internal Assert.Equal(0, content.Entries.Count); } + [Fact] + public void CopyTo_CopiesAllItems() + { + // Arrange + var source = new HtmlContentBuilder(); + source.AppendHtml(new TestHtmlContent("hello")); + source.Append("Test"); + + var destination = new HtmlContentBuilder(); + destination.Append("some-content"); + + // Act + source.CopyTo(destination); + + // Assert + Assert.Equal(2, source.Entries.Count); + Assert.Equal(3, destination.Entries.Count); + + Assert.Equal("some-content", Assert.IsType(destination.Entries[0])); + Assert.Equal(new TestHtmlContent("hello"), Assert.IsType(destination.Entries[1])); + Assert.Equal("Test", Assert.IsType(destination.Entries[2])); + } + + [Fact] + public void CopyTo_DoesDeepCopy() + { + // Arrange + var source = new HtmlContentBuilder(); + + var nested = new HtmlContentBuilder(); + source.AppendHtml(nested); + nested.AppendHtml(new TestHtmlContent("hello")); + source.Append("Test"); + + var destination = new HtmlContentBuilder(); + destination.Append("some-content"); + + // Act + source.CopyTo(destination); + + // Assert + Assert.Equal(2, source.Entries.Count); + Assert.Equal(1, nested.Entries.Count); + Assert.Equal(3, destination.Entries.Count); + + Assert.Equal("some-content", Assert.IsType(destination.Entries[0])); + Assert.Equal(new TestHtmlContent("hello"), Assert.IsType(destination.Entries[1])); + Assert.Equal("Test", Assert.IsType(destination.Entries[2])); + } + + [Fact] + public void MoveTo_CopiesAllItems_AndClears() + { + // Arrange + var source = new HtmlContentBuilder(); + source.AppendHtml(new TestHtmlContent("hello")); + source.Append("Test"); + + var destination = new HtmlContentBuilder(); + destination.Append("some-content"); + + // Act + source.MoveTo(destination); + + // Assert + Assert.Equal(0, source.Entries.Count); + Assert.Equal(3, destination.Entries.Count); + + Assert.Equal("some-content", Assert.IsType(destination.Entries[0])); + Assert.Equal(new TestHtmlContent("hello"), Assert.IsType(destination.Entries[1])); + Assert.Equal("Test", Assert.IsType(destination.Entries[2])); + } + + [Fact] + public void MoveTo_DoesDeepMove() + { + // Arrange + var source = new HtmlContentBuilder(); + + var nested = new HtmlContentBuilder(); + source.AppendHtml(nested); + nested.AppendHtml(new TestHtmlContent("hello")); + source.Append("Test"); + + var destination = new HtmlContentBuilder(); + destination.Append("some-content"); + + // Act + source.MoveTo(destination); + + // Assert + Assert.Equal(0, source.Entries.Count); + Assert.Equal(0, nested.Entries.Count); + Assert.Equal(3, destination.Entries.Count); + + Assert.Equal("some-content", Assert.IsType(destination.Entries[0])); + Assert.Equal(new TestHtmlContent("hello"), Assert.IsType(destination.Entries[1])); + Assert.Equal("Test", Assert.IsType(destination.Entries[2])); + } + [Fact] public void WriteTo_WritesAllItems() { @@ -122,7 +223,7 @@ namespace Microsoft.Extensions.Internal Assert.Equal("Written from TestHtmlContent: HelloHtmlEncode[[Test]]", writer.ToString()); } - private class TestHtmlContent : IHtmlContent + private class TestHtmlContent : IHtmlContent, IEquatable { private string _content; @@ -140,6 +241,27 @@ namespace Microsoft.Extensions.Internal { return "Written from TestHtmlContent: " + _content; } + + public override int GetHashCode() + { + return _content.GetHashCode(); + } + + public override bool Equals(object obj) + { + var other = obj as TestHtmlContent; + if (other != null) + { + return Equals(other); + } + + return base.Equals(obj); + } + + public bool Equals(TestHtmlContent other) + { + return string.Equals(_content, other._content); + } } } } From 52244da9e83ce267e0af5fb2081dc397c56f94da Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Fri, 4 Mar 2016 10:11:01 -0800 Subject: [PATCH 0117/1029] Temporary disable the tests that hang while investigating --- .../dotnet-watch.FunctionalTests/AppWithDepsTests.cs | 2 +- .../dotnet-watch.FunctionalTests/GlobbingAppTests.cs | 12 ++++++------ test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs b/test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs index 0b6144b1aa..c33696c1c0 100644 --- a/test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs +++ b/test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs @@ -13,7 +13,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30); // Change a file included in compilation - [Fact] + [Fact(Skip = "Disabled temporary")] public void ChangeFileInDependency() { using (var scenario = new AppWithDepsScenario()) diff --git a/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs b/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs index 3188706b0e..ab6fdf3328 100644 --- a/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs +++ b/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs @@ -16,7 +16,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests private static readonly TimeSpan _negativeTestWaitTime = TimeSpan.FromSeconds(10); // Change a file included in compilation - [Fact] + [Fact(Skip = "Disabled temporary")] public void ChangeCompiledFile() { using (var scenario = new GlobbingAppScenario()) @@ -34,7 +34,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } // Add a file to a folder included in compilation - [Fact] + [Fact(Skip = "Disabled temporary")] public void AddCompiledFile() { // Add a file in a folder that's included in compilation @@ -51,7 +51,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } // Delete a file included in compilation - [Fact] + [Fact(Skip = "Disabled temporary")] public void DeleteCompiledFile() { using (var scenario = new GlobbingAppScenario()) @@ -67,7 +67,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } // Rename a file included in compilation - [Fact] + [Fact(Skip = "Disabled temporary")] public void RenameCompiledFile() { using (var scenario = new GlobbingAppScenario()) @@ -85,7 +85,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } // Add a file that's in a included folder but not matching the globbing pattern - [Fact] + [Fact(Skip = "Disabled temporary")] public void ChangeNonCompiledFile() { using (var scenario = new GlobbingAppScenario()) @@ -107,7 +107,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } // Change a file that's in an excluded folder - [Fact] + [Fact(Skip = "Disabled temporary")] public void ChangeExcludedFile() { using (var scenario = new GlobbingAppScenario()) diff --git a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs index 418fe53fe1..a9d1080b30 100644 --- a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs +++ b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs @@ -12,7 +12,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests { private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30); - [Fact] + [Fact(Skip = "Disabled temporary")] public void RestartProcessOnFileChange() { using (var scenario = new NoDepsAppScenario()) @@ -51,7 +51,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } } - [Fact] + [Fact(Skip = "Disabled temporary")] public void RestartProcessThatTerminatesAfterFileChange() { using (var scenario = new NoDepsAppScenario()) @@ -91,7 +91,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } - [Fact] + [Fact(Skip = "Disabled temporary")] public void ExitOnChange() { using (var scenario = new NoDepsAppScenario()) From 8f959b04b18e0b09e01bcd09e48b9524171f5aa8 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Mon, 7 Mar 2016 20:54:54 -0800 Subject: [PATCH 0118/1029] Update the build scripts to the latest version --- build.ps1 | 33 ++++++++++++++++++++++++++++++++- build.sh | 15 +++++++++++++-- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/build.ps1 b/build.ps1 index 4fd24a30d5..8f2f99691a 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,3 +1,33 @@ +$ErrorActionPreference = "Stop" + +function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $retries) +{ + while($true) + { + try + { + Invoke-WebRequest $url -OutFile $downloadLocation + break + } + catch + { + $exceptionMessage = $_.Exception.Message + Write-Host "Failed to download '$url': $exceptionMessage" + if ($retries -gt 0) { + $retries-- + Write-Host "Waiting 10 seconds before retrying. Retries left: $retries" + Start-Sleep -Seconds 10 + + } + else + { + $exception = $_.Exception + throw $exception + } + } + } +} + cd $PSScriptRoot $repoFolder = $PSScriptRoot @@ -20,7 +50,8 @@ if (!(Test-Path $buildFolder)) { $localZipFile="$tempFolder\korebuild.zip" - Invoke-WebRequest $koreBuildZip -OutFile $localZipFile + DownloadWithRetry -url $koreBuildZip -downloadLocation $localZipFile -retries 6 + Add-Type -AssemblyName System.IO.Compression.FileSystem [System.IO.Compression.ZipFile]::ExtractToDirectory($localZipFile, $tempFolder) diff --git a/build.sh b/build.sh index 79638d06b6..f4208100eb 100755 --- a/build.sh +++ b/build.sh @@ -18,7 +18,18 @@ if test ! -d $buildFolder; then localZipFile="$tempFolder/korebuild.zip" - wget -O $localZipFile $koreBuildZip 2>/dev/null || curl -o $localZipFile --location $koreBuildZip /dev/null + retries=6 + until (wget -O $localZipFile $koreBuildZip 2>/dev/null || curl -o $localZipFile --location $koreBuildZip 2>/dev/null) + do + echo "Failed to download '$koreBuildZip'" + if [ "$retries" -le 0 ]; then + exit 1 + fi + retries=$((retries - 1)) + echo "Waiting 10 seconds before retrying. Retries left: $retries" + sleep 10s + done + unzip -q -d $tempFolder $localZipFile mkdir $buildFolder @@ -32,4 +43,4 @@ if test ! -d $buildFolder; then fi fi -$buildFile -r $repoFolder "$@" +$buildFile -r $repoFolder "$@" \ No newline at end of file From 5b5655f62808723e2be37b442277b393a813bf48 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Mon, 7 Mar 2016 20:54:58 -0800 Subject: [PATCH 0119/1029] Update the build scripts to the latest version --- build.ps1 | 33 ++++++++++++++++++++++++++++++++- build.sh | 15 +++++++++++++-- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/build.ps1 b/build.ps1 index 4fd24a30d5..8f2f99691a 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,3 +1,33 @@ +$ErrorActionPreference = "Stop" + +function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $retries) +{ + while($true) + { + try + { + Invoke-WebRequest $url -OutFile $downloadLocation + break + } + catch + { + $exceptionMessage = $_.Exception.Message + Write-Host "Failed to download '$url': $exceptionMessage" + if ($retries -gt 0) { + $retries-- + Write-Host "Waiting 10 seconds before retrying. Retries left: $retries" + Start-Sleep -Seconds 10 + + } + else + { + $exception = $_.Exception + throw $exception + } + } + } +} + cd $PSScriptRoot $repoFolder = $PSScriptRoot @@ -20,7 +50,8 @@ if (!(Test-Path $buildFolder)) { $localZipFile="$tempFolder\korebuild.zip" - Invoke-WebRequest $koreBuildZip -OutFile $localZipFile + DownloadWithRetry -url $koreBuildZip -downloadLocation $localZipFile -retries 6 + Add-Type -AssemblyName System.IO.Compression.FileSystem [System.IO.Compression.ZipFile]::ExtractToDirectory($localZipFile, $tempFolder) diff --git a/build.sh b/build.sh index 79638d06b6..f4208100eb 100755 --- a/build.sh +++ b/build.sh @@ -18,7 +18,18 @@ if test ! -d $buildFolder; then localZipFile="$tempFolder/korebuild.zip" - wget -O $localZipFile $koreBuildZip 2>/dev/null || curl -o $localZipFile --location $koreBuildZip /dev/null + retries=6 + until (wget -O $localZipFile $koreBuildZip 2>/dev/null || curl -o $localZipFile --location $koreBuildZip 2>/dev/null) + do + echo "Failed to download '$koreBuildZip'" + if [ "$retries" -le 0 ]; then + exit 1 + fi + retries=$((retries - 1)) + echo "Waiting 10 seconds before retrying. Retries left: $retries" + sleep 10s + done + unzip -q -d $tempFolder $localZipFile mkdir $buildFolder @@ -32,4 +43,4 @@ if test ! -d $buildFolder; then fi fi -$buildFile -r $repoFolder "$@" +$buildFile -r $repoFolder "$@" \ No newline at end of file From 3bccd97ff604c53b9aae4775643035ca494884e4 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Mon, 7 Mar 2016 20:55:07 -0800 Subject: [PATCH 0120/1029] Update the build scripts to the latest version --- build.ps1 | 33 ++++++++++++++++++++++++++++++++- build.sh | 15 +++++++++++++-- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/build.ps1 b/build.ps1 index 4fd24a30d5..8f2f99691a 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,3 +1,33 @@ +$ErrorActionPreference = "Stop" + +function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $retries) +{ + while($true) + { + try + { + Invoke-WebRequest $url -OutFile $downloadLocation + break + } + catch + { + $exceptionMessage = $_.Exception.Message + Write-Host "Failed to download '$url': $exceptionMessage" + if ($retries -gt 0) { + $retries-- + Write-Host "Waiting 10 seconds before retrying. Retries left: $retries" + Start-Sleep -Seconds 10 + + } + else + { + $exception = $_.Exception + throw $exception + } + } + } +} + cd $PSScriptRoot $repoFolder = $PSScriptRoot @@ -20,7 +50,8 @@ if (!(Test-Path $buildFolder)) { $localZipFile="$tempFolder\korebuild.zip" - Invoke-WebRequest $koreBuildZip -OutFile $localZipFile + DownloadWithRetry -url $koreBuildZip -downloadLocation $localZipFile -retries 6 + Add-Type -AssemblyName System.IO.Compression.FileSystem [System.IO.Compression.ZipFile]::ExtractToDirectory($localZipFile, $tempFolder) diff --git a/build.sh b/build.sh index 79638d06b6..f4208100eb 100755 --- a/build.sh +++ b/build.sh @@ -18,7 +18,18 @@ if test ! -d $buildFolder; then localZipFile="$tempFolder/korebuild.zip" - wget -O $localZipFile $koreBuildZip 2>/dev/null || curl -o $localZipFile --location $koreBuildZip /dev/null + retries=6 + until (wget -O $localZipFile $koreBuildZip 2>/dev/null || curl -o $localZipFile --location $koreBuildZip 2>/dev/null) + do + echo "Failed to download '$koreBuildZip'" + if [ "$retries" -le 0 ]; then + exit 1 + fi + retries=$((retries - 1)) + echo "Waiting 10 seconds before retrying. Retries left: $retries" + sleep 10s + done + unzip -q -d $tempFolder $localZipFile mkdir $buildFolder @@ -32,4 +43,4 @@ if test ! -d $buildFolder; then fi fi -$buildFile -r $repoFolder "$@" +$buildFile -r $repoFolder "$@" \ No newline at end of file From bef340a2c36d0c8d19cba6935bccdf3fa1924ff7 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 9 Mar 2016 12:52:50 -0800 Subject: [PATCH 0121/1029] Remove extra dependencies that produce NuGet warnings --- test/dotnet-watch.FunctionalTests/project.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/dotnet-watch.FunctionalTests/project.json b/test/dotnet-watch.FunctionalTests/project.json index 70c64e32c6..3e1db01183 100644 --- a/test/dotnet-watch.FunctionalTests/project.json +++ b/test/dotnet-watch.FunctionalTests/project.json @@ -9,10 +9,7 @@ "Microsoft.DotNet.Watcher.Core": "1.0.0-*", "Microsoft.NETCore.Platforms": "1.0.1-*", "Newtonsoft.Json": "8.0.2", - "xunit": "2.1.0", - "System.Diagnostics.Process": "4.1.0-*", - "System.IO.FileSystem.Watcher": "4.0.0-*", - "System.Xml.XDocument": "4.0.10-*" + "xunit": "2.1.0" }, "frameworks": { "dnxcore50": { From b7993bd562df1dca3c3f9d5d672f90911c880cf6 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 9 Mar 2016 16:35:07 -0800 Subject: [PATCH 0122/1029] Limit the branches that build on our public CI. [ci skip] --- .travis.yml | 6 ++++++ appveyor.yml | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/.travis.yml b/.travis.yml index e8f77f0f14..e63d71127a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,5 +16,11 @@ os: - linux - osx osx_image: xcode7.1 +branches: + only: + - master + - release + - dev + - /^(.*\\/)?ci-.*$/ script: - ./build.sh --quiet verify \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index 636a7618d3..15ffe737a5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,11 @@ init: - git config --global core.autocrlf true +branches: + only: + - master + - release + - dev + - /^(.*\\/)?ci-.*$/ build_script: - build.cmd --quiet verify clone_depth: 1 From e341d1b1e2bebe4f374542a309fb81f949326ac7 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 9 Mar 2016 16:35:10 -0800 Subject: [PATCH 0123/1029] Limit the branches that build on our public CI. [ci skip] --- .travis.yml | 6 ++++++ appveyor.yml | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/.travis.yml b/.travis.yml index e8f77f0f14..e63d71127a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,5 +16,11 @@ os: - linux - osx osx_image: xcode7.1 +branches: + only: + - master + - release + - dev + - /^(.*\\/)?ci-.*$/ script: - ./build.sh --quiet verify \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index 636a7618d3..15ffe737a5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,11 @@ init: - git config --global core.autocrlf true +branches: + only: + - master + - release + - dev + - /^(.*\\/)?ci-.*$/ build_script: - build.cmd --quiet verify clone_depth: 1 From 30cd2b88b3b55d03da179bc98f530be59df2c61f Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 9 Mar 2016 16:35:15 -0800 Subject: [PATCH 0124/1029] Limit the branches that build on our public CI. [ci skip] --- .travis.yml | 6 ++++++ appveyor.yml | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/.travis.yml b/.travis.yml index e8f77f0f14..e63d71127a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,5 +16,11 @@ os: - linux - osx osx_image: xcode7.1 +branches: + only: + - master + - release + - dev + - /^(.*\\/)?ci-.*$/ script: - ./build.sh --quiet verify \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index 636a7618d3..15ffe737a5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,11 @@ init: - git config --global core.autocrlf true +branches: + only: + - master + - release + - dev + - /^(.*\\/)?ci-.*$/ build_script: - build.cmd --quiet verify clone_depth: 1 From 104163e275cce1f95b5b77a6bd6c38abe64061fa Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 9 Mar 2016 17:44:47 -0800 Subject: [PATCH 0125/1029] Fix backslashes in yml config. [ci skip] --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e63d71127a..304e307169 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,6 @@ branches: - master - release - dev - - /^(.*\\/)?ci-.*$/ + - /^(.*\/)?ci-.*$/ script: - ./build.sh --quiet verify \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index 15ffe737a5..be95b88d6f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,7 +5,7 @@ branches: - master - release - dev - - /^(.*\\/)?ci-.*$/ + - /^(.*\/)?ci-.*$/ build_script: - build.cmd --quiet verify clone_depth: 1 From d8607779fd8bcd3453930c9e80764c5eeb7ab660 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 9 Mar 2016 17:44:48 -0800 Subject: [PATCH 0126/1029] Fix backslashes in yml config. [ci skip] --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e63d71127a..304e307169 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,6 @@ branches: - master - release - dev - - /^(.*\\/)?ci-.*$/ + - /^(.*\/)?ci-.*$/ script: - ./build.sh --quiet verify \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index 15ffe737a5..be95b88d6f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,7 +5,7 @@ branches: - master - release - dev - - /^(.*\\/)?ci-.*$/ + - /^(.*\/)?ci-.*$/ build_script: - build.cmd --quiet verify clone_depth: 1 From bc560b000353f0e7bf414d3ff812c3691ce0ceb7 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 9 Mar 2016 17:44:48 -0800 Subject: [PATCH 0127/1029] Fix backslashes in yml config. [ci skip] --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e63d71127a..304e307169 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,6 @@ branches: - master - release - dev - - /^(.*\\/)?ci-.*$/ + - /^(.*\/)?ci-.*$/ script: - ./build.sh --quiet verify \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index 15ffe737a5..be95b88d6f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,7 +5,7 @@ branches: - master - release - dev - - /^(.*\\/)?ci-.*$/ + - /^(.*\/)?ci-.*$/ build_script: - build.cmd --quiet verify clone_depth: 1 From 618e41fa1eb983d24f8911f8c5b32913b8474ce1 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Thu, 3 Mar 2016 15:06:33 -0800 Subject: [PATCH 0128/1029] Update the documentation to "dotnet-watch" --- README.md | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 45b7eb49dc..35eccfd22e 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,33 @@ -dnx-watch +dotnet-watch === -`dnx-watch` is a file watcher for `dnx` that restarts the specified application when changes in the source code are detected. Its' purpose is to replace `dnx --watch`. +`dotnet-watch` is a file watcher for `dotnet` that restarts the specified application when changes in the source code are detected. ### How To Install -From a console window run the following command `dnu commands install Microsoft.Dnx.Watcher` -Then the `dnx-watch` command will become available. -To install the latest unstable release add the following parameter to the command `--fallbacksource https://myget.org/F/aspnetvnext/api/v3/index.json` +Add `dotnet-watch` to the `tools` section of your `project.json` file: + +``` +{ +... + "tools": { + "dotnet-watch": "1.0.0-*" + } +... +} +``` ### How To Use -`dnx-watch ` -Example: +```dotnet watch -- ``` -* To run the command `kestrel` in the current folder: `dnx-watch kestrel` -* To run the command kestrel in a different folder: `dnx-watch --project C:\myproject --dnx-args kestrel` -* To run the command kestrel in a different folder with extra arguments: `dnx-watch --project C:\myproject --dnx-args kestrel arg1 arg2` +- `dotnet watch` (runs the application without arguments) +- `dotnet watch foo bar` (runs the application with the arguments `foo bar`) +- `dotnet watch --exit-on-change -- foo bar` (runs the application with the arguments `foo bar`. In addition, it passes `--exit-on-change` to the watcher). +- `dotnet watch --command test -- -parallel none` (runs `dotnet test` with the arguments `-parallel none`) AppVeyor: [![AppVeyor](https://ci.appveyor.com/api/projects/status/fxhto3omtehio3aj/branch/dev?svg=true)](https://ci.appveyor.com/project/aspnetci/dnx-watch/branch/dev) -Travis: [![Travis](https://travis-ci.org/aspnet/dnx-watch.svg?branch=dev)](https://travis-ci.org/aspnet/dnx-watch) +Travis: [![Travis](https://travis-ci.org/aspnet/dotnet-watch.svg?branch=dev)](https://travis-ci.org/aspnet/dotnet-watch) -### Remarks: - -* Everything after `--dnx-args` is passed to dnx and ignored by the watcher. -* The watcher always passes `--project` to dnx. Do not pass it as a `--dnx-args` argument. - This project is part of ASP.NET 5. You can find samples, documentation and getting started instructions for ASP.NET 5 at the [Home](https://github.com/aspnet/home) repo. From bc382be63277b1bfaadb7dd4b26badec3d21969d Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Fri, 4 Mar 2016 10:37:50 -0800 Subject: [PATCH 0129/1029] Fix the tests that hang --- .../Internal/Implementation/FileWatcher.cs | 11 +++- .../AppWithDepsTests.cs | 22 ++++--- .../GlobbingAppTests.cs | 57 +++++++++++-------- .../NoDepsAppTests.cs | 6 +- .../Scenario/ProjectToolScenario.cs | 11 ++-- .../WaitForFileToChange.cs | 20 +++++-- 6 files changed, 80 insertions(+), 47 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs index 48f13534f5..57f082a8d0 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs @@ -96,8 +96,17 @@ namespace Microsoft.DotNet.Watcher.Core.Internal private void DisposeWatcher(string directory) { - _watchers[directory].Dispose(); + var watcher = _watchers[directory]; _watchers.Remove(directory); + + watcher.EnableRaisingEvents = false; + + watcher.Changed -= WatcherChangedHandler; + watcher.Created -= WatcherChangedHandler; + watcher.Deleted -= WatcherChangedHandler; + watcher.Renamed -= WatcherRenamedHandler; + + watcher.Dispose(); } private void EnsureNotDisposed() diff --git a/test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs b/test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs index c33696c1c0..55678cf11b 100644 --- a/test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs +++ b/test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs @@ -13,19 +13,22 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30); // Change a file included in compilation - [Fact(Skip = "Disabled temporary")] + [Fact] public void ChangeFileInDependency() { using (var scenario = new AppWithDepsScenario()) - using (var wait = new WaitForFileToChange(scenario.StartedFile)) { - var fileToChange = Path.Combine(scenario.DependencyFolder, "Foo.cs"); - var programCs = File.ReadAllText(fileToChange); - File.WriteAllText(fileToChange, programCs); + scenario.Start(); + using (var wait = new WaitForFileToChange(scenario.StartedFile)) + { + var fileToChange = Path.Combine(scenario.DependencyFolder, "Foo.cs"); + var programCs = File.ReadAllText(fileToChange); + File.WriteAllText(fileToChange, programCs); - wait.Wait(_defaultTimeout, - expectedToChange: true, - errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); + wait.Wait(_defaultTimeout, + expectedToChange: true, + errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); + } } } @@ -51,7 +54,10 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests AppWithDepsFolder = Path.Combine(_scenario.WorkFolder, AppWithDeps); DependencyFolder = Path.Combine(_scenario.WorkFolder, Dependency); + } + public void Start() + { // Wait for the process to start using (var wait = new WaitForFileToChange(StatusFile)) { diff --git a/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs b/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs index ab6fdf3328..839ce62426 100644 --- a/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs +++ b/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs @@ -16,12 +16,14 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests private static readonly TimeSpan _negativeTestWaitTime = TimeSpan.FromSeconds(10); // Change a file included in compilation - [Fact(Skip = "Disabled temporary")] + [Fact] public void ChangeCompiledFile() { using (var scenario = new GlobbingAppScenario()) using (var wait = new WaitForFileToChange(scenario.StartedFile)) { + scenario.Start(); + var fileToChange = Path.Combine(scenario.TestAppFolder, "include", "Foo.cs"); var programCs = File.ReadAllText(fileToChange); File.WriteAllText(fileToChange, programCs); @@ -34,13 +36,15 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } // Add a file to a folder included in compilation - [Fact(Skip = "Disabled temporary")] + [Fact] public void AddCompiledFile() { // Add a file in a folder that's included in compilation using (var scenario = new GlobbingAppScenario()) using (var wait = new WaitForFileToChange(scenario.StartedFile)) { + scenario.Start(); + var fileToChange = Path.Combine(scenario.TestAppFolder, "include", "Bar.cs"); File.WriteAllText(fileToChange, ""); @@ -51,12 +55,14 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } // Delete a file included in compilation - [Fact(Skip = "Disabled temporary")] + [Fact] public void DeleteCompiledFile() { using (var scenario = new GlobbingAppScenario()) using (var wait = new WaitForFileToChange(scenario.StartedFile)) { + scenario.Start(); + var fileToChange = Path.Combine(scenario.TestAppFolder, "include", "Foo.cs"); File.Delete(fileToChange); @@ -67,13 +73,14 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } // Rename a file included in compilation - [Fact(Skip = "Disabled temporary")] + [Fact] public void RenameCompiledFile() { using (var scenario = new GlobbingAppScenario()) - using (var wait = new WaitForFileToChange(scenario.StatusFile)) { + scenario.Start(); + var oldFile = Path.Combine(scenario.TestAppFolder, "include", "Foo.cs"); var newFile = Path.Combine(scenario.TestAppFolder, "include", "Foo_new.cs"); File.Move(oldFile, newFile); @@ -85,19 +92,20 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } // Add a file that's in a included folder but not matching the globbing pattern - [Fact(Skip = "Disabled temporary")] + [Fact] public void ChangeNonCompiledFile() { using (var scenario = new GlobbingAppScenario()) - using (var wait = new WaitForFileToChange(scenario.StartedFile)) { + scenario.Start(); + var ids = File.ReadAllLines(scenario.StatusFile); var procId = int.Parse(ids[0]); var changedFile = Path.Combine(scenario.TestAppFolder, "include", "not_compiled.css"); File.WriteAllText(changedFile, ""); - Console.WriteLine($"Waiting {_negativeTestWaitTime} seconds to see if the app restarts"); + Console.WriteLine($"Waiting {_negativeTestWaitTime.TotalSeconds} seconds to see if the app restarts"); Waiters.WaitForProcessToStop( procId, _negativeTestWaitTime, @@ -107,27 +115,25 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } // Change a file that's in an excluded folder - [Fact(Skip = "Disabled temporary")] + [Fact] public void ChangeExcludedFile() { using (var scenario = new GlobbingAppScenario()) { - // Then wait for it to restart when we change a file that's included in the compilation files - using (var wait = new WaitForFileToChange(scenario.StartedFile)) - { - var ids = File.ReadAllLines(scenario.StatusFile); - var procId = int.Parse(ids[0]); - - var changedFile = Path.Combine(scenario.TestAppFolder, "exclude", "Baz.cs"); - File.WriteAllText(changedFile, ""); + scenario.Start(); - Console.WriteLine($"Waiting {_negativeTestWaitTime} seconds to see if the app restarts"); - Waiters.WaitForProcessToStop( - procId, - _negativeTestWaitTime, - expectedToStop: false, - errorMessage: "Test app restarted"); - } + var ids = File.ReadAllLines(scenario.StatusFile); + var procId = int.Parse(ids[0]); + + var changedFile = Path.Combine(scenario.TestAppFolder, "exclude", "Baz.cs"); + File.WriteAllText(changedFile, ""); + + Console.WriteLine($"Waiting {_negativeTestWaitTime.TotalSeconds} seconds to see if the app restarts"); + Waiters.WaitForProcessToStop( + procId, + _negativeTestWaitTime, + expectedToStop: false, + errorMessage: "Test app restarted"); } } @@ -146,7 +152,10 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests _scenario.Restore(); TestAppFolder = Path.Combine(_scenario.WorkFolder, TestAppName); + } + public void Start() + { // Wait for the process to start using (var wait = new WaitForFileToChange(StartedFile)) { diff --git a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs index a9d1080b30..418fe53fe1 100644 --- a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs +++ b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs @@ -12,7 +12,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests { private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30); - [Fact(Skip = "Disabled temporary")] + [Fact] public void RestartProcessOnFileChange() { using (var scenario = new NoDepsAppScenario()) @@ -51,7 +51,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } } - [Fact(Skip = "Disabled temporary")] + [Fact] public void RestartProcessThatTerminatesAfterFileChange() { using (var scenario = new NoDepsAppScenario()) @@ -91,7 +91,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } - [Fact(Skip = "Disabled temporary")] + [Fact] public void ExitOnChange() { using (var scenario = new NoDepsAppScenario()) diff --git a/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs index 41ee122cb1..be10d97fbc 100644 --- a/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -20,17 +20,14 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests Console.WriteLine($"The temporary test folder is {TempFolder}"); WorkFolder = Path.Combine(TempFolder, "work"); - PackagesFolder = Path.Combine(TempFolder, "packages"); - + CreateTestDirectory(); } - public string TempFolder { get; } = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + public string TempFolder { get; } = Path.Combine(Path.GetDirectoryName(FindNugetConfig()), "testWorkDir" , Guid.NewGuid().ToString()); public string WorkFolder { get; } - public string PackagesFolder { get; } - public void AddProject(string projectFolder) { var destinationFolder = Path.Combine(WorkFolder, Path.GetFileName(projectFolder)); @@ -95,6 +92,8 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests private void CreateTestDirectory() { Directory.CreateDirectory(WorkFolder); + File.WriteAllText(Path.Combine(WorkFolder, "global.json"), "{}"); + var nugetConfigFilePath = FindNugetConfig(); var tempNugetConfigFile = Path.Combine(WorkFolder, NugetConfigFileName); @@ -114,7 +113,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests return Process.Start(psi); } - private string FindNugetConfig() + private static string FindNugetConfig() { var currentDirPath = Directory.GetCurrentDirectory(); diff --git a/test/dotnet-watch.FunctionalTests/WaitForFileToChange.cs b/test/dotnet-watch.FunctionalTests/WaitForFileToChange.cs index 0105b74e8b..eb964f85d2 100644 --- a/test/dotnet-watch.FunctionalTests/WaitForFileToChange.cs +++ b/test/dotnet-watch.FunctionalTests/WaitForFileToChange.cs @@ -12,7 +12,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests private readonly FileSystemWatcher _watcher; private readonly string _expectedFile; - private readonly ManualResetEvent _changed = new ManualResetEvent(false); + private ManualResetEvent _changed = new ManualResetEvent(false); public WaitForFileToChange(string file) { @@ -30,23 +30,33 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests if (e.FullPath.Equals(_expectedFile, StringComparison.Ordinal)) { Waiters.WaitForFileToBeReadable(_expectedFile, TimeSpan.FromSeconds(10)); - _changed.Set(); + _changed?.Set(); } } public void Wait(TimeSpan timeout, bool expectedToChange, string errorMessage) { - var changed = _changed.WaitOne(timeout); - if (changed != expectedToChange) + if (_changed != null) { - throw new Exception(errorMessage); + var changed = _changed.WaitOne(timeout); + if (changed != expectedToChange) + { + throw new Exception(errorMessage); + } } } public void Dispose() { + _watcher.EnableRaisingEvents = false; + + _watcher.Changed -= WatcherEvent; + _watcher.Created -= WatcherEvent; + _watcher.Dispose(); _changed.Dispose(); + + _changed = null; } } } From b734291b1395d8134b911141c01d8c6aee9ea86e Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 10 Mar 2016 21:46:51 -0800 Subject: [PATCH 0130/1029] Target minimal TFMs --- .../Adapters/ObjectAdapter.cs | 4 ++-- .../Converters/TypedJsonPatchDocumentConverter.cs | 2 +- .../Helpers/ObjectTreeAnalyisResult.cs | 1 - src/Microsoft.AspNetCore.JsonPatch/project.json | 7 ++++--- test/Microsoft.AspNetCore.JsonPatch.Test/project.json | 5 +++-- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs index aeae454fa9..b70ff697c3 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs @@ -1023,14 +1023,14 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters { if (IsGenericListType(type)) { - return type.GetGenericArguments()[0]; + return type.GetTypeInfo().GenericTypeArguments[0]; } foreach (Type interfaceType in type.GetTypeInfo().ImplementedInterfaces) { if (IsGenericListType(interfaceType)) { - return interfaceType.GetGenericArguments()[0]; + return interfaceType.GetTypeInfo().GenericTypeArguments[0]; } } diff --git a/src/Microsoft.AspNetCore.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs b/src/Microsoft.AspNetCore.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs index a150bd0478..292a3be556 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs @@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Converters return null; } - var genericType = objectType.GetGenericArguments()[0]; + var genericType = objectType.GetTypeInfo().GenericTypeArguments[0]; // load jObject var jObject = JArray.Load(reader); diff --git a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ObjectTreeAnalyisResult.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ObjectTreeAnalyisResult.cs index 4d083bd073..782859ad5f 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ObjectTreeAnalyisResult.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ObjectTreeAnalyisResult.cs @@ -141,7 +141,6 @@ namespace Microsoft.AspNetCore.JsonPatch.Helpers } else if (targetObject is IList) { - System.Diagnostics.Debugger.Launch(); UseDynamicLogic = false; int index; diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index 6e66884725..abfc19cba3 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -16,13 +16,14 @@ "Newtonsoft.Json": "8.0.2" }, "frameworks": { - "net451": {}, - "netstandard1.3": { + "netstandard1.1": { "dependencies": { "Microsoft.CSharp": "4.0.1-*", "System.Collections.Concurrent": "4.0.12-*", "System.ComponentModel.TypeConverter": "4.0.1-*", + "System.Diagnostics.Debug": "4.0.11-*", "System.Globalization": "4.0.11-*", + "System.Linq": "4.1.0-*", "System.Reflection.Extensions": "4.0.1-*", "System.Resources.ResourceManager": "4.0.1-*", "System.Runtime.Extensions": "4.1.0-*", @@ -30,7 +31,7 @@ "System.Text.Encoding.Extensions": "4.0.11-*" }, "imports": [ - "dotnet5.4", + "dotnet5.2", "portable-net451+win8" ] } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index 6bfaeafb67..c8772f21fb 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -22,11 +22,12 @@ }, "net451": { "frameworkAssemblies": { - "System.Runtime": "", - "System.Threading.Tasks": "" + "System.Linq.Expressions": {"type": "build"}, + "System.Threading.Tasks": { "type": "build" } }, "dependencies": { "Moq": "4.2.1312.1622", + "System.Runtime": "4.1.0-*", "xunit.runner.console": "2.1.0" } } From 06c818c9e5d5c3b5225a8dfc5771f43a02ae6727 Mon Sep 17 00:00:00 2001 From: Brice Lambson Date: Thu, 10 Mar 2016 10:29:41 -0800 Subject: [PATCH 0131/1029] Don't reference facades in NuSpec These can be removed entirely after dotnet/cli#164 --- src/Microsoft.AspNetCore.Html.Abstractions/project.json | 4 ++-- src/Microsoft.Extensions.WebEncoders/project.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/project.json b/src/Microsoft.AspNetCore.Html.Abstractions/project.json index 921349d93f..6d2220cabe 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/project.json +++ b/src/Microsoft.AspNetCore.Html.Abstractions/project.json @@ -19,8 +19,8 @@ "frameworks": { "net451": { "frameworkAssemblies": { - "System.IO": "", - "System.Runtime": "" + "System.IO": { "type": "build" }, + "System.Runtime": { "type": "build" } } }, "netstandard1.3": { diff --git a/src/Microsoft.Extensions.WebEncoders/project.json b/src/Microsoft.Extensions.WebEncoders/project.json index 1c0e609f4c..1e24e36926 100644 --- a/src/Microsoft.Extensions.WebEncoders/project.json +++ b/src/Microsoft.Extensions.WebEncoders/project.json @@ -22,8 +22,8 @@ "frameworks": { "net451": { "frameworkAssemblies": { - "System.IO": "", - "System.Runtime": "" + "System.IO": { "type": "build" }, + "System.Runtime": { "type": "build" } } }, "netstandard1.3": { From 0e95ce9a8eda8e8ced4f2af169790b09b703f2a8 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Sat, 12 Mar 2016 08:22:32 -0800 Subject: [PATCH 0132/1029] Target minimal TFMs --- .../project.json | 10 ++-------- src/Microsoft.Extensions.WebEncoders/project.json | 10 ++-------- .../project.json | 5 +++-- .../project.json | 4 ++-- 4 files changed, 9 insertions(+), 20 deletions(-) diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/project.json b/src/Microsoft.AspNetCore.Html.Abstractions/project.json index 6d2220cabe..fc92b6e725 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/project.json +++ b/src/Microsoft.AspNetCore.Html.Abstractions/project.json @@ -17,19 +17,13 @@ "System.Text.Encodings.Web": "4.0.0-*" }, "frameworks": { - "net451": { - "frameworkAssemblies": { - "System.IO": { "type": "build" }, - "System.Runtime": { "type": "build" } - } - }, - "netstandard1.3": { + "netstandard1.0": { "dependencies": { "System.Collections": "4.0.11-*", "System.Resources.ResourceManager": "4.0.1-*" }, "imports": [ - "dotnet5.4" + "dotnet5.1" ] } } diff --git a/src/Microsoft.Extensions.WebEncoders/project.json b/src/Microsoft.Extensions.WebEncoders/project.json index 1e24e36926..5b12e9999c 100644 --- a/src/Microsoft.Extensions.WebEncoders/project.json +++ b/src/Microsoft.Extensions.WebEncoders/project.json @@ -20,15 +20,9 @@ "System.Text.Encodings.Web": "4.0.0-*" }, "frameworks": { - "net451": { - "frameworkAssemblies": { - "System.IO": { "type": "build" }, - "System.Runtime": { "type": "build" } - } - }, - "netstandard1.3": { + "netstandard1.0": { "imports": [ - "dotnet5.4" + "dotnet5.1" ] } } diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index a2b85b5cfe..5115e2741a 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -22,8 +22,9 @@ ] }, "net451": { - "dependencies": { - "xunit.runner.console": "2.1.0" + "frameworkAssemblies": { + "System.IO": { "type": "build" }, + "System.Runtime": { "type": "build" } } } } diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index 0e0c77023b..24fe63d6b1 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -22,8 +22,8 @@ ] }, "net451": { - "dependencies": { - "xunit.runner.console": "2.1.0" + "frameworkAssemblies": { + "System.Runtime": { "type": "build" } } } } From bfe81edbdc29c88a9814fbb939ea465293f960e3 Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Mon, 14 Mar 2016 14:42:18 -0700 Subject: [PATCH 0133/1029] Updated Json.Net version --- src/Microsoft.AspNetCore.JsonPatch/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index abfc19cba3..f4cc9ede98 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -13,7 +13,7 @@ "url": "git://github.com/aspnet/mvc" }, "dependencies": { - "Newtonsoft.Json": "8.0.2" + "Newtonsoft.Json": "8.0.3" }, "frameworks": { "netstandard1.1": { From 10c33445dcc7b0f2d45df8fdc803751d762c7e2e Mon Sep 17 00:00:00 2001 From: Cesar Blum Silveira Date: Mon, 14 Mar 2016 21:37:36 -0700 Subject: [PATCH 0134/1029] ASP.NET 5 -> ASP.NET Core --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c30d38e62f..6c27b76d9d 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,6 @@ AppVeyor: [![AppVeyor](https://ci.appveyor.com/api/projects/status/51gggjks5k3q6 Travis: [![Travis](https://travis-ci.org/aspnet/JsonPatch.svg?branch=dev)](https://travis-ci.org/aspnet/JsonPatch) -This project is part of ASP.NET 5. You can find samples, documentation and getting started instructions for ASP.NET 5 at the [Home](https://github.com/aspnet/home) repo. +This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo. From 66dccd14eab13387b6b0477f6b0184531dbe7149 Mon Sep 17 00:00:00 2001 From: Cesar Blum Silveira Date: Mon, 14 Mar 2016 21:43:50 -0700 Subject: [PATCH 0135/1029] ASP.NET 5 -> ASP.NET Core --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 799d29e1dc..c86577af48 100644 --- a/README.md +++ b/README.md @@ -6,4 +6,4 @@ Travis: [![Travis](https://travis-ci.org/aspnet/HtmlAbstractions.svg?branch=de HTML abstractions such as `IHtmlContent` and related APIs. -This project is part of ASP.NET 5. You can find samples, documentation and getting started instructions for ASP.NET 5 at the [Home](https://github.com/aspnet/home) repo. +This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo. From 73d50bbac381b747de61af1dea68085e764cae4e Mon Sep 17 00:00:00 2001 From: Cesar Blum Silveira Date: Mon, 14 Mar 2016 21:47:24 -0700 Subject: [PATCH 0136/1029] ASP.NET 5 -> ASP.NET Core --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 35eccfd22e..d49bd76306 100644 --- a/README.md +++ b/README.md @@ -30,4 +30,4 @@ AppVeyor: [![AppVeyor](https://ci.appveyor.com/api/projects/status/fxhto3omtehio Travis: [![Travis](https://travis-ci.org/aspnet/dotnet-watch.svg?branch=dev)](https://travis-ci.org/aspnet/dotnet-watch) -This project is part of ASP.NET 5. You can find samples, documentation and getting started instructions for ASP.NET 5 at the [Home](https://github.com/aspnet/home) repo. +This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo. From 4df44c8501889a0a5e83f87b8b0fe5660556b268 Mon Sep 17 00:00:00 2001 From: John Luo Date: Wed, 16 Mar 2016 18:02:59 -0700 Subject: [PATCH 0137/1029] Use KillTree from Common --- .gitignore | 1 + .../Internal/Implementation/ProcessWatcher.cs | 6 +- .../Internal/ProcessExtensions.cs | 113 ------------------ .../project.json | 5 +- .../Scenario/DotNetWatchScenario.cs | 6 +- .../dotnet-watch.FunctionalTests/project.json | 4 + 6 files changed, 13 insertions(+), 122 deletions(-) delete mode 100644 src/Microsoft.DotNet.Watcher.Core/Internal/ProcessExtensions.cs diff --git a/.gitignore b/.gitignore index d9e70ea3c8..79f4ca4258 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,5 @@ project.lock.json .testPublish/ .build/ /.vs/ +testWorkDir/ diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/ProcessWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/ProcessWatcher.cs index 0524284ba2..4fa8872d14 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/ProcessWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/ProcessWatcher.cs @@ -5,14 +5,12 @@ using System; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; -using Microsoft.Extensions.PlatformAbstractions; +using Microsoft.Extensions.Internal; namespace Microsoft.DotNet.Watcher.Core.Internal { public class ProcessWatcher : IProcessWatcher { - private static readonly TimeSpan _processKillTimeout = TimeSpan.FromSeconds(30); - private Process _runningProcess; public int Start(string executable, string arguments, string workingDir) @@ -43,7 +41,7 @@ namespace Microsoft.DotNet.Watcher.Core.Internal { if (_runningProcess != null) { - _runningProcess.KillTree(_processKillTimeout); + _runningProcess.KillTree(); } }); diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/ProcessExtensions.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/ProcessExtensions.cs deleted file mode 100644 index 56744e87c7..0000000000 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/ProcessExtensions.cs +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using Microsoft.Extensions.PlatformAbstractions; - -namespace Microsoft.DotNet.Watcher.Core.Internal -{ - public static class ProcessExtensions - { - private static readonly bool _isWindows = PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows; - - public static void KillTree(this Process process, TimeSpan timeout) - { - string stdout; - if (_isWindows) - { - RunProcessAndWaitForExit( - "taskkill", - $"/T /F /PID {process.Id}", - timeout, - out stdout); - } - else - { - var children = GetAllChildIdsUnix(process, timeout); - foreach (var childId in children) - { - KillProcessUnix(childId, timeout); - } - KillProcessUnix(process.Id, timeout); - } - } - - private static IEnumerable GetAllChildIdsUnix(Process process, TimeSpan timeout) - { - var children = new HashSet(); - GetAllChildIdsUnix(process.Id, children, timeout); - return children; - } - - private static void GetAllChildIdsUnix(int parentId, ISet children, TimeSpan timeout) - { - string stdout; - var exitCode = RunProcessAndWaitForExit( - "pgrep", - $"-P {parentId}", - timeout, - out stdout); - - if (exitCode == 0 && !string.IsNullOrEmpty(stdout)) - { - using (var reader = new StringReader(stdout)) - { - while (true) - { - var text = reader.ReadLine(); - if (text == null) - { - return; - } - - int id; - if (int.TryParse(text, out id)) - { - children.Add(id); - // Recursively get the children - GetAllChildIdsUnix(id, children, timeout); - } - } - } - } - } - - private static void KillProcessUnix(int processId, TimeSpan timeout) - { - string stdout; - RunProcessAndWaitForExit( - "kill", - $"-TERM {processId}", - timeout, - out stdout); - } - - private static int RunProcessAndWaitForExit(string fileName, string arguments, TimeSpan timeout, out string stdout) - { - var startInfo = new ProcessStartInfo - { - FileName = fileName, - Arguments = arguments, - RedirectStandardOutput = true, - UseShellExecute = false - }; - - var process = Process.Start(startInfo); - - stdout = null; - if (process.WaitForExit((int)timeout.TotalMilliseconds)) - { - stdout = process.StandardOutput.ReadToEnd(); - } - else - { - process.Kill(); - } - - return process.ExitCode; - } - } -} diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index a84beb6964..c03102b3bf 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -19,7 +19,10 @@ "Microsoft.Extensions.Logging.Abstractions": "1.0.0-*", "Microsoft.Extensions.FileSystemGlobbing": "1.0.0-*", "Microsoft.NETCore.Platforms": "1.0.1-*", - "System.Diagnostics.Process": "4.1.0-*" + "Microsoft.Extensions.ProcessHelper.Sources": { + "type": "build", + "version": "1.0.0-*" + } }, "frameworks": { "dnxcore50": { diff --git a/test/dotnet-watch.FunctionalTests/Scenario/DotNetWatchScenario.cs b/test/dotnet-watch.FunctionalTests/Scenario/DotNetWatchScenario.cs index ebcdebc00d..f143e8f734 100644 --- a/test/dotnet-watch.FunctionalTests/Scenario/DotNetWatchScenario.cs +++ b/test/dotnet-watch.FunctionalTests/Scenario/DotNetWatchScenario.cs @@ -4,14 +4,12 @@ using System; using System.Diagnostics; using System.IO; -using Microsoft.DotNet.Watcher.Core.Internal; +using Microsoft.Extensions.Internal; namespace Microsoft.DotNet.Watcher.FunctionalTests { public class DotNetWatchScenario : IDisposable { - private static readonly TimeSpan _processKillTimeout = TimeSpan.FromSeconds(30); - protected const string DotnetWatch = "dotnet-watch"; protected static readonly string _repositoryRoot = FindRepoRoot(); @@ -38,7 +36,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests { if (!WatcherProcess.HasExited) { - WatcherProcess.KillTree(_processKillTimeout); + WatcherProcess.KillTree(); } WatcherProcess.Dispose(); } diff --git a/test/dotnet-watch.FunctionalTests/project.json b/test/dotnet-watch.FunctionalTests/project.json index 3e1db01183..ca348c3751 100644 --- a/test/dotnet-watch.FunctionalTests/project.json +++ b/test/dotnet-watch.FunctionalTests/project.json @@ -6,6 +6,10 @@ "dependencies": { "dotnet-test-xunit": "1.0.0-dev-*", "Microsoft.Extensions.DependencyInjection": "1.0.0-*", + "Microsoft.Extensions.ProcessHelper.Sources": { + "type": "build", + "version": "1.0.0-*" + }, "Microsoft.DotNet.Watcher.Core": "1.0.0-*", "Microsoft.NETCore.Platforms": "1.0.1-*", "Newtonsoft.Json": "8.0.2", From 4e396b8443bfc0c73651d25e17791fd0296097c9 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Thu, 17 Mar 2016 14:27:21 -0700 Subject: [PATCH 0138/1029] Remove the makefile --- makefile.shade | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 makefile.shade diff --git a/makefile.shade b/makefile.shade deleted file mode 100644 index c87524a3ef..0000000000 --- a/makefile.shade +++ /dev/null @@ -1,12 +0,0 @@ - -var VERSION='0.1' -var FULL_VERSION='0.1' -var AUTHORS='Microsoft Open Technologies, Inc.' - -use-standard-lifecycle -k-standard-goals - -#xml-docs-test .clean .build-compile description='Check generated XML documentation files for errors' target='package' - k-xml-docs-test - - From 7c1c4df3109b5df1583c8cb5ef98750aac9b95c6 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Thu, 17 Mar 2016 14:31:32 -0700 Subject: [PATCH 0139/1029] Remove the makefile --- makefile.shade | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 makefile.shade diff --git a/makefile.shade b/makefile.shade deleted file mode 100644 index d5e473d558..0000000000 --- a/makefile.shade +++ /dev/null @@ -1,10 +0,0 @@ - -var VERSION='0.1' -var FULL_VERSION='0.1' -var AUTHORS='Microsoft Open Technologies, Inc.' - -use-standard-lifecycle -k-standard-goals - -#xml-docs-test .clean .build-compile description='Check generated XML documentation files for errors' target='package' - k-xml-docs-test From 73217edba52fae43c254334aa8802f5b3e52c09f Mon Sep 17 00:00:00 2001 From: John Luo Date: Thu, 17 Mar 2016 16:36:27 -0700 Subject: [PATCH 0140/1029] Update package name --- src/Microsoft.DotNet.Watcher.Core/project.json | 2 +- test/dotnet-watch.FunctionalTests/project.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index c03102b3bf..3c344f0f8e 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -19,7 +19,7 @@ "Microsoft.Extensions.Logging.Abstractions": "1.0.0-*", "Microsoft.Extensions.FileSystemGlobbing": "1.0.0-*", "Microsoft.NETCore.Platforms": "1.0.1-*", - "Microsoft.Extensions.ProcessHelper.Sources": { + "Microsoft.Extensions.Process.Sources": { "type": "build", "version": "1.0.0-*" } diff --git a/test/dotnet-watch.FunctionalTests/project.json b/test/dotnet-watch.FunctionalTests/project.json index ca348c3751..4c2596fffb 100644 --- a/test/dotnet-watch.FunctionalTests/project.json +++ b/test/dotnet-watch.FunctionalTests/project.json @@ -6,7 +6,7 @@ "dependencies": { "dotnet-test-xunit": "1.0.0-dev-*", "Microsoft.Extensions.DependencyInjection": "1.0.0-*", - "Microsoft.Extensions.ProcessHelper.Sources": { + "Microsoft.Extensions.Process.Sources": { "type": "build", "version": "1.0.0-*" }, From b5e2d43859132f5a629985951e7e7223ba6b460a Mon Sep 17 00:00:00 2001 From: Pranav K Date: Sat, 19 Mar 2016 12:10:40 -0700 Subject: [PATCH 0141/1029] Retarget tests to netstandardapp --- test/dotnet-watch.FunctionalTests/project.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/dotnet-watch.FunctionalTests/project.json b/test/dotnet-watch.FunctionalTests/project.json index 4c2596fffb..9cdb912244 100644 --- a/test/dotnet-watch.FunctionalTests/project.json +++ b/test/dotnet-watch.FunctionalTests/project.json @@ -16,8 +16,11 @@ "xunit": "2.1.0" }, "frameworks": { - "dnxcore50": { - "imports": "portable-net451+win8" + "netstandardapp1.5": { + "imports": [ + "portable-net451+win8", + "dnxcore50" + ] } }, "testRunner": "xunit" From f75ce04c4cfa72aedc50f2458636f95bfa820ff7 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Sat, 19 Mar 2016 12:41:52 -0700 Subject: [PATCH 0142/1029] Reacting to CoreCLR package changes --- test/dotnet-watch.FunctionalTests/project.json | 1 + 1 file changed, 1 insertion(+) diff --git a/test/dotnet-watch.FunctionalTests/project.json b/test/dotnet-watch.FunctionalTests/project.json index 9cdb912244..918e86fcb1 100644 --- a/test/dotnet-watch.FunctionalTests/project.json +++ b/test/dotnet-watch.FunctionalTests/project.json @@ -13,6 +13,7 @@ "Microsoft.DotNet.Watcher.Core": "1.0.0-*", "Microsoft.NETCore.Platforms": "1.0.1-*", "Newtonsoft.Json": "8.0.2", + "System.Threading": "4.0.11-*", "xunit": "2.1.0" }, "frameworks": { From 0e69fc2b17dfdb54464428b282d93e299440f107 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Sat, 19 Mar 2016 12:56:35 -0700 Subject: [PATCH 0143/1029] Reacting to CoreCLR package changes --- test/dotnet-watch.FunctionalTests/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/dotnet-watch.FunctionalTests/project.json b/test/dotnet-watch.FunctionalTests/project.json index 918e86fcb1..792bf09599 100644 --- a/test/dotnet-watch.FunctionalTests/project.json +++ b/test/dotnet-watch.FunctionalTests/project.json @@ -13,7 +13,7 @@ "Microsoft.DotNet.Watcher.Core": "1.0.0-*", "Microsoft.NETCore.Platforms": "1.0.1-*", "Newtonsoft.Json": "8.0.2", - "System.Threading": "4.0.11-*", + "System.Threading.Thread": "4.0.0-*", "xunit": "2.1.0" }, "frameworks": { From 70c0254dc26ec7659b51cf7244324a79f311922f Mon Sep 17 00:00:00 2001 From: David Fowler Date: Fri, 25 Mar 2016 01:48:01 -0700 Subject: [PATCH 0144/1029] Fixed build --- .../Microsoft.AspNetCore.Html.Abstractions.Test/project.json | 5 +++-- test/Microsoft.Extensions.WebEncoders.Tests/project.json | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index 5115e2741a..0b423932f0 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -7,14 +7,15 @@ "Microsoft.AspNetCore.Html.Abstractions": "1.0.0-*", "Microsoft.AspNetCore.Testing": "1.0.0-*", "Microsoft.Extensions.WebEncoders": "1.0.0-*", - "Microsoft.NETCore.Platforms": "1.0.1-*", "xunit": "2.1.0" }, "testRunner": "xunit", "frameworks": { "netstandardapp1.5": { "dependencies": { - "dotnet-test-xunit": "1.0.0-dev-*" + "dotnet-test-xunit": "1.0.0-dev-*", + "NETStandard.Library": "1.5.0-*", + "System.Diagnostics.Process": "4.1.0-*" }, "imports": [ "dnxcore50", diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index 24fe63d6b1..ab7264c378 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -2,7 +2,6 @@ "dependencies": { "Microsoft.Extensions.DependencyInjection": "1.0.0-*", "Microsoft.Extensions.WebEncoders": "1.0.0-*", - "Microsoft.NETCore.Platforms": "1.0.1-*", "xunit": "2.1.0" }, "testRunner": "xunit", @@ -14,7 +13,9 @@ "frameworks": { "netstandardapp1.5": { "dependencies": { - "dotnet-test-xunit": "1.0.0-dev-*" + "dotnet-test-xunit": "1.0.0-dev-*", + "NETStandard.Library": "1.5.0-*", + "System.Diagnostics.Process": "4.1.0-*" }, "imports": [ "dnxcore50", From 8965b63ec107fff486b46a03b4de4274be2f83dc Mon Sep 17 00:00:00 2001 From: David Fowler Date: Fri, 25 Mar 2016 02:02:41 -0700 Subject: [PATCH 0145/1029] Fixed build --- test/Microsoft.AspNetCore.JsonPatch.Test/project.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index c8772f21fb..72fdfa43b4 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -5,15 +5,16 @@ "dependencies": { "Microsoft.AspNetCore.JsonPatch": "1.0.0-*", "Microsoft.AspNetCore.Testing": "1.0.0-*", - "xunit": "2.1.0", - "Microsoft.NETCore.Platforms": "1.0.1-*" + "xunit": "2.1.0" }, "testRunner": "xunit", "frameworks": { "netstandardapp1.5": { "dependencies": { "moq.netcore": "4.4.0-beta8", - "dotnet-test-xunit": "1.0.0-dev-*" + "dotnet-test-xunit": "1.0.0-dev-*", + "NETStandard.Library": "1.5.0-*", + "System.Diagnostics.Process": "4.1.0-*" }, "imports": [ "dnxcore50", From 98e2d5d4c729770e5e8e146602ab2b6c5bdc439a Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 24 Mar 2016 12:59:08 -0700 Subject: [PATCH 0146/1029] Fix dotnet restore warning --- test/Microsoft.AspNetCore.JsonPatch.Test/project.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index 72fdfa43b4..4dcf2002cf 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -23,12 +23,12 @@ }, "net451": { "frameworkAssemblies": { - "System.Linq.Expressions": {"type": "build"}, + "System.Linq.Expressions": { "type": "build" }, + "System.Runtime": { "type": "build" }, "System.Threading.Tasks": { "type": "build" } }, "dependencies": { "Moq": "4.2.1312.1622", - "System.Runtime": "4.1.0-*", "xunit.runner.console": "2.1.0" } } From fd10621c1a3e03ae1770a4f381395b452d5c0a24 Mon Sep 17 00:00:00 2001 From: ryanbrandenburg Date: Fri, 25 Mar 2016 11:07:12 -0700 Subject: [PATCH 0147/1029] SetContent->SetHtmlContent --- .../HtmlContentBuilderExtensions.cs | 2 +- .../HtmlContentBuilderExtensionsTest.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilderExtensions.cs b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilderExtensions.cs index aaba4faefb..439b746a55 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilderExtensions.cs @@ -189,7 +189,7 @@ namespace Microsoft.AspNetCore.Html /// The . /// The value that replaces the content. /// The . - public static IHtmlContentBuilder SetContent(this IHtmlContentBuilder builder, IHtmlContent content) + public static IHtmlContentBuilder SetHtmlContent(this IHtmlContentBuilder builder, IHtmlContent content) { if (builder == null) { diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs b/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs index 08151b3675..b985c51890 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs @@ -104,7 +104,7 @@ namespace Microsoft.AspNetCore.Html.Test var content = new OtherHtmlContent("Hi"); // Act - builder.SetContent(content); + builder.SetHtmlContent(content); // Assert Assert.Collection( From c5d5ef6788a895627ef25e46129c0b2783d97722 Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Sat, 26 Mar 2016 15:00:56 -0700 Subject: [PATCH 0148/1029] Fix package metadata --- README.md | 2 +- src/Microsoft.AspNetCore.Html.Abstractions/project.json | 5 ++++- src/Microsoft.Extensions.WebEncoders/project.json | 5 ++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c86577af48..9939efe5b9 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,6 @@ AppVeyor: [![AppVeyor](https://ci.appveyor.com/api/projects/status/cu9y78vsdp19e Travis: [![Travis](https://travis-ci.org/aspnet/HtmlAbstractions.svg?branch=dev)](https://travis-ci.org/aspnet/HtmlAbstractions) -HTML abstractions such as `IHtmlContent` and related APIs. +HTML abstractions used for building HTML content, including types such as `HtmlEncodedString` and `IHtmlContent`. This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo. diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/project.json b/src/Microsoft.AspNetCore.Html.Abstractions/project.json index fc92b6e725..500041c2ed 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/project.json +++ b/src/Microsoft.AspNetCore.Html.Abstractions/project.json @@ -1,6 +1,9 @@ { "version": "1.0.0-*", - "description": "ASP.NET 5 HTML content interface.", + "description": "ASP.NET Core HTML abstractions used for building HTML content.\r\nCommonly used types:\r\nMicrosoft.AspNetCore.Html.HtmlEncodedString\r\nMicrosoft.AspNetCore.Html.IHtmlContent", + "tags": [ + "aspnetcore" + ], "repository": { "type": "git", "url": "git://github.com/aspnet/htmlabstractions" diff --git a/src/Microsoft.Extensions.WebEncoders/project.json b/src/Microsoft.Extensions.WebEncoders/project.json index 5b12e9999c..70be4220b9 100644 --- a/src/Microsoft.Extensions.WebEncoders/project.json +++ b/src/Microsoft.Extensions.WebEncoders/project.json @@ -1,6 +1,9 @@ { "version": "1.0.0-*", - "description": "Contains registration and configuration APIs for the core framework encoders.", + "description": "Contains registration and configuration APIs to add the core framework encoders to a dependency injection container.", + "tags": [ + "aspnetcore" + ], "repository": { "type": "git", "url": "git://github.com/aspnet/httpabstractions" From 794d0892ae6975014d3bfb393c9d7646511d81bc Mon Sep 17 00:00:00 2001 From: jacalvar Date: Mon, 28 Mar 2016 15:26:49 -0700 Subject: [PATCH 0149/1029] Return IServiceCollection from AddWebEncoders extension methods --- .../EncoderServiceCollectionExtensions.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.Extensions.WebEncoders/EncoderServiceCollectionExtensions.cs b/src/Microsoft.Extensions.WebEncoders/EncoderServiceCollectionExtensions.cs index 317d88f99d..72f5e369a1 100644 --- a/src/Microsoft.Extensions.WebEncoders/EncoderServiceCollectionExtensions.cs +++ b/src/Microsoft.Extensions.WebEncoders/EncoderServiceCollectionExtensions.cs @@ -19,8 +19,8 @@ namespace Microsoft.Extensions.DependencyInjection /// to the specified . /// /// The . - /// The instance after the encoders have been added. - public static void AddWebEncoders(this IServiceCollection services) + /// The so that additional calls can be chained. + public static IServiceCollection AddWebEncoders(this IServiceCollection services) { if (services == null) { @@ -37,6 +37,8 @@ namespace Microsoft.Extensions.DependencyInjection CreateFactory(() => JavaScriptEncoder.Default, settings => JavaScriptEncoder.Create(settings))); services.TryAddSingleton( CreateFactory(() => UrlEncoder.Default, settings => UrlEncoder.Create(settings))); + + return services; } /// @@ -45,7 +47,8 @@ namespace Microsoft.Extensions.DependencyInjection /// /// The . /// An to configure the provided . - public static void AddWebEncoders(this IServiceCollection services, Action setupAction) + /// The so that additional calls can be chained. + public static IServiceCollection AddWebEncoders(this IServiceCollection services, Action setupAction) { if (services == null) { @@ -59,6 +62,8 @@ namespace Microsoft.Extensions.DependencyInjection services.AddWebEncoders(); services.Configure(setupAction); + + return services; } private static Func CreateFactory( From 182cbc276cd742224feaa57f165613ffe89bc9db Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Wed, 30 Mar 2016 15:06:20 -0700 Subject: [PATCH 0150/1029] Webhooks notification --- .travis.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 304e307169..fe831028c8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,4 +23,10 @@ branches: - dev - /^(.*\/)?ci-.*$/ script: - - ./build.sh --quiet verify \ No newline at end of file + - ./build.sh --quiet verify +notifications: + webhooks: + secure: "dhjfYLtihxx3zDdj0TLMJjiN4YJ37Qu0L9ySx7ek+YsfOAqKPHUsI6JNDtChauQxUB2NoL/i80+47oHhMelPyXniu1xA0MWaHV8bddZHzNQs1N8vGjjPmtbC5DQ7jmy+p7Xa5+ZscZ9NWEvJRqBInNdqugDAstDEIWbC35bq8H9t+6tZYu1sJctp1zF/k/w4OjJUoI1ZNLuusYIB1E+G/irvVT2x4GOC2QY3wXM4lJ2ORcZE9NgUBLNx/Hy5Rst5i4zO/mrFkYM/wOY6bAM6/gjjanK+d1wQnD9HuZH1ZVQqJRH3lveurYq9ih4zxV8MbW3FdLL1cXswEZbUBeqHlxVE32KwWF18nFUwdmrNQebnYnrZ/VWsa4pl+bOFNy2nomI3ibJ4F4+RwqTPXXE13qCr0CsC5RKu5bVQTpi0t4CKlUMsVlevN2jJcmAA641bnETNTDwk5WdT7Mjf9Pnn+krLZ7im9li3Plc/d8ynR1oiRzwFdp3u/9m3Oc8K+zMsNO5IOxHul9WsWbIkh3sNecqKHPSyVHB4FgdUoQ65xpc0887YKorbuBTOnlZugP8M/FmowkcwLo5xDD7kchkxyq9X8dPjej+tzpTsNVJjrOg4LP+nKxmOa+qc1r62eF0GdnIjwU30y6NdfvBCXoQJE1y063/zyGPIxSfCRmVzq4A=" + on_success: always + on_failure: always + on_start: always \ No newline at end of file From 5e2ef6051955e73e2c86c4436e581bc650123d68 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Wed, 30 Mar 2016 15:40:25 -0700 Subject: [PATCH 0151/1029] Webhooks notification --- .travis.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 304e307169..dae036065b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,4 +23,10 @@ branches: - dev - /^(.*\/)?ci-.*$/ script: - - ./build.sh --quiet verify \ No newline at end of file + - ./build.sh --quiet verify +notifications: + webhooks: + secure: "d87o+y2WUx204s8TfSaEuekYudnSyyPaFEXkuzgs3uAyzkKAm/Hx0xcMSuKDqWhYmKaxL7VtgEd2z7mltr2cHZ4oyCrsf6V5v4iI48ojaGykqFXfv8ld6khmLwtdkC32lF2YyuDNL8kUvKNdP9jkrWlpoO/WC6QEqAUxdOuuLo/wLyfrPLbzIvbojwveXbmcwvsfDizLdZdVd88FZSV41h+yBKLnyhpeqRvHG85BTgT/GmVB7Vyjs3yChiS639Aq5DoOP8jBaRdB8Bqs09KibFXzJwDBlKvALIqiwzog3hpd5SVxrgOTCkWbOwqq4TSkahDE425W3vFbmLDANgdfsyAkqgt8daE2BkFTojEHQED+u9CEd8oJVX6FoGnYpuDzge4FVh9iG3HSuKwoVdlONzzew4oJ75iQ+0f67ZNV9oDuScdva/SGb2gYgVUkeJIjDoMxKuaZyhbBT9jRXRBI+LsIjziEhLU/649FjTSmQx0HLpcT7+kaeSmhqT9JffVLidMdvZwhPZsLxPSG9UVBH9G8rdyHXP2e0ZlicHNjjNV6kbDqfDPhHx2/MfZGugsJXjOONKu/5LZduQzmAOysqdLKqkBVkMq2xl7aGV+yVZAtTmZB3nqOWGyKlFC9kLGO+qlJ4tBac26lHCZWTK+4VOAtN5Dag0DkDikgGdZaq78=" + on_success: always + on_failure: always + on_start: always \ No newline at end of file From 7eb34ad25775f0c5d0c4f1055954d2429ad7ef57 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Thu, 31 Mar 2016 12:08:59 -0700 Subject: [PATCH 0152/1029] Update project.json Fixed System.Runtime.Serialization.Primitives version --- src/Microsoft.AspNetCore.JsonPatch/project.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index f4cc9ede98..9749ef91a1 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -27,7 +27,7 @@ "System.Reflection.Extensions": "4.0.1-*", "System.Resources.ResourceManager": "4.0.1-*", "System.Runtime.Extensions": "4.1.0-*", - "System.Runtime.Serialization.Primitives": "4.1.0-*", + "System.Runtime.Serialization.Primitives": "4.1.1-*", "System.Text.Encoding.Extensions": "4.0.11-*" }, "imports": [ @@ -36,4 +36,4 @@ ] } } -} \ No newline at end of file +} From 4788506b57c736c7d54f4c05fd2c3b1cbe620a10 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 1 Apr 2016 06:41:43 -0700 Subject: [PATCH 0153/1029] Reacting to CLI breaking change --- .../Internal/Implementation/Project.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs index 655308066e..4d5c2c31db 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs @@ -26,7 +26,7 @@ namespace Microsoft.DotNet.Watcher.Core.Internal if (File.Exists(projectLockJsonPath)) { - var lockFile = LockFileReader.Read(projectLockJsonPath); + var lockFile = LockFileReader.Read(projectLockJsonPath, designTime: false); ProjectDependencies = lockFile.ProjectLibraries.Select(dep => GetProjectRelativeFullPath(dep.Path)).ToList(); } else From 4ddf7c2cc79f6f37b38a6e339fc6e2496a84f8f2 Mon Sep 17 00:00:00 2001 From: BrennanConroy Date: Fri, 1 Apr 2016 11:11:09 -0700 Subject: [PATCH 0154/1029] React to Logging changes --- src/dotnet-watch/CommandOutputLogger.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotnet-watch/CommandOutputLogger.cs b/src/dotnet-watch/CommandOutputLogger.cs index 673f7ee8d8..aeb90f45c2 100644 --- a/src/dotnet-watch/CommandOutputLogger.cs +++ b/src/dotnet-watch/CommandOutputLogger.cs @@ -23,7 +23,7 @@ namespace Microsoft.DotNet.Watcher _loggerName = loggerName; } - public IDisposable BeginScopeImpl(object state) + public IDisposable BeginScope(TState state) { throw new NotImplementedException(); } From e74665e55058c79becda81baa4055d1c78d5ae2b Mon Sep 17 00:00:00 2001 From: ryanbrandenburg Date: Fri, 1 Apr 2016 16:05:28 -0700 Subject: [PATCH 0155/1029] Revert "Reacting to CLI breaking change" This reverts commit 4788506b57c736c7d54f4c05fd2c3b1cbe620a10. --- .../Internal/Implementation/Project.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs index 4d5c2c31db..655308066e 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs @@ -26,7 +26,7 @@ namespace Microsoft.DotNet.Watcher.Core.Internal if (File.Exists(projectLockJsonPath)) { - var lockFile = LockFileReader.Read(projectLockJsonPath, designTime: false); + var lockFile = LockFileReader.Read(projectLockJsonPath); ProjectDependencies = lockFile.ProjectLibraries.Select(dep => GetProjectRelativeFullPath(dep.Path)).ToList(); } else From d1c52323f2134dc0f51eb3a9f251d9f9383bb0ec Mon Sep 17 00:00:00 2001 From: Pranav K Date: Sat, 2 Apr 2016 05:50:03 -0700 Subject: [PATCH 0156/1029] Revert "Revert "Reacting to CLI breaking change"" This reverts commit e74665e55058c79becda81baa4055d1c78d5ae2b. --- .../Internal/Implementation/Project.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs index 655308066e..4d5c2c31db 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs @@ -26,7 +26,7 @@ namespace Microsoft.DotNet.Watcher.Core.Internal if (File.Exists(projectLockJsonPath)) { - var lockFile = LockFileReader.Read(projectLockJsonPath); + var lockFile = LockFileReader.Read(projectLockJsonPath, designTime: false); ProjectDependencies = lockFile.ProjectLibraries.Select(dep => GetProjectRelativeFullPath(dep.Path)).ToList(); } else From 1de783c26bf158d0005a1328c265961f5efcdeb9 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 6 Apr 2016 09:45:27 -0700 Subject: [PATCH 0157/1029] Updating to release. --- NuGet.config | 4 ++-- build.ps1 | 2 +- build.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/NuGet.config b/NuGet.config index 5500f6d507..71b9724a09 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + - + diff --git a/build.ps1 b/build.ps1 index 8f2f99691a..cf8bff13bb 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/release.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index f4208100eb..f88fe4052e 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/release.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi From 62d452abebcddffd372919755122477c1ed423e1 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 6 Apr 2016 09:45:59 -0700 Subject: [PATCH 0158/1029] Updating to release. --- NuGet.config | 2 +- build.ps1 | 2 +- build.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NuGet.config b/NuGet.config index 52bf414192..71b9724a09 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + diff --git a/build.ps1 b/build.ps1 index 8f2f99691a..cf8bff13bb 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/release.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index f4208100eb..f88fe4052e 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/release.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi From ffaf2c8b23aa22708c28b58916a179db16883df1 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 6 Apr 2016 09:46:06 -0700 Subject: [PATCH 0159/1029] Updating to release. --- NuGet.config | 4 ++-- build.ps1 | 2 +- build.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/NuGet.config b/NuGet.config index 03704957e8..9db87a421e 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + - + \ No newline at end of file diff --git a/build.ps1 b/build.ps1 index 8f2f99691a..cf8bff13bb 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/release.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index f4208100eb..f88fe4052e 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/release.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi From 09434e56256f1cfc4d07c4a2f579ba946c86cde2 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Wed, 6 Apr 2016 09:33:55 -0700 Subject: [PATCH 0160/1029] Remove unused dependencies --- src/Microsoft.DotNet.Watcher.Core/project.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index 3c344f0f8e..9b7d46268e 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -11,11 +11,6 @@ "Microsoft.Extensions.FileProviders.Abstractions": "1.0.0-*", "Microsoft.Extensions.FileProviders.Physical": "1.0.0-*", "Microsoft.Extensions.PlatformAbstractions": "1.0.0-*", - "Microsoft.Extensions.CompilationAbstractions": "1.0.0-*", - "Microsoft.Extensions.JsonParser.Sources": { - "type": "build", - "version": "1.0.0-*" - }, "Microsoft.Extensions.Logging.Abstractions": "1.0.0-*", "Microsoft.Extensions.FileSystemGlobbing": "1.0.0-*", "Microsoft.NETCore.Platforms": "1.0.1-*", From aa2b72636321fab965a94c11c79ccd64705848eb Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Wed, 6 Apr 2016 15:09:59 -0700 Subject: [PATCH 0161/1029] Remove unused dependencies --- src/Microsoft.DotNet.Watcher.Core/project.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index 3c344f0f8e..9b7d46268e 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -11,11 +11,6 @@ "Microsoft.Extensions.FileProviders.Abstractions": "1.0.0-*", "Microsoft.Extensions.FileProviders.Physical": "1.0.0-*", "Microsoft.Extensions.PlatformAbstractions": "1.0.0-*", - "Microsoft.Extensions.CompilationAbstractions": "1.0.0-*", - "Microsoft.Extensions.JsonParser.Sources": { - "type": "build", - "version": "1.0.0-*" - }, "Microsoft.Extensions.Logging.Abstractions": "1.0.0-*", "Microsoft.Extensions.FileSystemGlobbing": "1.0.0-*", "Microsoft.NETCore.Platforms": "1.0.1-*", From 89c9c3260b2cbc8fe40c5cceb63a411a7c62b3b8 Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Wed, 6 Apr 2016 13:46:26 -0700 Subject: [PATCH 0162/1029] Make HtmlFormattableString public We've had this class for a while backing the implementation of the AppendFormat extension method. Making this public so we can use it in MVC in localization. Some updates to the API surface and name to be aligned with System.FormattableString --- .../HtmlContentBuilderExtensions.cs | 146 +----------- .../HtmlFormattableString.cs | 184 +++++++++++++++ .../HtmlFormattableStringTest.cs | 217 ++++++++++++++++++ 3 files changed, 403 insertions(+), 144 deletions(-) create mode 100644 src/Microsoft.AspNetCore.Html.Abstractions/HtmlFormattableString.cs create mode 100644 test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlFormattableStringTest.cs diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilderExtensions.cs b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilderExtensions.cs index 439b746a55..f7474ca3f2 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilderExtensions.cs @@ -48,7 +48,7 @@ namespace Microsoft.AspNetCore.Html throw new ArgumentNullException(nameof(args)); } - builder.AppendHtml(new HtmlFormatString(format, args)); + builder.AppendHtml(new HtmlFormattableString(format, args)); return builder; } @@ -88,7 +88,7 @@ namespace Microsoft.AspNetCore.Html throw new ArgumentNullException(nameof(args)); } - builder.AppendHtml(new HtmlFormatString(formatProvider, format, args)); + builder.AppendHtml(new HtmlFormattableString(formatProvider, format, args)); return builder; } @@ -219,147 +219,5 @@ namespace Microsoft.AspNetCore.Html builder.AppendHtml(encoded); return builder; } - - [DebuggerDisplay("{DebuggerToString()}")] - private class HtmlFormatString : IHtmlContent - { - private readonly IFormatProvider _formatProvider; - private readonly string _format; - private readonly object[] _args; - - public HtmlFormatString(string format, object[] args) - : this(null, format, args) - { - } - - public HtmlFormatString(IFormatProvider formatProvider, string format, object[] args) - { - Debug.Assert(format != null); - Debug.Assert(args != null); - - _formatProvider = formatProvider ?? CultureInfo.CurrentCulture; - _format = format; - _args = args; - } - - public void WriteTo(TextWriter writer, HtmlEncoder encoder) - { - if (writer == null) - { - throw new ArgumentNullException(nameof(writer)); - } - - if (encoder == null) - { - throw new ArgumentNullException(nameof(encoder)); - } - - var formatProvider = new EncodingFormatProvider(_formatProvider, encoder); - writer.Write(string.Format(formatProvider, _format, _args)); - } - - private string DebuggerToString() - { - using (var writer = new StringWriter()) - { - WriteTo(writer, HtmlEncoder.Default); - return writer.ToString(); - } - } - } - - // This class implements Html encoding via an ICustomFormatter. Passing an instance of this - // class into a string.Format method or anything similar will evaluate arguments implementing - // IHtmlContent without HTML encoding them, and will give other arguments the standard - // composite format string treatment, and then HTML encode the result. - // - // Plenty of examples of ICustomFormatter and the interactions with string.Format here: - // https://msdn.microsoft.com/en-us/library/system.string.format(v=vs.110).aspx#Format6_Example - private class EncodingFormatProvider : IFormatProvider, ICustomFormatter - { - private readonly HtmlEncoder _encoder; - private readonly IFormatProvider _formatProvider; - - public EncodingFormatProvider(IFormatProvider formatProvider, HtmlEncoder encoder) - { - Debug.Assert(formatProvider != null); - Debug.Assert(encoder != null); - - _formatProvider = formatProvider; - _encoder = encoder; - } - - public string Format(string format, object arg, IFormatProvider formatProvider) - { - // These are the cases we need to special case. We trust the HtmlEncodedString or IHtmlContent instance - // to do the right thing with encoding. - var htmlString = arg as HtmlEncodedString; - if (htmlString != null) - { - return htmlString.ToString(); - } - - var htmlContent = arg as IHtmlContent; - if (htmlContent != null) - { - using (var writer = new StringWriter()) - { - htmlContent.WriteTo(writer, _encoder); - return writer.ToString(); - } - } - - // If we get here then 'arg' is not an IHtmlContent, and we want to handle it the way a normal - // string.Format would work, but then HTML encode the result. - // - // First check for an ICustomFormatter - if the IFormatProvider is a CultureInfo, then it's likely - // that ICustomFormatter will be null. - var customFormatter = (ICustomFormatter)_formatProvider.GetFormat(typeof(ICustomFormatter)); - if (customFormatter != null) - { - var result = customFormatter.Format(format, arg, _formatProvider); - if (result != null) - { - return _encoder.Encode(result); - } - } - - // Next check if 'arg' is an IFormattable (DateTime is an example). - // - // An IFormattable will likely call back into the IFormatterProvider and ask for more information - // about how to format itself. This is the typical case when IFormatterProvider is a CultureInfo. - var formattable = arg as IFormattable; - if (formattable != null) - { - var result = formattable.ToString(format, _formatProvider); - if (result != null) - { - return _encoder.Encode(result); - } - } - - // If we get here then there's nothing really smart left to try. - if (arg != null) - { - var result = arg.ToString(); - if (result != null) - { - return _encoder.Encode(result); - } - } - - return string.Empty; - } - - public object GetFormat(Type formatType) - { - if (formatType == typeof(ICustomFormatter)) - { - return this; - } - - return null; - } - } } } diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlFormattableString.cs b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlFormattableString.cs new file mode 100644 index 0000000000..82e9b69d98 --- /dev/null +++ b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlFormattableString.cs @@ -0,0 +1,184 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Text.Encodings.Web; + +namespace Microsoft.AspNetCore.Html +{ + /// + /// An implementation of composite string formatting + /// (see https://msdn.microsoft.com/en-us/library/txafckwd(v=vs.110).aspx) which HTML encodes + /// formatted arguments. + /// + [DebuggerDisplay("{DebuggerToString()}")] + public class HtmlFormattableString : IHtmlContent + { + private readonly IFormatProvider _formatProvider; + private readonly string _format; + private readonly object[] _args; + + /// + /// Creates a new with the given and + /// . + /// + /// A composite format string. + /// An array that contains objects to format. + public HtmlFormattableString(string format, params object[] args) + : this(formatProvider: null, format: format, args: args) + { + } + + /// + /// Creates a new with the given , + /// and . + /// + /// An object that provides culture-specific formatting information. + /// A composite format string. + /// An array that contains objects to format. + public HtmlFormattableString(IFormatProvider formatProvider, string format, params object[] args) + { + if (format == null) + { + throw new ArgumentNullException(nameof(format)); + } + + if (args == null) + { + throw new ArgumentNullException(nameof(args)); + } + + _formatProvider = formatProvider ?? CultureInfo.CurrentCulture; + _format = format; + _args = args; + } + + /// + public void WriteTo(TextWriter writer, HtmlEncoder encoder) + { + if (writer == null) + { + throw new ArgumentNullException(nameof(writer)); + } + + if (encoder == null) + { + throw new ArgumentNullException(nameof(encoder)); + } + + var formatProvider = new EncodingFormatProvider(_formatProvider, encoder); + writer.Write(string.Format(formatProvider, _format, _args)); + } + + private string DebuggerToString() + { + using (var writer = new StringWriter()) + { + WriteTo(writer, HtmlEncoder.Default); + return writer.ToString(); + } + } + + // This class implements Html encoding via an ICustomFormatter. Passing an instance of this + // class into a string.Format method or anything similar will evaluate arguments implementing + // IHtmlContent without HTML encoding them, and will give other arguments the standard + // composite format string treatment, and then HTML encode the result. + // + // Plenty of examples of ICustomFormatter and the interactions with string.Format here: + // https://msdn.microsoft.com/en-us/library/system.string.format(v=vs.110).aspx#Format6_Example + private class EncodingFormatProvider : IFormatProvider, ICustomFormatter + { + private readonly HtmlEncoder _encoder; + private readonly IFormatProvider _formatProvider; + + private StringWriter _writer; + + public EncodingFormatProvider(IFormatProvider formatProvider, HtmlEncoder encoder) + { + Debug.Assert(formatProvider != null); + Debug.Assert(encoder != null); + + _formatProvider = formatProvider; + _encoder = encoder; + } + + public string Format(string format, object arg, IFormatProvider formatProvider) + { + // These are the cases we need to special case. We trust the HtmlEncodedString or IHtmlContent instance + // to do the right thing with encoding. + var htmlString = arg as HtmlEncodedString; + if (htmlString != null) + { + return htmlString.ToString(); + } + + var htmlContent = arg as IHtmlContent; + if (htmlContent != null) + { + _writer = _writer ?? new StringWriter(); + + htmlContent.WriteTo(_writer, _encoder); + + var result = _writer.ToString(); + _writer.GetStringBuilder().Clear(); + + return result; + } + + // If we get here then 'arg' is not an IHtmlContent, and we want to handle it the way a normal + // string.Format would work, but then HTML encode the result. + // + // First check for an ICustomFormatter - if the IFormatProvider is a CultureInfo, then it's likely + // that ICustomFormatter will be null. + var customFormatter = (ICustomFormatter)_formatProvider.GetFormat(typeof(ICustomFormatter)); + if (customFormatter != null) + { + var result = customFormatter.Format(format, arg, _formatProvider); + if (result != null) + { + return _encoder.Encode(result); + } + } + + // Next check if 'arg' is an IFormattable (DateTime is an example). + // + // An IFormattable will likely call back into the IFormatterProvider and ask for more information + // about how to format itself. This is the typical case when IFormatterProvider is a CultureInfo. + var formattable = arg as IFormattable; + if (formattable != null) + { + var result = formattable.ToString(format, _formatProvider); + if (result != null) + { + return _encoder.Encode(result); + } + } + + // If we get here then there's nothing really smart left to try. + if (arg != null) + { + var result = arg.ToString(); + if (result != null) + { + return _encoder.Encode(result); + } + } + + return string.Empty; + } + + public object GetFormat(Type formatType) + { + if (formatType == typeof(ICustomFormatter)) + { + return this; + } + + return null; + } + } + } +} diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlFormattableStringTest.cs b/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlFormattableStringTest.cs new file mode 100644 index 0000000000..6f466e6046 --- /dev/null +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlFormattableStringTest.cs @@ -0,0 +1,217 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Globalization; +using System.IO; +using Microsoft.AspNetCore.Testing; +using Microsoft.Extensions.WebEncoders.Testing; +using Xunit; + +namespace Microsoft.AspNetCore.Html +{ + public class HtmlFormattableStringTest + { + [Fact] + public void HtmlFormattableString_EmptyArgs() + { + // Arrange + var formattableString = new HtmlFormattableString("Hello, World!"); + + // Act + var result = HtmlContentToString(formattableString); + + // Assert + Assert.Equal("Hello, World!", result); + } + + [Fact] + public void HtmlFormattableString_EmptyArgsAndCulture() + { + // Arrange + var formattableString = new HtmlFormattableString(CultureInfo.CurrentCulture, "Hello, World!"); + + // Act + var result = HtmlContentToString(formattableString); + + // Assert + Assert.Equal("Hello, World!", result); + } + + [Fact] + public void HtmlFormattableString_MultipleArguments() + { + // Arrange + var formattableString = new HtmlFormattableString("{0} {1} {2} {3}!", "First", "Second", "Third", "Fourth"); + + // Act + var result = HtmlContentToString(formattableString); + + // Assert + Assert.Equal( + "HtmlEncode[[First]] HtmlEncode[[Second]] HtmlEncode[[Third]] HtmlEncode[[Fourth]]!", + result); + } + + [Fact] + public void HtmlFormattableString_WithHtmlEncodedString() + { + // Arrange + var formattableString = new HtmlFormattableString("{0}!", new HtmlEncodedString("First")); + + // Act + var result = HtmlContentToString(formattableString); + + // Assert + Assert.Equal("First!", result); + } + + [Fact] + public void HtmlFormattableString_WithOtherIHtmlContent() + { + // Arrange + var builder = new HtmlContentBuilder(); + builder.Append("First"); + + var formattableString = new HtmlFormattableString("{0}!", builder); + + // Act + var result = HtmlContentToString(formattableString); + + // Assert + Assert.Equal("HtmlEncode[[First]]!", result); + } + + // This test is needed to ensure the shared StringWriter gets cleared. + [Fact] + public void HtmlFormattableString_WithMultipleHtmlContentArguments() + { + // Arrange + var formattableString = new HtmlFormattableString( + "Happy {0}, {1}!", + new HtmlEncodedString("Birthday"), + new HtmlContentBuilder().Append("Billy")); + + // Act + var result = HtmlContentToString(formattableString); + + // Assert + Assert.Equal("Happy Birthday, HtmlEncode[[Billy]]!", result); + } + + [Fact] + public void HtmlFormattableString_WithHtmlEncodedString_AndOffset() + { + // Arrange + var formattableString = new HtmlFormattableString("{0, 20}!", new HtmlEncodedString("First")); + + // Act + var result = HtmlContentToString(formattableString); + + // Assert + Assert.Equal(" First!", result); + } + + [Fact] + public void HtmlFormattableString_With3Arguments() + { + // Arrange + var formattableString = new HtmlFormattableString("0x{0:X} - {1} equivalent for {2}.", 50, "hex", 50); + + // Act + var result = HtmlContentToString(formattableString); + + // Assert + Assert.Equal( + "0xHtmlEncode[[32]] - HtmlEncode[[hex]] equivalent for HtmlEncode[[50]].", + result); + } + + [Fact] + public void HtmlFormattableString_WithAlignmentComponent() + { + // Arrange + var formattableString = new HtmlFormattableString("{0, -25} World!", "Hello"); + + // Act + var result = HtmlContentToString(formattableString); + + // Assert + Assert.Equal( + "HtmlEncode[[Hello]] World!", result); + } + + [Fact] + public void HtmlFormattableString_WithFormatStringComponent() + { + // Arrange + var formattableString = new HtmlFormattableString("0x{0:X}", 50); + + // Act + var result = HtmlContentToString(formattableString); + + // Assert + Assert.Equal("0xHtmlEncode[[32]]", result); + } + + [Fact] + public void HtmlFormattableString_WithCulture() + { + // Arrange + var formattableString = new HtmlFormattableString( + CultureInfo.InvariantCulture, + "Numbers in InvariantCulture - {0, -5:N} {1} {2} {3}!", + 1.1, + 2.98, + 145.82, + 32.86); + + // Act + var result = HtmlContentToString(formattableString); + + // Assert + Assert.Equal( + "Numbers in InvariantCulture - HtmlEncode[[1.10]] HtmlEncode[[2.98]] " + + "HtmlEncode[[145.82]] HtmlEncode[[32.86]]!", + result); + } + + [Fact] + [ReplaceCulture("en-US", "en-US")] + public void HtmlFormattableString_UsesPassedInCulture() + { + // Arrange + var culture = new CultureInfo("fr-FR"); + var formattableString = new HtmlFormattableString(culture, "{0} in french!", 1.21); + + // Act + var result = HtmlContentToString(formattableString); + + // Assert + Assert.Equal("HtmlEncode[[1,21]] in french!", result); + } + + [Fact] + [ReplaceCulture("de-DE", "de-DE")] + public void HtmlFormattableString_UsesCurrentCulture() + { + // Arrange + var formattableString = new HtmlFormattableString("{0:D}", DateTime.Parse("01/02/2015")); + + // Act + var result = HtmlContentToString(formattableString); + + // Assert + Assert.Equal("HtmlEncode[[Sonntag, 1. Februar 2015]]", result); + } + + private static string HtmlContentToString(IHtmlContent content) + { + using (var writer = new StringWriter()) + { + content.WriteTo(writer, new HtmlTestEncoder()); + return writer.ToString(); + } + } + } +} From aeb3939ac8418b072db5a8472f876315b5e975c9 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 7 Apr 2016 15:17:00 -0700 Subject: [PATCH 0163/1029] Removing imports from src projects --- src/Microsoft.AspNetCore.JsonPatch/project.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index 9749ef91a1..1d736bfde3 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -31,9 +31,8 @@ "System.Text.Encoding.Extensions": "4.0.11-*" }, "imports": [ - "dotnet5.2", "portable-net451+win8" ] } } -} +} \ No newline at end of file From 4d9d196b4a4bbe23e68174c5eac03a88d68a91c9 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 7 Apr 2016 15:27:11 -0700 Subject: [PATCH 0164/1029] Removing imports from src projects --- src/Microsoft.AspNetCore.Html.Abstractions/project.json | 5 +---- src/Microsoft.Extensions.WebEncoders/project.json | 6 +----- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/project.json b/src/Microsoft.AspNetCore.Html.Abstractions/project.json index 500041c2ed..69b0215834 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/project.json +++ b/src/Microsoft.AspNetCore.Html.Abstractions/project.json @@ -24,10 +24,7 @@ "dependencies": { "System.Collections": "4.0.11-*", "System.Resources.ResourceManager": "4.0.1-*" - }, - "imports": [ - "dotnet5.1" - ] + } } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.WebEncoders/project.json b/src/Microsoft.Extensions.WebEncoders/project.json index 70be4220b9..beeac94efe 100644 --- a/src/Microsoft.Extensions.WebEncoders/project.json +++ b/src/Microsoft.Extensions.WebEncoders/project.json @@ -23,10 +23,6 @@ "System.Text.Encodings.Web": "4.0.0-*" }, "frameworks": { - "netstandard1.0": { - "imports": [ - "dotnet5.1" - ] - } + "netstandard1.0": {} } } \ No newline at end of file From 46d4c6edcb374060b4e8ebf83e3ccd399f8f61ae Mon Sep 17 00:00:00 2001 From: moozzyk Date: Mon, 28 Mar 2016 16:47:18 -0700 Subject: [PATCH 0165/1029] Updating dotnet-watch to netstandard --- .../project.json | 9 ++++-- src/dotnet-watch/project.json | 16 ++++++++--- test/TestApps/AppWithDeps/project.json | 21 ++++++++------ test/TestApps/Dependency/project.json | 16 +++++------ test/TestApps/GlobbingApp/project.json | 19 +++++++------ test/TestApps/NoDepsApp/project.json | 20 ++++++------- .../Scenario/ProjectToolScenario.cs | 28 ++++++++++++++----- .../dotnet-watch.FunctionalTests/project.json | 2 +- 8 files changed, 80 insertions(+), 51 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index 9b7d46268e..d6c75b463d 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -13,15 +13,18 @@ "Microsoft.Extensions.PlatformAbstractions": "1.0.0-*", "Microsoft.Extensions.Logging.Abstractions": "1.0.0-*", "Microsoft.Extensions.FileSystemGlobbing": "1.0.0-*", - "Microsoft.NETCore.Platforms": "1.0.1-*", + "NETStandard.Library": "1.5.0-*", "Microsoft.Extensions.Process.Sources": { "type": "build", "version": "1.0.0-*" } }, "frameworks": { - "dnxcore50": { - "imports": "portable-net451+win8" + "netstandard1.5": { + "imports": [ + "dnxcore50", + "portable-net451+win8" + ] } } } diff --git a/src/dotnet-watch/project.json b/src/dotnet-watch/project.json index 1c46b27251..3017b1b110 100644 --- a/src/dotnet-watch/project.json +++ b/src/dotnet-watch/project.json @@ -11,12 +11,20 @@ "Microsoft.DotNet.Watcher.Core": "1.0.0-*", "Microsoft.Extensions.CommandLineUtils": "1.0.0-*", "Microsoft.Extensions.Logging": "1.0.0-*", - "Microsoft.Extensions.Logging.Console": "1.0.0-*", - "Microsoft.NETCore.Platforms": "1.0.1-*" + "Microsoft.Extensions.Logging.Console": "1.0.0-*" }, "frameworks": { - "dnxcore50": { - "imports": "portable-net451+win8" + "netstandard1.5": { + "imports": [ + "portable-net451+win8", + "dnxcore50" + ], + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-*" + } + } } } } diff --git a/test/TestApps/AppWithDeps/project.json b/test/TestApps/AppWithDeps/project.json index c9ce3f74a3..a102058c92 100644 --- a/test/TestApps/AppWithDeps/project.json +++ b/test/TestApps/AppWithDeps/project.json @@ -3,18 +3,23 @@ "compilationOptions": { "emitEntryPoint": true }, + "dependencies": { - "Dependency": "1.0.0", - "NETStandard.Library": "1.0.0-*" + "Dependency": "1.0.0" }, + "frameworks": { - "dnxcore50": { + "netstandardapp1.5": { "dependencies": { - "System.Console": "4.0.0-*", - "System.Diagnostics.Process": "4.1.0-*", - "System.IO": "4.0.11-*", - "System.IO.FileSystem": "4.0.1-*" - } + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-*" + } + }, + "imports": [ + "dnxcore50", + "portable-net451+win8" + ] } } } \ No newline at end of file diff --git a/test/TestApps/Dependency/project.json b/test/TestApps/Dependency/project.json index 89004d9d47..a39c53433e 100644 --- a/test/TestApps/Dependency/project.json +++ b/test/TestApps/Dependency/project.json @@ -1,18 +1,16 @@ { "version": "1.0.0-*", - + "dependencies": { - "NETStandard.Library": "1.0.0-*" + "NETStandard.Library": "1.5.0-*" }, "frameworks": { - "dnxcore50": { - "dependencies": { - "System.Console": "4.0.0-*", - "System.Diagnostics.Process": "4.1.0-*", - "System.IO": "4.0.11-*", - "System.IO.FileSystem": "4.0.1-*" - } + "netstandardapp1.5": { + "imports": [ + "dnxcore50", + "portable-net451+win8" + ] } } } diff --git a/test/TestApps/GlobbingApp/project.json b/test/TestApps/GlobbingApp/project.json index 1a6b3da081..46e1d29d53 100644 --- a/test/TestApps/GlobbingApp/project.json +++ b/test/TestApps/GlobbingApp/project.json @@ -10,18 +10,19 @@ "exclude": [ "exclude/*" ], - "dependencies": { - "NETStandard.Library": "1.0.0-*" - }, "frameworks": { - "dnxcore50": { + "netstandardapp1.5": { "dependencies": { - "System.Console": "4.0.0-*", - "System.Diagnostics.Process": "4.1.0-*", - "System.IO": "4.0.11-*", - "System.IO.FileSystem": "4.0.1-*" - } + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-*" + } + }, + "imports": [ + "dnxcore50", + "portable-net451+win8" + ] } } } diff --git a/test/TestApps/NoDepsApp/project.json b/test/TestApps/NoDepsApp/project.json index 380a03bc97..a01cd35453 100644 --- a/test/TestApps/NoDepsApp/project.json +++ b/test/TestApps/NoDepsApp/project.json @@ -4,18 +4,18 @@ "emitEntryPoint": true }, - "dependencies": { - "NETStandard.Library": "1.0.0-*" - }, - "frameworks": { - "dnxcore50": { + "netstandardapp1.5": { "dependencies": { - "System.Console": "4.0.0-*", - "System.Diagnostics.Process": "4.1.0-*", - "System.IO": "4.0.11-*", - "System.IO.FileSystem": "4.0.1-*" - } + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-*" + } + }, + "imports": [ + "dnxcore50", + "portable-net451+win8" + ] } } } diff --git a/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs index be10d97fbc..22ea8f5cac 100644 --- a/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -15,12 +15,14 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests { private const string NugetConfigFileName = "NuGet.config"; + private static readonly object _restoreLock = new object(); + public ProjectToolScenario() { Console.WriteLine($"The temporary test folder is {TempFolder}"); WorkFolder = Path.Combine(TempFolder, "work"); - + CreateTestDirectory(); } @@ -65,7 +67,13 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests Console.WriteLine($"Adding {toolName} to {projectFile}"); var projectJson = JObject.Parse(File.ReadAllText(projectFile)); - projectJson.Add("tools", new JObject(new JProperty(toolName, "1.0.0-*"))); + projectJson.Add("tools", + new JObject( + new JProperty(toolName, + new JObject( + new JProperty("version", "1.0.0-*"), + new JProperty("imports", "portable-net451+win8"))))); + File.WriteAllText(projectFile, projectJson.ToString()); } @@ -80,12 +88,18 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests project = Path.Combine(WorkFolder, project); } - var restore = ExecuteDotnet($"restore -v Minimal", project); - restore.WaitForExit(); - - if (restore.ExitCode != 0) + // Tests are run in parallel and they try to restore tools concurrently. + // This causes issues because the deps json file for a tool is being written from + // multiple threads - which results in either sharing violation or corrupted json. + lock(_restoreLock) { - throw new Exception($"Exit code {restore.ExitCode}"); + var restore = ExecuteDotnet($"restore -v Minimal", project); + restore.WaitForExit(); + + if (restore.ExitCode != 0) + { + throw new Exception($"Exit code {restore.ExitCode}"); + } } } diff --git a/test/dotnet-watch.FunctionalTests/project.json b/test/dotnet-watch.FunctionalTests/project.json index 792bf09599..ce80cc69aa 100644 --- a/test/dotnet-watch.FunctionalTests/project.json +++ b/test/dotnet-watch.FunctionalTests/project.json @@ -11,7 +11,7 @@ "version": "1.0.0-*" }, "Microsoft.DotNet.Watcher.Core": "1.0.0-*", - "Microsoft.NETCore.Platforms": "1.0.1-*", + "NETStandard.Library": "1.5.0-*", "Newtonsoft.Json": "8.0.2", "System.Threading.Thread": "4.0.0-*", "xunit": "2.1.0" From 78d3428eb7494f7f8e53fc15b5ca8e84a892ed55 Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Tue, 12 Apr 2016 19:06:55 -0700 Subject: [PATCH 0166/1029] Fix package metadata --- src/Microsoft.AspNetCore.JsonPatch/project.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index 1d736bfde3..0eeb88f010 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -1,5 +1,11 @@ { "version": "1.0.0-*", + "description": "ASP.NET Core support for JSON PATCH.", + "tags": [ + "aspnetcore", + "json", + "jsonpatch" + ], "compilationOptions": { "warningsAsErrors": true, "keyFile": "../../tools/Key.snk", @@ -10,7 +16,7 @@ }, "repository": { "type": "git", - "url": "git://github.com/aspnet/mvc" + "url": "git://github.com/aspnet/jsonpatch" }, "dependencies": { "Newtonsoft.Json": "8.0.3" From 8f1f3c0772953c95e95b1b614f8ecf6e20cf14c0 Mon Sep 17 00:00:00 2001 From: moozzyk Date: Mon, 28 Mar 2016 16:47:18 -0700 Subject: [PATCH 0167/1029] Add a polling watcher --- .../Internal/FileWatcher/DotnetFileWatcher.cs | 136 +++++++ .../FileWatcher/FileWatcherFactory.cs | 28 ++ .../FileWatcher/IFileSystemWatcher.cs | 16 + .../FileWatcher/PollingFileWatcher.cs | 243 ++++++++++++ .../Internal/Implementation/FileWatcher.cs | 29 +- .../FileWatcherTests.cs | 349 ++++++++++++++++++ .../GlobbingAppTests.cs | 34 +- .../Scenario/DotNetWatchScenario.cs | 14 +- .../Scenario/ProjectToolScenario.cs | 20 +- .../WaitForFileToChange.cs | 19 +- 10 files changed, 848 insertions(+), 40 deletions(-) create mode 100644 src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/DotnetFileWatcher.cs create mode 100644 src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/FileWatcherFactory.cs create mode 100644 src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/IFileSystemWatcher.cs create mode 100644 src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/PollingFileWatcher.cs create mode 100644 test/dotnet-watch.FunctionalTests/FileWatcherTests.cs diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/DotnetFileWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/DotnetFileWatcher.cs new file mode 100644 index 0000000000..8f2e44b5e7 --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/DotnetFileWatcher.cs @@ -0,0 +1,136 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; + +namespace Microsoft.DotNet.Watcher.Core.Internal +{ + internal class DotnetFileWatcher : IFileSystemWatcher + { + private readonly Func _watcherFactory; + private readonly string _watchedDirectory; + + private FileSystemWatcher _fileSystemWatcher; + + private readonly object _createLock = new object(); + + public DotnetFileWatcher(string watchedDirectory) + : this(watchedDirectory, DefaultWatcherFactory) + { + } + + internal DotnetFileWatcher(string watchedDirectory, Func fileSystemWatcherFactory) + { + if (string.IsNullOrEmpty(watchedDirectory)) + { + throw new ArgumentNullException(nameof(watchedDirectory)); + } + + _watchedDirectory = watchedDirectory; + _watcherFactory = fileSystemWatcherFactory; + CreateFileSystemWatcher(); + } + + public event EventHandler OnFileChange; + + public event EventHandler OnError; + + private static FileSystemWatcher DefaultWatcherFactory(string watchedDirectory) + { + if (string.IsNullOrEmpty(watchedDirectory)) + { + throw new ArgumentNullException(nameof(watchedDirectory)); + } + + return new FileSystemWatcher(watchedDirectory); + } + + private void WatcherErrorHandler(object sender, ErrorEventArgs e) + { + // Recreate the watcher + CreateFileSystemWatcher(); + + if (OnError != null) + { + OnError(this, null); + } + } + + private void WatcherRenameHandler(object sender, RenamedEventArgs e) + { + NotifyChange(e.OldFullPath); + NotifyChange(e.FullPath); + + if (Directory.Exists(e.FullPath)) + { + foreach (var newLocation in Directory.EnumerateFileSystemEntries(e.FullPath, "*", SearchOption.AllDirectories)) + { + // Calculated previous path of this moved item. + var oldLocation = Path.Combine(e.OldFullPath, newLocation.Substring(e.FullPath.Length + 1)); + NotifyChange(oldLocation); + NotifyChange(newLocation); + } + } + } + + private void WatcherChangeHandler(object sender, FileSystemEventArgs e) + { + NotifyChange(e.FullPath); + } + + private void NotifyChange(string fullPath) + { + if (OnFileChange != null) + { + // Only report file changes + OnFileChange(this, fullPath); + } + } + + private void CreateFileSystemWatcher() + { + lock (_createLock) + { + bool enableEvents = false; + + if (_fileSystemWatcher != null) + { + enableEvents = _fileSystemWatcher.EnableRaisingEvents; + + _fileSystemWatcher.EnableRaisingEvents = false; + + _fileSystemWatcher.Created -= WatcherChangeHandler; + _fileSystemWatcher.Deleted -= WatcherChangeHandler; + _fileSystemWatcher.Changed -= WatcherChangeHandler; + _fileSystemWatcher.Renamed -= WatcherRenameHandler; + _fileSystemWatcher.Error -= WatcherErrorHandler; + + _fileSystemWatcher.Dispose(); + } + + _fileSystemWatcher = _watcherFactory(_watchedDirectory); + _fileSystemWatcher.IncludeSubdirectories = true; + + _fileSystemWatcher.Created += WatcherChangeHandler; + _fileSystemWatcher.Deleted += WatcherChangeHandler; + _fileSystemWatcher.Changed += WatcherChangeHandler; + _fileSystemWatcher.Renamed += WatcherRenameHandler; + _fileSystemWatcher.Error += WatcherErrorHandler; + + _fileSystemWatcher.EnableRaisingEvents = enableEvents; + } + } + + public bool EnableRaisingEvents + { + get { return _fileSystemWatcher.EnableRaisingEvents; } + set { _fileSystemWatcher.EnableRaisingEvents = value; } + } + + public void Dispose() + { + _fileSystemWatcher.Dispose(); + } + } +} diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/FileWatcherFactory.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/FileWatcherFactory.cs new file mode 100644 index 0000000000..35e7e7c739 --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/FileWatcherFactory.cs @@ -0,0 +1,28 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.DotNet.Watcher.Core.Internal +{ + public static class FileWatcherFactory + { + public static IFileSystemWatcher CreateWatcher(string watchedDirectory) + { + var envVar = Environment.GetEnvironmentVariable("USE_POLLING_FILE_WATCHER"); + var usePollingWatcher = + envVar != null && + (envVar.Equals("1", StringComparison.OrdinalIgnoreCase) || + envVar.Equals("true", StringComparison.OrdinalIgnoreCase)); + + return CreateWatcher(watchedDirectory, usePollingWatcher); + } + + public static IFileSystemWatcher CreateWatcher(string watchedDirectory, bool usePollingWatcher) + { + return usePollingWatcher ? + new PollingFileWatcher(watchedDirectory) : + new DotnetFileWatcher(watchedDirectory) as IFileSystemWatcher; + } + } +} diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/IFileSystemWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/IFileSystemWatcher.cs new file mode 100644 index 0000000000..c944bb9d64 --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/IFileSystemWatcher.cs @@ -0,0 +1,16 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.DotNet.Watcher.Core.Internal +{ + public interface IFileSystemWatcher : IDisposable + { + event EventHandler OnFileChange; + + event EventHandler OnError; + + bool EnableRaisingEvents { get; set; } + } +} diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/PollingFileWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/PollingFileWatcher.cs new file mode 100644 index 0000000000..b7d6866f69 --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/PollingFileWatcher.cs @@ -0,0 +1,243 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Threading; + +namespace Microsoft.DotNet.Watcher.Core.Internal +{ + internal class PollingFileWatcher : IFileSystemWatcher + { + // The minimum interval to rerun the scan + private static readonly TimeSpan _minRunInternal = TimeSpan.FromSeconds(.5); + + private readonly DirectoryInfo _watchedDirectory; + + private Dictionary _knownEntities = new Dictionary(); + private Dictionary _tempDictionary = new Dictionary(); + private HashSet _changes = new HashSet(); + + private Thread _pollingThread; + private bool _raiseEvents; + + private bool _disposed; + + public PollingFileWatcher(string watchedDirectory) + { + if (string.IsNullOrEmpty(watchedDirectory)) + { + throw new ArgumentNullException(nameof(watchedDirectory)); + } + + _watchedDirectory = new DirectoryInfo(watchedDirectory); + + _pollingThread = new Thread(new ThreadStart(PollingLoop)); + _pollingThread.IsBackground = true; + _pollingThread.Name = nameof(PollingFileWatcher); + _pollingThread.Start(); + } + + public event EventHandler OnFileChange; + +#pragma warning disable CS0067 // not used + public event EventHandler OnError; +#pragma warning restore + + public bool EnableRaisingEvents + { + get + { + return _raiseEvents; + } + set + { + EnsureNotDisposed(); + + if (value == true) + { + CreateKnownFilesSnapshot(); + + if (_pollingThread.ThreadState == System.Threading.ThreadState.Unstarted) + { + // Start the loop the first time events are enabled + _pollingThread.Start(); + } + } + _raiseEvents = value; + } + } + + private void PollingLoop() + { + var stopwatch = Stopwatch.StartNew(); + stopwatch.Start(); + + while (!_disposed) + { + if (stopwatch.Elapsed < _minRunInternal) + { + // Don't run too often + // The min wait time here can be double + // the value of the variable (FYI) + Thread.Sleep(_minRunInternal); + } + + stopwatch.Reset(); + + if (!_raiseEvents) + { + continue; + } + + CheckForChangedFiles(); + } + + stopwatch.Stop(); + } + + private void CreateKnownFilesSnapshot() + { + _knownEntities.Clear(); + + ForeachEntityInDirectory(_watchedDirectory, f => + { + _knownEntities.Add(f.FullName, new FileMeta(f)); + }); + } + + private void CheckForChangedFiles() + { + _changes.Clear(); + + ForeachEntityInDirectory(_watchedDirectory, f => + { + var fullFilePath = f.FullName; + + if (!_knownEntities.ContainsKey(fullFilePath)) + { + // New file + RecordChange(f); + } + else + { + var fileMeta = _knownEntities[fullFilePath]; + if (fileMeta.FileInfo.LastWriteTime != f.LastWriteTime) + { + // File changed + RecordChange(f); + } + + _knownEntities[fullFilePath] = new FileMeta(fileMeta.FileInfo, true); + } + + _tempDictionary.Add(f.FullName, new FileMeta(f)); + }); + + foreach (var file in _knownEntities) + { + if (!file.Value.FoundAgain) + { + // File deleted + RecordChange(file.Value.FileInfo); + } + } + + NotifyChanges(); + + // Swap the two dictionaries + var swap = _knownEntities; + _knownEntities = _tempDictionary; + _tempDictionary = swap; + + _tempDictionary.Clear(); + } + + private void RecordChange(FileSystemInfo fileInfo) + { + if (_changes.Contains(fileInfo.FullName) || + fileInfo.FullName.Equals(_watchedDirectory.FullName, StringComparison.Ordinal)) + { + return; + } + + _changes.Add(fileInfo.FullName); + if (fileInfo.FullName != _watchedDirectory.FullName) + { + var file = fileInfo as FileInfo; + if (file != null) + { + RecordChange(file.Directory); + } + else + { + var dir = fileInfo as DirectoryInfo; + if (dir != null) + { + RecordChange(dir.Parent); + } + } + } + } + + private void ForeachEntityInDirectory(DirectoryInfo dirInfo, Action fileAction) + { + var entities = dirInfo.EnumerateFileSystemInfos("*.*"); + foreach (var entity in entities) + { + fileAction(entity); + + var subdirInfo = entity as DirectoryInfo; + if (subdirInfo != null) + { + ForeachEntityInDirectory(subdirInfo, fileAction); + } + } + } + + private void NotifyChanges() + { + foreach (var path in _changes) + { + if (_disposed || !_raiseEvents) + { + break; + } + + if (OnFileChange != null) + { + OnFileChange(this, path); + } + } + } + + private void EnsureNotDisposed() + { + if (_disposed) + { + throw new ObjectDisposedException(nameof(PollingFileWatcher)); + } + } + + public void Dispose() + { + EnableRaisingEvents = false; + _disposed = true; + } + + private struct FileMeta + { + public FileMeta(FileSystemInfo fileInfo, bool foundAgain = false) + { + FileInfo = fileInfo; + FoundAgain = foundAgain; + } + + public FileSystemInfo FileInfo; + + public bool FoundAgain; + } + } +} diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs index 57f082a8d0..388f7f52ab 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; namespace Microsoft.DotNet.Watcher.Core.Internal @@ -12,7 +11,7 @@ namespace Microsoft.DotNet.Watcher.Core.Internal { private bool _disposed; - private readonly IDictionary _watchers = new Dictionary(); + private readonly IDictionary _watchers = new Dictionary(); public event Action OnFileChange; @@ -62,28 +61,16 @@ namespace Microsoft.DotNet.Watcher.Core.Internal } } - var newWatcher = new FileSystemWatcher(directory); - newWatcher.IncludeSubdirectories = true; - - newWatcher.Changed += WatcherChangedHandler; - newWatcher.Created += WatcherChangedHandler; - newWatcher.Deleted += WatcherChangedHandler; - newWatcher.Renamed += WatcherRenamedHandler; - + var newWatcher = FileWatcherFactory.CreateWatcher(directory); + newWatcher.OnFileChange += WatcherChangedHandler; newWatcher.EnableRaisingEvents = true; _watchers.Add(directory, newWatcher); } - private void WatcherRenamedHandler(object sender, RenamedEventArgs e) + private void WatcherChangedHandler(object sender, string changedPath) { - NotifyChange(e.OldFullPath); - NotifyChange(e.FullPath); - } - - private void WatcherChangedHandler(object sender, FileSystemEventArgs e) - { - NotifyChange(e.FullPath); + NotifyChange(changedPath); } private void NotifyChange(string path) @@ -100,11 +87,7 @@ namespace Microsoft.DotNet.Watcher.Core.Internal _watchers.Remove(directory); watcher.EnableRaisingEvents = false; - - watcher.Changed -= WatcherChangedHandler; - watcher.Created -= WatcherChangedHandler; - watcher.Deleted -= WatcherChangedHandler; - watcher.Renamed -= WatcherRenamedHandler; + watcher.OnFileChange -= WatcherChangedHandler; watcher.Dispose(); } diff --git a/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs b/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs new file mode 100644 index 0000000000..d31cce667d --- /dev/null +++ b/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs @@ -0,0 +1,349 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using Microsoft.DotNet.Watcher.Core.Internal; +using Xunit; + +namespace Microsoft.DotNet.Watcher.FunctionalTests +{ + public class FileWatcherTests + { + private const int DefaultTimeout = 10 * 1000; // 10 sec + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void NewFile(bool usePolling) + { + UsingTempDirectory(dir => + { + using (var changedEv = new ManualResetEvent(false)) + using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling)) + { + var filesChanged = new HashSet(); + + watcher.OnFileChange += (_, f) => + { + filesChanged.Add(f); + changedEv.Set(); + }; + watcher.EnableRaisingEvents = true; + + var testFileFullPath = Path.Combine(dir, "foo"); + File.WriteAllText(testFileFullPath, string.Empty); + + Assert.True(changedEv.WaitOne(DefaultTimeout)); + Assert.Equal(testFileFullPath, filesChanged.Single()); + } + }); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void ChangeFile(bool usePolling) + { + UsingTempDirectory(dir => + { + var testFileFullPath = Path.Combine(dir, "foo"); + File.WriteAllText(testFileFullPath, string.Empty); + + using (var changedEv = new ManualResetEvent(false)) + using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling)) + { + var filesChanged = new HashSet(); + + watcher.OnFileChange += (_, f) => + { + filesChanged.Add(f); + changedEv.Set(); + }; + watcher.EnableRaisingEvents = true; + + File.WriteAllText(testFileFullPath, string.Empty); + + Assert.True(changedEv.WaitOne(DefaultTimeout)); + Assert.Equal(testFileFullPath, filesChanged.Single()); + } + }); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void MoveFile(bool usePolling) + { + UsingTempDirectory(dir => + { + var srcFile = Path.Combine(dir, "foo"); + var dstFile = Path.Combine(dir, "foo2"); + + File.WriteAllText(srcFile, string.Empty); + + using (var changedEv = new ManualResetEvent(false)) + using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling)) + { + var filesChanged = new HashSet(); + + var changeCount = 0; + watcher.OnFileChange += (_, f) => + { + filesChanged.Add(f); + + changeCount++; + + if (changeCount >= 2) + { + changedEv.Set(); + } + }; + watcher.EnableRaisingEvents = true; + + File.Move(srcFile, dstFile); + + Assert.True(changedEv.WaitOne(DefaultTimeout)); + Assert.True(filesChanged.Contains(srcFile)); + Assert.True(filesChanged.Contains(dstFile)); + } + }); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void FileInSubdirectory(bool usePolling) + { + UsingTempDirectory(dir => + { + var subdir = Path.Combine(dir, "subdir"); + Directory.CreateDirectory(subdir); + + var testFileFullPath = Path.Combine(subdir, "foo"); + File.WriteAllText(testFileFullPath, string.Empty); + + using (var changedEv = new ManualResetEvent(false)) + using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling)) + { + var filesChanged = new HashSet(); + + var totalChanges = 0; + watcher.OnFileChange += (_, f) => + { + filesChanged.Add(f); + + totalChanges++; + if (totalChanges >= 2) + { + changedEv.Set(); + } + }; + watcher.EnableRaisingEvents = true; + + File.WriteAllText(testFileFullPath, string.Empty); + + Assert.True(changedEv.WaitOne(DefaultTimeout)); + Assert.True(filesChanged.Contains(subdir)); + Assert.True(filesChanged.Contains(testFileFullPath)); + } + }); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void NoNotificationIfDisabled(bool usePolling) + { + UsingTempDirectory(dir => + { + using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling)) + using (var changedEv = new ManualResetEvent(false)) + { + watcher.OnFileChange += (_, f) => changedEv.Set(); + + // Disable + watcher.EnableRaisingEvents = false; + + var testFileFullPath = Path.Combine(dir, "foo"); + File.WriteAllText(testFileFullPath, string.Empty); + + Assert.False(changedEv.WaitOne(DefaultTimeout / 2)); + } + }); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void DisposedNoEvents(bool usePolling) + { + UsingTempDirectory(dir => + { + using (var changedEv = new ManualResetEvent(false)) + { + using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling)) + { + watcher.OnFileChange += (_, f) => changedEv.Set(); + watcher.EnableRaisingEvents = true; + } + + var testFileFullPath = Path.Combine(dir, "foo"); + File.WriteAllText(testFileFullPath, string.Empty); + + Assert.False(changedEv.WaitOne(DefaultTimeout / 2)); + } + }); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void MultipleFiles(bool usePolling) + { + UsingTempDirectory(dir => + { + File.WriteAllText(Path.Combine(dir, "foo1"), string.Empty); + File.WriteAllText(Path.Combine(dir, "foo2"), string.Empty); + File.WriteAllText(Path.Combine(dir, "foo3"), string.Empty); + File.WriteAllText(Path.Combine(dir, "foo4"), string.Empty); + File.WriteAllText(Path.Combine(dir, "foo4"), string.Empty); + + var testFileFullPath = Path.Combine(dir, "foo3"); + + using (var changedEv = new ManualResetEvent(false)) + using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling)) + { + var filesChanged = new HashSet(); + + watcher.OnFileChange += (_, f) => + { + filesChanged.Add(f); + changedEv.Set(); + }; + watcher.EnableRaisingEvents = true; + + File.WriteAllText(testFileFullPath, string.Empty); + + Assert.True(changedEv.WaitOne(DefaultTimeout)); + Assert.Equal(testFileFullPath, filesChanged.Single()); + } + }); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void MultipleTriggers(bool usePolling) + { + UsingTempDirectory(dir => + { + using (var changedEv = new AutoResetEvent(false)) + using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling)) + { + var filesChanged = new HashSet(); + + watcher.OnFileChange += (_, f) => + { + filesChanged.Add(f); + changedEv.Set(); + }; + watcher.EnableRaisingEvents = true; + + var testFileFullPath = Path.Combine(dir, "foo1"); + File.WriteAllText(testFileFullPath, string.Empty); + Assert.True(changedEv.WaitOne(DefaultTimeout)); + Assert.Equal(testFileFullPath, filesChanged.Single()); + filesChanged.Clear(); + + testFileFullPath = Path.Combine(dir, "foo2"); + File.WriteAllText(testFileFullPath, string.Empty); + Assert.True(changedEv.WaitOne(DefaultTimeout)); + Assert.Equal(testFileFullPath, filesChanged.Single()); + filesChanged.Clear(); + + testFileFullPath = Path.Combine(dir, "foo3"); + File.WriteAllText(testFileFullPath, string.Empty); + Assert.True(changedEv.WaitOne(DefaultTimeout)); + Assert.Equal(testFileFullPath, filesChanged.Single()); + filesChanged.Clear(); + + File.WriteAllText(testFileFullPath, string.Empty); + Assert.True(changedEv.WaitOne(DefaultTimeout)); + Assert.Equal(testFileFullPath, filesChanged.Single()); + } + }); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void DeleteSubfolder(bool usePolling) + { + UsingTempDirectory(dir => + { + var subdir = Path.Combine(dir, "subdir"); + Directory.CreateDirectory(subdir); + + var f1 = Path.Combine(subdir, "foo1"); + var f2 = Path.Combine(subdir, "foo2"); + var f3 = Path.Combine(subdir, "foo3"); + + File.WriteAllText(f1, string.Empty); + File.WriteAllText(f2, string.Empty); + File.WriteAllText(f3, string.Empty); + + using (var changedEv = new AutoResetEvent(false)) + using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling)) + { + var filesChanged = new HashSet(); + + var totalChanges = 0; + watcher.OnFileChange += (_, f) => + { + filesChanged.Add(f); + + totalChanges++; + if (totalChanges >= 4) + { + changedEv.Set(); + } + }; + watcher.EnableRaisingEvents = true; + + Directory.Delete(subdir, recursive: true); + + Assert.True(changedEv.WaitOne(DefaultTimeout)); + + Assert.True(filesChanged.Contains(f1)); + Assert.True(filesChanged.Contains(f2)); + Assert.True(filesChanged.Contains(f3)); + Assert.True(filesChanged.Contains(subdir)); + } + }); + } + + private static void UsingTempDirectory(Action action) + { + var tempFolder = Path.Combine(Path.GetTempPath(), $"{nameof(FileWatcherTests)}-{Guid.NewGuid().ToString("N")}"); + if (Directory.Exists(tempFolder)) + { + Directory.Delete(tempFolder, recursive: true); + } + + Directory.CreateDirectory(tempFolder); + + try + { + action(tempFolder); + } + finally + { + Directory.Delete(tempFolder, recursive: true); + } + } + } +} diff --git a/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs b/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs index 839ce62426..9df0d466f3 100644 --- a/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs +++ b/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs @@ -15,13 +15,26 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests private static readonly TimeSpan _negativeTestWaitTime = TimeSpan.FromSeconds(10); - // Change a file included in compilation [Fact] - public void ChangeCompiledFile() + public void ChangeCompiledFile_PollingWatcher() + { + ChangeCompiledFile(usePollingWatcher: true); + } + + [Fact] + public void ChangeCompiledFile_DotNetWatcher() + { + ChangeCompiledFile(usePollingWatcher: false); + } + + // Change a file included in compilation + private void ChangeCompiledFile(bool usePollingWatcher) { using (var scenario = new GlobbingAppScenario()) using (var wait = new WaitForFileToChange(scenario.StartedFile)) { + scenario.UsePollingWatcher = usePollingWatcher; + scenario.Start(); var fileToChange = Path.Combine(scenario.TestAppFolder, "include", "Foo.cs"); @@ -91,12 +104,25 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } } - // Add a file that's in a included folder but not matching the globbing pattern [Fact] - public void ChangeNonCompiledFile() + public void ChangeNonCompiledFile_PollingWatcher() { + ChangeNonCompiledFile(usePollingWatcher: true); + } + + [Fact] + public void ChangeNonCompiledFile_DotNetWatcher() + { + ChangeNonCompiledFile(usePollingWatcher: false); + } + + // Add a file that's in a included folder but not matching the globbing pattern + private void ChangeNonCompiledFile(bool usePollingWatcher) + { using (var scenario = new GlobbingAppScenario()) { + scenario.UsePollingWatcher = usePollingWatcher; + scenario.Start(); var ids = File.ReadAllLines(scenario.StatusFile); diff --git a/test/dotnet-watch.FunctionalTests/Scenario/DotNetWatchScenario.cs b/test/dotnet-watch.FunctionalTests/Scenario/DotNetWatchScenario.cs index f143e8f734..2a0b2e441c 100644 --- a/test/dotnet-watch.FunctionalTests/Scenario/DotNetWatchScenario.cs +++ b/test/dotnet-watch.FunctionalTests/Scenario/DotNetWatchScenario.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using Microsoft.Extensions.Internal; @@ -25,9 +26,20 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests public Process WatcherProcess { get; private set; } + public bool UsePollingWatcher { get; set; } + protected void RunDotNetWatch(string arguments, string workingFolder) { - WatcherProcess = _scenario.ExecuteDotnet("watch " + arguments, workingFolder); + IDictionary envVariables = null; + if (UsePollingWatcher) + { + envVariables = new Dictionary() + { + ["USE_POLLING_FILE_WATCHER"] = "true" + }; + } + + WatcherProcess = _scenario.ExecuteDotnet("watch " + arguments, workingFolder, envVariables); } public virtual void Dispose() diff --git a/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs index 22ea8f5cac..c4976ef3ac 100644 --- a/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; @@ -114,16 +115,31 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests File.Copy(nugetConfigFilePath, tempNugetConfigFile); } - public Process ExecuteDotnet(string arguments, string workDir) + public Process ExecuteDotnet(string arguments, string workDir, IDictionary environmentVariables = null) { Console.WriteLine($"Running dotnet {arguments} in {workDir}"); var psi = new ProcessStartInfo("dotnet", arguments) { UseShellExecute = false, - WorkingDirectory = workDir + WorkingDirectory = workDir, }; + if (environmentVariables != null) + { + foreach (var newEnvVar in environmentVariables) + { + if (psi.Environment.ContainsKey(newEnvVar.Key)) + { + psi.Environment[newEnvVar.Key] = newEnvVar.Value; + } + else + { + psi.Environment.Add(newEnvVar.Key, newEnvVar.Value); + } + } + } + return Process.Start(psi); } diff --git a/test/dotnet-watch.FunctionalTests/WaitForFileToChange.cs b/test/dotnet-watch.FunctionalTests/WaitForFileToChange.cs index eb964f85d2..64c59c61dc 100644 --- a/test/dotnet-watch.FunctionalTests/WaitForFileToChange.cs +++ b/test/dotnet-watch.FunctionalTests/WaitForFileToChange.cs @@ -4,30 +4,30 @@ using System; using System.IO; using System.Threading; +using Microsoft.DotNet.Watcher.Core.Internal; namespace Microsoft.DotNet.Watcher.FunctionalTests { public class WaitForFileToChange : IDisposable { - private readonly FileSystemWatcher _watcher; + private readonly IFileSystemWatcher _watcher; private readonly string _expectedFile; private ManualResetEvent _changed = new ManualResetEvent(false); public WaitForFileToChange(string file) { - _watcher = new FileSystemWatcher(Path.GetDirectoryName(file), "*" + Path.GetExtension(file)); + _watcher = FileWatcherFactory.CreateWatcher(Path.GetDirectoryName(file), usePollingWatcher: true); _expectedFile = file; - _watcher.Changed += WatcherEvent; - _watcher.Created += WatcherEvent; - + _watcher.OnFileChange += WatcherEvent; + _watcher.EnableRaisingEvents = true; } - private void WatcherEvent(object sender, FileSystemEventArgs e) + private void WatcherEvent(object sender, string file) { - if (e.FullPath.Equals(_expectedFile, StringComparison.Ordinal)) + if (file.Equals(_expectedFile, StringComparison.Ordinal)) { Waiters.WaitForFileToBeReadable(_expectedFile, TimeSpan.FromSeconds(10)); _changed?.Set(); @@ -50,9 +50,8 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests { _watcher.EnableRaisingEvents = false; - _watcher.Changed -= WatcherEvent; - _watcher.Created -= WatcherEvent; - + _watcher.OnFileChange -= WatcherEvent; + _watcher.Dispose(); _changed.Dispose(); From e054eac3bd2f7bdb558db12239d2158e8c3cd115 Mon Sep 17 00:00:00 2001 From: moozzyk Date: Tue, 12 Apr 2016 15:51:53 -0700 Subject: [PATCH 0168/1029] Fixing tests to use the package that was just built Disabling parallel run to prevent random issues Adding additional details that should help diagnose failures --- .../Properties/AssemblyInfo.cs | 3 +++ .../Scenario/ProjectToolScenario.cs | 8 +++++++- test/dotnet-watch.FunctionalTests/Waiters.cs | 19 +++++++++++++++---- 3 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 test/dotnet-watch.FunctionalTests/Properties/AssemblyInfo.cs diff --git a/test/dotnet-watch.FunctionalTests/Properties/AssemblyInfo.cs b/test/dotnet-watch.FunctionalTests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..d776ca34eb --- /dev/null +++ b/test/dotnet-watch.FunctionalTests/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using Xunit; + +[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)] \ No newline at end of file diff --git a/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs index c4976ef3ac..e2f548e7a2 100644 --- a/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -67,12 +67,18 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests var projectFile = Path.Combine(WorkFolder, projectName, "project.json"); Console.WriteLine($"Adding {toolName} to {projectFile}"); + var versionSuffix = Environment.GetEnvironmentVariable("DOTNET_BUILD_VERSION"); + if (string.IsNullOrEmpty(versionSuffix)) + { + versionSuffix = "*"; + } + var projectJson = JObject.Parse(File.ReadAllText(projectFile)); projectJson.Add("tools", new JObject( new JProperty(toolName, new JObject( - new JProperty("version", "1.0.0-*"), + new JProperty("version", "1.0.0-" + versionSuffix), new JProperty("imports", "portable-net451+win8"))))); File.WriteAllText(projectFile, projectJson.ToString()); diff --git a/test/dotnet-watch.FunctionalTests/Waiters.cs b/test/dotnet-watch.FunctionalTests/Waiters.cs index b24a11e054..a65a80feb3 100644 --- a/test/dotnet-watch.FunctionalTests/Waiters.cs +++ b/test/dotnet-watch.FunctionalTests/Waiters.cs @@ -14,6 +14,8 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests { var watch = new Stopwatch(); + Exception lastException = null; + watch.Start(); while (watch.Elapsed < timeout) { @@ -23,14 +25,21 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests watch.Stop(); return; } - catch + catch (Exception e) { + lastException = e; } Thread.Sleep(500); } watch.Stop(); - throw new Exception($"{file} is not readable."); + if (lastException != null) + { + Console.WriteLine("Last exception:"); + Console.WriteLine(lastException); + } + + throw new InvalidOperationException($"{file} is not readable."); } public static void WaitForProcessToStop(int processId, TimeSpan timeout, bool expectedToStop, string errorMessage) @@ -41,8 +50,10 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests { process = Process.GetProcessById(processId); } - catch + catch (Exception e) { + Console.WriteLine("Could not get process id:"); + Console.WriteLine(e); } var watch = new Stopwatch(); @@ -60,7 +71,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests bool isStopped = process == null || process.HasExited; if (isStopped != expectedToStop) { - throw new Exception(errorMessage); + throw new InvalidOperationException(errorMessage); } } } From cf465b2001fbd7a81ddea8834a95356f7b3bdab4 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Wed, 13 Apr 2016 12:07:54 -0700 Subject: [PATCH 0169/1029] Fix tests on unix and make tests more reliable on all platforms --- .../FileWatcher/PollingFileWatcher.cs | 15 ++---- test/TestApps/AppWithDeps/Program.cs | 22 ++++++-- test/TestApps/GlobbingApp/Program.cs | 22 ++++++-- test/TestApps/NoDepsApp/Program.cs | 22 ++++++-- .../FileWatcherTests.cs | 51 +++++++++++++++++-- 5 files changed, 107 insertions(+), 25 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/PollingFileWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/PollingFileWatcher.cs index b7d6866f69..2bc335f76a 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/PollingFileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/PollingFileWatcher.cs @@ -37,6 +37,9 @@ namespace Microsoft.DotNet.Watcher.Core.Internal _pollingThread = new Thread(new ThreadStart(PollingLoop)); _pollingThread.IsBackground = true; _pollingThread.Name = nameof(PollingFileWatcher); + + CreateKnownFilesSnapshot(); + _pollingThread.Start(); } @@ -55,17 +58,6 @@ namespace Microsoft.DotNet.Watcher.Core.Internal set { EnsureNotDisposed(); - - if (value == true) - { - CreateKnownFilesSnapshot(); - - if (_pollingThread.ThreadState == System.Threading.ThreadState.Unstarted) - { - // Start the loop the first time events are enabled - _pollingThread.Start(); - } - } _raiseEvents = value; } } @@ -124,6 +116,7 @@ namespace Microsoft.DotNet.Watcher.Core.Internal else { var fileMeta = _knownEntities[fullFilePath]; + if (fileMeta.FileInfo.LastWriteTime != f.LastWriteTime) { // File changed diff --git a/test/TestApps/AppWithDeps/Program.cs b/test/TestApps/AppWithDeps/Program.cs index 6c67ed0901..a5aaf90366 100644 --- a/test/TestApps/AppWithDeps/Program.cs +++ b/test/TestApps/AppWithDeps/Program.cs @@ -4,20 +4,36 @@ using System; using System.Diagnostics; using System.IO; +using System.Threading; namespace ConsoleApplication { public class Program { + private static readonly int processId = Process.GetCurrentProcess().Id; + public static void Main(string[] args) { - Console.WriteLine("AppWithDeps started."); + ConsoleWrite("AppWithDeps started."); - var processId = Process.GetCurrentProcess().Id; File.AppendAllLines(args[0], new string[] { $"{processId}" }); File.WriteAllText(args[0] + ".started", ""); - Console.ReadLine(); + Block(); + } + + private static void ConsoleWrite(string text) + { + Console.WriteLine($"[{processId}] {text}"); + } + + private static void Block() + { + while (true) + { + ConsoleWrite("Blocked..."); + Thread.Sleep(1000); + } } } } diff --git a/test/TestApps/GlobbingApp/Program.cs b/test/TestApps/GlobbingApp/Program.cs index ae996205d5..9e89b57a60 100644 --- a/test/TestApps/GlobbingApp/Program.cs +++ b/test/TestApps/GlobbingApp/Program.cs @@ -4,20 +4,36 @@ using System; using System.Diagnostics; using System.IO; +using System.Threading; namespace ConsoleApplication { public class Program { + private static readonly int processId = Process.GetCurrentProcess().Id; + public static void Main(string[] args) { - Console.WriteLine("GlobbingApp started."); + ConsoleWrite("GlobbingApp started."); - var processId = Process.GetCurrentProcess().Id; File.AppendAllLines(args[0], new string[] { $"{processId}" }); File.WriteAllText(args[0] + ".started", ""); - Console.ReadLine(); + Block(); + } + + private static void ConsoleWrite(string text) + { + Console.WriteLine($"[{processId}] {text}"); + } + + private static void Block() + { + while (true) + { + ConsoleWrite("Blocked..."); + Thread.Sleep(1000); + } } } } diff --git a/test/TestApps/NoDepsApp/Program.cs b/test/TestApps/NoDepsApp/Program.cs index 2309fabd26..cbff2063f8 100644 --- a/test/TestApps/NoDepsApp/Program.cs +++ b/test/TestApps/NoDepsApp/Program.cs @@ -4,23 +4,39 @@ using System; using System.Diagnostics; using System.IO; +using System.Threading; namespace ConsoleApplication { public class Program { + private static readonly int processId = Process.GetCurrentProcess().Id; + public static void Main(string[] args) { - Console.WriteLine("NoDepsApp started."); + ConsoleWrite("NoDepsApp started."); - var processId = Process.GetCurrentProcess().Id; File.AppendAllLines(args[0], new string[] { $"{processId}" }); File.WriteAllText(args[0] + ".started", ""); if (args.Length > 1 && args[1] == "--no-exit") { - Console.ReadLine(); + Block(); + } + } + + private static void ConsoleWrite(string text) + { + Console.WriteLine($"[{processId}] {text}"); + } + + private static void Block() + { + while (true) + { + ConsoleWrite("Blocked..."); + Thread.Sleep(1000); } } } diff --git a/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs b/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs index d31cce667d..9a652f4325 100644 --- a/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs +++ b/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs @@ -65,6 +65,10 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests }; watcher.EnableRaisingEvents = true; + // On Unix the file write time is in 1s increments; + // if we don't wait, there's a chance that the polling + // watcher will not detect the change + Thread.Sleep(1000); File.WriteAllText(testFileFullPath, string.Empty); Assert.True(changedEv.WaitOne(DefaultTimeout)); @@ -113,10 +117,8 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests }); } - [Theory] - [InlineData(true)] - [InlineData(false)] - public void FileInSubdirectory(bool usePolling) + [Fact] + public void FileInSubdirectory() { UsingTempDirectory(dir => { @@ -127,7 +129,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests File.WriteAllText(testFileFullPath, string.Empty); using (var changedEv = new ManualResetEvent(false)) - using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling)) + using (var watcher = FileWatcherFactory.CreateWatcher(dir, true)) { var filesChanged = new HashSet(); @@ -144,6 +146,10 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests }; watcher.EnableRaisingEvents = true; + // On Unix the file write time is in 1s increments; + // if we don't wait, there's a chance that the polling + // watcher will not detect the change + Thread.Sleep(1000); File.WriteAllText(testFileFullPath, string.Empty); Assert.True(changedEv.WaitOne(DefaultTimeout)); @@ -169,6 +175,11 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests watcher.EnableRaisingEvents = false; var testFileFullPath = Path.Combine(dir, "foo"); + + // On Unix the file write time is in 1s increments; + // if we don't wait, there's a chance that the polling + // watcher will not detect the change + Thread.Sleep(1000); File.WriteAllText(testFileFullPath, string.Empty); Assert.False(changedEv.WaitOne(DefaultTimeout / 2)); @@ -192,6 +203,11 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } var testFileFullPath = Path.Combine(dir, "foo"); + + // On Unix the file write time is in 1s increments; + // if we don't wait, there's a chance that the polling + // watcher will not detect the change + Thread.Sleep(1000); File.WriteAllText(testFileFullPath, string.Empty); Assert.False(changedEv.WaitOne(DefaultTimeout / 2)); @@ -226,6 +242,11 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests }; watcher.EnableRaisingEvents = true; + // On Unix the file write time is in 1s increments; + // if we don't wait, there's a chance that the polling + // watcher will not detect the change + Thread.Sleep(1000); + File.WriteAllText(testFileFullPath, string.Empty); Assert.True(changedEv.WaitOne(DefaultTimeout)); @@ -253,24 +274,44 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests }; watcher.EnableRaisingEvents = true; + // On Unix the file write time is in 1s increments; + // if we don't wait, there's a chance that the polling + // watcher will not detect the change + Thread.Sleep(1000); + var testFileFullPath = Path.Combine(dir, "foo1"); File.WriteAllText(testFileFullPath, string.Empty); Assert.True(changedEv.WaitOne(DefaultTimeout)); Assert.Equal(testFileFullPath, filesChanged.Single()); filesChanged.Clear(); + // On Unix the file write time is in 1s increments; + // if we don't wait, there's a chance that the polling + // watcher will not detect the change + Thread.Sleep(1000); + testFileFullPath = Path.Combine(dir, "foo2"); File.WriteAllText(testFileFullPath, string.Empty); Assert.True(changedEv.WaitOne(DefaultTimeout)); Assert.Equal(testFileFullPath, filesChanged.Single()); filesChanged.Clear(); + // On Unix the file write time is in 1s increments; + // if we don't wait, there's a chance that the polling + // watcher will not detect the change + Thread.Sleep(1000); + testFileFullPath = Path.Combine(dir, "foo3"); File.WriteAllText(testFileFullPath, string.Empty); Assert.True(changedEv.WaitOne(DefaultTimeout)); Assert.Equal(testFileFullPath, filesChanged.Single()); filesChanged.Clear(); + // On Unix the file write time is in 1s increments; + // if we don't wait, there's a chance that the polling + // watcher will not detect the change + Thread.Sleep(1000); + File.WriteAllText(testFileFullPath, string.Empty); Assert.True(changedEv.WaitOne(DefaultTimeout)); Assert.Equal(testFileFullPath, filesChanged.Single()); From 98b73cbec5f845cddf1dcffc03ed4cb1d204a7b9 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Thu, 14 Apr 2016 14:01:34 -0700 Subject: [PATCH 0170/1029] Migrate tests, tools and samples to portable --- .../project.json | 15 +++++++++++---- .../project.json | 11 ++++++++--- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index 0b423932f0..f05677f95c 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -11,10 +11,13 @@ }, "testRunner": "xunit", "frameworks": { - "netstandardapp1.5": { + "netcoreapp1.0": { "dependencies": { + "Microsoft.NETCore.App": { + "version": "1.0.0-*", + "type": "platform" + }, "dotnet-test-xunit": "1.0.0-dev-*", - "NETStandard.Library": "1.5.0-*", "System.Diagnostics.Process": "4.1.0-*" }, "imports": [ @@ -24,8 +27,12 @@ }, "net451": { "frameworkAssemblies": { - "System.IO": { "type": "build" }, - "System.Runtime": { "type": "build" } + "System.IO": { + "type": "build" + }, + "System.Runtime": { + "type": "build" + } } } } diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index ab7264c378..63433fa2c6 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -11,10 +11,13 @@ "keyFile": "../../tools/Key.snk" }, "frameworks": { - "netstandardapp1.5": { + "netcoreapp1.0": { "dependencies": { + "Microsoft.NETCore.App": { + "version": "1.0.0-*", + "type": "platform" + }, "dotnet-test-xunit": "1.0.0-dev-*", - "NETStandard.Library": "1.5.0-*", "System.Diagnostics.Process": "4.1.0-*" }, "imports": [ @@ -24,7 +27,9 @@ }, "net451": { "frameworkAssemblies": { - "System.Runtime": { "type": "build" } + "System.Runtime": { + "type": "build" + } } } } From 9337f3e48e1d609b3d88e129a5676ec3185b2cb2 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Mon, 18 Apr 2016 16:28:14 -0700 Subject: [PATCH 0171/1029] Migrate tests, tools and samples to portable --- .../project.json | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index 4dcf2002cf..9455e29da1 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -3,18 +3,23 @@ "warningsAsErrors": true }, "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1-*", "Microsoft.AspNetCore.JsonPatch": "1.0.0-*", "Microsoft.AspNetCore.Testing": "1.0.0-*", "xunit": "2.1.0" }, "testRunner": "xunit", "frameworks": { - "netstandardapp1.5": { + "netcoreapp1.0": { "dependencies": { + "Microsoft.NETCore.App": { + "version": "1.0.0-*", + "type": "platform" + }, "moq.netcore": "4.4.0-beta8", "dotnet-test-xunit": "1.0.0-dev-*", - "NETStandard.Library": "1.5.0-*", - "System.Diagnostics.Process": "4.1.0-*" + "System.Diagnostics.Process": "4.1.0-*", + "System.Diagnostics.TraceSource": "4.0.0-*" }, "imports": [ "dnxcore50", @@ -23,9 +28,15 @@ }, "net451": { "frameworkAssemblies": { - "System.Linq.Expressions": { "type": "build" }, - "System.Runtime": { "type": "build" }, - "System.Threading.Tasks": { "type": "build" } + "System.Linq.Expressions": { + "type": "build" + }, + "System.Runtime": { + "type": "build" + }, + "System.Threading.Tasks": { + "type": "build" + } }, "dependencies": { "Moq": "4.2.1312.1622", From f94faf427623012a3f760ccffb3aba59f004e00e Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Mon, 18 Apr 2016 16:36:54 -0700 Subject: [PATCH 0172/1029] Bring Microsoft.NETCore.Platforms dependency back --- test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json | 1 + test/Microsoft.Extensions.WebEncoders.Tests/project.json | 1 + 2 files changed, 2 insertions(+) diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index f05677f95c..6a1156028f 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -4,6 +4,7 @@ "keyFile": "../../tools/Key.snk" }, "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1-*", "Microsoft.AspNetCore.Html.Abstractions": "1.0.0-*", "Microsoft.AspNetCore.Testing": "1.0.0-*", "Microsoft.Extensions.WebEncoders": "1.0.0-*", diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index 63433fa2c6..69cdc308b0 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -1,5 +1,6 @@ { "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1-*", "Microsoft.Extensions.DependencyInjection": "1.0.0-*", "Microsoft.Extensions.WebEncoders": "1.0.0-*", "xunit": "2.1.0" From 684ee87f20be9cdf0af3442fa4032780e4168da2 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Mon, 18 Apr 2016 16:57:52 -0700 Subject: [PATCH 0173/1029] Fix the prefix comparison --- .../Internal/FileWatcher/PollingFileWatcher.cs | 3 ++- .../Internal/Implementation/FileWatcher.cs | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/PollingFileWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/PollingFileWatcher.cs index 2bc335f76a..d1f2dac231 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/PollingFileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/PollingFileWatcher.cs @@ -150,7 +150,8 @@ namespace Microsoft.DotNet.Watcher.Core.Internal private void RecordChange(FileSystemInfo fileInfo) { - if (_changes.Contains(fileInfo.FullName) || + if (fileInfo == null || + _changes.Contains(fileInfo.FullName) || fileInfo.FullName.Equals(_watchedDirectory.FullName, StringComparison.Ordinal)) { return; diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs index 388f7f52ab..e0dbcabed5 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; namespace Microsoft.DotNet.Watcher.Core.Internal @@ -39,6 +40,8 @@ namespace Microsoft.DotNet.Watcher.Core.Internal private void AddDirectoryWatcher(string directory) { + directory = EnsureTrailingSlash(directory); + var alreadyWatched = _watchers .Where(d => directory.StartsWith(d.Key)) .Any(); @@ -99,5 +102,16 @@ namespace Microsoft.DotNet.Watcher.Core.Internal throw new ObjectDisposedException(nameof(FileWatcher)); } } + + private static string EnsureTrailingSlash(string path) + { + if (!string.IsNullOrEmpty(path) && + path[path.Length - 1] != Path.DirectorySeparatorChar) + { + return path + Path.DirectorySeparatorChar; + } + + return path; + } } } \ No newline at end of file From afe01eedbf58aa4401db21b922e63f3dcada511e Mon Sep 17 00:00:00 2001 From: moozzyk Date: Tue, 19 Apr 2016 10:38:59 -0700 Subject: [PATCH 0174/1029] Renaming dotnet-watch folders to Microsoft.DotNet.Watcher.Tools --- dotnet-watch.sln => Microsoft.DotNet.Watcher.Tools.sln | 4 ++-- .../CommandOutputLogger.cs | 0 .../CommandOutputProvider.cs | 0 .../Microsoft.DotNet.Watcher.Tools.xproj} | 0 .../Program.cs | 0 .../Properties/AssemblyInfo.cs | 0 .../project.json | 0 .../AppWithDepsTests.cs | 0 .../FileWatcherTests.cs | 0 .../GlobbingAppTests.cs | 0 .../Microsoft.DotNet.Watcher.Tools.FunctionalTests.xproj} | 0 .../NoDepsAppTests.cs | 0 .../Properties/AssemblyInfo.cs | 0 .../Scenario/DotNetWatchScenario.cs | 0 .../Scenario/ProjectToolScenario.cs | 0 .../WaitForFileToChange.cs | 0 .../Waiters.cs | 0 .../project.json | 0 18 files changed, 2 insertions(+), 2 deletions(-) rename dotnet-watch.sln => Microsoft.DotNet.Watcher.Tools.sln (91%) rename src/{dotnet-watch => Microsoft.DotNet.Watcher.Tools}/CommandOutputLogger.cs (100%) rename src/{dotnet-watch => Microsoft.DotNet.Watcher.Tools}/CommandOutputProvider.cs (100%) rename src/{dotnet-watch/dotnet-watch.xproj => Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.xproj} (100%) rename src/{dotnet-watch => Microsoft.DotNet.Watcher.Tools}/Program.cs (100%) rename src/{dotnet-watch => Microsoft.DotNet.Watcher.Tools}/Properties/AssemblyInfo.cs (100%) rename src/{dotnet-watch => Microsoft.DotNet.Watcher.Tools}/project.json (100%) rename test/{dotnet-watch.FunctionalTests => Microsoft.DotNet.Watcher.Tools.FunctionalTests}/AppWithDepsTests.cs (100%) rename test/{dotnet-watch.FunctionalTests => Microsoft.DotNet.Watcher.Tools.FunctionalTests}/FileWatcherTests.cs (100%) rename test/{dotnet-watch.FunctionalTests => Microsoft.DotNet.Watcher.Tools.FunctionalTests}/GlobbingAppTests.cs (100%) rename test/{dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.xproj => Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.xproj} (100%) rename test/{dotnet-watch.FunctionalTests => Microsoft.DotNet.Watcher.Tools.FunctionalTests}/NoDepsAppTests.cs (100%) rename test/{dotnet-watch.FunctionalTests => Microsoft.DotNet.Watcher.Tools.FunctionalTests}/Properties/AssemblyInfo.cs (100%) rename test/{dotnet-watch.FunctionalTests => Microsoft.DotNet.Watcher.Tools.FunctionalTests}/Scenario/DotNetWatchScenario.cs (100%) rename test/{dotnet-watch.FunctionalTests => Microsoft.DotNet.Watcher.Tools.FunctionalTests}/Scenario/ProjectToolScenario.cs (100%) rename test/{dotnet-watch.FunctionalTests => Microsoft.DotNet.Watcher.Tools.FunctionalTests}/WaitForFileToChange.cs (100%) rename test/{dotnet-watch.FunctionalTests => Microsoft.DotNet.Watcher.Tools.FunctionalTests}/Waiters.cs (100%) rename test/{dotnet-watch.FunctionalTests => Microsoft.DotNet.Watcher.Tools.FunctionalTests}/project.json (100%) diff --git a/dotnet-watch.sln b/Microsoft.DotNet.Watcher.Tools.sln similarity index 91% rename from dotnet-watch.sln rename to Microsoft.DotNet.Watcher.Tools.sln index c35ff1f2d6..05d379e36b 100644 --- a/dotnet-watch.sln +++ b/Microsoft.DotNet.Watcher.Tools.sln @@ -5,7 +5,7 @@ VisualStudioVersion = 14.0.23107.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66517987-2A5A-4330-B130-207039378FD4}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-watch", "src\dotnet-watch\dotnet-watch.xproj", "{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Watcher.Tools", "src\Microsoft.DotNet.Watcher.Tools\Microsoft.DotNet.Watcher.Tools.xproj", "{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}" EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Watcher.Core", "src\Microsoft.DotNet.Watcher.Core\Microsoft.DotNet.Watcher.Core.xproj", "{D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}" EndProject @@ -17,7 +17,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F5B382BC-258F-46E1-AC3D-10E5CCD55134}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-watch.FunctionalTests", "test\dotnet-watch.FunctionalTests\dotnet-watch.FunctionalTests.xproj", "{16BADE2F-1184-4518-8A70-B68A19D0805B}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Watcher.Tools.FunctionalTests", "test\Microsoft.DotNet.Watcher.Tools.FunctionalTests\Microsoft.DotNet.Watcher.Tools.FunctionalTests.xproj", "{16BADE2F-1184-4518-8A70-B68A19D0805B}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestApps", "TestApps", "{2876B12E-5841-4792-85A8-2929AEE11885}" EndProject diff --git a/src/dotnet-watch/CommandOutputLogger.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandOutputLogger.cs similarity index 100% rename from src/dotnet-watch/CommandOutputLogger.cs rename to src/Microsoft.DotNet.Watcher.Tools/CommandOutputLogger.cs diff --git a/src/dotnet-watch/CommandOutputProvider.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs similarity index 100% rename from src/dotnet-watch/CommandOutputProvider.cs rename to src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs diff --git a/src/dotnet-watch/dotnet-watch.xproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.xproj similarity index 100% rename from src/dotnet-watch/dotnet-watch.xproj rename to src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.xproj diff --git a/src/dotnet-watch/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs similarity index 100% rename from src/dotnet-watch/Program.cs rename to src/Microsoft.DotNet.Watcher.Tools/Program.cs diff --git a/src/dotnet-watch/Properties/AssemblyInfo.cs b/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs similarity index 100% rename from src/dotnet-watch/Properties/AssemblyInfo.cs rename to src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs diff --git a/src/dotnet-watch/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json similarity index 100% rename from src/dotnet-watch/project.json rename to src/Microsoft.DotNet.Watcher.Tools/project.json diff --git a/test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs diff --git a/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/FileWatcherTests.cs rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs diff --git a/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs diff --git a/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.xproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.xproj similarity index 100% rename from test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.xproj rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.xproj diff --git a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs diff --git a/test/dotnet-watch.FunctionalTests/Properties/AssemblyInfo.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Properties/AssemblyInfo.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/Properties/AssemblyInfo.cs rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Properties/AssemblyInfo.cs diff --git a/test/dotnet-watch.FunctionalTests/Scenario/DotNetWatchScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/Scenario/DotNetWatchScenario.cs rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs diff --git a/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs diff --git a/test/dotnet-watch.FunctionalTests/WaitForFileToChange.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/WaitForFileToChange.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/WaitForFileToChange.cs rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/WaitForFileToChange.cs diff --git a/test/dotnet-watch.FunctionalTests/Waiters.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Waiters.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/Waiters.cs rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Waiters.cs diff --git a/test/dotnet-watch.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json similarity index 100% rename from test/dotnet-watch.FunctionalTests/project.json rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json From c248e539f3004bb073efe0c94dc417dd5848202d Mon Sep 17 00:00:00 2001 From: moozzyk Date: Tue, 19 Apr 2016 11:26:40 -0700 Subject: [PATCH 0175/1029] Renaming namespaces and fixing tests --- NuGetPackageVerifier.json | 2 +- src/Microsoft.DotNet.Watcher.Tools/CommandOutputLogger.cs | 2 +- src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs | 2 +- src/Microsoft.DotNet.Watcher.Tools/Program.cs | 2 +- src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs | 1 - src/Microsoft.DotNet.Watcher.Tools/project.json | 1 + .../AppWithDepsTests.cs | 2 +- .../FileWatcherTests.cs | 2 +- .../GlobbingAppTests.cs | 2 +- .../NoDepsAppTests.cs | 2 +- .../Scenario/DotNetWatchScenario.cs | 4 ++-- .../Scenario/ProjectToolScenario.cs | 2 +- .../WaitForFileToChange.cs | 2 +- .../Microsoft.DotNet.Watcher.Tools.FunctionalTests/Waiters.cs | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index d80b811540..447bab830f 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -4,7 +4,7 @@ "AdxVerificationCompositeRule" ], "packages": { - "dotnet-watch": { }, + "Microsoft.DotNet.Watcher.Tools": { }, "Microsoft.DotNet.Watcher.Core": { } } }, diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandOutputLogger.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandOutputLogger.cs index aeb90f45c2..9ad0149db1 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandOutputLogger.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandOutputLogger.cs @@ -5,7 +5,7 @@ using System; using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Logging; -namespace Microsoft.DotNet.Watcher +namespace Microsoft.DotNet.Watcher.Tools { /// /// Logger to print formatted command output. diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs index fd4945a078..a7ce107196 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs @@ -5,7 +5,7 @@ using System; using Microsoft.Extensions.PlatformAbstractions; using Microsoft.Extensions.Logging; -namespace Microsoft.DotNet.Watcher +namespace Microsoft.DotNet.Watcher.Tools { public class CommandOutputProvider : ILoggerProvider { diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index 7f5c0ac257..96fdb8404a 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -11,7 +11,7 @@ using Microsoft.Extensions.PlatformAbstractions; using Microsoft.DotNet.Watcher.Core; using Microsoft.Extensions.Logging; -namespace Microsoft.DotNet.Watcher +namespace Microsoft.DotNet.Watcher.Tools { public class Program { diff --git a/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs b/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs index 43612c95ba..e29eda63c2 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs @@ -5,7 +5,6 @@ using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; -[assembly:InternalsVisibleTo("dotnet-watch.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: AssemblyMetadata("Serviceable", "True")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: AssemblyCompany("Microsoft Corporation.")] diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index 3017b1b110..55166cb20b 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -1,6 +1,7 @@ { "version": "1.0.0-*", "compilationOptions": { + "outputName": "dotnet-watch", "warningsAsErrors": true, "emitEntryPoint": true, "keyFile": "../../tools/Key.snk", diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs index 55678cf11b..913c79abb2 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs @@ -6,7 +6,7 @@ using System.Diagnostics; using System.IO; using Xunit; -namespace Microsoft.DotNet.Watcher.FunctionalTests +namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { public class AppWithDepsTests { diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs index 9a652f4325..6de6151209 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs @@ -9,7 +9,7 @@ using System.Threading; using Microsoft.DotNet.Watcher.Core.Internal; using Xunit; -namespace Microsoft.DotNet.Watcher.FunctionalTests +namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { public class FileWatcherTests { diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs index 9df0d466f3..456d7a7ec0 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs @@ -7,7 +7,7 @@ using System.IO; using System.Threading; using Xunit; -namespace Microsoft.DotNet.Watcher.FunctionalTests +namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { public class GlobbingAppTests { diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs index 418fe53fe1..5ea274b3b1 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs @@ -6,7 +6,7 @@ using System.Diagnostics; using System.IO; using Xunit; -namespace Microsoft.DotNet.Watcher.FunctionalTests +namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { public class NoDepsAppTests { diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs index 2a0b2e441c..10a20ce7ab 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs @@ -7,11 +7,11 @@ using System.Diagnostics; using System.IO; using Microsoft.Extensions.Internal; -namespace Microsoft.DotNet.Watcher.FunctionalTests +namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { public class DotNetWatchScenario : IDisposable { - protected const string DotnetWatch = "dotnet-watch"; + protected const string DotnetWatch = "Microsoft.DotNet.Watcher.Tools"; protected static readonly string _repositoryRoot = FindRepoRoot(); protected static readonly string _artifactsFolder = Path.Combine(_repositoryRoot, "artifacts", "build"); diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs index e2f548e7a2..a5abaab1fd 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -10,7 +10,7 @@ using System.Threading; using System.Xml.Linq; using Newtonsoft.Json.Linq; -namespace Microsoft.DotNet.Watcher.FunctionalTests +namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { public class ProjectToolScenario: IDisposable { diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/WaitForFileToChange.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/WaitForFileToChange.cs index 64c59c61dc..38ced6b437 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/WaitForFileToChange.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/WaitForFileToChange.cs @@ -6,7 +6,7 @@ using System.IO; using System.Threading; using Microsoft.DotNet.Watcher.Core.Internal; -namespace Microsoft.DotNet.Watcher.FunctionalTests +namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { public class WaitForFileToChange : IDisposable { diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Waiters.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Waiters.cs index a65a80feb3..113d339769 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Waiters.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Waiters.cs @@ -6,7 +6,7 @@ using System.Diagnostics; using System.IO; using System.Threading; -namespace Microsoft.DotNet.Watcher.FunctionalTests +namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { public static class Waiters { From 265c90cbd1947fb5ca94d0f762c7b28a0efd5154 Mon Sep 17 00:00:00 2001 From: moozzyk Date: Tue, 19 Apr 2016 11:54:44 -0700 Subject: [PATCH 0176/1029] Moving dotnet-watch to netcoreapp1.0 --- src/Microsoft.DotNet.Watcher.Tools/project.json | 2 +- .../project.json | 10 ++++++++-- test/TestApps/AppWithDeps/project.json | 2 +- test/TestApps/Dependency/project.json | 2 +- test/TestApps/GlobbingApp/project.json | 2 +- test/TestApps/NoDepsApp/project.json | 2 +- 6 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index 55166cb20b..d08d1b0ee7 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -15,7 +15,7 @@ "Microsoft.Extensions.Logging.Console": "1.0.0-*" }, "frameworks": { - "netstandard1.5": { + "netcoreapp1.0": { "imports": [ "portable-net451+win8", "dnxcore50" diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index ce80cc69aa..b6145e44b3 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -17,11 +17,17 @@ "xunit": "2.1.0" }, "frameworks": { - "netstandardapp1.5": { + "netcoreapp1.0": { "imports": [ "portable-net451+win8", "dnxcore50" - ] + ], + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-*" + } + } } }, "testRunner": "xunit" diff --git a/test/TestApps/AppWithDeps/project.json b/test/TestApps/AppWithDeps/project.json index a102058c92..234e21ed87 100644 --- a/test/TestApps/AppWithDeps/project.json +++ b/test/TestApps/AppWithDeps/project.json @@ -9,7 +9,7 @@ }, "frameworks": { - "netstandardapp1.5": { + "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", diff --git a/test/TestApps/Dependency/project.json b/test/TestApps/Dependency/project.json index a39c53433e..9966f18ccc 100644 --- a/test/TestApps/Dependency/project.json +++ b/test/TestApps/Dependency/project.json @@ -6,7 +6,7 @@ }, "frameworks": { - "netstandardapp1.5": { + "netstandard1.5": { "imports": [ "dnxcore50", "portable-net451+win8" diff --git a/test/TestApps/GlobbingApp/project.json b/test/TestApps/GlobbingApp/project.json index 46e1d29d53..2f3ca272dd 100644 --- a/test/TestApps/GlobbingApp/project.json +++ b/test/TestApps/GlobbingApp/project.json @@ -12,7 +12,7 @@ ], "frameworks": { - "netstandardapp1.5": { + "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", diff --git a/test/TestApps/NoDepsApp/project.json b/test/TestApps/NoDepsApp/project.json index a01cd35453..f79acee579 100644 --- a/test/TestApps/NoDepsApp/project.json +++ b/test/TestApps/NoDepsApp/project.json @@ -5,7 +5,7 @@ }, "frameworks": { - "netstandardapp1.5": { + "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", From fa2ec5fdcdf1eedde60e9fa6fb1188bd1064cbb7 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 19 Apr 2016 14:53:55 -0700 Subject: [PATCH 0177/1029] Use latest build of dotnet-test-xunit --- .../Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index b6145e44b3..4484e3111b 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -4,7 +4,7 @@ "keyFile": "../../tools/Key.snk" }, "dependencies": { - "dotnet-test-xunit": "1.0.0-dev-*", + "dotnet-test-xunit": "1.0.0-*", "Microsoft.Extensions.DependencyInjection": "1.0.0-*", "Microsoft.Extensions.Process.Sources": { "type": "build", From cfc071071b00f51d0fc8f1d8e2f3033b145d7af7 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 19 Apr 2016 14:54:02 -0700 Subject: [PATCH 0178/1029] Use latest build of dotnet-test-xunit --- test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json | 2 +- test/Microsoft.Extensions.WebEncoders.Tests/project.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index 6a1156028f..15b3e92d51 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -18,7 +18,7 @@ "version": "1.0.0-*", "type": "platform" }, - "dotnet-test-xunit": "1.0.0-dev-*", + "dotnet-test-xunit": "1.0.0-*", "System.Diagnostics.Process": "4.1.0-*" }, "imports": [ diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index 69cdc308b0..43836130e5 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -18,7 +18,7 @@ "version": "1.0.0-*", "type": "platform" }, - "dotnet-test-xunit": "1.0.0-dev-*", + "dotnet-test-xunit": "1.0.0-*", "System.Diagnostics.Process": "4.1.0-*" }, "imports": [ From 088d8b291ac4beaddebd6ec0a97747ef3dc7ba12 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 19 Apr 2016 14:54:04 -0700 Subject: [PATCH 0179/1029] Use latest build of dotnet-test-xunit --- test/Microsoft.AspNetCore.JsonPatch.Test/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index 9455e29da1..8dfb164801 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -17,7 +17,7 @@ "type": "platform" }, "moq.netcore": "4.4.0-beta8", - "dotnet-test-xunit": "1.0.0-dev-*", + "dotnet-test-xunit": "1.0.0-*", "System.Diagnostics.Process": "4.1.0-*", "System.Diagnostics.TraceSource": "4.0.0-*" }, From 21951d62f3c923d4dcc7934ca78154660de1a26c Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Fri, 22 Apr 2016 10:38:24 -0700 Subject: [PATCH 0180/1029] Fix command line parsing around the -- separator --- Microsoft.DotNet.Watcher.Tools.sln | 9 +- .../DotNetWatcher.cs | 34 +++---- src/Microsoft.DotNet.Watcher.Tools/Program.cs | 71 ++++++++++---- .../Properties/AssemblyInfo.cs | 4 +- .../ArgumentSeparatorTests.cs | 95 +++++++++++++++++++ ...Microsoft.DotNet.Watcher.Tools.Tests.xproj | 19 ++++ .../project.json | 27 ++++++ 7 files changed, 216 insertions(+), 43 deletions(-) create mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/ArgumentSeparatorTests.cs create mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.xproj create mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/project.json diff --git a/Microsoft.DotNet.Watcher.Tools.sln b/Microsoft.DotNet.Watcher.Tools.sln index 05d379e36b..08e32fa200 100644 --- a/Microsoft.DotNet.Watcher.Tools.sln +++ b/Microsoft.DotNet.Watcher.Tools.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +VisualStudioVersion = 14.0.25123.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66517987-2A5A-4330-B130-207039378FD4}" EndProject @@ -29,6 +29,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AppWithDeps", "test\TestApp EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Dependency", "test\TestApps\Dependency\Dependency.xproj", "{2F48041A-F7D1-478F-9C38-D41F0F05E8CA}" EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Watcher.Tools.Tests", "test\Microsoft.DotNet.Watcher.Tools.Tests\Microsoft.DotNet.Watcher.Tools.Tests.xproj", "{2E2FE108-0EB7-48CE-BD52-147E90180090}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -63,6 +65,10 @@ Global {2F48041A-F7D1-478F-9C38-D41F0F05E8CA}.Debug|Any CPU.Build.0 = Debug|Any CPU {2F48041A-F7D1-478F-9C38-D41F0F05E8CA}.Release|Any CPU.ActiveCfg = Release|Any CPU {2F48041A-F7D1-478F-9C38-D41F0F05E8CA}.Release|Any CPU.Build.0 = Release|Any CPU + {2E2FE108-0EB7-48CE-BD52-147E90180090}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E2FE108-0EB7-48CE-BD52-147E90180090}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E2FE108-0EB7-48CE-BD52-147E90180090}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E2FE108-0EB7-48CE-BD52-147E90180090}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -76,5 +82,6 @@ Global {2AB1A28B-2022-49EA-AF77-AC8A875915CC} = {2876B12E-5841-4792-85A8-2929AEE11885} {F7734E61-F510-41E0-AD15-301A64081CD1} = {2876B12E-5841-4792-85A8-2929AEE11885} {2F48041A-F7D1-478F-9C38-D41F0F05E8CA} = {2876B12E-5841-4792-85A8-2929AEE11885} + {2E2FE108-0EB7-48CE-BD52-147E90180090} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} EndGlobalSection EndGlobal diff --git a/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs index 9ef05d2eb0..61b1cc586b 100644 --- a/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.DotNet.Watcher.Core.Internal; @@ -58,29 +57,24 @@ namespace Microsoft.DotNet.Watcher.Core throw new ArgumentNullException(nameof(cancellationToken)); } - if (dotnetArguments.Length > 0) - { - dotnetArguments = new string[] { command, "--" } - .Concat(dotnetArguments) - .ToArray(); - } - else - { - dotnetArguments = new string[] { command }; - } + var fullDotnetArgs = new string[dotnetArguments.Length + 1]; + fullDotnetArgs[0] = command; - dotnetArguments = dotnetArguments - .Select(arg => + for (var i = 0; i < dotnetArguments.Length; i++) + { + var arg = dotnetArguments[i]; + foreach (char c in arg) { - // If the argument has spaces, make sure we quote it - if (arg.Contains(" ") || arg.Contains("\t")) + if (c == ' ' || + c == '\t') { - return $"\"{arg}\""; + arg = $"\"{arg}\""; + break; } - - return arg; - }) - .ToArray(); + } + fullDotnetArgs[i + 1] = arg; + } + dotnetArguments = fullDotnetArgs; var dotnetArgumentsAsString = string.Join(" ", dotnetArguments); diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index 96fdb8404a..776cf0cd2a 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -3,13 +3,12 @@ using System; using System.IO; -using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.Extensions.CommandLineUtils; -using Microsoft.Extensions.PlatformAbstractions; using Microsoft.DotNet.Watcher.Core; +using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.PlatformAbstractions; namespace Microsoft.DotNet.Watcher.Tools { @@ -50,31 +49,46 @@ namespace Microsoft.DotNet.Watcher.Tools // To pass "--help" to the app being watched, you must use "--": dotnet watch -- --help internal static void SeparateWatchArguments(string[] args, out string[] watchArgs, out string[] appArgs) { + if (args.Length == 0) + { + watchArgs = new string[0]; + appArgs = new string[0]; + return; + } + // Special case "--help" - if (args.Length > 0 && ( - args[0].Equals("--help", StringComparison.OrdinalIgnoreCase) || + if (args[0].Equals("--help", StringComparison.OrdinalIgnoreCase) || args[0].Equals("-h", StringComparison.OrdinalIgnoreCase) || - args[0].Equals("-?", StringComparison.OrdinalIgnoreCase))) + args[0].Equals("-?", StringComparison.OrdinalIgnoreCase)) { watchArgs = new string[] { args[0] }; appArgs = new string[0]; return; } - int argsIndex = -1; - watchArgs = args.TakeWhile((arg, idx) => + var separatorIndex = -1; + for (var i = 0; i < args.Length; i++) { - argsIndex = idx; - return !string.Equals(arg, AppArgumentSeparator, StringComparison.OrdinalIgnoreCase); - }).ToArray(); + if (string.Equals(args[i], AppArgumentSeparator, StringComparison.OrdinalIgnoreCase)) + { + separatorIndex = i; + break; + } + } - appArgs = args.Skip(argsIndex + 1).ToArray(); - - if (appArgs.Length == 0) + if (separatorIndex == -1) { - // If no explicit watcher arguments then all arguments get passed to the app being watched - appArgs = watchArgs; watchArgs = new string[0]; + appArgs = args; + } + else + { + watchArgs = new string[separatorIndex]; + Array.Copy(args, 0, watchArgs, 0, separatorIndex); + + var appArgsLength = args.Length - separatorIndex - 1; + appArgs = new string[appArgsLength]; + Array.Copy(args, separatorIndex + 1, appArgs, 0, appArgsLength); } } @@ -101,19 +115,34 @@ namespace Microsoft.DotNet.Watcher.Tools "Optional. The watcher will exit when a file change is detected instead of restarting the process. Default: not set.", CommandOptionType.NoValue); - app.OnExecute(() => { var projectToWatch = Path.Combine(Directory.GetCurrentDirectory(), ProjectModel.Project.FileName); + var command = commandArg.Value(); + if (!commandArg.HasValue()) + { + // The default command is "run". In this case we always assume the arguments are passed to the application being run. + // If you want a different behaviour for run you need to use --command and pass the full arguments + // Run is special because it requires a "--" before the arguments being passed to the application, + // so the two command below are equivalent and resolve to "dotnet run -- --foo": + // 1. dotnet watch --foo + // 2. dotnet watch --command run -- -- --foo (yes, there are two "--") + if (appArgs.Length > 0) + { + var newAppArgs = new string[appArgs.Length + 1]; + newAppArgs[0] = AppArgumentSeparator; + appArgs.CopyTo(newAppArgs, 1); + appArgs = newAppArgs; + } + + command = "run"; + } + var workingDir = workingDirArg.HasValue() ? workingDirArg.Value() : Path.GetDirectoryName(projectToWatch); - var command = commandArg.HasValue() ? - commandArg.Value() : - "run"; - var watcher = DotNetWatcher.CreateDefault(_loggerFactory); watcher.ExitOnChange = exitOnChangeArg.HasValue(); diff --git a/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs b/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs index e29eda63c2..35b4b58d45 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs @@ -9,4 +9,6 @@ using System.Runtime.CompilerServices; [assembly: NeutralResourcesLanguage("en-US")] [assembly: AssemblyCompany("Microsoft Corporation.")] [assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] -[assembly: AssemblyProduct("Microsoft .NET")] \ No newline at end of file +[assembly: AssemblyProduct("Microsoft .NET")] + +[assembly: InternalsVisibleTo("Microsoft.DotNet.Watcher.Tools.Tests, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/ArgumentSeparatorTests.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/ArgumentSeparatorTests.cs new file mode 100644 index 0000000000..a9178eb1ad --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/ArgumentSeparatorTests.cs @@ -0,0 +1,95 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Xunit; + +namespace Microsoft.DotNet.Watcher.Tools.Tests +{ + public class ArgumentSeparatorTests + { + [Theory] + [InlineData(new string[0], + new string[0], + new string[0])] + [InlineData(new string[] { "--" }, + new string[0], + new string[0])] + [InlineData(new string[] { "--appArg1" }, + new string[0], + new string[] { "--appArg1" })] + [InlineData(new string[] { "--command", "test" }, + new string[0], + new string[] { "--command", "test" })] + [InlineData(new string[] { "--command", "test", "--" }, + new string[] { "--command", "test" }, + new string[0])] + [InlineData(new string[] { "--command", "test", "--", "--appArg1", "arg1Value" }, + new string[] { "--command", "test" }, + new string[] { "--appArg1", "arg1Value" })] + [InlineData(new string[] { "--", "--appArg1", "arg1Value" }, + new string[0], + new string[] { "--appArg1", "arg1Value" })] + [InlineData(new string[] { "--", "--" }, + new string[0], + new string[] { "--" })] + [InlineData(new string[] { "--", "--", "--" }, + new string[0], + new string[] { "--", "--" })] + [InlineData(new string[] { "--command", "run", "--", "--", "--appArg", "foo" }, + new string[] { "--command", "run" }, + new string[] { "--", "--appArg", "foo" })] + [InlineData(new string[] { "--command", "run", "--", "-f", "net451", "--", "--appArg", "foo" }, + new string[] { "--command", "run" }, + new string[] { "-f", "net451", "--", "--appArg", "foo" })] + public void SeparateWatchArguments(string[] args, string[] expectedWatchArgs, string[] expectedAppArgs) + { + SeparateWatchArgumentsTest(args, expectedWatchArgs, expectedAppArgs); + } + + [Theory] + // Help is special if it's the first argument + [InlineData(new string[] { "--help" }, + new string[] { "--help" }, + new string[0])] + [InlineData(new string[] { "-h" }, + new string[] { "-h" }, + new string[0])] + [InlineData(new string[] { "-?" }, + new string[] { "-?" }, + new string[0])] + [InlineData(new string[] { "--help", "--this-is-ignored" }, + new string[] { "--help" }, + new string[0])] + [InlineData(new string[] { "--help", "--", "--this-is-ignored" }, + new string[] { "--help" }, + new string[0])] + // But not otherwise + [InlineData(new string[] { "--", "--help" }, + new string[0], + new string[] { "--help" })] + [InlineData(new string[] { "--foo", "--help" }, + new string[0], + new string[] { "--foo", "--help" })] + [InlineData(new string[] { "--foo", "--help" }, + new string[0], + new string[] { "--foo", "--help" })] + [InlineData(new string[] { "--foo", "--", "--help" }, + new string[] { "--foo" }, + new string[] { "--help" })] + public void SeparateWatchArguments_Help(string[] args, string[] expectedWatchArgs, string[] expectedAppArgs) + { + SeparateWatchArgumentsTest(args, expectedWatchArgs, expectedAppArgs); + } + + private static void SeparateWatchArgumentsTest(string[] args, string[] expectedWatchArgs, string[] expectedAppArgs) + { + string[] actualWatchArgs; + string[] actualAppArgs; + + Program.SeparateWatchArguments(args, out actualWatchArgs, out actualAppArgs); + + Assert.Equal(expectedWatchArgs, actualWatchArgs); + Assert.Equal(expectedAppArgs, actualAppArgs); + } + } +} diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.xproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.xproj new file mode 100644 index 0000000000..2c2d6b6b34 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.xproj @@ -0,0 +1,19 @@ + + + + 14.0.25123 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 2e2fe108-0eb7-48ce-bd52-147e90180090 + Microsoft.DotNet.Watcher.Tools.Tests + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json new file mode 100644 index 0000000000..4ce4fce759 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json @@ -0,0 +1,27 @@ +{ + "compilationOptions": { + "warningsAsErrors": true, + "keyFile": "../../tools/Key.snk" + }, + "dependencies": { + "dotnet-test-xunit": "1.0.0-*", + "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", + "NETStandard.Library": "1.5.0-*", + "xunit": "2.1.0" + }, + "frameworks": { + "netcoreapp1.0": { + "imports": [ + "portable-net451+win8", + "dnxcore50" + ], + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-*" + } + } + } + }, + "testRunner": "xunit" +} \ No newline at end of file From 2f8ef7ef0d90fa91f8267e1b249ad9793e729e7c Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Sat, 23 Apr 2016 22:09:32 -0700 Subject: [PATCH 0181/1029] Update the readme file with the new name --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d49bd76306..41acfad989 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,16 @@ dotnet-watch ### How To Install -Add `dotnet-watch` to the `tools` section of your `project.json` file: +Add `Microsoft.DotNet.Watcher.Tools` to the `tools` section of your `project.json` file: ``` { ... "tools": { - "dotnet-watch": "1.0.0-*" + "Microsoft.DotNet.Watcher.Tools": { + "version": "1.0.0-*", + "imports": "portable-net451+win8" + } } ... } From cb426cb325e6f184ffd36735e7d368209533d7d3 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 28 Apr 2016 08:34:42 -0700 Subject: [PATCH 0182/1029] Remove references to IRuntimeEnvironment --- .../CommandOutputProvider.cs | 7 +++---- src/Microsoft.DotNet.Watcher.Tools/Program.cs | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs index a7ce107196..595b713b0e 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs @@ -1,9 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; -using Microsoft.Extensions.PlatformAbstractions; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.PlatformAbstractions; namespace Microsoft.DotNet.Watcher.Tools { @@ -11,9 +10,9 @@ namespace Microsoft.DotNet.Watcher.Tools { private readonly bool _isWindows; - public CommandOutputProvider(IRuntimeEnvironment runtimeEnv) + public CommandOutputProvider() { - _isWindows = runtimeEnv.OperatingSystem == "Windows"; + _isWindows = PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows; } public ILogger CreateLogger(string name) diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index 776cf0cd2a..8ea1b8a2f0 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -22,7 +22,7 @@ namespace Microsoft.DotNet.Watcher.Tools { _loggerFactory = new LoggerFactory(); - var commandProvider = new CommandOutputProvider(PlatformServices.Default.Runtime); + var commandProvider = new CommandOutputProvider(); _loggerFactory.AddProvider(commandProvider); } From d22a638e5576c113c719e772d150a2ed97408e8d Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Thu, 28 Apr 2016 09:59:30 -0700 Subject: [PATCH 0183/1029] React to TryGetProject changes --- .../Internal/Implementation/ProjectProvider.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/ProjectProvider.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/ProjectProvider.cs index fc41f81888..a03bae0cf6 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/ProjectProvider.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/ProjectProvider.cs @@ -40,10 +40,16 @@ namespace Microsoft.DotNet.Watcher.Core.Internal { try { - var errors = new List(); - if (!ProjectReader.TryGetProject(projectFile, out project, errors)) + if (!ProjectReader.TryGetProject(projectFile, out project)) { - errorMessage = string.Join(Environment.NewLine, errors.Select(e => e.ToString())); + if (project?.Diagnostics != null && project.Diagnostics.Any()) + { + errorMessage = string.Join(Environment.NewLine, project.Diagnostics.Select(e => e.ToString())); + } + else + { + errorMessage = "Failed to read project.json"; + } } else { From 63a9d64394717f9876e307ccdc67c23ac49a16c7 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 2 May 2016 11:27:09 -0700 Subject: [PATCH 0184/1029] Fix build warnings --- src/Microsoft.DotNet.Watcher.Core/project.json | 8 +++++--- src/Microsoft.DotNet.Watcher.Tools/project.json | 8 +++++--- .../project.json | 2 +- test/Microsoft.DotNet.Watcher.Tools.Tests/project.json | 2 +- test/TestApps/AppWithDeps/project.json | 4 +--- test/TestApps/Dependency/project.json | 4 +--- test/TestApps/GlobbingApp/project.json | 5 ++--- test/TestApps/NoDepsApp/project.json | 5 ++--- 8 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index d6c75b463d..f6926c7dca 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -1,9 +1,11 @@ { "version": "1.0.0-*", - "compilationOptions": { + "buildOptions": { "warningsAsErrors": true, "keyFile": "../../tools/Key.snk", - "nowarn": [ "CS1591" ], + "nowarn": [ + "CS1591" + ], "xmlDoc": true }, "dependencies": { @@ -27,4 +29,4 @@ ] } } -} +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index d08d1b0ee7..867642edfe 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -1,11 +1,13 @@ { "version": "1.0.0-*", - "compilationOptions": { + "buildOptions": { "outputName": "dotnet-watch", "warningsAsErrors": true, "emitEntryPoint": true, "keyFile": "../../tools/Key.snk", - "nowarn": [ "CS1591" ], + "nowarn": [ + "CS1591" + ], "xmlDoc": true }, "dependencies": { @@ -28,4 +30,4 @@ } } } -} +} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index 4484e3111b..16b2386717 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -1,5 +1,5 @@ { - "compilationOptions": { + "buildOptions": { "warningsAsErrors": true, "keyFile": "../../tools/Key.snk" }, diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json index 4ce4fce759..44db712712 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json @@ -1,5 +1,5 @@ { - "compilationOptions": { + "buildOptions": { "warningsAsErrors": true, "keyFile": "../../tools/Key.snk" }, diff --git a/test/TestApps/AppWithDeps/project.json b/test/TestApps/AppWithDeps/project.json index 234e21ed87..8fbde9fc51 100644 --- a/test/TestApps/AppWithDeps/project.json +++ b/test/TestApps/AppWithDeps/project.json @@ -1,13 +1,11 @@ { "version": "1.0.0-*", - "compilationOptions": { + "buildOptions": { "emitEntryPoint": true }, - "dependencies": { "Dependency": "1.0.0" }, - "frameworks": { "netcoreapp1.0": { "dependencies": { diff --git a/test/TestApps/Dependency/project.json b/test/TestApps/Dependency/project.json index 9966f18ccc..2b16faf607 100644 --- a/test/TestApps/Dependency/project.json +++ b/test/TestApps/Dependency/project.json @@ -1,10 +1,8 @@ { "version": "1.0.0-*", - "dependencies": { "NETStandard.Library": "1.5.0-*" }, - "frameworks": { "netstandard1.5": { "imports": [ @@ -13,4 +11,4 @@ ] } } -} +} \ No newline at end of file diff --git a/test/TestApps/GlobbingApp/project.json b/test/TestApps/GlobbingApp/project.json index 2f3ca272dd..fd675dbad6 100644 --- a/test/TestApps/GlobbingApp/project.json +++ b/test/TestApps/GlobbingApp/project.json @@ -1,6 +1,6 @@ { "version": "1.0.0-*", - "compilationOptions": { + "buildOptions": { "emitEntryPoint": true }, "compile": [ @@ -10,7 +10,6 @@ "exclude": [ "exclude/*" ], - "frameworks": { "netcoreapp1.0": { "dependencies": { @@ -25,4 +24,4 @@ ] } } -} +} \ No newline at end of file diff --git a/test/TestApps/NoDepsApp/project.json b/test/TestApps/NoDepsApp/project.json index f79acee579..f0eb960bb6 100644 --- a/test/TestApps/NoDepsApp/project.json +++ b/test/TestApps/NoDepsApp/project.json @@ -1,9 +1,8 @@ { "version": "1.0.0-*", - "compilationOptions": { + "buildOptions": { "emitEntryPoint": true }, - "frameworks": { "netcoreapp1.0": { "dependencies": { @@ -18,4 +17,4 @@ ] } } -} +} \ No newline at end of file From a97ac1b23bbbe6e77042f874cc7b79d827632a97 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 2 May 2016 11:27:16 -0700 Subject: [PATCH 0185/1029] Fix build warnings --- .../project.json | 16 +++++++++------- .../project.json | 16 +++++++++------- .../project.json | 4 ++-- .../project.json | 4 ++-- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/project.json b/src/Microsoft.AspNetCore.Html.Abstractions/project.json index 69b0215834..d117f96abe 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/project.json +++ b/src/Microsoft.AspNetCore.Html.Abstractions/project.json @@ -1,14 +1,16 @@ { "version": "1.0.0-*", "description": "ASP.NET Core HTML abstractions used for building HTML content.\r\nCommonly used types:\r\nMicrosoft.AspNetCore.Html.HtmlEncodedString\r\nMicrosoft.AspNetCore.Html.IHtmlContent", - "tags": [ - "aspnetcore" - ], - "repository": { - "type": "git", - "url": "git://github.com/aspnet/htmlabstractions" + "packOptions": { + "repository": { + "type": "git", + "url": "git://github.com/aspnet/htmlabstractions" + }, + "tags": [ + "aspnetcore" + ] }, - "compilationOptions": { + "buildOptions": { "warningsAsErrors": true, "keyFile": "../../tools/Key.snk", "nowarn": [ diff --git a/src/Microsoft.Extensions.WebEncoders/project.json b/src/Microsoft.Extensions.WebEncoders/project.json index beeac94efe..857361e4e4 100644 --- a/src/Microsoft.Extensions.WebEncoders/project.json +++ b/src/Microsoft.Extensions.WebEncoders/project.json @@ -1,14 +1,16 @@ { "version": "1.0.0-*", "description": "Contains registration and configuration APIs to add the core framework encoders to a dependency injection container.", - "tags": [ - "aspnetcore" - ], - "repository": { - "type": "git", - "url": "git://github.com/aspnet/httpabstractions" + "packOptions": { + "repository": { + "type": "git", + "url": "git://github.com/aspnet/httpabstractions" + }, + "tags": [ + "aspnetcore" + ] }, - "compilationOptions": { + "buildOptions": { "warningsAsErrors": true, "allowUnsafe": true, "keyFile": "../../tools/Key.snk", diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index 15b3e92d51..2efabff127 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -1,9 +1,10 @@ { - "compilationOptions": { + "buildOptions": { "warningsAsErrors": true, "keyFile": "../../tools/Key.snk" }, "dependencies": { + "dotnet-test-xunit": "1.0.0-*", "Microsoft.NETCore.Platforms": "1.0.1-*", "Microsoft.AspNetCore.Html.Abstractions": "1.0.0-*", "Microsoft.AspNetCore.Testing": "1.0.0-*", @@ -18,7 +19,6 @@ "version": "1.0.0-*", "type": "platform" }, - "dotnet-test-xunit": "1.0.0-*", "System.Diagnostics.Process": "4.1.0-*" }, "imports": [ diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index 43836130e5..2cb866fcc3 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -1,12 +1,13 @@ { "dependencies": { + "dotnet-test-xunit": "1.0.0-*", "Microsoft.NETCore.Platforms": "1.0.1-*", "Microsoft.Extensions.DependencyInjection": "1.0.0-*", "Microsoft.Extensions.WebEncoders": "1.0.0-*", "xunit": "2.1.0" }, "testRunner": "xunit", - "compilationOptions": { + "buildOptions": { "allowUnsafe": true, "warningsAsErrors": true, "keyFile": "../../tools/Key.snk" @@ -18,7 +19,6 @@ "version": "1.0.0-*", "type": "platform" }, - "dotnet-test-xunit": "1.0.0-*", "System.Diagnostics.Process": "4.1.0-*" }, "imports": [ From 2cd905dd44caff74332a8dc85b7fbcd253f79387 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 2 May 2016 11:27:18 -0700 Subject: [PATCH 0186/1029] Fix build warnings --- .../project.json | 20 ++++++++++--------- .../project.json | 4 ++-- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index 0eeb88f010..1860893f6b 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -1,12 +1,7 @@ { "version": "1.0.0-*", "description": "ASP.NET Core support for JSON PATCH.", - "tags": [ - "aspnetcore", - "json", - "jsonpatch" - ], - "compilationOptions": { + "buildOptions": { "warningsAsErrors": true, "keyFile": "../../tools/Key.snk", "nowarn": [ @@ -14,9 +9,16 @@ ], "xmlDoc": true }, - "repository": { - "type": "git", - "url": "git://github.com/aspnet/jsonpatch" + "packOptions": { + "repository": { + "type": "git", + "url": "git://github.com/aspnet/jsonpatch" + }, + "tags": [ + "aspnetcore", + "json", + "jsonpatch" + ] }, "dependencies": { "Newtonsoft.Json": "8.0.3" diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index 8dfb164801..dac020cb6c 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -1,8 +1,9 @@ { - "compilationOptions": { + "buildOptions": { "warningsAsErrors": true }, "dependencies": { + "dotnet-test-xunit": "1.0.0-*", "Microsoft.NETCore.Platforms": "1.0.1-*", "Microsoft.AspNetCore.JsonPatch": "1.0.0-*", "Microsoft.AspNetCore.Testing": "1.0.0-*", @@ -17,7 +18,6 @@ "type": "platform" }, "moq.netcore": "4.4.0-beta8", - "dotnet-test-xunit": "1.0.0-*", "System.Diagnostics.Process": "4.1.0-*", "System.Diagnostics.TraceSource": "4.0.0-*" }, From 912971120fb76ba2e4081e573b6e7a7a4c3a807b Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 6 May 2016 14:52:50 -0700 Subject: [PATCH 0187/1029] Update to preview1 version --- makefile.shade | 1 + test/TestApps/Dependency/project.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/makefile.shade b/makefile.shade index 562494d144..c57a5ee034 100644 --- a/makefile.shade +++ b/makefile.shade @@ -2,6 +2,7 @@ var VERSION='0.1' var FULL_VERSION='0.1' var AUTHORS='Microsoft Open Technologies, Inc.' +-BuildQuality = "preview1"; use-standard-lifecycle k-standard-goals diff --git a/test/TestApps/Dependency/project.json b/test/TestApps/Dependency/project.json index 2b16faf607..d8ac93175b 100644 --- a/test/TestApps/Dependency/project.json +++ b/test/TestApps/Dependency/project.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-*", + "version": "1.0.0", "dependencies": { "NETStandard.Library": "1.5.0-*" }, From fe563b1459e9c913b9fb2a0fadf212fb64adf036 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Mon, 16 May 2016 16:06:01 -0700 Subject: [PATCH 0188/1029] Rename `HtmlEncodedString` => `HtmlString`. - This rename makes the type more consistent with its `HtmlContentBuilder` counterparts (`AppendHtml`). #25 --- README.md | 2 +- .../HtmlContentBuilder.cs | 2 +- .../HtmlContentBuilderExtensions.cs | 8 ++++---- .../HtmlFormattableString.cs | 6 +++--- .../{HtmlEncodedString.cs => HtmlString.cs} | 15 ++++++++++----- .../project.json | 2 +- .../HtmlContentBuilderExtensionsTest.cs | 4 ++-- .../HtmlFormattableStringTest.cs | 10 +++++----- 8 files changed, 27 insertions(+), 22 deletions(-) rename src/Microsoft.AspNetCore.Html.Abstractions/{HtmlEncodedString.cs => HtmlString.cs} (71%) diff --git a/README.md b/README.md index 9939efe5b9..a1e3579e7a 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,6 @@ AppVeyor: [![AppVeyor](https://ci.appveyor.com/api/projects/status/cu9y78vsdp19e Travis: [![Travis](https://travis-ci.org/aspnet/HtmlAbstractions.svg?branch=dev)](https://travis-ci.org/aspnet/HtmlAbstractions) -HTML abstractions used for building HTML content, including types such as `HtmlEncodedString` and `IHtmlContent`. +HTML abstractions used for building HTML content, including types such as `HtmlString` and `IHtmlContent`. This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo. diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilder.cs b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilder.cs index be218244b0..864f3c8a65 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilder.cs +++ b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilder.cs @@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.Html { if (!string.IsNullOrEmpty(encoded)) { - Entries.Add(new HtmlEncodedString(encoded)); + Entries.Add(new HtmlString(encoded)); } return this; diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilderExtensions.cs b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilderExtensions.cs index f7474ca3f2..a5a83fdbb3 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilderExtensions.cs @@ -104,7 +104,7 @@ namespace Microsoft.AspNetCore.Html throw new ArgumentNullException(nameof(builder)); } - builder.AppendHtml(HtmlEncodedString.NewLine); + builder.AppendHtml(HtmlString.NewLine); return builder; } @@ -123,7 +123,7 @@ namespace Microsoft.AspNetCore.Html } builder.Append(unencoded); - builder.AppendHtml(HtmlEncodedString.NewLine); + builder.AppendHtml(HtmlString.NewLine); return builder; } @@ -141,7 +141,7 @@ namespace Microsoft.AspNetCore.Html } builder.AppendHtml(content); - builder.AppendHtml(HtmlEncodedString.NewLine); + builder.AppendHtml(HtmlString.NewLine); return builder; } @@ -160,7 +160,7 @@ namespace Microsoft.AspNetCore.Html } builder.AppendHtml(encoded); - builder.AppendHtml(HtmlEncodedString.NewLine); + builder.AppendHtml(HtmlString.NewLine); return builder; } diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlFormattableString.cs b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlFormattableString.cs index 82e9b69d98..24bc7c5e2f 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlFormattableString.cs +++ b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlFormattableString.cs @@ -10,7 +10,7 @@ using System.Text.Encodings.Web; namespace Microsoft.AspNetCore.Html { /// - /// An implementation of composite string formatting + /// An implementation of composite string formatting /// (see https://msdn.microsoft.com/en-us/library/txafckwd(v=vs.110).aspx) which HTML encodes /// formatted arguments. /// @@ -107,9 +107,9 @@ namespace Microsoft.AspNetCore.Html public string Format(string format, object arg, IFormatProvider formatProvider) { - // These are the cases we need to special case. We trust the HtmlEncodedString or IHtmlContent instance + // These are the cases we need to special case. We trust the HtmlString or IHtmlContent instance // to do the right thing with encoding. - var htmlString = arg as HtmlEncodedString; + var htmlString = arg as HtmlString; if (htmlString != null) { return htmlString.ToString(); diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlEncodedString.cs b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlString.cs similarity index 71% rename from src/Microsoft.AspNetCore.Html.Abstractions/HtmlEncodedString.cs rename to src/Microsoft.AspNetCore.Html.Abstractions/HtmlString.cs index bf38ac3682..e7a516bd04 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlEncodedString.cs +++ b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlString.cs @@ -10,18 +10,23 @@ namespace Microsoft.AspNetCore.Html /// /// An implementation that wraps an HTML encoded . /// - public class HtmlEncodedString : IHtmlContent + public class HtmlString : IHtmlContent { /// - /// An instance for . + /// An instance for . /// - public static readonly IHtmlContent NewLine = new HtmlEncodedString(Environment.NewLine); + public static readonly HtmlString NewLine = new HtmlString(Environment.NewLine); /// - /// Creates a new . + /// An instance for . + /// + public static readonly HtmlString Empty = new HtmlString(string.Empty); + + /// + /// Creates a new . /// /// The HTML encoded value. - public HtmlEncodedString(string value) + public HtmlString(string value) { Value = value; } diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/project.json b/src/Microsoft.AspNetCore.Html.Abstractions/project.json index d117f96abe..72763e5b05 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/project.json +++ b/src/Microsoft.AspNetCore.Html.Abstractions/project.json @@ -1,6 +1,6 @@ { "version": "1.0.0-*", - "description": "ASP.NET Core HTML abstractions used for building HTML content.\r\nCommonly used types:\r\nMicrosoft.AspNetCore.Html.HtmlEncodedString\r\nMicrosoft.AspNetCore.Html.IHtmlContent", + "description": "ASP.NET Core HTML abstractions used for building HTML content.\r\nCommonly used types:\r\nMicrosoft.AspNetCore.Html.HtmlString\r\nMicrosoft.AspNetCore.Html.IHtmlContent", "packOptions": { "repository": { "type": "git", diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs b/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs index b985c51890..c14daeeebb 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs @@ -159,13 +159,13 @@ namespace Microsoft.AspNetCore.Html.Test } [Fact] - public void Builder_AppendFormat_HtmlEncodedString() + public void Builder_AppendFormat_HtmlString() { // Arrange var builder = new TestHtmlContentBuilder(); // Act - builder.AppendFormat("{0}!", new HtmlEncodedString("First")); + builder.AppendFormat("{0}!", new HtmlString("First")); // Assert Assert.Equal("First!", HtmlContentToString(builder)); diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlFormattableStringTest.cs b/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlFormattableStringTest.cs index 6f466e6046..64e000751e 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlFormattableStringTest.cs +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlFormattableStringTest.cs @@ -54,10 +54,10 @@ namespace Microsoft.AspNetCore.Html } [Fact] - public void HtmlFormattableString_WithHtmlEncodedString() + public void HtmlFormattableString_WithHtmlString() { // Arrange - var formattableString = new HtmlFormattableString("{0}!", new HtmlEncodedString("First")); + var formattableString = new HtmlFormattableString("{0}!", new HtmlString("First")); // Act var result = HtmlContentToString(formattableString); @@ -89,7 +89,7 @@ namespace Microsoft.AspNetCore.Html // Arrange var formattableString = new HtmlFormattableString( "Happy {0}, {1}!", - new HtmlEncodedString("Birthday"), + new HtmlString("Birthday"), new HtmlContentBuilder().Append("Billy")); // Act @@ -100,10 +100,10 @@ namespace Microsoft.AspNetCore.Html } [Fact] - public void HtmlFormattableString_WithHtmlEncodedString_AndOffset() + public void HtmlFormattableString_WithHtmlString_AndOffset() { // Arrange - var formattableString = new HtmlFormattableString("{0, 20}!", new HtmlEncodedString("First")); + var formattableString = new HtmlFormattableString("{0, 20}!", new HtmlString("First")); // Act var result = HtmlContentToString(formattableString); From ca1e53bb34ace9802dd20df8e555d1ce4b1a29d7 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Tue, 17 May 2016 12:28:18 -0700 Subject: [PATCH 0189/1029] Update minor version of TypeConverter (#22) --- src/Microsoft.AspNetCore.JsonPatch/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index 1860893f6b..d01e21cbb9 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -28,7 +28,7 @@ "dependencies": { "Microsoft.CSharp": "4.0.1-*", "System.Collections.Concurrent": "4.0.12-*", - "System.ComponentModel.TypeConverter": "4.0.1-*", + "System.ComponentModel.TypeConverter": "4.1.0-*", "System.Diagnostics.Debug": "4.0.11-*", "System.Globalization": "4.0.11-*", "System.Linq": "4.1.0-*", From 47ee8e0cfaa002cce1c57d3f22b40eed9ffd5cb7 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 18 May 2016 09:44:47 -0700 Subject: [PATCH 0190/1029] Revert "Update minor version of TypeConverter (#22)" This reverts commit ca1e53bb34ace9802dd20df8e555d1ce4b1a29d7. --- src/Microsoft.AspNetCore.JsonPatch/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index d01e21cbb9..1860893f6b 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -28,7 +28,7 @@ "dependencies": { "Microsoft.CSharp": "4.0.1-*", "System.Collections.Concurrent": "4.0.12-*", - "System.ComponentModel.TypeConverter": "4.1.0-*", + "System.ComponentModel.TypeConverter": "4.0.1-*", "System.Diagnostics.Debug": "4.0.11-*", "System.Globalization": "4.0.11-*", "System.Linq": "4.1.0-*", From c68145f44f47da4ab5af8f371bb2ef9605a86b29 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Fri, 20 May 2016 14:18:56 -0700 Subject: [PATCH 0191/1029] Remove `Microsoft.DotNet.Watcher.Tools.FunctionalTests.NoDepsAppTests.RestartProcessThatTerminatesAfterFileChange` - test is not reliable (95% success rate) - should be restored as part of #98 --- .../NoDepsAppTests.cs | 40 ------------------- 1 file changed, 40 deletions(-) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs index 5ea274b3b1..09557dc8b9 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs @@ -51,46 +51,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } } - [Fact] - public void RestartProcessThatTerminatesAfterFileChange() - { - using (var scenario = new NoDepsAppScenario()) - { - // Wait for the process to start - using (var wait = new WaitForFileToChange(scenario.StartedFile)) - { - scenario.RunDotNetWatch(scenario.StatusFile); - - wait.Wait(_defaultTimeout, - expectedToChange: true, - errorMessage: $"File not created: {scenario.StartedFile}"); - } - - // Then wait for the app to exit - Waiters.WaitForFileToBeReadable(scenario.StartedFile, _defaultTimeout); - var ids = File.ReadAllLines(scenario.StatusFile); - var procId = int.Parse(ids[0]); - Waiters.WaitForProcessToStop( - procId, - _defaultTimeout, - expectedToStop: true, - errorMessage: "Test app did not exit"); - - // Then wait for it to restart when we change a file - using (var wait = new WaitForFileToChange(scenario.StartedFile)) - { - var fileToChange = Path.Combine(scenario.TestAppFolder, "Program.cs"); - var programCs = File.ReadAllText(fileToChange); - File.WriteAllText(fileToChange, programCs); - - wait.Wait(_defaultTimeout, - expectedToChange: true, - errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); - } - } - } - - [Fact] public void ExitOnChange() { From cb86ca81b1f1398f190042bad478b37184f05a67 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Fri, 20 May 2016 14:20:38 -0700 Subject: [PATCH 0192/1029] Revert "Remove `Microsoft.DotNet.Watcher.Tools.FunctionalTests.NoDepsAppTests.RestartProcessThatTerminatesAfterFileChange`" This reverts commit c68145f44f47da4ab5af8f371bb2ef9605a86b29. --- .../NoDepsAppTests.cs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs index 09557dc8b9..5ea274b3b1 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs @@ -51,6 +51,46 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } } + [Fact] + public void RestartProcessThatTerminatesAfterFileChange() + { + using (var scenario = new NoDepsAppScenario()) + { + // Wait for the process to start + using (var wait = new WaitForFileToChange(scenario.StartedFile)) + { + scenario.RunDotNetWatch(scenario.StatusFile); + + wait.Wait(_defaultTimeout, + expectedToChange: true, + errorMessage: $"File not created: {scenario.StartedFile}"); + } + + // Then wait for the app to exit + Waiters.WaitForFileToBeReadable(scenario.StartedFile, _defaultTimeout); + var ids = File.ReadAllLines(scenario.StatusFile); + var procId = int.Parse(ids[0]); + Waiters.WaitForProcessToStop( + procId, + _defaultTimeout, + expectedToStop: true, + errorMessage: "Test app did not exit"); + + // Then wait for it to restart when we change a file + using (var wait = new WaitForFileToChange(scenario.StartedFile)) + { + var fileToChange = Path.Combine(scenario.TestAppFolder, "Program.cs"); + var programCs = File.ReadAllText(fileToChange); + File.WriteAllText(fileToChange, programCs); + + wait.Wait(_defaultTimeout, + expectedToChange: true, + errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); + } + } + } + + [Fact] public void ExitOnChange() { From dc9feade5a18f83f762e14b06ed837e8790b105c Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Mon, 23 May 2016 11:53:35 -0700 Subject: [PATCH 0193/1029] Disable `Microsoft.DotNet.Watcher.Tools.FunctionalTests.NoDepsAppTests.RestartProcessThatTerminatesAfterFileChange` - test is not reliable (95% success rate) - should be restored as part of #98 --- .../NoDepsAppTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs index 5ea274b3b1..5be7ff0b89 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs @@ -51,7 +51,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } } - [Fact] + [Fact(Skip = "aspnet/dotnet-watch#98")] public void RestartProcessThatTerminatesAfterFileChange() { using (var scenario = new NoDepsAppScenario()) From 63bbafdb1d79384ff3ec1c424147ff7fa2cf6401 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Tue, 24 May 2016 11:34:08 -0700 Subject: [PATCH 0194/1029] Simplify watcher arguments by passing everything to dotnet --- Microsoft.DotNet.Watcher.Tools.sln | 7 - README.md | 15 ++- makefile.shade | 15 +-- .../DotNetWatcher.cs | 33 +---- src/Microsoft.DotNet.Watcher.Tools/Program.cs | 121 +++--------------- .../AppWithDepsTests.cs | 2 +- .../GlobbingAppTests.cs | 2 +- ...DotNet.Watcher.Tools.FunctionalTests.xproj | 2 +- .../NoDepsAppTests.cs | 42 +----- .../ArgumentSeparatorTests.cs | 95 -------------- ...Microsoft.DotNet.Watcher.Tools.Tests.xproj | 19 --- .../project.json | 27 ---- test/TestApps/AppWithDeps/AppWithDeps.xproj | 3 +- test/TestApps/Dependency/Dependency.xproj | 3 +- test/TestApps/GlobbingApp/GlobbingApp.xproj | 3 +- test/TestApps/NoDepsApp/NoDepsApp.xproj | 3 +- 16 files changed, 49 insertions(+), 343 deletions(-) delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/ArgumentSeparatorTests.cs delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.xproj delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/project.json diff --git a/Microsoft.DotNet.Watcher.Tools.sln b/Microsoft.DotNet.Watcher.Tools.sln index 08e32fa200..658ce28d54 100644 --- a/Microsoft.DotNet.Watcher.Tools.sln +++ b/Microsoft.DotNet.Watcher.Tools.sln @@ -29,8 +29,6 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AppWithDeps", "test\TestApp EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Dependency", "test\TestApps\Dependency\Dependency.xproj", "{2F48041A-F7D1-478F-9C38-D41F0F05E8CA}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Watcher.Tools.Tests", "test\Microsoft.DotNet.Watcher.Tools.Tests\Microsoft.DotNet.Watcher.Tools.Tests.xproj", "{2E2FE108-0EB7-48CE-BD52-147E90180090}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -65,10 +63,6 @@ Global {2F48041A-F7D1-478F-9C38-D41F0F05E8CA}.Debug|Any CPU.Build.0 = Debug|Any CPU {2F48041A-F7D1-478F-9C38-D41F0F05E8CA}.Release|Any CPU.ActiveCfg = Release|Any CPU {2F48041A-F7D1-478F-9C38-D41F0F05E8CA}.Release|Any CPU.Build.0 = Release|Any CPU - {2E2FE108-0EB7-48CE-BD52-147E90180090}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2E2FE108-0EB7-48CE-BD52-147E90180090}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2E2FE108-0EB7-48CE-BD52-147E90180090}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2E2FE108-0EB7-48CE-BD52-147E90180090}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -82,6 +76,5 @@ Global {2AB1A28B-2022-49EA-AF77-AC8A875915CC} = {2876B12E-5841-4792-85A8-2929AEE11885} {F7734E61-F510-41E0-AD15-301A64081CD1} = {2876B12E-5841-4792-85A8-2929AEE11885} {2F48041A-F7D1-478F-9C38-D41F0F05E8CA} = {2876B12E-5841-4792-85A8-2929AEE11885} - {2E2FE108-0EB7-48CE-BD52-147E90180090} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} EndGlobalSection EndGlobal diff --git a/README.md b/README.md index 41acfad989..9fe921f7aa 100644 --- a/README.md +++ b/README.md @@ -21,16 +21,19 @@ Add `Microsoft.DotNet.Watcher.Tools` to the `tools` section of your `project.jso ### How To Use -```dotnet watch -- ``` + dotnet watch [dotnet arguments] -- `dotnet watch` (runs the application without arguments) -- `dotnet watch foo bar` (runs the application with the arguments `foo bar`) -- `dotnet watch --exit-on-change -- foo bar` (runs the application with the arguments `foo bar`. In addition, it passes `--exit-on-change` to the watcher). -- `dotnet watch --command test -- -parallel none` (runs `dotnet test` with the arguments `-parallel none`) +Add `watch` after `dotnet` in the command that you want to run: + +| What you want to run | Dotnet watch command | +| ---------------------------------------------- | -------------------------------------------------------- | +| dotnet run | dotnet **watch** run | +| dotnet run --arg1 value1 | dotnet **watch** run --arg1 value | +| dotnet run --framework net451 -- --arg1 value1 | dotnet **watch** run --framework net451 -- --arg1 value1 | +| dotnet test | dotnet **watch** test | AppVeyor: [![AppVeyor](https://ci.appveyor.com/api/projects/status/fxhto3omtehio3aj/branch/dev?svg=true)](https://ci.appveyor.com/project/aspnetci/dnx-watch/branch/dev) Travis: [![Travis](https://travis-ci.org/aspnet/dotnet-watch.svg?branch=dev)](https://travis-ci.org/aspnet/dotnet-watch) - This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo. diff --git a/makefile.shade b/makefile.shade index c57a5ee034..861bab6a2e 100644 --- a/makefile.shade +++ b/makefile.shade @@ -1,8 +1,7 @@ - -var VERSION='0.1' -var FULL_VERSION='0.1' -var AUTHORS='Microsoft Open Technologies, Inc.' --BuildQuality = "preview1"; - -use-standard-lifecycle -k-standard-goals +var VERSION='0.1' +var FULL_VERSION='0.1' +var AUTHORS='Microsoft Open Technologies, Inc.' +-BuildQuality = "preview1"; + +use-standard-lifecycle +k-standard-goals \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs index 61b1cc586b..cdb5ba7483 100644 --- a/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.IO; using System.Threading; using System.Threading.Tasks; using Microsoft.DotNet.Watcher.Core.Internal; @@ -18,8 +19,6 @@ namespace Microsoft.DotNet.Watcher.Core private readonly ILogger _logger; - public bool ExitOnChange { get; set; } - public DotNetWatcher( Func fileWatcherFactory, Func processWatcherFactory, @@ -34,32 +33,23 @@ namespace Microsoft.DotNet.Watcher.Core _logger = _loggerFactory.CreateLogger(nameof(DotNetWatcher)); } - public async Task WatchAsync(string projectFile, string command, string[] dotnetArguments, string workingDir, CancellationToken cancellationToken) + public async Task WatchAsync(string projectFile, string[] dotnetArguments, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(projectFile)) { throw new ArgumentNullException(nameof(projectFile)); } - if (string.IsNullOrEmpty(command)) - { - throw new ArgumentNullException(nameof(command)); - } if (dotnetArguments == null) { throw new ArgumentNullException(nameof(dotnetArguments)); } - if (string.IsNullOrEmpty(workingDir)) - { - throw new ArgumentNullException(nameof(workingDir)); - } if (cancellationToken == null) { throw new ArgumentNullException(nameof(cancellationToken)); } - var fullDotnetArgs = new string[dotnetArguments.Length + 1]; - fullDotnetArgs[0] = command; - + // If any argument has spaces then quote it because we're going to convert everything + // to string for (var i = 0; i < dotnetArguments.Length; i++) { var arg = dotnetArguments[i]; @@ -72,12 +62,13 @@ namespace Microsoft.DotNet.Watcher.Core break; } } - fullDotnetArgs[i + 1] = arg; + dotnetArguments[i] = arg; } - dotnetArguments = fullDotnetArgs; var dotnetArgumentsAsString = string.Join(" ", dotnetArguments); + var workingDir = Path.GetDirectoryName(projectFile); + while (true) { await WaitForValidProjectJsonAsync(projectFile, cancellationToken); @@ -116,11 +107,6 @@ namespace Microsoft.DotNet.Watcher.Core _logger.LogError($"dotnet exit code: {dotnetExitCode}"); } - if (ExitOnChange) - { - break; - } - _logger.LogInformation("Waiting for a file to change before restarting dotnet..."); // Now wait for a file to change before restarting dotnet await WaitForProjectFileToChangeAsync(projectFile, cancellationToken); @@ -130,11 +116,6 @@ namespace Microsoft.DotNet.Watcher.Core // This is a file watcher task string changedFile = fileWatchingTask.Result; _logger.LogInformation($"File changed: {fileWatchingTask.Result}"); - - if (ExitOnChange) - { - break; - } } } } diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index 8ea1b8a2f0..d27c68e543 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -8,14 +8,11 @@ using System.Threading.Tasks; using Microsoft.DotNet.Watcher.Core; using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.PlatformAbstractions; namespace Microsoft.DotNet.Watcher.Tools { public class Program { - private const string AppArgumentSeparator = "--"; - private readonly ILoggerFactory _loggerFactory; public Program() @@ -35,120 +32,27 @@ namespace Microsoft.DotNet.Watcher.Tools ctrlCTokenSource.Cancel(); ev.Cancel = false; }; - - string[] watchArgs, appArgs; - SeparateWatchArguments(args, out watchArgs, out appArgs); - - return new Program().MainInternal(watchArgs, appArgs, ctrlCTokenSource.Token); + + return new Program().MainInternal(args, ctrlCTokenSource.Token); } } - // The argument separation rules are: if no "--" is encountered, all arguments are passed to the app being watched. - // Unless, the argument is "--help", in which case the help for the watcher is being invoked and everything else is discarded. - // To pass arguments to both the watcher and the app use "--" as separator. - // To pass "--help" to the app being watched, you must use "--": dotnet watch -- --help - internal static void SeparateWatchArguments(string[] args, out string[] watchArgs, out string[] appArgs) - { - if (args.Length == 0) - { - watchArgs = new string[0]; - appArgs = new string[0]; - return; - } - - // Special case "--help" - if (args[0].Equals("--help", StringComparison.OrdinalIgnoreCase) || - args[0].Equals("-h", StringComparison.OrdinalIgnoreCase) || - args[0].Equals("-?", StringComparison.OrdinalIgnoreCase)) - { - watchArgs = new string[] { args[0] }; - appArgs = new string[0]; - return; - } - - var separatorIndex = -1; - for (var i = 0; i < args.Length; i++) - { - if (string.Equals(args[i], AppArgumentSeparator, StringComparison.OrdinalIgnoreCase)) - { - separatorIndex = i; - break; - } - } - - if (separatorIndex == -1) - { - watchArgs = new string[0]; - appArgs = args; - } - else - { - watchArgs = new string[separatorIndex]; - Array.Copy(args, 0, watchArgs, 0, separatorIndex); - - var appArgsLength = args.Length - separatorIndex - 1; - appArgs = new string[appArgsLength]; - Array.Copy(args, separatorIndex + 1, appArgs, 0, appArgsLength); - } - } - - private int MainInternal(string[] watchArgs, string[] appArgs, CancellationToken cancellationToken) + private int MainInternal(string[] args, CancellationToken cancellationToken) { var app = new CommandLineApplication(); app.Name = "dotnet-watch"; app.FullName = "Microsoft dotnet File Watcher"; app.HelpOption("-?|-h|--help"); - - var commandArg = app.Option( - "--command ", - "Optional. The dotnet command to run. Default: 'run'.", - CommandOptionType.SingleValue); - - var workingDirArg = app.Option( - "--working-dir ", - "Optional. The working directory. Default: project's directory.", - CommandOptionType.SingleValue); - - var exitOnChangeArg = app.Option( - "--exit-on-change", - "Optional. The watcher will exit when a file change is detected instead of restarting the process. Default: not set.", - CommandOptionType.NoValue); - + app.OnExecute(() => { var projectToWatch = Path.Combine(Directory.GetCurrentDirectory(), ProjectModel.Project.FileName); - - var command = commandArg.Value(); - if (!commandArg.HasValue()) - { - // The default command is "run". In this case we always assume the arguments are passed to the application being run. - // If you want a different behaviour for run you need to use --command and pass the full arguments - // Run is special because it requires a "--" before the arguments being passed to the application, - // so the two command below are equivalent and resolve to "dotnet run -- --foo": - // 1. dotnet watch --foo - // 2. dotnet watch --command run -- -- --foo (yes, there are two "--") - if (appArgs.Length > 0) - { - var newAppArgs = new string[appArgs.Length + 1]; - newAppArgs[0] = AppArgumentSeparator; - appArgs.CopyTo(newAppArgs, 1); - appArgs = newAppArgs; - } - - command = "run"; - } - - var workingDir = workingDirArg.HasValue() ? - workingDirArg.Value() : - Path.GetDirectoryName(projectToWatch); - var watcher = DotNetWatcher.CreateDefault(_loggerFactory); - watcher.ExitOnChange = exitOnChangeArg.HasValue(); try { - watcher.WatchAsync(projectToWatch, command, appArgs, workingDir, cancellationToken).Wait(); + watcher.WatchAsync(projectToWatch, args, cancellationToken).Wait(); } catch (AggregateException ex) { @@ -158,11 +62,20 @@ namespace Microsoft.DotNet.Watcher.Tools } } - - return 1; + return 0; }); - return app.Execute(watchArgs); + if (args == null || + args.Length == 0 || + args[0].Equals("--help", StringComparison.OrdinalIgnoreCase) || + args[0].Equals("-h", StringComparison.OrdinalIgnoreCase) || + args[0].Equals("-?", StringComparison.OrdinalIgnoreCase)) + { + app.ShowHelp(); + return 1; + } + + return app.Execute(); } } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs index 913c79abb2..da092e8463 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs @@ -61,7 +61,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // Wait for the process to start using (var wait = new WaitForFileToChange(StatusFile)) { - RunDotNetWatch(StatusFile, Path.Combine(_scenario.WorkFolder, AppWithDeps)); + RunDotNetWatch($"run {StatusFile}", Path.Combine(_scenario.WorkFolder, AppWithDeps)); wait.Wait(_defaultTimeout, expectedToChange: true, diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs index 456d7a7ec0..0a8f48908d 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs @@ -185,7 +185,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // Wait for the process to start using (var wait = new WaitForFileToChange(StartedFile)) { - RunDotNetWatch(StatusFile, Path.Combine(_scenario.WorkFolder, TestAppName)); + RunDotNetWatch($"run {StatusFile}", Path.Combine(_scenario.WorkFolder, TestAppName)); wait.Wait(_defaultTimeout, expectedToChange: true, diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.xproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.xproj index 7fd8ef1ab9..317f69fb4a 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.xproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.xproj @@ -8,7 +8,7 @@ 16bade2f-1184-4518-8a70-b68a19d0805b ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + .\bin\ 2.0 diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs index 5be7ff0b89..b87d54e6dc 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs @@ -20,7 +20,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // Wait for the process to start using (var wait = new WaitForFileToChange(scenario.StartedFile)) { - scenario.RunDotNetWatch($"{scenario.StatusFile} --no-exit"); + scenario.RunDotNetWatch($"run {scenario.StatusFile} --no-exit"); wait.Wait(_defaultTimeout, expectedToChange: true, @@ -59,7 +59,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // Wait for the process to start using (var wait = new WaitForFileToChange(scenario.StartedFile)) { - scenario.RunDotNetWatch(scenario.StatusFile); + scenario.RunDotNetWatch($"run {scenario.StatusFile}"); wait.Wait(_defaultTimeout, expectedToChange: true, @@ -90,44 +90,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } } - - [Fact] - public void ExitOnChange() - { - using (var scenario = new NoDepsAppScenario()) - { - // Wait for the process to start - using (var wait = new WaitForFileToChange(scenario.StartedFile)) - { - scenario.RunDotNetWatch($"--exit-on-change -- {scenario.StatusFile} --no-exit"); - - wait.Wait(_defaultTimeout, - expectedToChange: true, - errorMessage: $"File not created: {scenario.StartedFile}"); - } - - // Change a file - var fileToChange = Path.Combine(scenario.TestAppFolder, "Program.cs"); - var programCs = File.ReadAllText(fileToChange); - File.WriteAllText(fileToChange, programCs); - - Waiters.WaitForProcessToStop( - scenario.WatcherProcess.Id, - _defaultTimeout, - expectedToStop: true, - errorMessage: "The watcher did not stop"); - - // Check that the first child process is no longer running - var ids = File.ReadAllLines(scenario.StatusFile); - var firstProcessId = int.Parse(ids[0]); - Waiters.WaitForProcessToStop( - firstProcessId, - TimeSpan.FromSeconds(1), - expectedToStop: true, - errorMessage: $"PID: {firstProcessId} is still alive"); - } - } - private class NoDepsAppScenario : DotNetWatchScenario { private const string TestAppName = "NoDepsApp"; diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/ArgumentSeparatorTests.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/ArgumentSeparatorTests.cs deleted file mode 100644 index a9178eb1ad..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/ArgumentSeparatorTests.cs +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Xunit; - -namespace Microsoft.DotNet.Watcher.Tools.Tests -{ - public class ArgumentSeparatorTests - { - [Theory] - [InlineData(new string[0], - new string[0], - new string[0])] - [InlineData(new string[] { "--" }, - new string[0], - new string[0])] - [InlineData(new string[] { "--appArg1" }, - new string[0], - new string[] { "--appArg1" })] - [InlineData(new string[] { "--command", "test" }, - new string[0], - new string[] { "--command", "test" })] - [InlineData(new string[] { "--command", "test", "--" }, - new string[] { "--command", "test" }, - new string[0])] - [InlineData(new string[] { "--command", "test", "--", "--appArg1", "arg1Value" }, - new string[] { "--command", "test" }, - new string[] { "--appArg1", "arg1Value" })] - [InlineData(new string[] { "--", "--appArg1", "arg1Value" }, - new string[0], - new string[] { "--appArg1", "arg1Value" })] - [InlineData(new string[] { "--", "--" }, - new string[0], - new string[] { "--" })] - [InlineData(new string[] { "--", "--", "--" }, - new string[0], - new string[] { "--", "--" })] - [InlineData(new string[] { "--command", "run", "--", "--", "--appArg", "foo" }, - new string[] { "--command", "run" }, - new string[] { "--", "--appArg", "foo" })] - [InlineData(new string[] { "--command", "run", "--", "-f", "net451", "--", "--appArg", "foo" }, - new string[] { "--command", "run" }, - new string[] { "-f", "net451", "--", "--appArg", "foo" })] - public void SeparateWatchArguments(string[] args, string[] expectedWatchArgs, string[] expectedAppArgs) - { - SeparateWatchArgumentsTest(args, expectedWatchArgs, expectedAppArgs); - } - - [Theory] - // Help is special if it's the first argument - [InlineData(new string[] { "--help" }, - new string[] { "--help" }, - new string[0])] - [InlineData(new string[] { "-h" }, - new string[] { "-h" }, - new string[0])] - [InlineData(new string[] { "-?" }, - new string[] { "-?" }, - new string[0])] - [InlineData(new string[] { "--help", "--this-is-ignored" }, - new string[] { "--help" }, - new string[0])] - [InlineData(new string[] { "--help", "--", "--this-is-ignored" }, - new string[] { "--help" }, - new string[0])] - // But not otherwise - [InlineData(new string[] { "--", "--help" }, - new string[0], - new string[] { "--help" })] - [InlineData(new string[] { "--foo", "--help" }, - new string[0], - new string[] { "--foo", "--help" })] - [InlineData(new string[] { "--foo", "--help" }, - new string[0], - new string[] { "--foo", "--help" })] - [InlineData(new string[] { "--foo", "--", "--help" }, - new string[] { "--foo" }, - new string[] { "--help" })] - public void SeparateWatchArguments_Help(string[] args, string[] expectedWatchArgs, string[] expectedAppArgs) - { - SeparateWatchArgumentsTest(args, expectedWatchArgs, expectedAppArgs); - } - - private static void SeparateWatchArgumentsTest(string[] args, string[] expectedWatchArgs, string[] expectedAppArgs) - { - string[] actualWatchArgs; - string[] actualAppArgs; - - Program.SeparateWatchArguments(args, out actualWatchArgs, out actualAppArgs); - - Assert.Equal(expectedWatchArgs, actualWatchArgs); - Assert.Equal(expectedAppArgs, actualAppArgs); - } - } -} diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.xproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.xproj deleted file mode 100644 index 2c2d6b6b34..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.xproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - 14.0.25123 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 2e2fe108-0eb7-48ce-bd52-147e90180090 - Microsoft.DotNet.Watcher.Tools.Tests - ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ - - - - 2.0 - - - \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json deleted file mode 100644 index 44db712712..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "buildOptions": { - "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk" - }, - "dependencies": { - "dotnet-test-xunit": "1.0.0-*", - "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", - "NETStandard.Library": "1.5.0-*", - "xunit": "2.1.0" - }, - "frameworks": { - "netcoreapp1.0": { - "imports": [ - "portable-net451+win8", - "dnxcore50" - ], - "dependencies": { - "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.0.0-*" - } - } - } - }, - "testRunner": "xunit" -} \ No newline at end of file diff --git a/test/TestApps/AppWithDeps/AppWithDeps.xproj b/test/TestApps/AppWithDeps/AppWithDeps.xproj index 289874a39b..42ff14fd34 100644 --- a/test/TestApps/AppWithDeps/AppWithDeps.xproj +++ b/test/TestApps/AppWithDeps/AppWithDeps.xproj @@ -9,9 +9,8 @@ f7734e61-f510-41e0-ad15-301a64081cd1 AppWithDeps ..\..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\..\artifacts\bin\$(MSBuildProjectName)\ + .\bin\ - 2.0 diff --git a/test/TestApps/Dependency/Dependency.xproj b/test/TestApps/Dependency/Dependency.xproj index d1edb4ad06..406bf0a295 100644 --- a/test/TestApps/Dependency/Dependency.xproj +++ b/test/TestApps/Dependency/Dependency.xproj @@ -9,9 +9,8 @@ 2f48041a-f7d1-478f-9c38-d41f0f05e8ca Dependency ..\..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\..\artifacts\bin\$(MSBuildProjectName)\ + .\bin\ - 2.0 diff --git a/test/TestApps/GlobbingApp/GlobbingApp.xproj b/test/TestApps/GlobbingApp/GlobbingApp.xproj index 791e441f8f..b170a846ad 100644 --- a/test/TestApps/GlobbingApp/GlobbingApp.xproj +++ b/test/TestApps/GlobbingApp/GlobbingApp.xproj @@ -9,9 +9,8 @@ 2ab1a28b-2022-49ea-af77-ac8a875915cc GlobbingApp ..\..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\..\artifacts\bin\$(MSBuildProjectName)\ + .\bin\ - 2.0 diff --git a/test/TestApps/NoDepsApp/NoDepsApp.xproj b/test/TestApps/NoDepsApp/NoDepsApp.xproj index 959a38dc0e..50d9989df2 100644 --- a/test/TestApps/NoDepsApp/NoDepsApp.xproj +++ b/test/TestApps/NoDepsApp/NoDepsApp.xproj @@ -9,9 +9,8 @@ 4f0d8a80-221f-4bcb-822e-44a0655f537e NoDepsApp ..\..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\..\artifacts\bin\$(MSBuildProjectName)\ + .\bin\ - 2.0 From 07d504cf9a93811e735e6a8cdb7842dc4f0633d6 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Wed, 25 May 2016 10:11:04 -0700 Subject: [PATCH 0195/1029] Update the project.json metadata --- src/Microsoft.DotNet.Watcher.Core/project.json | 7 +++++++ src/Microsoft.DotNet.Watcher.Tools/project.json | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index f6926c7dca..8794bffc70 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -1,5 +1,12 @@ { "version": "1.0.0-*", + "description": "Core logic for the dotnet-watch command line tool.", + "packOptions": { + "tags": [ + "dotnet", + "watch" + ] + }, "buildOptions": { "warningsAsErrors": true, "keyFile": "../../tools/Key.snk", diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index 867642edfe..c023d40101 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -1,5 +1,12 @@ { "version": "1.0.0-*", + "description": "Command line tool to watch for source file changes during development and restart the dotnet command.", + "packOptions": { + "tags": [ + "dotnet", + "watch" + ] + }, "buildOptions": { "outputName": "dotnet-watch", "warningsAsErrors": true, From f154a9ee3ec82149e2dec42a13e0c7a154fff7f2 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Thu, 26 May 2016 10:22:47 -0700 Subject: [PATCH 0196/1029] Revert "Disable `Microsoft.DotNet.Watcher.Tools.FunctionalTests.NoDepsAppTests.RestartProcessThatTerminatesAfterFileChange`" This reverts commit dc9feade5a18f83f762e14b06ed837e8790b105c. --- .../NoDepsAppTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs index b87d54e6dc..6a4fa1b542 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs @@ -51,7 +51,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } } - [Fact(Skip = "aspnet/dotnet-watch#98")] + [Fact] public void RestartProcessThatTerminatesAfterFileChange() { using (var scenario = new NoDepsAppScenario()) From 8ab32c44f7d9bf30ed80295bc4579dd43bd31ae4 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Wed, 25 May 2016 11:48:20 -0700 Subject: [PATCH 0197/1029] Make RestartProcessThatTerminatesAfterFileChange more reliable --- .../NoDepsAppTests.cs | 6 ++++++ .../Waiters.cs | 10 ++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs index 6a4fa1b542..1b7109828c 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; using System.IO; +using System.Threading; using Xunit; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests @@ -79,6 +80,11 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // Then wait for it to restart when we change a file using (var wait = new WaitForFileToChange(scenario.StartedFile)) { + // On Unix the file write time is in 1s increments; + // if we don't wait, there's a chance that the polling + // watcher will not detect the change + Thread.Sleep(1000); + var fileToChange = Path.Combine(scenario.TestAppFolder, "Program.cs"); var programCs = File.ReadAllText(fileToChange); File.WriteAllText(fileToChange, programCs); diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Waiters.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Waiters.cs index 113d339769..de8c0f7f3f 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Waiters.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Waiters.cs @@ -44,6 +44,8 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public static void WaitForProcessToStop(int processId, TimeSpan timeout, bool expectedToStop, string errorMessage) { + Console.WriteLine($"Waiting for process {processId} to stop..."); + Process process = null; try @@ -52,8 +54,11 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } catch (Exception e) { - Console.WriteLine("Could not get process id:"); - Console.WriteLine(e); + // If we expect the process to stop, then it might have stopped already + if (!expectedToStop) + { + Console.WriteLine($"Could not find process {processId}: {e}"); + } } var watch = new Stopwatch(); @@ -62,6 +67,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { if (process == null || process.HasExited) { + Console.WriteLine($"Process {processId} is no longer running"); break; } Thread.Sleep(500); From 526f22f072c40f1b3ba278e60a75f71448c40f44 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Thu, 26 May 2016 15:13:19 -0700 Subject: [PATCH 0198/1029] Rename the environment variable used for polling watcher --- .../Internal/FileWatcher/FileWatcherFactory.cs | 2 +- .../Scenario/DotNetWatchScenario.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/FileWatcherFactory.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/FileWatcherFactory.cs index 35e7e7c739..7d782a0db7 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/FileWatcherFactory.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/FileWatcherFactory.cs @@ -9,7 +9,7 @@ namespace Microsoft.DotNet.Watcher.Core.Internal { public static IFileSystemWatcher CreateWatcher(string watchedDirectory) { - var envVar = Environment.GetEnvironmentVariable("USE_POLLING_FILE_WATCHER"); + var envVar = Environment.GetEnvironmentVariable("DOTNET_USE_POLLING_FILE_WATCHER"); var usePollingWatcher = envVar != null && (envVar.Equals("1", StringComparison.OrdinalIgnoreCase) || diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs index 10a20ce7ab..89cb67ef35 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs @@ -35,7 +35,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { envVariables = new Dictionary() { - ["USE_POLLING_FILE_WATCHER"] = "true" + ["DOTNET_USE_POLLING_FILE_WATCHER"] = "true" }; } From 2cf772b575d3da4a3dd4282dabf8bff48c3067d3 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Wed, 25 May 2016 15:15:28 -0700 Subject: [PATCH 0199/1029] - Bugfix: Trigger on new project.json file structure - Bugfix: Trigger on folder deletion - Add test for folder deletion --- .../IncludeContextExtensions.cs | 25 +++++++++++++ .../Internal/Implementation/Project.cs | 35 +++++++++++++++---- .../Internal/ProjectWatcher.cs | 4 +++ .../GlobbingAppTests.cs | 18 ++++++++++ test/TestApps/GlobbingApp/project.json | 18 +++++----- 5 files changed, 85 insertions(+), 15 deletions(-) create mode 100644 src/Microsoft.DotNet.Watcher.Core/IncludeContextExtensions.cs diff --git a/src/Microsoft.DotNet.Watcher.Core/IncludeContextExtensions.cs b/src/Microsoft.DotNet.Watcher.Core/IncludeContextExtensions.cs new file mode 100644 index 0000000000..2f422c777d --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Core/IncludeContextExtensions.cs @@ -0,0 +1,25 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.DotNet.ProjectModel.Files; + +namespace Microsoft.DotNet.Watcher.Core +{ + internal static class IncludeContextExtensions + { + public static IEnumerable ResolveFiles(this IncludeContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + return IncludeFilesResolver + .GetIncludeFiles(context, "/", diagnostics: null) + .Select(f => f.SourcePath); + } + } +} diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs index 4d5c2c31db..d8175329b3 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs @@ -1,9 +1,11 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.IO; using System.Linq; +using Microsoft.DotNet.ProjectModel.Files; using Microsoft.DotNet.ProjectModel.Graph; namespace Microsoft.DotNet.Watcher.Core.Internal @@ -15,15 +17,34 @@ namespace Microsoft.DotNet.Watcher.Core.Internal ProjectFile = runtimeProject.ProjectFilePath; ProjectDirectory = runtimeProject.ProjectDirectory; - Files = runtimeProject.Files.SourceFiles.Concat( - runtimeProject.Files.ResourceFiles.Values.Concat( - runtimeProject.Files.PreprocessSourceFiles.Concat( - runtimeProject.Files.SharedFiles))).Concat( - new string[] { runtimeProject.ProjectFilePath }) - .ToList(); + var compilerOptions = runtimeProject.GetCompilerOptions(targetFramework: null, configurationName: null); + + var filesToWatch = new List() { runtimeProject.ProjectFilePath }; + if (compilerOptions?.CompileInclude != null) + { + filesToWatch.AddRange(compilerOptions.CompileInclude.ResolveFiles()); + } + else + { + filesToWatch.AddRange(runtimeProject.Files.SourceFiles); + } + + if (compilerOptions?.EmbedInclude != null) + { + filesToWatch.AddRange(compilerOptions.EmbedInclude.ResolveFiles()); + } + else + { + filesToWatch.AddRange(runtimeProject.Files.ResourceFiles.Values); + } + + filesToWatch.AddRange(runtimeProject.Files.SharedFiles); + filesToWatch.AddRange(runtimeProject.Files.PreprocessSourceFiles); + + Files = filesToWatch; var projectLockJsonPath = Path.Combine(runtimeProject.ProjectDirectory, "project.lock.json"); - + if (File.Exists(projectLockJsonPath)) { var lockFile = LockFileReader.Read(projectLockJsonPath, designTime: false); diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/ProjectWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/ProjectWatcher.cs index e94afb7dd4..b3438186d4 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/ProjectWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/ProjectWatcher.cs @@ -107,6 +107,10 @@ namespace Microsoft.DotNet.Watcher.Core.Internal foreach (var file in project.Files) { closure.Add(file); + + // We need to add the folder because folder deletions only trigger + // for the folder, not for the files inside it + closure.Add(Path.GetDirectoryName(file)); } foreach (var dependency in project.ProjectDependencies) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs index 0a8f48908d..aa730877de 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs @@ -85,6 +85,24 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } } + // Delete an entire folder + [Fact] + public void DeleteSourceFolder() + { + using (var scenario = new GlobbingAppScenario()) + using (var wait = new WaitForFileToChange(scenario.StartedFile)) + { + scenario.Start(); + + var folderToDelete = Path.Combine(scenario.TestAppFolder, "include"); + Directory.Delete(folderToDelete, recursive: true); + + wait.Wait(_defaultTimeout, + expectedToChange: true, + errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); + } + } + // Rename a file included in compilation [Fact] public void RenameCompiledFile() diff --git a/test/TestApps/GlobbingApp/project.json b/test/TestApps/GlobbingApp/project.json index fd675dbad6..68104394d3 100644 --- a/test/TestApps/GlobbingApp/project.json +++ b/test/TestApps/GlobbingApp/project.json @@ -1,15 +1,17 @@ { "version": "1.0.0-*", "buildOptions": { - "emitEntryPoint": true + "emitEntryPoint": true, + "compile": { + "include": [ + "Program.cs", + "include/*.cs" + ], + "exclude": [ + "exclude/*" + ] + } }, - "compile": [ - "Program.cs", - "include/*.cs" - ], - "exclude": [ - "exclude/*" - ], "frameworks": { "netcoreapp1.0": { "dependencies": { From a2e3bdf408938bd670ab988c0aad6a08565915d4 Mon Sep 17 00:00:00 2001 From: John Luo Date: Thu, 26 May 2016 18:29:26 -0700 Subject: [PATCH 0200/1029] React to updated CoreCLR packages https://github.com/aspnet/Coherence/issues/97 --- src/Microsoft.AspNetCore.JsonPatch/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index 1860893f6b..d01e21cbb9 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -28,7 +28,7 @@ "dependencies": { "Microsoft.CSharp": "4.0.1-*", "System.Collections.Concurrent": "4.0.12-*", - "System.ComponentModel.TypeConverter": "4.0.1-*", + "System.ComponentModel.TypeConverter": "4.1.0-*", "System.Diagnostics.Debug": "4.0.11-*", "System.Globalization": "4.0.11-*", "System.Linq": "4.1.0-*", From bf5f6b927585251f3c4041de95f377f4191e907f Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 27 May 2016 07:36:33 -0700 Subject: [PATCH 0201/1029] Updating to netstandard1.6 Fixes https://github.com/aspnet/Coherence/issues/101 --- src/Microsoft.DotNet.Watcher.Core/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index 8794bffc70..ea47f13da5 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -29,7 +29,7 @@ } }, "frameworks": { - "netstandard1.5": { + "netstandard1.6": { "imports": [ "dnxcore50", "portable-net451+win8" From f98f39283ab075a20f7213427a9f2e5bb932c62b Mon Sep 17 00:00:00 2001 From: Cesar Blum Silveira Date: Fri, 27 May 2016 11:24:49 -0700 Subject: [PATCH 0202/1029] Fix OSX build on Travis. --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index fe831028c8..eea7a1dd5b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,6 +22,8 @@ branches: - release - dev - /^(.*\/)?ci-.*$/ +before_install: + - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; brew link --force openssl; fi script: - ./build.sh --quiet verify notifications: From 8bd631170328b5bfcbf7b8503487a05ba0b886b7 Mon Sep 17 00:00:00 2001 From: Cesar Blum Silveira Date: Fri, 27 May 2016 11:32:14 -0700 Subject: [PATCH 0203/1029] Fix OSX build on Travis. --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 304e307169..bb366b178f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,5 +22,7 @@ branches: - release - dev - /^(.*\/)?ci-.*$/ +before_install: + - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; brew link --force openssl; fi script: - ./build.sh --quiet verify \ No newline at end of file From 45b4960e265ddfc3c4e8d06dc4a22157b0512ea6 Mon Sep 17 00:00:00 2001 From: Cesar Blum Silveira Date: Fri, 27 May 2016 11:53:04 -0700 Subject: [PATCH 0204/1029] Fix OSX build on Travis. --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index dae036065b..59d308953d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,6 +22,8 @@ branches: - release - dev - /^(.*\/)?ci-.*$/ +before_install: + - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; brew link --force openssl; fi script: - ./build.sh --quiet verify notifications: From c5abb2e2ebdc73d7814d09aae56490fdb32921b2 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Tue, 31 May 2016 09:18:02 -0700 Subject: [PATCH 0205/1029] Revert the fix for notification on folder deletion because it requires a big redesign. The simple fix doesn't work --- src/Microsoft.DotNet.Watcher.Core/Internal/ProjectWatcher.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/ProjectWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/ProjectWatcher.cs index b3438186d4..e94afb7dd4 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/ProjectWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/ProjectWatcher.cs @@ -107,10 +107,6 @@ namespace Microsoft.DotNet.Watcher.Core.Internal foreach (var file in project.Files) { closure.Add(file); - - // We need to add the folder because folder deletions only trigger - // for the folder, not for the files inside it - closure.Add(Path.GetDirectoryName(file)); } foreach (var dependency in project.ProjectDependencies) From 060a1c8f5ae4d92e6accaa07b9662b9ad55e7e8d Mon Sep 17 00:00:00 2001 From: BrennanConroy Date: Fri, 27 May 2016 15:02:18 -0700 Subject: [PATCH 0206/1029] Replace PlatformAbstractions with RuntimeInformation --- src/Microsoft.DotNet.Watcher.Core/project.json | 1 - src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs | 4 ++-- src/Microsoft.DotNet.Watcher.Tools/project.json | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index ea47f13da5..8ce59f4698 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -19,7 +19,6 @@ "Microsoft.DotNet.ProjectModel": "1.0.0-*", "Microsoft.Extensions.FileProviders.Abstractions": "1.0.0-*", "Microsoft.Extensions.FileProviders.Physical": "1.0.0-*", - "Microsoft.Extensions.PlatformAbstractions": "1.0.0-*", "Microsoft.Extensions.Logging.Abstractions": "1.0.0-*", "Microsoft.Extensions.FileSystemGlobbing": "1.0.0-*", "NETStandard.Library": "1.5.0-*", diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs index 595b713b0e..34d2149009 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs @@ -1,8 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Runtime.InteropServices; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.PlatformAbstractions; namespace Microsoft.DotNet.Watcher.Tools { @@ -12,7 +12,7 @@ namespace Microsoft.DotNet.Watcher.Tools public CommandOutputProvider() { - _isWindows = PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows; + _isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); } public ILogger CreateLogger(string name) diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index c023d40101..ccfeb680b2 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -18,6 +18,7 @@ "xmlDoc": true }, "dependencies": { + "System.Runtime.InteropServices.RuntimeInformation": "4.0.0-*", "Microsoft.DotNet.Watcher.Core": "1.0.0-*", "Microsoft.Extensions.CommandLineUtils": "1.0.0-*", "Microsoft.Extensions.Logging": "1.0.0-*", From 0d471b827b2ce8f99d16783e047499aa9ea310e8 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 1 Jun 2016 14:31:42 -0700 Subject: [PATCH 0207/1029] Update NetStandard.Library version --- src/Microsoft.DotNet.Watcher.Core/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index 8ce59f4698..38bf545e91 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -21,7 +21,7 @@ "Microsoft.Extensions.FileProviders.Physical": "1.0.0-*", "Microsoft.Extensions.Logging.Abstractions": "1.0.0-*", "Microsoft.Extensions.FileSystemGlobbing": "1.0.0-*", - "NETStandard.Library": "1.5.0-*", + "NETStandard.Library": "1.6.0-*", "Microsoft.Extensions.Process.Sources": { "type": "build", "version": "1.0.0-*" From 188bf58fe835522e0a11b699d30df00358fba2e0 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Wed, 1 Jun 2016 14:50:37 -0700 Subject: [PATCH 0208/1029] Remove netstandard.library --- src/Microsoft.DotNet.Watcher.Core/project.json | 1 - test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index 38bf545e91..9c7524d344 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -21,7 +21,6 @@ "Microsoft.Extensions.FileProviders.Physical": "1.0.0-*", "Microsoft.Extensions.Logging.Abstractions": "1.0.0-*", "Microsoft.Extensions.FileSystemGlobbing": "1.0.0-*", - "NETStandard.Library": "1.6.0-*", "Microsoft.Extensions.Process.Sources": { "type": "build", "version": "1.0.0-*" diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index 16b2386717..1daaba2860 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -11,7 +11,6 @@ "version": "1.0.0-*" }, "Microsoft.DotNet.Watcher.Core": "1.0.0-*", - "NETStandard.Library": "1.5.0-*", "Newtonsoft.Json": "8.0.2", "System.Threading.Thread": "4.0.0-*", "xunit": "2.1.0" From 29bc24004452477e73067b3211bb2c5f13bd909a Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Wed, 1 Jun 2016 16:15:55 -0700 Subject: [PATCH 0209/1029] Fix a timing issue in the polling watcher --- .../Internal/FileWatcher/PollingFileWatcher.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/PollingFileWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/PollingFileWatcher.cs index d1f2dac231..a6ed82ce1c 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/PollingFileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/PollingFileWatcher.cs @@ -117,13 +117,20 @@ namespace Microsoft.DotNet.Watcher.Core.Internal { var fileMeta = _knownEntities[fullFilePath]; - if (fileMeta.FileInfo.LastWriteTime != f.LastWriteTime) + try { - // File changed - RecordChange(f); - } + if (fileMeta.FileInfo.LastWriteTime != f.LastWriteTime) + { + // File changed + RecordChange(f); + } - _knownEntities[fullFilePath] = new FileMeta(fileMeta.FileInfo, true); + _knownEntities[fullFilePath] = new FileMeta(fileMeta.FileInfo, true); + } + catch(FileNotFoundException) + { + _knownEntities[fullFilePath] = new FileMeta(fileMeta.FileInfo, false); + } } _tempDictionary.Add(f.FullName, new FileMeta(f)); From d7206dee8da2e5e6a11e2127ba03940365c4fe18 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Thu, 2 Jun 2016 08:21:51 -0700 Subject: [PATCH 0210/1029] Disable a test that hangs --- .../GlobbingAppTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs index aa730877de..0512b2fd80 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs @@ -86,7 +86,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } // Delete an entire folder - [Fact] + [Fact(Skip = "Blocking build")] public void DeleteSourceFolder() { using (var scenario = new GlobbingAppScenario()) From 599a41b380741fb7110162640d0a3ac434b892be Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Thu, 2 Jun 2016 18:50:15 -0700 Subject: [PATCH 0211/1029] Improve test stability by disposing correctly --- .../FileWatcherTests.cs | 58 ++++++++++++++----- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs index 6de6151209..dc696e6c93 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs @@ -58,11 +58,17 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { var filesChanged = new HashSet(); - watcher.OnFileChange += (_, f) => + EventHandler handler = null; + handler = (_, f) => { + watcher.EnableRaisingEvents = false; + watcher.OnFileChange -= handler; + filesChanged.Add(f); changedEv.Set(); }; + + watcher.OnFileChange += handler; watcher.EnableRaisingEvents = true; // On Unix the file write time is in 1s increments; @@ -94,18 +100,21 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { var filesChanged = new HashSet(); - var changeCount = 0; - watcher.OnFileChange += (_, f) => + EventHandler handler = null; + handler = (_, f) => { filesChanged.Add(f); - changeCount++; - - if (changeCount >= 2) + if (filesChanged.Count >= 2) { + watcher.EnableRaisingEvents = false; + watcher.OnFileChange -= handler; + changedEv.Set(); } }; + + watcher.OnFileChange += handler; watcher.EnableRaisingEvents = true; File.Move(srcFile, dstFile); @@ -133,17 +142,20 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { var filesChanged = new HashSet(); - var totalChanges = 0; - watcher.OnFileChange += (_, f) => + EventHandler handler = null; + handler = (_, f) => { filesChanged.Add(f); - totalChanges++; - if (totalChanges >= 2) + if (filesChanged.Count >= 2) { + watcher.EnableRaisingEvents = false; + watcher.OnFileChange -= handler; changedEv.Set(); } }; + + watcher.OnFileChange += handler; watcher.EnableRaisingEvents = true; // On Unix the file write time is in 1s increments; @@ -235,11 +247,16 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { var filesChanged = new HashSet(); - watcher.OnFileChange += (_, f) => + EventHandler handler = null; + handler = (_, f) => { + watcher.EnableRaisingEvents = false; + watcher.OnFileChange -= handler; filesChanged.Add(f); changedEv.Set(); }; + + watcher.OnFileChange += handler; watcher.EnableRaisingEvents = true; // On Unix the file write time is in 1s increments; @@ -267,11 +284,14 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { var filesChanged = new HashSet(); - watcher.OnFileChange += (_, f) => + EventHandler handler = null; + handler = (_, f) => { filesChanged.Add(f); changedEv.Set(); }; + + watcher.OnFileChange += handler; watcher.EnableRaisingEvents = true; // On Unix the file write time is in 1s increments; @@ -315,6 +335,9 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests File.WriteAllText(testFileFullPath, string.Empty); Assert.True(changedEv.WaitOne(DefaultTimeout)); Assert.Equal(testFileFullPath, filesChanged.Single()); + + watcher.EnableRaisingEvents = false; + watcher.OnFileChange -= handler; } }); } @@ -342,17 +365,20 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { var filesChanged = new HashSet(); - var totalChanges = 0; - watcher.OnFileChange += (_, f) => + EventHandler handler = null; + handler = (_, f) => { filesChanged.Add(f); - totalChanges++; - if (totalChanges >= 4) + if (filesChanged.Count >= 4) { + watcher.EnableRaisingEvents = false; + watcher.OnFileChange -= handler; changedEv.Set(); } }; + + watcher.OnFileChange += handler; watcher.EnableRaisingEvents = true; Directory.Delete(subdir, recursive: true); From 0f1836c6dd418bbab40520c25ab6a27002691d1b Mon Sep 17 00:00:00 2001 From: jacalvar Date: Fri, 3 Jun 2016 13:08:19 -0700 Subject: [PATCH 0212/1029] Update Json.NET to 9.0.1-beta1 --- src/Microsoft.AspNetCore.JsonPatch/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index d01e21cbb9..78a4fe8fb2 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -21,7 +21,7 @@ ] }, "dependencies": { - "Newtonsoft.Json": "8.0.3" + "Newtonsoft.Json": "9.0.1-beta1" }, "frameworks": { "netstandard1.1": { From 2cf172c66e7455585154989a4e450e5667f4ef1a Mon Sep 17 00:00:00 2001 From: jacalvar Date: Mon, 6 Jun 2016 23:18:24 -0700 Subject: [PATCH 0213/1029] Update to Json.NET 9.0.1-beta1 --- .../Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index 1daaba2860..0255fc9ffa 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -11,7 +11,7 @@ "version": "1.0.0-*" }, "Microsoft.DotNet.Watcher.Core": "1.0.0-*", - "Newtonsoft.Json": "8.0.2", + "Newtonsoft.Json": "9.0.1-beta1", "System.Threading.Thread": "4.0.0-*", "xunit": "2.1.0" }, From 15454ae254cd19f921a44565e596f4ece657fc90 Mon Sep 17 00:00:00 2001 From: jacalvar Date: Tue, 7 Jun 2016 16:45:47 -0700 Subject: [PATCH 0214/1029] Remove unncessary imports --- src/Microsoft.DotNet.Watcher.Core/project.json | 4 ---- src/Microsoft.DotNet.Watcher.Tools/project.json | 4 ---- 2 files changed, 8 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index 9c7524d344..3629fc24e7 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -28,10 +28,6 @@ }, "frameworks": { "netstandard1.6": { - "imports": [ - "dnxcore50", - "portable-net451+win8" - ] } } } \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index ccfeb680b2..f4b4358ec1 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -26,10 +26,6 @@ }, "frameworks": { "netcoreapp1.0": { - "imports": [ - "portable-net451+win8", - "dnxcore50" - ], "dependencies": { "Microsoft.NETCore.App": { "type": "platform", From 4d77dce803855d31c6405bdc81403fbf8ada6e3e Mon Sep 17 00:00:00 2001 From: jacalvar Date: Tue, 7 Jun 2016 22:08:02 -0700 Subject: [PATCH 0215/1029] Remove unncessary imports --- src/Microsoft.AspNetCore.JsonPatch/project.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index 78a4fe8fb2..6395f3ecf1 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -37,10 +37,7 @@ "System.Runtime.Extensions": "4.1.0-*", "System.Runtime.Serialization.Primitives": "4.1.1-*", "System.Text.Encoding.Extensions": "4.0.11-*" - }, - "imports": [ - "portable-net451+win8" - ] + } } } } \ No newline at end of file From ad9e22d42acbec4d92e950deb234494659f72911 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 8 Jun 2016 16:52:27 -0700 Subject: [PATCH 0216/1029] Update to preview2 --- makefile.shade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile.shade b/makefile.shade index 861bab6a2e..15ad68190f 100644 --- a/makefile.shade +++ b/makefile.shade @@ -1,7 +1,7 @@ var VERSION='0.1' var FULL_VERSION='0.1' var AUTHORS='Microsoft Open Technologies, Inc.' --BuildQuality = "preview1"; +-BuildQuality = "preview2"; use-standard-lifecycle k-standard-goals \ No newline at end of file From af8e9fb4434c0f24f35ea4a15d82b0995d8569c5 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Mon, 13 Jun 2016 15:27:34 -0700 Subject: [PATCH 0217/1029] Remove direct Microsoft.NETCore.Platforms dependency. - Microsoft.NETCore.App now pulls this package in. aspnet/Coherence-Signed#344 --- test/Microsoft.AspNetCore.JsonPatch.Test/project.json | 1 - 1 file changed, 1 deletion(-) diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index dac020cb6c..dc9abdb71c 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -4,7 +4,6 @@ }, "dependencies": { "dotnet-test-xunit": "1.0.0-*", - "Microsoft.NETCore.Platforms": "1.0.1-*", "Microsoft.AspNetCore.JsonPatch": "1.0.0-*", "Microsoft.AspNetCore.Testing": "1.0.0-*", "xunit": "2.1.0" From 0aab6898131d9848728705e146799864bb185be4 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Mon, 13 Jun 2016 15:28:17 -0700 Subject: [PATCH 0218/1029] Remove direct Microsoft.NETCore.Platforms dependency. - Microsoft.NETCore.App now pulls this package in. aspnet/Coherence-Signed#344 --- test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json | 1 - test/Microsoft.Extensions.WebEncoders.Tests/project.json | 1 - 2 files changed, 2 deletions(-) diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index 2efabff127..7519592e34 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -5,7 +5,6 @@ }, "dependencies": { "dotnet-test-xunit": "1.0.0-*", - "Microsoft.NETCore.Platforms": "1.0.1-*", "Microsoft.AspNetCore.Html.Abstractions": "1.0.0-*", "Microsoft.AspNetCore.Testing": "1.0.0-*", "Microsoft.Extensions.WebEncoders": "1.0.0-*", diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index 2cb866fcc3..7e1a202424 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -1,7 +1,6 @@ { "dependencies": { "dotnet-test-xunit": "1.0.0-*", - "Microsoft.NETCore.Platforms": "1.0.1-*", "Microsoft.Extensions.DependencyInjection": "1.0.0-*", "Microsoft.Extensions.WebEncoders": "1.0.0-*", "xunit": "2.1.0" From 288810c95ce6f6d2589f4cbbd016e12d48a8e4c3 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 14 Jun 2016 16:21:56 -0700 Subject: [PATCH 0219/1029] Updating to release. --- NuGet.config | 4 ++-- build.ps1 | 2 +- build.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/NuGet.config b/NuGet.config index 5500f6d507..71b9724a09 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + - + diff --git a/build.ps1 b/build.ps1 index 8f2f99691a..cf8bff13bb 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/release.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index f4208100eb..f88fe4052e 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/release.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi From 3df9256f123a9cd78dbc69006e511532888abbd2 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 14 Jun 2016 16:22:14 -0700 Subject: [PATCH 0220/1029] Updating to release. --- NuGet.config | 2 +- build.ps1 | 2 +- build.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NuGet.config b/NuGet.config index 52bf414192..71b9724a09 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + diff --git a/build.ps1 b/build.ps1 index 8f2f99691a..cf8bff13bb 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/release.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index f4208100eb..f88fe4052e 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/release.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi From 2fffcb9da7639401f5a197d96bce401175a86c9b Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 14 Jun 2016 16:22:16 -0700 Subject: [PATCH 0221/1029] Updating to release. --- NuGet.config | 4 ++-- build.ps1 | 2 +- build.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/NuGet.config b/NuGet.config index 03704957e8..9db87a421e 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + - + \ No newline at end of file diff --git a/build.ps1 b/build.ps1 index 8f2f99691a..cf8bff13bb 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/release.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index f4208100eb..f88fe4052e 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/release.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi From d7d8af57f6a890360d77e65a68fc54b7cd45d0f6 Mon Sep 17 00:00:00 2001 From: jacalvar Date: Mon, 13 Jun 2016 14:24:30 -0700 Subject: [PATCH 0222/1029] Update Json.NET to 9.0.1 --- src/Microsoft.AspNetCore.JsonPatch/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index 6395f3ecf1..ac582cbac3 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -21,7 +21,7 @@ ] }, "dependencies": { - "Newtonsoft.Json": "9.0.1-beta1" + "Newtonsoft.Json": "9.0.1" }, "frameworks": { "netstandard1.1": { From a86db45a19cd0812e7efef5f33dc3658befcdd1f Mon Sep 17 00:00:00 2001 From: jacalvar Date: Mon, 13 Jun 2016 14:24:25 -0700 Subject: [PATCH 0223/1029] Update Json.NET to 9.0.1 --- .../Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index 0255fc9ffa..497e18d8a2 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -11,7 +11,7 @@ "version": "1.0.0-*" }, "Microsoft.DotNet.Watcher.Core": "1.0.0-*", - "Newtonsoft.Json": "9.0.1-beta1", + "Newtonsoft.Json": "9.0.1", "System.Threading.Thread": "4.0.0-*", "xunit": "2.1.0" }, From 67fe579e748f3ae2ef71771952174d8b80706934 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 16 Jun 2016 10:17:45 -0700 Subject: [PATCH 0224/1029] Updating to dev versions --- makefile.shade | 2 +- src/Microsoft.DotNet.Watcher.Core/project.json | 13 ++++++------- src/Microsoft.DotNet.Watcher.Tools/project.json | 6 +++--- .../project.json | 4 ++-- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/makefile.shade b/makefile.shade index 15ad68190f..56bf6d2cda 100644 --- a/makefile.shade +++ b/makefile.shade @@ -1,7 +1,7 @@ var VERSION='0.1' var FULL_VERSION='0.1' var AUTHORS='Microsoft Open Technologies, Inc.' --BuildQuality = "preview2"; +-BuildQuality = "preview3"; use-standard-lifecycle k-standard-goals \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index 3629fc24e7..53730690fc 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -17,17 +17,16 @@ }, "dependencies": { "Microsoft.DotNet.ProjectModel": "1.0.0-*", - "Microsoft.Extensions.FileProviders.Abstractions": "1.0.0-*", - "Microsoft.Extensions.FileProviders.Physical": "1.0.0-*", - "Microsoft.Extensions.Logging.Abstractions": "1.0.0-*", - "Microsoft.Extensions.FileSystemGlobbing": "1.0.0-*", + "Microsoft.Extensions.FileProviders.Abstractions": "1.1.0-*", + "Microsoft.Extensions.FileProviders.Physical": "1.1.0-*", + "Microsoft.Extensions.Logging.Abstractions": "1.1.0-*", + "Microsoft.Extensions.FileSystemGlobbing": "1.1.0-*", "Microsoft.Extensions.Process.Sources": { "type": "build", - "version": "1.0.0-*" + "version": "1.1.0-*" } }, "frameworks": { - "netstandard1.6": { - } + "netstandard1.6": {} } } \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index f4b4358ec1..16e648aab8 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -20,9 +20,9 @@ "dependencies": { "System.Runtime.InteropServices.RuntimeInformation": "4.0.0-*", "Microsoft.DotNet.Watcher.Core": "1.0.0-*", - "Microsoft.Extensions.CommandLineUtils": "1.0.0-*", - "Microsoft.Extensions.Logging": "1.0.0-*", - "Microsoft.Extensions.Logging.Console": "1.0.0-*" + "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", + "Microsoft.Extensions.Logging": "1.1.0-*", + "Microsoft.Extensions.Logging.Console": "1.1.0-*" }, "frameworks": { "netcoreapp1.0": { diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index 497e18d8a2..98ae86c2a3 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -5,10 +5,10 @@ }, "dependencies": { "dotnet-test-xunit": "1.0.0-*", - "Microsoft.Extensions.DependencyInjection": "1.0.0-*", + "Microsoft.Extensions.DependencyInjection": "1.1.0-*", "Microsoft.Extensions.Process.Sources": { "type": "build", - "version": "1.0.0-*" + "version": "1.1.0-*" }, "Microsoft.DotNet.Watcher.Core": "1.0.0-*", "Newtonsoft.Json": "9.0.1", From 66518476aff65545f85a3796788f18bf40cfa7e5 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 16 Jun 2016 10:17:56 -0700 Subject: [PATCH 0225/1029] Updating to dev versions --- src/Microsoft.AspNetCore.Html.Abstractions/project.json | 2 +- src/Microsoft.Extensions.WebEncoders/project.json | 6 +++--- .../project.json | 6 +++--- test/Microsoft.Extensions.WebEncoders.Tests/project.json | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/project.json b/src/Microsoft.AspNetCore.Html.Abstractions/project.json index 72763e5b05..7d42a7746d 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/project.json +++ b/src/Microsoft.AspNetCore.Html.Abstractions/project.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-*", + "version": "1.1.0-*", "description": "ASP.NET Core HTML abstractions used for building HTML content.\r\nCommonly used types:\r\nMicrosoft.AspNetCore.Html.HtmlString\r\nMicrosoft.AspNetCore.Html.IHtmlContent", "packOptions": { "repository": { diff --git a/src/Microsoft.Extensions.WebEncoders/project.json b/src/Microsoft.Extensions.WebEncoders/project.json index 857361e4e4..1e765f8b80 100644 --- a/src/Microsoft.Extensions.WebEncoders/project.json +++ b/src/Microsoft.Extensions.WebEncoders/project.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-*", + "version": "1.1.0-*", "description": "Contains registration and configuration APIs to add the core framework encoders to a dependency injection container.", "packOptions": { "repository": { @@ -20,8 +20,8 @@ "xmlDoc": true }, "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "1.0.0-*", - "Microsoft.Extensions.Options": "1.0.0-*", + "Microsoft.Extensions.DependencyInjection.Abstractions": "1.1.0-*", + "Microsoft.Extensions.Options": "1.1.0-*", "System.Text.Encodings.Web": "4.0.0-*" }, "frameworks": { diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index 7519592e34..cbcb78bf6e 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -5,9 +5,9 @@ }, "dependencies": { "dotnet-test-xunit": "1.0.0-*", - "Microsoft.AspNetCore.Html.Abstractions": "1.0.0-*", - "Microsoft.AspNetCore.Testing": "1.0.0-*", - "Microsoft.Extensions.WebEncoders": "1.0.0-*", + "Microsoft.AspNetCore.Html.Abstractions": "1.1.0-*", + "Microsoft.AspNetCore.Testing": "1.1.0-*", + "Microsoft.Extensions.WebEncoders": "1.1.0-*", "xunit": "2.1.0" }, "testRunner": "xunit", diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index 7e1a202424..65a29bd9c1 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -1,8 +1,8 @@ { "dependencies": { "dotnet-test-xunit": "1.0.0-*", - "Microsoft.Extensions.DependencyInjection": "1.0.0-*", - "Microsoft.Extensions.WebEncoders": "1.0.0-*", + "Microsoft.Extensions.DependencyInjection": "1.1.0-*", + "Microsoft.Extensions.WebEncoders": "1.1.0-*", "xunit": "2.1.0" }, "testRunner": "xunit", From 36e5c0e6fae4d9f547904509b5044678ad559430 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 16 Jun 2016 10:18:06 -0700 Subject: [PATCH 0226/1029] Updating to dev versions --- src/Microsoft.AspNetCore.JsonPatch/project.json | 2 +- test/Microsoft.AspNetCore.JsonPatch.Test/project.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index ac582cbac3..44daeef0e9 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-*", + "version": "1.1.0-*", "description": "ASP.NET Core support for JSON PATCH.", "buildOptions": { "warningsAsErrors": true, diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index dc9abdb71c..4bd3e6450b 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -4,8 +4,8 @@ }, "dependencies": { "dotnet-test-xunit": "1.0.0-*", - "Microsoft.AspNetCore.JsonPatch": "1.0.0-*", - "Microsoft.AspNetCore.Testing": "1.0.0-*", + "Microsoft.AspNetCore.JsonPatch": "1.1.0-*", + "Microsoft.AspNetCore.Testing": "1.1.0-*", "xunit": "2.1.0" }, "testRunner": "xunit", From 92c658216f76f8700ec2fef5e3012c747d0bb36f Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 29 Jun 2016 16:43:38 -0700 Subject: [PATCH 0227/1029] Updating to RTM builds of xunit --- .../AppWithDepsTests.cs | 2 -- .../project.json | 8 ++------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs index da092e8463..cae3959577 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Diagnostics; using System.IO; using Xunit; @@ -32,7 +31,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } } - private class AppWithDepsScenario : DotNetWatchScenario { private const string AppWithDeps = "AppWithDeps"; diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index 98ae86c2a3..e7671bd373 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -4,7 +4,7 @@ "keyFile": "../../tools/Key.snk" }, "dependencies": { - "dotnet-test-xunit": "1.0.0-*", + "dotnet-test-xunit": "2.2.0-*", "Microsoft.Extensions.DependencyInjection": "1.1.0-*", "Microsoft.Extensions.Process.Sources": { "type": "build", @@ -13,14 +13,10 @@ "Microsoft.DotNet.Watcher.Core": "1.0.0-*", "Newtonsoft.Json": "9.0.1", "System.Threading.Thread": "4.0.0-*", - "xunit": "2.1.0" + "xunit": "2.2.0-*" }, "frameworks": { "netcoreapp1.0": { - "imports": [ - "portable-net451+win8", - "dnxcore50" - ], "dependencies": { "Microsoft.NETCore.App": { "type": "platform", From 60a66aaa6db5f7d79fab80d84936fb58a443083a Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 30 Jun 2016 14:52:36 -0700 Subject: [PATCH 0228/1029] Updating to RTM builds of xunit --- .../project.json | 22 ++++--------------- .../project.json | 16 ++++---------- 2 files changed, 8 insertions(+), 30 deletions(-) diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index cbcb78bf6e..8c2d135d8a 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -4,11 +4,11 @@ "keyFile": "../../tools/Key.snk" }, "dependencies": { - "dotnet-test-xunit": "1.0.0-*", + "dotnet-test-xunit": "2.2.0-*", "Microsoft.AspNetCore.Html.Abstractions": "1.1.0-*", "Microsoft.AspNetCore.Testing": "1.1.0-*", "Microsoft.Extensions.WebEncoders": "1.1.0-*", - "xunit": "2.1.0" + "xunit": "2.2.0-*" }, "testRunner": "xunit", "frameworks": { @@ -17,23 +17,9 @@ "Microsoft.NETCore.App": { "version": "1.0.0-*", "type": "platform" - }, - "System.Diagnostics.Process": "4.1.0-*" - }, - "imports": [ - "dnxcore50", - "portable-net451+win8" - ] - }, - "net451": { - "frameworkAssemblies": { - "System.IO": { - "type": "build" - }, - "System.Runtime": { - "type": "build" } } - } + }, + "net451": {} } } \ No newline at end of file diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index 65a29bd9c1..6ed331d6ec 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -1,13 +1,12 @@ { "dependencies": { - "dotnet-test-xunit": "1.0.0-*", + "dotnet-test-xunit": "2.2.0-*", "Microsoft.Extensions.DependencyInjection": "1.1.0-*", "Microsoft.Extensions.WebEncoders": "1.1.0-*", - "xunit": "2.1.0" + "xunit": "2.2.0-*" }, "testRunner": "xunit", "buildOptions": { - "allowUnsafe": true, "warningsAsErrors": true, "keyFile": "../../tools/Key.snk" }, @@ -17,20 +16,13 @@ "Microsoft.NETCore.App": { "version": "1.0.0-*", "type": "platform" - }, - "System.Diagnostics.Process": "4.1.0-*" + } }, "imports": [ "dnxcore50", "portable-net451+win8" ] }, - "net451": { - "frameworkAssemblies": { - "System.Runtime": { - "type": "build" - } - } - } + "net451": {} } } \ No newline at end of file From 24439bc400ab5c67e9480dfc56ed9d8f361a5f4c Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 30 Jun 2016 15:36:11 -0700 Subject: [PATCH 0229/1029] Updating to RTM builds of xunit and Moq --- .gitignore | 13 ++++++++--- .../project.json | 22 ++++--------------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index 2e4b2d6b5d..06cfaa0cbe 100644 --- a/.gitignore +++ b/.gitignore @@ -8,15 +8,18 @@ TestResults/ _ReSharper.*/ packages/ artifacts/ -.build/ PublishProfiles/ +.vs/ +bower_components/ +node_modules/ +debugSettings.json +project.lock.json *.user *.suo *.cache *.docstates _ReSharper.* nuget.exe -project.lock.json *net45.csproj *net451.csproj *k10.csproj @@ -28,4 +31,8 @@ project.lock.json *.ncrunchsolution *.*sdf *.ipch -.build/ \ No newline at end of file +.settings +*.sln.ide +node_modules +*launchSettings.json +*.orig \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index 4bd3e6450b..d6f8f5cbc6 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -3,10 +3,11 @@ "warningsAsErrors": true }, "dependencies": { - "dotnet-test-xunit": "1.0.0-*", + "dotnet-test-xunit": "2.2.0-*", "Microsoft.AspNetCore.JsonPatch": "1.1.0-*", "Microsoft.AspNetCore.Testing": "1.1.0-*", - "xunit": "2.1.0" + "Moq": "4.6.25-*", + "xunit": "2.2.0-*" }, "testRunner": "xunit", "frameworks": { @@ -16,30 +17,15 @@ "version": "1.0.0-*", "type": "platform" }, - "moq.netcore": "4.4.0-beta8", - "System.Diagnostics.Process": "4.1.0-*", "System.Diagnostics.TraceSource": "4.0.0-*" }, - "imports": [ - "dnxcore50", - "portable-net451+win8" - ] + "imports": "dotnet5.4" }, "net451": { "frameworkAssemblies": { "System.Linq.Expressions": { "type": "build" - }, - "System.Runtime": { - "type": "build" - }, - "System.Threading.Tasks": { - "type": "build" } - }, - "dependencies": { - "Moq": "4.2.1312.1622", - "xunit.runner.console": "2.1.0" } } } From 21b35259332877ef60730971a8d1a28b99e63475 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Tue, 5 Jul 2016 09:57:11 -0700 Subject: [PATCH 0230/1029] Make MultipleTriggers more stable --- .../FileWatcherTests.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs index dc696e6c93..e9be4869a1 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs @@ -288,7 +288,21 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests handler = (_, f) => { filesChanged.Add(f); - changedEv.Set(); + try + { + changedEv.Set(); + } + catch(ObjectDisposedException) + { + // There's a known race condition here: + // even though we tell the watcher to stop raising events and we unsubscribe the handler + // there might be in-flight events that will still process. Since we dispose the reset + // event, this code will fail if the handler executes after Dispose happens. There's no + // better way to guard against it than catch because we cannot check if the object is + // disposed nor can we check if there are any in-flight events. + // This is actually a known issue in the corefx file watcher. It can trigger multiple + // times for the same item. + } }; watcher.OnFileChange += handler; From 9d16d2e9b514183ff34e7d37d977dff617e8a2d2 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Tue, 5 Jul 2016 09:30:13 -0700 Subject: [PATCH 0231/1029] Use the scenario tool tested from testing common --- .../Scenario/DotNetWatchScenario.cs | 1 + .../Scenario/ProjectToolScenario.cs | 185 ------------------ .../project.json | 1 + 3 files changed, 2 insertions(+), 185 deletions(-) delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs index 89cb67ef35..5b6799fab4 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; +using Microsoft.AspNetCore.Testing.Functional; using Microsoft.Extensions.Internal; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs deleted file mode 100644 index a5abaab1fd..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Threading; -using System.Xml.Linq; -using Newtonsoft.Json.Linq; - -namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests -{ - public class ProjectToolScenario: IDisposable - { - private const string NugetConfigFileName = "NuGet.config"; - - private static readonly object _restoreLock = new object(); - - public ProjectToolScenario() - { - Console.WriteLine($"The temporary test folder is {TempFolder}"); - - WorkFolder = Path.Combine(TempFolder, "work"); - - CreateTestDirectory(); - } - - public string TempFolder { get; } = Path.Combine(Path.GetDirectoryName(FindNugetConfig()), "testWorkDir" , Guid.NewGuid().ToString()); - - public string WorkFolder { get; } - - public void AddProject(string projectFolder) - { - var destinationFolder = Path.Combine(WorkFolder, Path.GetFileName(projectFolder)); - Console.WriteLine($"Copying project {projectFolder} to {destinationFolder}"); - - Directory.CreateDirectory(destinationFolder); - - foreach (var directory in Directory.GetDirectories(projectFolder, "*", SearchOption.AllDirectories)) - { - Directory.CreateDirectory(directory.Replace(projectFolder, destinationFolder)); - } - - foreach (var file in Directory.GetFiles(projectFolder, "*.*", SearchOption.AllDirectories)) - { - File.Copy(file, file.Replace(projectFolder, destinationFolder), true); - } - } - - public void AddNugetFeed(string feedName, string feed) - { - var tempNugetConfigFile = Path.Combine(WorkFolder, NugetConfigFileName); - - var nugetConfig = XDocument.Load(tempNugetConfigFile); - var packageSource = nugetConfig.Element("configuration").Element("packageSources"); - packageSource.Add(new XElement("add", new XAttribute("key", feedName), new XAttribute("value", feed))); - using (var stream = File.OpenWrite(tempNugetConfigFile)) - { - nugetConfig.Save(stream); - } - } - - public void AddToolToProject(string projectName, string toolName) - { - var projectFile = Path.Combine(WorkFolder, projectName, "project.json"); - Console.WriteLine($"Adding {toolName} to {projectFile}"); - - var versionSuffix = Environment.GetEnvironmentVariable("DOTNET_BUILD_VERSION"); - if (string.IsNullOrEmpty(versionSuffix)) - { - versionSuffix = "*"; - } - - var projectJson = JObject.Parse(File.ReadAllText(projectFile)); - projectJson.Add("tools", - new JObject( - new JProperty(toolName, - new JObject( - new JProperty("version", "1.0.0-" + versionSuffix), - new JProperty("imports", "portable-net451+win8"))))); - - File.WriteAllText(projectFile, projectJson.ToString()); - } - - public void Restore(string project = null) - { - if (project == null) - { - project = WorkFolder; - } - else - { - project = Path.Combine(WorkFolder, project); - } - - // Tests are run in parallel and they try to restore tools concurrently. - // This causes issues because the deps json file for a tool is being written from - // multiple threads - which results in either sharing violation or corrupted json. - lock(_restoreLock) - { - var restore = ExecuteDotnet($"restore -v Minimal", project); - restore.WaitForExit(); - - if (restore.ExitCode != 0) - { - throw new Exception($"Exit code {restore.ExitCode}"); - } - } - } - - private void CreateTestDirectory() - { - Directory.CreateDirectory(WorkFolder); - File.WriteAllText(Path.Combine(WorkFolder, "global.json"), "{}"); - - var nugetConfigFilePath = FindNugetConfig(); - - var tempNugetConfigFile = Path.Combine(WorkFolder, NugetConfigFileName); - File.Copy(nugetConfigFilePath, tempNugetConfigFile); - } - - public Process ExecuteDotnet(string arguments, string workDir, IDictionary environmentVariables = null) - { - Console.WriteLine($"Running dotnet {arguments} in {workDir}"); - - var psi = new ProcessStartInfo("dotnet", arguments) - { - UseShellExecute = false, - WorkingDirectory = workDir, - }; - - if (environmentVariables != null) - { - foreach (var newEnvVar in environmentVariables) - { - if (psi.Environment.ContainsKey(newEnvVar.Key)) - { - psi.Environment[newEnvVar.Key] = newEnvVar.Value; - } - else - { - psi.Environment.Add(newEnvVar.Key, newEnvVar.Value); - } - } - } - - return Process.Start(psi); - } - - private static string FindNugetConfig() - { - var currentDirPath = Directory.GetCurrentDirectory(); - - string nugetConfigFile; - while (true) - { - nugetConfigFile = Directory.GetFiles(currentDirPath).SingleOrDefault(f => Path.GetFileName(f).Equals(NugetConfigFileName, StringComparison.Ordinal)); - if (!string.IsNullOrEmpty(nugetConfigFile)) - { - break; - } - - currentDirPath = Path.GetDirectoryName(currentDirPath); - } - - return nugetConfigFile; - } - - public void Dispose() - { - try - { - Directory.Delete(TempFolder, recursive: true); - } - catch - { - Console.WriteLine($"Failed to delete {TempFolder}. Retrying..."); - Thread.Sleep(TimeSpan.FromSeconds(5)); - Directory.Delete(TempFolder, recursive: true); - } - } - } -} diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index e7671bd373..0881b8ae53 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -5,6 +5,7 @@ }, "dependencies": { "dotnet-test-xunit": "2.2.0-*", + "Microsoft.AspNetCore.Testing": "1.1.0-*", "Microsoft.Extensions.DependencyInjection": "1.1.0-*", "Microsoft.Extensions.Process.Sources": { "type": "build", From 9f6a691655d8a55b6e3daa410dce30efdd0eaa33 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Wed, 6 Jul 2016 22:09:57 -0700 Subject: [PATCH 0232/1029] One build to rule them all - well, at least VS and command-line builds will share output - part of aspnet/Coherence-Signed#277 --- .../Microsoft.DotNet.Watcher.Core.xproj | 4 ++-- .../Microsoft.DotNet.Watcher.Tools.xproj | 4 ++-- .../Microsoft.DotNet.Watcher.Tools.FunctionalTests.xproj | 2 +- test/TestApps/AppWithDeps/AppWithDeps.xproj | 7 +++---- test/TestApps/Dependency/Dependency.xproj | 7 +++---- test/TestApps/GlobbingApp/GlobbingApp.xproj | 7 +++---- test/TestApps/NoDepsApp/NoDepsApp.xproj | 7 +++---- 7 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/Microsoft.DotNet.Watcher.Core.xproj b/src/Microsoft.DotNet.Watcher.Core/Microsoft.DotNet.Watcher.Core.xproj index 1467ed1975..c8b26f14d5 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Microsoft.DotNet.Watcher.Core.xproj +++ b/src/Microsoft.DotNet.Watcher.Core/Microsoft.DotNet.Watcher.Core.xproj @@ -7,8 +7,8 @@ d3da3bbb-e206-404f-aee6-17fb9b6f1221 - ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\ + .\obj + .\bin\ 2.0 diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.xproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.xproj index bc07d744ea..8d14e52973 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.xproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.xproj @@ -7,8 +7,8 @@ 8a8ceabc-ac47-43ff-a5df-69224f7e1f46 - ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\ + .\obj + .\bin\ 2.0 diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.xproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.xproj index 317f69fb4a..ed54a4cec7 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.xproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.xproj @@ -7,7 +7,7 @@ 16bade2f-1184-4518-8a70-b68a19d0805b - ..\..\artifacts\obj\$(MSBuildProjectName) + .\obj .\bin\ diff --git a/test/TestApps/AppWithDeps/AppWithDeps.xproj b/test/TestApps/AppWithDeps/AppWithDeps.xproj index 42ff14fd34..0359495322 100644 --- a/test/TestApps/AppWithDeps/AppWithDeps.xproj +++ b/test/TestApps/AppWithDeps/AppWithDeps.xproj @@ -1,14 +1,13 @@  - + - 14.0.23107 + 14.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) f7734e61-f510-41e0-ad15-301a64081cd1 - AppWithDeps - ..\..\..\artifacts\obj\$(MSBuildProjectName) + .\obj .\bin\ diff --git a/test/TestApps/Dependency/Dependency.xproj b/test/TestApps/Dependency/Dependency.xproj index 406bf0a295..bab595dfee 100644 --- a/test/TestApps/Dependency/Dependency.xproj +++ b/test/TestApps/Dependency/Dependency.xproj @@ -1,14 +1,13 @@  - + - 14.0.23107 + 14.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 2f48041a-f7d1-478f-9c38-d41f0f05e8ca - Dependency - ..\..\..\artifacts\obj\$(MSBuildProjectName) + .\obj .\bin\ diff --git a/test/TestApps/GlobbingApp/GlobbingApp.xproj b/test/TestApps/GlobbingApp/GlobbingApp.xproj index b170a846ad..6d89d4053b 100644 --- a/test/TestApps/GlobbingApp/GlobbingApp.xproj +++ b/test/TestApps/GlobbingApp/GlobbingApp.xproj @@ -1,14 +1,13 @@  - + - 14.0.23107 + 14.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 2ab1a28b-2022-49ea-af77-ac8a875915cc - GlobbingApp - ..\..\..\artifacts\obj\$(MSBuildProjectName) + .\obj .\bin\ diff --git a/test/TestApps/NoDepsApp/NoDepsApp.xproj b/test/TestApps/NoDepsApp/NoDepsApp.xproj index 50d9989df2..a85e3bced4 100644 --- a/test/TestApps/NoDepsApp/NoDepsApp.xproj +++ b/test/TestApps/NoDepsApp/NoDepsApp.xproj @@ -1,14 +1,13 @@  - + - 14.0.23107 + 14.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 4f0d8a80-221f-4bcb-822e-44a0655f537e - NoDepsApp - ..\..\..\artifacts\obj\$(MSBuildProjectName) + .\obj .\bin\ From 717e4fe083aee435536ead22c2993278f63f1487 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Thu, 7 Jul 2016 12:00:26 -0700 Subject: [PATCH 0233/1029] One build to rule them all - well, at least VS and command-line builds will share output - part of aspnet/Coherence-Signed#277 --- .../Microsoft.AspNetCore.Html.Abstractions.xproj | 4 ++-- .../Microsoft.Extensions.WebEncoders.xproj | 4 ++-- .../Microsoft.AspNetCore.Html.Abstractions.Test.xproj | 4 ++-- .../Microsoft.Extensions.WebEncoders.Tests.xproj | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.xproj b/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.xproj index 7a3801b2b1..25d87d97bb 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.xproj +++ b/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.xproj @@ -7,8 +7,8 @@ 68a28e4a-3ade-4187-9625-4ff185887cb3 - ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\ + .\obj + .\bin\ 2.0 diff --git a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.xproj b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.xproj index 0f278d6c98..f458d42cf1 100644 --- a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.xproj +++ b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.xproj @@ -7,8 +7,8 @@ dd2ce416-765e-4000-a03e-c2ff165da1b6 - ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\ + .\obj + .\bin\ 2.0 diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.xproj b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.xproj index 20389ad4bf..3d3d10b2ac 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.xproj +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.xproj @@ -7,8 +7,8 @@ 2d187b88-94bd-4a39-ac97-f8f8b9363301 - ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\ + .\obj + .\bin\ 2.0 diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.xproj b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.xproj index 9ad3cb3d4f..a7810a9e17 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.xproj +++ b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.xproj @@ -7,8 +7,8 @@ 7ae2731d-43cd-4cf8-850a-4914de2ce930 - ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\ + .\obj + .\bin\ 2.0 From 6b08efb12271fd6c81ab60e1c509032cf5ed5e39 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Thu, 7 Jul 2016 12:06:18 -0700 Subject: [PATCH 0234/1029] One build to rule them all - well, at least VS and command-line builds will share output - part of aspnet/Coherence-Signed#277 --- .../Microsoft.AspNetCore.JsonPatch.xproj | 4 ++-- .../Microsoft.AspNetCore.JsonPatch.Test.xproj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.xproj b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.xproj index d11d600744..0ebf789691 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.xproj +++ b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.xproj @@ -7,8 +7,8 @@ 4d55f4d8-633b-462f-a5b1-feb84bd2d534 - ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\ + .\obj + .\bin\ 2.0 diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.xproj b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.xproj index 0b71c5d301..c8942c121e 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.xproj +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.xproj @@ -7,8 +7,8 @@ 81c20848-e063-4e12-ac40-0b55a532c16c - ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\ + .\obj + .\bin\ 2.0 From c769d8dee9991b9adff83455afae8797b01084eb Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Thu, 14 Jul 2016 11:48:48 -0700 Subject: [PATCH 0235/1029] Fix null ref exception when referencing csproj --- .../Internal/Implementation/Project.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs index d8175329b3..e0803c2d1f 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs @@ -48,7 +48,10 @@ namespace Microsoft.DotNet.Watcher.Core.Internal if (File.Exists(projectLockJsonPath)) { var lockFile = LockFileReader.Read(projectLockJsonPath, designTime: false); - ProjectDependencies = lockFile.ProjectLibraries.Select(dep => GetProjectRelativeFullPath(dep.Path)).ToList(); + ProjectDependencies = lockFile.ProjectLibraries + .Where(dep => !string.IsNullOrEmpty(dep.Path)) // The dependency path is null for xproj -> csproj reference + .Select(dep => GetProjectRelativeFullPath(dep.Path)) + .ToList(); } else { From ed91ba0c2f886217a6e39e6ba5f4547f6bff1712 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Fri, 15 Jul 2016 11:53:45 -0700 Subject: [PATCH 0236/1029] - Fix a NullRef exception that was happening when projects have resx files - Print the changed file name in all cases --- src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs | 11 ++++++++--- .../Internal/Implementation/Project.cs | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs index cdb5ba7483..92577d59fe 100644 --- a/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs @@ -93,6 +93,7 @@ namespace Microsoft.DotNet.Watcher.Core cancellationToken.ThrowIfCancellationRequested(); + string changedFile; if (finishedTaskIndex == 0) { // This is the dotnet task @@ -109,13 +110,17 @@ namespace Microsoft.DotNet.Watcher.Core _logger.LogInformation("Waiting for a file to change before restarting dotnet..."); // Now wait for a file to change before restarting dotnet - await WaitForProjectFileToChangeAsync(projectFile, cancellationToken); + changedFile = await WaitForProjectFileToChangeAsync(projectFile, cancellationToken); } else { // This is a file watcher task - string changedFile = fileWatchingTask.Result; - _logger.LogInformation($"File changed: {fileWatchingTask.Result}"); + changedFile = fileWatchingTask.Result; + } + + if (!string.IsNullOrEmpty(changedFile)) + { + _logger.LogInformation($"File changed: {changedFile}"); } } } diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs index e0803c2d1f..11df0238c1 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs @@ -35,7 +35,8 @@ namespace Microsoft.DotNet.Watcher.Core.Internal } else { - filesToWatch.AddRange(runtimeProject.Files.ResourceFiles.Values); + // For resource files the key is the name of the file, not the value + filesToWatch.AddRange(runtimeProject.Files.ResourceFiles.Keys); } filesToWatch.AddRange(runtimeProject.Files.SharedFiles); From 3c445638a9f628ab0cfb5ee65b3bacdc78444882 Mon Sep 17 00:00:00 2001 From: BrennanConroy Date: Tue, 2 Aug 2016 13:10:39 -0700 Subject: [PATCH 0237/1029] Update .travis.yml --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index eea7a1dd5b..3097eccc74 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ branches: - dev - /^(.*\/)?ci-.*$/ before_install: - - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; brew link --force openssl; fi + - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; fi script: - ./build.sh --quiet verify notifications: @@ -31,4 +31,4 @@ notifications: secure: "dhjfYLtihxx3zDdj0TLMJjiN4YJ37Qu0L9ySx7ek+YsfOAqKPHUsI6JNDtChauQxUB2NoL/i80+47oHhMelPyXniu1xA0MWaHV8bddZHzNQs1N8vGjjPmtbC5DQ7jmy+p7Xa5+ZscZ9NWEvJRqBInNdqugDAstDEIWbC35bq8H9t+6tZYu1sJctp1zF/k/w4OjJUoI1ZNLuusYIB1E+G/irvVT2x4GOC2QY3wXM4lJ2ORcZE9NgUBLNx/Hy5Rst5i4zO/mrFkYM/wOY6bAM6/gjjanK+d1wQnD9HuZH1ZVQqJRH3lveurYq9ih4zxV8MbW3FdLL1cXswEZbUBeqHlxVE32KwWF18nFUwdmrNQebnYnrZ/VWsa4pl+bOFNy2nomI3ibJ4F4+RwqTPXXE13qCr0CsC5RKu5bVQTpi0t4CKlUMsVlevN2jJcmAA641bnETNTDwk5WdT7Mjf9Pnn+krLZ7im9li3Plc/d8ynR1oiRzwFdp3u/9m3Oc8K+zMsNO5IOxHul9WsWbIkh3sNecqKHPSyVHB4FgdUoQ65xpc0887YKorbuBTOnlZugP8M/FmowkcwLo5xDD7kchkxyq9X8dPjej+tzpTsNVJjrOg4LP+nKxmOa+qc1r62eF0GdnIjwU30y6NdfvBCXoQJE1y063/zyGPIxSfCRmVzq4A=" on_success: always on_failure: always - on_start: always \ No newline at end of file + on_start: always From c7035517724bc5b0fbdc8cd1b67656f90a953f0a Mon Sep 17 00:00:00 2001 From: BrennanConroy Date: Tue, 2 Aug 2016 13:14:37 -0700 Subject: [PATCH 0238/1029] Update .travis.yml --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index bb366b178f..631adcf570 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,6 @@ branches: - dev - /^(.*\/)?ci-.*$/ before_install: - - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; brew link --force openssl; fi + - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; fi script: - - ./build.sh --quiet verify \ No newline at end of file + - ./build.sh --quiet verify From cbe53312d4b3a41122e334ae38810191363a0486 Mon Sep 17 00:00:00 2001 From: BrennanConroy Date: Tue, 2 Aug 2016 13:15:00 -0700 Subject: [PATCH 0239/1029] Update .travis.yml --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 59d308953d..1ba51470ba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ branches: - dev - /^(.*\/)?ci-.*$/ before_install: - - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; brew link --force openssl; fi + - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; fi script: - ./build.sh --quiet verify notifications: @@ -31,4 +31,4 @@ notifications: secure: "d87o+y2WUx204s8TfSaEuekYudnSyyPaFEXkuzgs3uAyzkKAm/Hx0xcMSuKDqWhYmKaxL7VtgEd2z7mltr2cHZ4oyCrsf6V5v4iI48ojaGykqFXfv8ld6khmLwtdkC32lF2YyuDNL8kUvKNdP9jkrWlpoO/WC6QEqAUxdOuuLo/wLyfrPLbzIvbojwveXbmcwvsfDizLdZdVd88FZSV41h+yBKLnyhpeqRvHG85BTgT/GmVB7Vyjs3yChiS639Aq5DoOP8jBaRdB8Bqs09KibFXzJwDBlKvALIqiwzog3hpd5SVxrgOTCkWbOwqq4TSkahDE425W3vFbmLDANgdfsyAkqgt8daE2BkFTojEHQED+u9CEd8oJVX6FoGnYpuDzge4FVh9iG3HSuKwoVdlONzzew4oJ75iQ+0f67ZNV9oDuScdva/SGb2gYgVUkeJIjDoMxKuaZyhbBT9jRXRBI+LsIjziEhLU/649FjTSmQx0HLpcT7+kaeSmhqT9JffVLidMdvZwhPZsLxPSG9UVBH9G8rdyHXP2e0ZlicHNjjNV6kbDqfDPhHx2/MfZGugsJXjOONKu/5LZduQzmAOysqdLKqkBVkMq2xl7aGV+yVZAtTmZB3nqOWGyKlFC9kLGO+qlJ4tBac26lHCZWTK+4VOAtN5Dag0DkDikgGdZaq78=" on_success: always on_failure: always - on_start: always \ No newline at end of file + on_start: always From e991ebaa4fd6b0011d7492f0e30520f657d02119 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 8 Aug 2016 14:29:46 -0700 Subject: [PATCH 0240/1029] Updating to Moq \ Castle.Core that does not require imports --- test/Microsoft.AspNetCore.JsonPatch.Test/project.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index d6f8f5cbc6..acc8390c6d 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -6,7 +6,7 @@ "dotnet-test-xunit": "2.2.0-*", "Microsoft.AspNetCore.JsonPatch": "1.1.0-*", "Microsoft.AspNetCore.Testing": "1.1.0-*", - "Moq": "4.6.25-*", + "Moq": "4.6.36-*", "xunit": "2.2.0-*" }, "testRunner": "xunit", @@ -18,8 +18,7 @@ "type": "platform" }, "System.Diagnostics.TraceSource": "4.0.0-*" - }, - "imports": "dotnet5.4" + } }, "net451": { "frameworkAssemblies": { From 79cb3b0ed9f6740f30fb9c4a3af8f1186ea70168 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 9 Aug 2016 14:58:36 -0700 Subject: [PATCH 0241/1029] Switching to dotnet.myget.org feed --- NuGet.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NuGet.config b/NuGet.config index 52bf414192..0fd623ffdd 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + - + From acab75a1bb3c897f9343ae32c5e460bffad786e1 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 9 Aug 2016 15:03:00 -0700 Subject: [PATCH 0242/1029] Switching to dotnet.myget.org feed --- NuGet.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NuGet.config b/NuGet.config index 03704957e8..826a1f9035 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@  - + \ No newline at end of file From 2e53d0e55be8fde8f7bf112dd2d814eea8f490a8 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 9 Aug 2016 15:04:20 -0700 Subject: [PATCH 0243/1029] Switching to dotnet.myget.org feed --- NuGet.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NuGet.config b/NuGet.config index 5500f6d507..0fd623ffdd 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@  - + From ac2f21514f2627484dd545e2e6243a231fddf1a4 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Wed, 31 Aug 2016 09:30:33 -0700 Subject: [PATCH 0244/1029] Add a flag to specify the log level --- README.md | 11 ++++++++++- src/Microsoft.DotNet.Watcher.Tools/Program.cs | 17 ++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9fe921f7aa..11b1f68db4 100644 --- a/README.md +++ b/README.md @@ -25,13 +25,22 @@ Add `Microsoft.DotNet.Watcher.Tools` to the `tools` section of your `project.jso Add `watch` after `dotnet` in the command that you want to run: -| What you want to run | Dotnet watch command | +| What you want to run | Dotnet watch command | | ---------------------------------------------- | -------------------------------------------------------- | | dotnet run | dotnet **watch** run | | dotnet run --arg1 value1 | dotnet **watch** run --arg1 value | | dotnet run --framework net451 -- --arg1 value1 | dotnet **watch** run --framework net451 -- --arg1 value1 | | dotnet test | dotnet **watch** test | +### Advanced configuration options + +Configuration options can be passed to `dotnet watch` through environment variables. The available variables are: + +| Variable | Effect | +| ---------------------------------------------- | -------------------------------------------------------- | +| DOTNET_USE_POLLING_FILE_WATCHER | If set to "1" or "true", `dotnet watch` will use a polling file watcher instead of CoreFx's `FileSystemWatcher`. Used when watching files on network shares or Docker mounted volumes. | +| DOTNET_WATCH_LOG_LEVEL | Used to set the logging level for messages coming from `dotnet watch`. Accepted values `None`, `Trace`, `Debug`, `Information`, `Warning`, `Error`, `Critical`. Default: `Information`. | + AppVeyor: [![AppVeyor](https://ci.appveyor.com/api/projects/status/fxhto3omtehio3aj/branch/dev?svg=true)](https://ci.appveyor.com/project/aspnetci/dnx-watch/branch/dev) Travis: [![Travis](https://travis-ci.org/aspnet/dotnet-watch.svg?branch=dev)](https://travis-ci.org/aspnet/dotnet-watch) diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index d27c68e543..5b0cde0b71 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -19,7 +19,18 @@ namespace Microsoft.DotNet.Watcher.Tools { _loggerFactory = new LoggerFactory(); - var commandProvider = new CommandOutputProvider(); + var logVar = Environment.GetEnvironmentVariable("DOTNET_WATCH_LOG_LEVEL"); + + LogLevel logLevel; + if (string.IsNullOrEmpty(logVar) || !Enum.TryParse(logVar, out logLevel)) + { + logLevel = LogLevel.Information; + } + + var commandProvider = new CommandOutputProvider() + { + LogLevel = logLevel + }; _loggerFactory.AddProvider(commandProvider); } @@ -32,7 +43,7 @@ namespace Microsoft.DotNet.Watcher.Tools ctrlCTokenSource.Cancel(); ev.Cancel = false; }; - + return new Program().MainInternal(args, ctrlCTokenSource.Token); } } @@ -44,7 +55,7 @@ namespace Microsoft.DotNet.Watcher.Tools app.FullName = "Microsoft dotnet File Watcher"; app.HelpOption("-?|-h|--help"); - + app.OnExecute(() => { var projectToWatch = Path.Combine(Directory.GetCurrentDirectory(), ProjectModel.Project.FileName); From 6eec856fe39d6c99bdcbcdf5248d36924f264711 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Sat, 3 Sep 2016 22:28:55 -0700 Subject: [PATCH 0245/1029] Increase .travis.yml consistency between repos - aspnet/Universe#349 - minimize `dotnet` setup time; no need for caching --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 3097eccc74..a040cef874 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,10 @@ addons: - libssl-dev - libunwind8 - zlib1g +env: + global: + - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + - DOTNET_CLI_TELEMETRY_OPTOUT: 1 mono: - 4.0.5 os: From c2690023d8f14f8deb64b9571212ad2da5ff6541 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Sun, 4 Sep 2016 12:44:17 -0700 Subject: [PATCH 0246/1029] Increase .travis.yml consistency between repos - aspnet/Universe#349 - minimize `dotnet` setup time; no need for caching --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 1ba51470ba..e2abeda7d4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,10 @@ addons: - libssl-dev - libunwind8 - zlib1g +env: + global: + - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + - DOTNET_CLI_TELEMETRY_OPTOUT: 1 mono: - 4.0.5 os: From e72d4b4876ca0599aa1afc685e8d50b50ed6d71b Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Sun, 4 Sep 2016 15:46:35 -0700 Subject: [PATCH 0247/1029] Increase .travis.yml consistency between repos - aspnet/Universe#349 - minimize `dotnet` setup time; no need for caching --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 631adcf570..d7636fa329 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,10 @@ addons: - libssl-dev - libunwind8 - zlib1g +env: + global: + - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + - DOTNET_CLI_TELEMETRY_OPTOUT: 1 mono: - 4.0.5 os: From 484f35691a49f8c13165a3a41f47cd0f7cb49bb2 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 7 Sep 2016 11:19:56 -0700 Subject: [PATCH 0248/1029] Don't use DOTNET_BUILD_VERSION in code. Clean up test projects --- .../Scenario/DotNetWatchScenario.cs | 2 +- .../Scenario/ProjectToolScenario.cs | 178 ++++++++++++++++++ test/TestApps/AppWithDeps/project.json | 13 +- test/TestApps/Dependency/project.json | 10 +- test/TestApps/GlobbingApp/project.json | 9 +- test/TestApps/NoDepsApp/project.json | 9 +- 6 files changed, 190 insertions(+), 31 deletions(-) create mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs index 5b6799fab4..4af46b1171 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; -using Microsoft.AspNetCore.Testing.Functional; using Microsoft.Extensions.Internal; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests @@ -22,6 +21,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public DotNetWatchScenario() { _scenario = new ProjectToolScenario(); + Directory.CreateDirectory(_artifactsFolder); _scenario.AddNugetFeed(DotnetWatch, _artifactsFolder); } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs new file mode 100644 index 0000000000..48af21836e --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -0,0 +1,178 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Threading; +using System.Xml.Linq; +using Newtonsoft.Json.Linq; + +namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests +{ + public class ProjectToolScenario : IDisposable + { + private const string NugetConfigFileName = "NuGet.config"; + + private static readonly object _restoreLock = new object(); + + public ProjectToolScenario() + { + Console.WriteLine($"The temporary test folder is {TempFolder}"); + + WorkFolder = Path.Combine(TempFolder, "work"); + + CreateTestDirectory(); + } + + public string TempFolder { get; } = Path.Combine(Path.GetDirectoryName(FindNugetConfig()), "testWorkDir", Guid.NewGuid().ToString()); + + public string WorkFolder { get; } + + public void AddProject(string projectFolder) + { + var destinationFolder = Path.Combine(WorkFolder, Path.GetFileName(projectFolder)); + Console.WriteLine($"Copying project {projectFolder} to {destinationFolder}"); + + Directory.CreateDirectory(destinationFolder); + + foreach (var directory in Directory.GetDirectories(projectFolder, "*", SearchOption.AllDirectories)) + { + Directory.CreateDirectory(directory.Replace(projectFolder, destinationFolder)); + } + + foreach (var file in Directory.GetFiles(projectFolder, "*.*", SearchOption.AllDirectories)) + { + File.Copy(file, file.Replace(projectFolder, destinationFolder), true); + } + } + + public void AddNugetFeed(string feedName, string feed) + { + var tempNugetConfigFile = Path.Combine(WorkFolder, NugetConfigFileName); + + var nugetConfig = XDocument.Load(tempNugetConfigFile); + var packageSource = nugetConfig.Element("configuration").Element("packageSources"); + packageSource.Add(new XElement("add", new XAttribute("key", feedName), new XAttribute("value", feed))); + using (var stream = File.OpenWrite(tempNugetConfigFile)) + { + nugetConfig.Save(stream); + } + } + + public void AddToolToProject(string projectName, string toolName) + { + var projectFile = Path.Combine(WorkFolder, projectName, "project.json"); + Console.WriteLine($"Adding {toolName} to {projectFile}"); + + var projectJson = JObject.Parse(File.ReadAllText(projectFile)); + projectJson.Add("tools", + new JObject( + new JProperty(toolName, + new JObject( + new JProperty("version", "1.0.0-*"), + new JProperty("target", "package"))))); + + File.WriteAllText(projectFile, projectJson.ToString()); + } + + public void Restore(string project = null) + { + if (project == null) + { + project = WorkFolder; + } + else + { + project = Path.Combine(WorkFolder, project); + } + + // Tests are run in parallel and they try to restore tools concurrently. + // This causes issues because the deps json file for a tool is being written from + // multiple threads - which results in either sharing violation or corrupted json. + lock (_restoreLock) + { + var restore = ExecuteDotnet($"restore -v Minimal", project); + restore.WaitForExit(); + + if (restore.ExitCode != 0) + { + throw new Exception($"Exit code {restore.ExitCode}"); + } + } + } + + private void CreateTestDirectory() + { + Directory.CreateDirectory(WorkFolder); + File.WriteAllText(Path.Combine(WorkFolder, "global.json"), "{}"); + + var nugetConfigFilePath = FindNugetConfig(); + + var tempNugetConfigFile = Path.Combine(WorkFolder, NugetConfigFileName); + File.Copy(nugetConfigFilePath, tempNugetConfigFile); + } + + public Process ExecuteDotnet(string arguments, string workDir, IDictionary environmentVariables = null) + { + Console.WriteLine($"Running dotnet {arguments} in {workDir}"); + + var psi = new ProcessStartInfo("dotnet", arguments) + { + UseShellExecute = false, + WorkingDirectory = workDir, + }; + + if (environmentVariables != null) + { + foreach (var newEnvVar in environmentVariables) + { + var varKey = newEnvVar.Key; + var varValue = newEnvVar.Value; +#if NET451 + psi.EnvironmentVariables[varKey] = varValue; + +#else + psi.Environment[varKey] = varValue; +#endif + } + } + + return Process.Start(psi); + } + + private static string FindNugetConfig() + { + var currentDirPath = Directory.GetCurrentDirectory(); + + string nugetConfigFile; + while (true) + { + nugetConfigFile = Path.Combine(currentDirPath, NugetConfigFileName); + if (File.Exists(nugetConfigFile)) + { + break; + } + + currentDirPath = Path.GetDirectoryName(currentDirPath); + } + + return nugetConfigFile; + } + + public void Dispose() + { + try + { + Directory.Delete(TempFolder, recursive: true); + } + catch + { + Console.WriteLine($"Failed to delete {TempFolder}. Retrying..."); + Thread.Sleep(TimeSpan.FromSeconds(5)); + Directory.Delete(TempFolder, recursive: true); + } + } + } +} \ No newline at end of file diff --git a/test/TestApps/AppWithDeps/project.json b/test/TestApps/AppWithDeps/project.json index 8fbde9fc51..d197767c64 100644 --- a/test/TestApps/AppWithDeps/project.json +++ b/test/TestApps/AppWithDeps/project.json @@ -1,23 +1,20 @@ { - "version": "1.0.0-*", "buildOptions": { "emitEntryPoint": true }, "dependencies": { - "Dependency": "1.0.0" + "Dependency": { + "target": "project" + } }, "frameworks": { "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", - "version": "1.0.0-*" + "version": "1.0.0" } - }, - "imports": [ - "dnxcore50", - "portable-net451+win8" - ] + } } } } \ No newline at end of file diff --git a/test/TestApps/Dependency/project.json b/test/TestApps/Dependency/project.json index d8ac93175b..49853f2561 100644 --- a/test/TestApps/Dependency/project.json +++ b/test/TestApps/Dependency/project.json @@ -1,14 +1,8 @@ { - "version": "1.0.0", "dependencies": { - "NETStandard.Library": "1.5.0-*" + "NETStandard.Library": "1.6.0" }, "frameworks": { - "netstandard1.5": { - "imports": [ - "dnxcore50", - "portable-net451+win8" - ] - } + "netstandard1.5": {} } } \ No newline at end of file diff --git a/test/TestApps/GlobbingApp/project.json b/test/TestApps/GlobbingApp/project.json index 68104394d3..99e2421e43 100644 --- a/test/TestApps/GlobbingApp/project.json +++ b/test/TestApps/GlobbingApp/project.json @@ -1,5 +1,4 @@ { - "version": "1.0.0-*", "buildOptions": { "emitEntryPoint": true, "compile": { @@ -17,13 +16,9 @@ "dependencies": { "Microsoft.NETCore.App": { "type": "platform", - "version": "1.0.0-*" + "version": "1.0.0" } - }, - "imports": [ - "dnxcore50", - "portable-net451+win8" - ] + } } } } \ No newline at end of file diff --git a/test/TestApps/NoDepsApp/project.json b/test/TestApps/NoDepsApp/project.json index f0eb960bb6..327fafbef0 100644 --- a/test/TestApps/NoDepsApp/project.json +++ b/test/TestApps/NoDepsApp/project.json @@ -1,5 +1,4 @@ { - "version": "1.0.0-*", "buildOptions": { "emitEntryPoint": true }, @@ -8,13 +7,9 @@ "dependencies": { "Microsoft.NETCore.App": { "type": "platform", - "version": "1.0.0-*" + "version": "1.0.0" } - }, - "imports": [ - "dnxcore50", - "portable-net451+win8" - ] + } } } } \ No newline at end of file From e0663483edb40d36c48ed1b16442635a6e849d51 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 8 Sep 2016 15:47:15 -0700 Subject: [PATCH 0249/1029] Downgrade to 1.0.0 runtime dependencies --- makefile.shade | 7 ------- src/Microsoft.DotNet.Watcher.Core/project.json | 12 ++++++------ src/Microsoft.DotNet.Watcher.Tools/project.json | 12 ++++++------ .../project.json | 6 +++--- 4 files changed, 15 insertions(+), 22 deletions(-) delete mode 100644 makefile.shade diff --git a/makefile.shade b/makefile.shade deleted file mode 100644 index 56bf6d2cda..0000000000 --- a/makefile.shade +++ /dev/null @@ -1,7 +0,0 @@ -var VERSION='0.1' -var FULL_VERSION='0.1' -var AUTHORS='Microsoft Open Technologies, Inc.' --BuildQuality = "preview3"; - -use-standard-lifecycle -k-standard-goals \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index 53730690fc..ebc5bfdad6 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-*", + "version": "1.0.0-preview3-*", "description": "Core logic for the dotnet-watch command line tool.", "packOptions": { "tags": [ @@ -16,11 +16,11 @@ "xmlDoc": true }, "dependencies": { - "Microsoft.DotNet.ProjectModel": "1.0.0-*", - "Microsoft.Extensions.FileProviders.Abstractions": "1.1.0-*", - "Microsoft.Extensions.FileProviders.Physical": "1.1.0-*", - "Microsoft.Extensions.Logging.Abstractions": "1.1.0-*", - "Microsoft.Extensions.FileSystemGlobbing": "1.1.0-*", + "Microsoft.DotNet.ProjectModel": "1.0.0-rc3-003121", + "Microsoft.Extensions.FileProviders.Abstractions": "1.0.0", + "Microsoft.Extensions.FileProviders.Physical": "1.0.0", + "Microsoft.Extensions.Logging.Abstractions": "1.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "1.0.0", "Microsoft.Extensions.Process.Sources": { "type": "build", "version": "1.1.0-*" diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index 16e648aab8..c74d2973dc 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-*", + "version": "1.0.0-preview3-*", "description": "Command line tool to watch for source file changes during development and restart the dotnet command.", "packOptions": { "tags": [ @@ -18,18 +18,18 @@ "xmlDoc": true }, "dependencies": { - "System.Runtime.InteropServices.RuntimeInformation": "4.0.0-*", "Microsoft.DotNet.Watcher.Core": "1.0.0-*", - "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", - "Microsoft.Extensions.Logging": "1.1.0-*", - "Microsoft.Extensions.Logging.Console": "1.1.0-*" + "System.Runtime.InteropServices.RuntimeInformation": "4.0.0", + "Microsoft.Extensions.CommandLineUtils": "1.0.0", + "Microsoft.Extensions.Logging": "1.0.0", + "Microsoft.Extensions.Logging.Console": "1.0.0" }, "frameworks": { "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", - "version": "1.0.0-*" + "version": "1.0.0" } } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index 0881b8ae53..e49165f59e 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -6,14 +6,14 @@ "dependencies": { "dotnet-test-xunit": "2.2.0-*", "Microsoft.AspNetCore.Testing": "1.1.0-*", - "Microsoft.Extensions.DependencyInjection": "1.1.0-*", + "Microsoft.Extensions.DependencyInjection": "1.0.0", "Microsoft.Extensions.Process.Sources": { "type": "build", "version": "1.1.0-*" }, "Microsoft.DotNet.Watcher.Core": "1.0.0-*", "Newtonsoft.Json": "9.0.1", - "System.Threading.Thread": "4.0.0-*", + "System.Threading.Thread": "4.0.0", "xunit": "2.2.0-*" }, "frameworks": { @@ -21,7 +21,7 @@ "dependencies": { "Microsoft.NETCore.App": { "type": "platform", - "version": "1.0.0-*" + "version": "1.0.0" } } } From bf5d2f5dff7aaeb53277f9fb4e80b4efd7ac0c08 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 9 Sep 2016 09:01:36 -0700 Subject: [PATCH 0250/1029] Revert deletion of makefile.shade from e0663483edb40d36c48ed1b16442635a6e849d51 --- makefile.shade | 7 +++++++ src/Microsoft.DotNet.Watcher.Core/project.json | 2 +- src/Microsoft.DotNet.Watcher.Tools/project.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 makefile.shade diff --git a/makefile.shade b/makefile.shade new file mode 100644 index 0000000000..2493f0fcd3 --- /dev/null +++ b/makefile.shade @@ -0,0 +1,7 @@ +var VERSION='0.1' +var FULL_VERSION='0.1' +var AUTHORS='Microsoft Open Technologies, Inc.' +-BuildQuality = "preview3"; + +use-standard-lifecycle +k-standard-goals \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index ebc5bfdad6..e670669233 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-preview3-*", + "version": "1.0.0-*", "description": "Core logic for the dotnet-watch command line tool.", "packOptions": { "tags": [ diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index c74d2973dc..0a7c32d17b 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-preview3-*", + "version": "1.0.0-*", "description": "Command line tool to watch for source file changes during development and restart the dotnet command.", "packOptions": { "tags": [ From bbffd97633979c8f85998591dd6af445230d7566 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 9 Sep 2016 10:14:52 -0700 Subject: [PATCH 0251/1029] :arrow_up: Bump tool on dev branch to 'preview4' and re-up dependencies to latest dev versions --- makefile.shade | 2 +- src/Microsoft.DotNet.Watcher.Core/project.json | 10 +++++----- src/Microsoft.DotNet.Watcher.Tools/project.json | 6 +++--- .../project.json | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/makefile.shade b/makefile.shade index 2493f0fcd3..92e774c3cd 100644 --- a/makefile.shade +++ b/makefile.shade @@ -1,7 +1,7 @@ var VERSION='0.1' var FULL_VERSION='0.1' var AUTHORS='Microsoft Open Technologies, Inc.' --BuildQuality = "preview3"; +-BuildQuality = "preview4"; use-standard-lifecycle k-standard-goals \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index e670669233..53730690fc 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -16,11 +16,11 @@ "xmlDoc": true }, "dependencies": { - "Microsoft.DotNet.ProjectModel": "1.0.0-rc3-003121", - "Microsoft.Extensions.FileProviders.Abstractions": "1.0.0", - "Microsoft.Extensions.FileProviders.Physical": "1.0.0", - "Microsoft.Extensions.Logging.Abstractions": "1.0.0", - "Microsoft.Extensions.FileSystemGlobbing": "1.0.0", + "Microsoft.DotNet.ProjectModel": "1.0.0-*", + "Microsoft.Extensions.FileProviders.Abstractions": "1.1.0-*", + "Microsoft.Extensions.FileProviders.Physical": "1.1.0-*", + "Microsoft.Extensions.Logging.Abstractions": "1.1.0-*", + "Microsoft.Extensions.FileSystemGlobbing": "1.1.0-*", "Microsoft.Extensions.Process.Sources": { "type": "build", "version": "1.1.0-*" diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index 0a7c32d17b..e9cf189495 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -20,9 +20,9 @@ "dependencies": { "Microsoft.DotNet.Watcher.Core": "1.0.0-*", "System.Runtime.InteropServices.RuntimeInformation": "4.0.0", - "Microsoft.Extensions.CommandLineUtils": "1.0.0", - "Microsoft.Extensions.Logging": "1.0.0", - "Microsoft.Extensions.Logging.Console": "1.0.0" + "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", + "Microsoft.Extensions.Logging": "1.1.0-*", + "Microsoft.Extensions.Logging.Console": "1.1.0-*" }, "frameworks": { "netcoreapp1.0": { diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index e49165f59e..76af431397 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -6,7 +6,7 @@ "dependencies": { "dotnet-test-xunit": "2.2.0-*", "Microsoft.AspNetCore.Testing": "1.1.0-*", - "Microsoft.Extensions.DependencyInjection": "1.0.0", + "Microsoft.Extensions.DependencyInjection": "1.1.0-*", "Microsoft.Extensions.Process.Sources": { "type": "build", "version": "1.1.0-*" From 3b351ad1bb636b71c12fdffea7a9e0456924fd02 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 16 Sep 2016 10:08:57 -0700 Subject: [PATCH 0252/1029] Restore tool version to preview3 --- makefile.shade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile.shade b/makefile.shade index 92e774c3cd..2493f0fcd3 100644 --- a/makefile.shade +++ b/makefile.shade @@ -1,7 +1,7 @@ var VERSION='0.1' var FULL_VERSION='0.1' var AUTHORS='Microsoft Open Technologies, Inc.' --BuildQuality = "preview4"; +-BuildQuality = "preview3"; use-standard-lifecycle k-standard-goals \ No newline at end of file From 8f2eccbd3601eec1fd5a19439e3e665a3a17fc2c Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 19 Sep 2016 10:50:49 -0700 Subject: [PATCH 0253/1029] Move dotnet-user-secrets into current repo --- ...otNet.Watcher.Tools.sln => DotNetTools.sln | 16 +- NuGetPackageVerifier.json | 3 +- README.md | 50 +-- src/Microsoft.DotNet.Watcher.Tools/README.md | 39 +++ .../CommandOutputLogger.cs | 62 ++++ .../CommandOutputProvider.cs | 23 ++ .../Internal/ClearCommand.cs | 28 ++ .../CommandLineApplicationExtensions.cs | 24 ++ .../Internal/CommandLineOptions.cs | 70 +++++ .../Internal/GracefulException.cs | 25 ++ .../Internal/ICommand.cs | 12 + .../Internal/ListCommand.cs | 37 +++ .../Internal/RemoveCommand.cs | 49 +++ .../Internal/SecretsStore.cs | 78 +++++ .../Internal/SetCommand.cs | 51 ++++ ...osoft.Extensions.SecretManager.Tools.xproj | 17 ++ .../Program.cs | 183 +++++++++++ .../Properties/AssemblyInfo.cs | 11 + .../Properties/InternalsVisibleTo.cs | 6 + .../Properties/Resources.Designer.cs | 142 +++++++++ .../Resources.resx | 141 +++++++++ .../project.json | 43 +++ ...Extensions.SecretManager.Tools.Tests.xproj | 21 ++ .../SecretManagerTests.cs | 284 ++++++++++++++++++ .../TestLogger.cs | 50 +++ .../UserSecretHelper.cs | 47 +++ .../project.json | 22 ++ 27 files changed, 1489 insertions(+), 45 deletions(-) rename Microsoft.DotNet.Watcher.Tools.sln => DotNetTools.sln (80%) create mode 100644 src/Microsoft.DotNet.Watcher.Tools/README.md create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/CommandOutputLogger.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/CommandOutputProvider.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Internal/ClearCommand.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineApplicationExtensions.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Internal/GracefulException.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Internal/ICommand.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Internal/ListCommand.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.xproj create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Program.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Properties/AssemblyInfo.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Properties/InternalsVisibleTo.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Resources.resx create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/project.json create mode 100644 test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.xproj create mode 100644 test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs create mode 100644 test/Microsoft.Extensions.SecretManager.Tools.Tests/TestLogger.cs create mode 100644 test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretHelper.cs create mode 100644 test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json diff --git a/Microsoft.DotNet.Watcher.Tools.sln b/DotNetTools.sln similarity index 80% rename from Microsoft.DotNet.Watcher.Tools.sln rename to DotNetTools.sln index 658ce28d54..e600c724c1 100644 --- a/Microsoft.DotNet.Watcher.Tools.sln +++ b/DotNetTools.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66517987-2A5A-4330-B130-207039378FD4}" EndProject @@ -29,6 +29,10 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AppWithDeps", "test\TestApp EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Dependency", "test\TestApps\Dependency\Dependency.xproj", "{2F48041A-F7D1-478F-9C38-D41F0F05E8CA}" EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.SecretManager.Tools", "src\Microsoft.Extensions.SecretManager.Tools\Microsoft.Extensions.SecretManager.Tools.xproj", "{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.SecretManager.Tools.Tests", "test\Microsoft.Extensions.SecretManager.Tools.Tests\Microsoft.Extensions.SecretManager.Tools.Tests.xproj", "{7B331122-83B1-4F08-A119-DC846959844C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -63,6 +67,14 @@ Global {2F48041A-F7D1-478F-9C38-D41F0F05E8CA}.Debug|Any CPU.Build.0 = Debug|Any CPU {2F48041A-F7D1-478F-9C38-D41F0F05E8CA}.Release|Any CPU.ActiveCfg = Release|Any CPU {2F48041A-F7D1-478F-9C38-D41F0F05E8CA}.Release|Any CPU.Build.0 = Release|Any CPU + {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.Build.0 = Release|Any CPU + {7B331122-83B1-4F08-A119-DC846959844C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7B331122-83B1-4F08-A119-DC846959844C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -76,5 +88,7 @@ Global {2AB1A28B-2022-49EA-AF77-AC8A875915CC} = {2876B12E-5841-4792-85A8-2929AEE11885} {F7734E61-F510-41E0-AD15-301A64081CD1} = {2876B12E-5841-4792-85A8-2929AEE11885} {2F48041A-F7D1-478F-9C38-D41F0F05E8CA} = {2876B12E-5841-4792-85A8-2929AEE11885} + {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E} = {66517987-2A5A-4330-B130-207039378FD4} + {7B331122-83B1-4F08-A119-DC846959844C} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} EndGlobalSection EndGlobal diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index 447bab830f..932af6fb14 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -5,7 +5,8 @@ ], "packages": { "Microsoft.DotNet.Watcher.Tools": { }, - "Microsoft.DotNet.Watcher.Core": { } + "Microsoft.DotNet.Watcher.Core": { }, + "Microsoft.Extensions.SecretManager.Tools": { } } }, "Default": { // Rules to run for packages not listed in any other set. diff --git a/README.md b/README.md index 11b1f68db4..64eb8a2cee 100644 --- a/README.md +++ b/README.md @@ -1,48 +1,12 @@ -dotnet-watch -=== -`dotnet-watch` is a file watcher for `dotnet` that restarts the specified application when changes in the source code are detected. +DotNetTools +=========== -### How To Install +[![Travis build status](https://img.shields.io/travis/aspnet/dotnet-watch.svg?label=travis-ci&branch=dev&style=flat-square)](https://travis-ci.org/aspnet/dotnet-watch/branches) +[![AppVeyor build status](https://img.shields.io/appveyor/ci/aspnetci/dnx-watch/dev.svg?label=appveyor&style=flat-square)](https://ci.appveyor.com/project/aspnetci/dnx-watch/branch/dev) -Add `Microsoft.DotNet.Watcher.Tools` to the `tools` section of your `project.json` file: +The project contains command-line tools for the .NET Core SDK. -``` -{ -... - "tools": { - "Microsoft.DotNet.Watcher.Tools": { - "version": "1.0.0-*", - "imports": "portable-net451+win8" - } - } -... -} -``` - -### How To Use - - dotnet watch [dotnet arguments] - -Add `watch` after `dotnet` in the command that you want to run: - -| What you want to run | Dotnet watch command | -| ---------------------------------------------- | -------------------------------------------------------- | -| dotnet run | dotnet **watch** run | -| dotnet run --arg1 value1 | dotnet **watch** run --arg1 value | -| dotnet run --framework net451 -- --arg1 value1 | dotnet **watch** run --framework net451 -- --arg1 value1 | -| dotnet test | dotnet **watch** test | - -### Advanced configuration options - -Configuration options can be passed to `dotnet watch` through environment variables. The available variables are: - -| Variable | Effect | -| ---------------------------------------------- | -------------------------------------------------------- | -| DOTNET_USE_POLLING_FILE_WATCHER | If set to "1" or "true", `dotnet watch` will use a polling file watcher instead of CoreFx's `FileSystemWatcher`. Used when watching files on network shares or Docker mounted volumes. | -| DOTNET_WATCH_LOG_LEVEL | Used to set the logging level for messages coming from `dotnet watch`. Accepted values `None`, `Trace`, `Debug`, `Information`, `Warning`, `Error`, `Critical`. Default: `Information`. | - -AppVeyor: [![AppVeyor](https://ci.appveyor.com/api/projects/status/fxhto3omtehio3aj/branch/dev?svg=true)](https://ci.appveyor.com/project/aspnetci/dnx-watch/branch/dev) - -Travis: [![Travis](https://travis-ci.org/aspnet/dotnet-watch.svg?branch=dev)](https://travis-ci.org/aspnet/dotnet-watch) + - [dotnet-watch](src/Microsoft.DotNet.Watcher.Tools/) + - [dotnet-user-secrets](src/Microsoft.Extensions.SecretManager.Tools/) This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo. diff --git a/src/Microsoft.DotNet.Watcher.Tools/README.md b/src/Microsoft.DotNet.Watcher.Tools/README.md new file mode 100644 index 0000000000..b244177440 --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/README.md @@ -0,0 +1,39 @@ +dotnet-watch +============ +`dotnet-watch` is a file watcher for `dotnet` that restarts the specified application when changes in the source code are detected. + +### How To Install + +Add `Microsoft.DotNet.Watcher.Tools` to the `tools` section of your `project.json` file: + +``` +{ +... + "tools": { + "Microsoft.DotNet.Watcher.Tools": "1.0.0-*" + } +... +} +``` + +### How To Use + + dotnet watch [dotnet arguments] + +Add `watch` after `dotnet` in the command that you want to run: + +| What you want to run | Dotnet watch command | +| ---------------------------------------------- | -------------------------------------------------------- | +| dotnet run | dotnet **watch** run | +| dotnet run --arg1 value1 | dotnet **watch** run --arg1 value | +| dotnet run --framework net451 -- --arg1 value1 | dotnet **watch** run --framework net451 -- --arg1 value1 | +| dotnet test | dotnet **watch** test | + +### Advanced configuration options + +Configuration options can be passed to `dotnet watch` through environment variables. The available variables are: + +| Variable | Effect | +| ---------------------------------------------- | -------------------------------------------------------- | +| DOTNET_USE_POLLING_FILE_WATCHER | If set to "1" or "true", `dotnet watch` will use a polling file watcher instead of CoreFx's `FileSystemWatcher`. Used when watching files on network shares or Docker mounted volumes. | +| DOTNET_WATCH_LOG_LEVEL | Used to set the logging level for messages coming from `dotnet watch`. Accepted values `None`, `Trace`, `Debug`, `Information`, `Warning`, `Error`, `Critical`. Default: `Information`. | diff --git a/src/Microsoft.Extensions.SecretManager.Tools/CommandOutputLogger.cs b/src/Microsoft.Extensions.SecretManager.Tools/CommandOutputLogger.cs new file mode 100644 index 0000000000..f648400f65 --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/CommandOutputLogger.cs @@ -0,0 +1,62 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.Extensions.CommandLineUtils; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Extensions.SecretManager.Tools +{ + /// + /// Logger to print formatted command output. + /// + public class CommandOutputLogger : ILogger + { + private readonly CommandOutputProvider _provider; + private readonly AnsiConsole _outConsole; + + public CommandOutputLogger(CommandOutputProvider commandOutputProvider, bool useConsoleColor) + { + _provider = commandOutputProvider; + _outConsole = AnsiConsole.GetOutput(useConsoleColor); + } + + public IDisposable BeginScope(TState state) + { + throw new NotImplementedException(); + } + + public bool IsEnabled(LogLevel logLevel) + { + if (logLevel < _provider.LogLevel) + { + return false; + } + + return true; + } + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + if (IsEnabled(logLevel)) + { + _outConsole.WriteLine(string.Format("{0}: {1}", Caption(logLevel), formatter(state, exception))); + } + } + + private string Caption(LogLevel logLevel) + { + switch (logLevel) + { + case LogLevel.Trace: return "\x1b[35mtrace\x1b[39m"; + case LogLevel.Debug: return "\x1b[35mdebug\x1b[39m"; + case LogLevel.Information: return "\x1b[32minfo\x1b[39m"; + case LogLevel.Warning: return "\x1b[33mwarn\x1b[39m"; + case LogLevel.Error: return "\x1b[31mfail\x1b[39m"; + case LogLevel.Critical: return "\x1b[31mcritical\x1b[39m"; + } + + throw new Exception("Unknown LogLevel"); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/CommandOutputProvider.cs b/src/Microsoft.Extensions.SecretManager.Tools/CommandOutputProvider.cs new file mode 100644 index 0000000000..0791830a69 --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/CommandOutputProvider.cs @@ -0,0 +1,23 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Runtime.InteropServices; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Extensions.SecretManager.Tools +{ + public class CommandOutputProvider : ILoggerProvider + { + public ILogger CreateLogger(string name) + { + var useConsoleColor = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + return new CommandOutputLogger(this, useConsoleColor); + } + + public void Dispose() + { + } + + public LogLevel LogLevel { get; set; } = LogLevel.Information; + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ClearCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ClearCommand.cs new file mode 100644 index 0000000000..41c6634364 --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ClearCommand.cs @@ -0,0 +1,28 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Extensions.CommandLineUtils; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Extensions.SecretManager.Tools.Internal +{ + internal class ClearCommand : ICommand + { + public static void Configure(CommandLineApplication command, CommandLineOptions options) + { + command.Description = "Deletes all the application secrets"; + command.HelpOption(); + + command.OnExecute(() => + { + options.Command = new ClearCommand(); + }); + } + + public void Execute(SecretsStore store, ILogger logger) + { + store.Clear(); + store.Save(); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineApplicationExtensions.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineApplicationExtensions.cs new file mode 100644 index 0000000000..386a5ddf30 --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineApplicationExtensions.cs @@ -0,0 +1,24 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.Extensions.CommandLineUtils +{ + public static class UserSecretsCommandLineExtensions + { + public static CommandOption HelpOption(this CommandLineApplication app) + { + return app.HelpOption("-?|-h|--help"); + } + + public static void OnExecute(this CommandLineApplication app, Action action) + { + app.OnExecute(() => + { + action(); + return 0; + }); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs new file mode 100644 index 0000000000..1b93392b4d --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs @@ -0,0 +1,70 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; +using System.Reflection; +using Microsoft.Extensions.CommandLineUtils; + +namespace Microsoft.Extensions.SecretManager.Tools.Internal +{ + public class CommandLineOptions + { + public bool IsVerbose { get; set; } + public bool IsHelp { get; set; } + public string Project { get; set; } + internal ICommand Command { get; set; } + + public static CommandLineOptions Parse(string[] args, TextWriter output) + { + var app = new CommandLineApplication() + { + Out = output, + Name = "dotnet user-secrets", + FullName = "User Secrets Manager", + Description = "Manages user secrets" + }; + + app.HelpOption(); + app.VersionOption("--version", GetInformationalVersion()); + + var optionVerbose = app.Option("-v|--verbose", "Verbose output", + CommandOptionType.NoValue, inherited: true); + + var optionProject = app.Option("-p|--project ", "Path to project, default is current directory", + CommandOptionType.SingleValue, inherited: true); + + var options = new CommandLineOptions(); + app.Command("set", c => SetCommand.Configure(c, options)); + app.Command("remove", c => RemoveCommand.Configure(c, options)); + app.Command("list", c => ListCommand.Configure(c, options)); + app.Command("clear", c => ClearCommand.Configure(c, options)); + + // Show help information if no subcommand/option was specified. + app.OnExecute(() => app.ShowHelp()); + + if (app.Execute(args) != 0) + { + // when command line parsing error in subcommand + return null; + } + + options.IsHelp = app.IsShowingInformation; + options.IsVerbose = optionVerbose.HasValue(); + options.Project = optionProject.Value(); + + return options; + } + + private static string GetInformationalVersion() + { + var assembly = typeof(Program).GetTypeInfo().Assembly; + var attribute = assembly.GetCustomAttribute(); + + var versionAttribute = attribute == null ? + assembly.GetName().Version.ToString() : + attribute.InformationalVersion; + + return versionAttribute; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/GracefulException.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/GracefulException.cs new file mode 100644 index 0000000000..7e54c8ba2f --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/GracefulException.cs @@ -0,0 +1,25 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.Extensions.SecretManager.Tools.Internal +{ + /// + /// An exception whose stack trace should be suppressed in console output + /// + public class GracefulException : Exception + { + public GracefulException() + { + } + + public GracefulException(string message) : base(message) + { + } + + public GracefulException(string message, Exception innerException) : base(message, innerException) + { + } + } +} diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ICommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ICommand.cs new file mode 100644 index 0000000000..3d6035d083 --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ICommand.cs @@ -0,0 +1,12 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Extensions.Logging; + +namespace Microsoft.Extensions.SecretManager.Tools.Internal +{ + internal interface ICommand + { + void Execute(SecretsStore store, ILogger logger); + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ListCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ListCommand.cs new file mode 100644 index 0000000000..efc012cd5a --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ListCommand.cs @@ -0,0 +1,37 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Extensions.CommandLineUtils; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Extensions.SecretManager.Tools.Internal +{ + internal class ListCommand : ICommand + { + public static void Configure(CommandLineApplication command, CommandLineOptions options) + { + command.Description = "Lists all the application secrets"; + command.HelpOption(); + + command.OnExecute(() => + { + options.Command = new ListCommand(); + }); + } + + public void Execute(SecretsStore store, ILogger logger) + { + if (store.Count == 0) + { + logger.LogInformation(Resources.Error_No_Secrets_Found); + } + else + { + foreach (var secret in store.AsEnumerable()) + { + logger.LogInformation(Resources.FormatMessage_Secret_Value_Format(secret.Key, secret.Value)); + } + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs new file mode 100644 index 0000000000..ff48c253cc --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs @@ -0,0 +1,49 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Extensions.CommandLineUtils; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Extensions.SecretManager.Tools.Internal +{ + internal class RemoveCommand : ICommand + { + private readonly string _keyName; + + public static void Configure(CommandLineApplication command, CommandLineOptions options) + { + command.Description = "Removes the specified user secret"; + command.HelpOption(); + + var keyArg = command.Argument("[name]", "Name of the secret"); + command.OnExecute(() => + { + if (keyArg.Value == null) + { + throw new GracefulException("Missing parameter value for 'name'.\nUse the '--help' flag to see info."); + } + + options.Command = new RemoveCommand(keyArg.Value); + }); + } + + + public RemoveCommand(string keyName) + { + _keyName = keyName; + } + + public void Execute(SecretsStore store, ILogger logger) + { + if (!store.ContainsKey(_keyName)) + { + logger.LogWarning(Resources.Error_Missing_Secret, _keyName); + } + else + { + store.Remove(_keyName); + store.Save(); + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs new file mode 100644 index 0000000000..7863fb725a --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs @@ -0,0 +1,78 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration.UserSecrets; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json.Linq; + +namespace Microsoft.Extensions.SecretManager.Tools.Internal +{ + internal class SecretsStore + { + private readonly string _secretsFilePath; + private IDictionary _secrets; + + public SecretsStore(string userSecretsId, ILogger logger) + { + if (userSecretsId == null) + { + throw new ArgumentNullException(nameof(userSecretsId)); + } + + _secretsFilePath = PathHelper.GetSecretsPathFromSecretsId(userSecretsId); + logger.LogDebug(Resources.Message_Secret_File_Path, _secretsFilePath); + + // workaround https://github.com/aspnet/Configuration/issues/478 + // TODO remove when tool upgrades to use 1.1.0 + Directory.CreateDirectory(Path.GetDirectoryName(_secretsFilePath)); + //end workaround + + _secrets = new ConfigurationBuilder() + .AddJsonFile(_secretsFilePath, optional: true) + .Build() + .AsEnumerable() + .Where(i => i.Value != null) + .ToDictionary(i => i.Key, i => i.Value, StringComparer.OrdinalIgnoreCase); + } + + public int Count => _secrets.Count; + + public bool ContainsKey(string key) => _secrets.ContainsKey(key); + + public IEnumerable> AsEnumerable() => _secrets; + + public void Clear() => _secrets.Clear(); + + public void Set(string key, string value) => _secrets[key] = value; + + public void Remove(string key) + { + if (_secrets.ContainsKey(key)) + { + _secrets.Remove(key); + } + } + + public void Save() + { + Directory.CreateDirectory(Path.GetDirectoryName(_secretsFilePath)); + + var contents = new JObject(); + if (_secrets != null) + { + foreach (var secret in _secrets.AsEnumerable()) + { + contents[secret.Key] = secret.Value; + } + } + + File.WriteAllText(_secretsFilePath, contents.ToString(), Encoding.UTF8); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs new file mode 100644 index 0000000000..15852cef64 --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs @@ -0,0 +1,51 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Extensions.CommandLineUtils; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Extensions.SecretManager.Tools.Internal +{ + internal class SetCommand : ICommand + { + private readonly string _keyName; + private readonly string _keyValue; + + public static void Configure(CommandLineApplication command, CommandLineOptions options) + { + command.Description = "Sets the user secret to the specified value"; + command.HelpOption(); + + var keyArg = command.Argument("[name]", "Name of the secret"); + var valueArg = command.Argument("[value]", "Value of the secret"); + + command.OnExecute(() => + { + if (keyArg.Value == null) + { + throw new GracefulException("Missing parameter value for 'name'.\nUse the '--help' flag to see info."); + } + + if (valueArg.Value == null) + { + throw new GracefulException("Missing parameter value for 'value'.\nUse the '--help' flag to see info."); + } + + options.Command = new SetCommand(keyArg.Value, valueArg.Value); + }); + } + + public SetCommand(string keyName, string keyValue) + { + _keyName = keyName; + _keyValue = keyValue; + } + + public void Execute(SecretsStore store, ILogger logger) + { + store.Set(_keyName, _keyValue); + store.Save(); + logger.LogInformation(Resources.Message_Saved_Secret, _keyName, _keyValue); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.xproj b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.xproj new file mode 100644 index 0000000000..aad10398ce --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.xproj @@ -0,0 +1,17 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 8730e848-ca0f-4e0a-9a2f-bc22ad0b2c4e + .\obj + .\bin\ + + + 2.0 + + + \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs new file mode 100644 index 0000000000..0da29bd567 --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs @@ -0,0 +1,183 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.FileProviders.Physical; +using Microsoft.Extensions.SecretManager.Tools.Internal; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Microsoft.Extensions.SecretManager.Tools +{ + public class Program + { + private ILogger _logger; + private CommandOutputProvider _loggerProvider; + private readonly TextWriter _consoleOutput; + private readonly string _workingDirectory; + + public Program() + : this(Console.Out, Directory.GetCurrentDirectory()) + { + } + + internal Program(TextWriter consoleOutput, string workingDirectory) + { + _consoleOutput = consoleOutput; + _workingDirectory = workingDirectory; + + var loggerFactory = new LoggerFactory(); + CommandOutputProvider = new CommandOutputProvider(); + loggerFactory.AddProvider(CommandOutputProvider); + Logger = loggerFactory.CreateLogger(); + } + + public ILogger Logger + { + get { return _logger; } + set + { + if (value == null) + { + throw new ArgumentNullException("value"); + } + + _logger = value; + } + } + + public CommandOutputProvider CommandOutputProvider + { + get { return _loggerProvider; } + set + { + if (value == null) + { + throw new ArgumentNullException("value"); + } + + _loggerProvider = value; + } + } + + public static int Main(string[] args) + { + HandleDebugFlag(ref args); + + int rc; + new Program().TryRun(args, out rc); + return rc; + } + + [Conditional("DEBUG")] + private static void HandleDebugFlag(ref string[] args) + { + for (var i = 0; i < args.Length; ++i) + { + if (args[i] == "--debug") + { + Console.WriteLine("Process ID " + Process.GetCurrentProcess().Id); + Console.WriteLine("Paused for debugger. Press ENTER to continue"); + Console.ReadLine(); + + args = args.Take(i).Concat(args.Skip(i + 1)).ToArray(); + + return; + } + } + } + + public bool TryRun(string[] args, out int returnCode) + { + try + { + returnCode = RunInternal(args); + return true; + } + catch (Exception exception) + { + if (exception is GracefulException) + { + Logger.LogError(exception.Message); + } + else + { + Logger.LogDebug(exception.ToString()); + Logger.LogCritical(Resources.Error_Command_Failed, exception.Message); + } + returnCode = 1; + return false; + } + } + + internal int RunInternal(params string[] args) + { + var options = CommandLineOptions.Parse(args, _consoleOutput); + + if (options == null) + { + return 1; + } + + if (options.IsHelp) + { + return 2; + } + + if (options.IsVerbose) + { + CommandOutputProvider.LogLevel = LogLevel.Debug; + } + + var userSecretsId = ResolveUserSecretsId(options); + var store = new SecretsStore(userSecretsId, Logger); + options.Command.Execute(store, Logger); + return 0; + } + + private string ResolveUserSecretsId(CommandLineOptions options) + { + var projectPath = options.Project ?? _workingDirectory; + + if (!projectPath.EndsWith("project.json", StringComparison.OrdinalIgnoreCase)) + { + projectPath = Path.Combine(projectPath, "project.json"); + } + + var fileInfo = new PhysicalFileInfo(new FileInfo(projectPath)); + + Logger.LogDebug(Resources.Message_Project_File_Path, fileInfo.PhysicalPath); + return ReadUserSecretsId(fileInfo); + } + + // TODO can use runtime API when upgrading to 1.1 + private string ReadUserSecretsId(IFileInfo fileInfo) + { + if (fileInfo == null || !fileInfo.Exists) + { + throw new GracefulException($"Could not find file '{fileInfo.PhysicalPath}'"); + } + + using (var stream = fileInfo.CreateReadStream()) + using (var streamReader = new StreamReader(stream)) + using (var jsonReader = new JsonTextReader(streamReader)) + { + var obj = JObject.Load(jsonReader); + + var userSecretsId = obj.Value("userSecretsId"); + + if (string.IsNullOrEmpty(userSecretsId)) + { + throw new GracefulException($"Could not find 'userSecretsId' in json file '{fileInfo.PhysicalPath}'"); + } + + return userSecretsId; + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Properties/AssemblyInfo.cs b/src/Microsoft.Extensions.SecretManager.Tools/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..8d8d88195c --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Properties/AssemblyInfo.cs @@ -0,0 +1,11 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Reflection; +using System.Resources; + +[assembly: AssemblyMetadata("Serviceable", "True")] +[assembly: NeutralResourcesLanguage("en-us")] +[assembly: AssemblyCompany("Microsoft Corporation.")] +[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] +[assembly: AssemblyProduct("Microsoft .NET Extensions")] diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Properties/InternalsVisibleTo.cs b/src/Microsoft.Extensions.SecretManager.Tools/Properties/InternalsVisibleTo.cs new file mode 100644 index 0000000000..8057e7a4d5 --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Properties/InternalsVisibleTo.cs @@ -0,0 +1,6 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Microsoft.Extensions.SecretManager.Tools.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs b/src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..c79e6e1fa2 --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs @@ -0,0 +1,142 @@ +// +namespace Microsoft.Extensions.SecretManager.Tools +{ + using System.Globalization; + using System.Reflection; + using System.Resources; + + internal static class Resources + { + private static readonly ResourceManager _resourceManager + = new ResourceManager("Microsoft.Extensions.SecretManager.Tools.Resources", typeof(Resources).GetTypeInfo().Assembly); + + /// + /// Command failed : {message} + /// + internal static string Error_Command_Failed + { + get { return GetString("Error_Command_Failed"); } + } + + /// + /// Command failed : {message} + /// + internal static string FormatError_Command_Failed(object message) + { + return string.Format(CultureInfo.CurrentCulture, GetString("Error_Command_Failed", "message"), message); + } + + /// + /// Cannot find '{key}' in the secret store. + /// + internal static string Error_Missing_Secret + { + get { return GetString("Error_Missing_Secret"); } + } + + /// + /// Cannot find '{key}' in the secret store. + /// + internal static string FormatError_Missing_Secret(object key) + { + return string.Format(CultureInfo.CurrentCulture, GetString("Error_Missing_Secret", "key"), key); + } + + /// + /// No secrets configured for this application. + /// + internal static string Error_No_Secrets_Found + { + get { return GetString("Error_No_Secrets_Found"); } + } + + /// + /// No secrets configured for this application. + /// + internal static string FormatError_No_Secrets_Found() + { + return GetString("Error_No_Secrets_Found"); + } + + /// + /// Project file path {project}. + /// + internal static string Message_Project_File_Path + { + get { return GetString("Message_Project_File_Path"); } + } + + /// + /// Project file path {project}. + /// + internal static string FormatMessage_Project_File_Path(object project) + { + return string.Format(CultureInfo.CurrentCulture, GetString("Message_Project_File_Path", "project"), project); + } + + /// + /// Successfully saved {key} = {value} to the secret store. + /// + internal static string Message_Saved_Secret + { + get { return GetString("Message_Saved_Secret"); } + } + + /// + /// Successfully saved {key} = {value} to the secret store. + /// + internal static string FormatMessage_Saved_Secret(object key, object value) + { + return string.Format(CultureInfo.CurrentCulture, GetString("Message_Saved_Secret", "key", "value"), key, value); + } + + /// + /// Secrets file path {secretsFilePath}. + /// + internal static string Message_Secret_File_Path + { + get { return GetString("Message_Secret_File_Path"); } + } + + /// + /// Secrets file path {secretsFilePath}. + /// + internal static string FormatMessage_Secret_File_Path(object secretsFilePath) + { + return string.Format(CultureInfo.CurrentCulture, GetString("Message_Secret_File_Path", "secretsFilePath"), secretsFilePath); + } + + /// + /// {key} = {value} + /// + internal static string Message_Secret_Value_Format + { + get { return GetString("Message_Secret_Value_Format"); } + } + + /// + /// {key} = {value} + /// + internal static string FormatMessage_Secret_Value_Format(object key, object value) + { + return string.Format(CultureInfo.CurrentCulture, GetString("Message_Secret_Value_Format", "key", "value"), key, value); + } + + private static string GetString(string name, params string[] formatterNames) + { + var value = _resourceManager.GetString(name); + + System.Diagnostics.Debug.Assert(value != null); + + if (formatterNames != null) + { + for (var i = 0; i < formatterNames.Length; i++) + { + value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); + } + } + + return value; + } + } +} diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Resources.resx b/src/Microsoft.Extensions.SecretManager.Tools/Resources.resx new file mode 100644 index 0000000000..13c953c727 --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Resources.resx @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Command failed : {message} + + + Cannot find '{key}' in the secret store. + + + No secrets configured for this application. + + + Project file path {project}. + + + Successfully saved {key} = {value} to the secret store. + + + Secrets file path {secretsFilePath}. + + + {key} = {value} + + \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json new file mode 100644 index 0000000000..bd470ffdc8 --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -0,0 +1,43 @@ +{ + "version": "1.0.0-*", + "buildOptions": { + "outputName": "dotnet-user-secrets", + "emitEntryPoint": true, + "warningsAsErrors": true, + "keyFile": "../../tools/Key.snk", + "nowarn": [ + "CS1591" + ], + "xmlDoc": true + }, + "description": "Command line tool to manage user secrets for Microsoft.Extensions.Configuration.", + "packOptions": { + "repository": { + "type": "git", + "url": "https://github.com/aspnet/DotNetTools" + }, + "tags": [ + "configuration", + "secrets", + "usersecrets" + ] + }, + "dependencies": { + "Microsoft.Extensions.Configuration.UserSecrets": "1.1.0-*", + "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", + "Microsoft.Extensions.Logging": "1.1.0-*", + "Newtonsoft.Json": "9.0.1", + "System.Runtime.InteropServices.RuntimeInformation": "4.0.0", + "System.Runtime.Serialization.Primitives": "4.1.1" + }, + "frameworks": { + "netcoreapp1.0": { + "dependencies": { + "Microsoft.NETCore.App": { + "version": "1.0.0", + "type": "platform" + } + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.xproj b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.xproj new file mode 100644 index 0000000000..2f0849b6ac --- /dev/null +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.xproj @@ -0,0 +1,21 @@ + + + + 14.0.25420 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 7b331122-83b1-4f08-a119-dc846959844c + Microsoft.Extensions.SecretManager.Tools.Tests + .\obj + .\bin\ + + + 2.0 + + + + + + \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs new file mode 100644 index 0000000000..4618b5a92b --- /dev/null +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs @@ -0,0 +1,284 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using Microsoft.Extensions.Configuration.UserSecrets; +using Microsoft.Extensions.Configuration.UserSecrets.Tests; +using Microsoft.Extensions.Logging; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.Extensions.SecretManager.Tools.Tests +{ + public class SecretManagerTests + { + private TestLogger _logger; + + public SecretManagerTests(ITestOutputHelper output) + { + _logger = new TestLogger(output); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void SetSecrets(bool fromCurrentDirectory) + { + var secrets = new KeyValuePair[] + { + new KeyValuePair("key1", Guid.NewGuid().ToString()), + new KeyValuePair("Facebook:AppId", Guid.NewGuid().ToString()), + new KeyValuePair(@"key-@\/.~123!#$%^&*())-+==", @"key-@\/.~123!#$%^&*())-+=="), + new KeyValuePair("key2", string.Empty) + }; + + var projectPath = UserSecretHelper.GetTempSecretProject(); + + var dir = fromCurrentDirectory + ? projectPath + : Path.GetTempPath(); + var secretManager = new Program(Console.Out, dir) { Logger = _logger }; + + foreach (var secret in secrets) + { + var parameters = fromCurrentDirectory ? + new string[] { "set", secret.Key, secret.Value } : + new string[] { "set", secret.Key, secret.Value, "-p", projectPath }; + secretManager.RunInternal(parameters); + } + + Assert.Equal(4, _logger.Messages.Count); + + foreach (var keyValue in secrets) + { + Assert.Contains( + string.Format("Successfully saved {0} = {1} to the secret store.", keyValue.Key, keyValue.Value), + _logger.Messages); + } + + _logger.Messages.Clear(); + var args = fromCurrentDirectory + ? new string[] { "list" } + : new string[] { "list", "-p", projectPath }; + secretManager.RunInternal(args); + Assert.Equal(4, _logger.Messages.Count); + foreach (var keyValue in secrets) + { + Assert.Contains( + string.Format("{0} = {1}", keyValue.Key, keyValue.Value), + _logger.Messages); + } + + // Remove secrets. + _logger.Messages.Clear(); + foreach (var secret in secrets) + { + var parameters = fromCurrentDirectory ? + new string[] { "remove", secret.Key } : + new string[] { "remove", secret.Key, "-p", projectPath }; + secretManager.RunInternal(parameters); + } + + // Verify secrets are removed. + _logger.Messages.Clear(); + args = fromCurrentDirectory + ? new string[] { "list" } + : new string[] { "list", "-p", projectPath }; + secretManager.RunInternal(args); + Assert.Equal(1, _logger.Messages.Count); + Assert.Contains(Resources.Error_No_Secrets_Found, _logger.Messages); + + UserSecretHelper.DeleteTempSecretProject(projectPath); + } + + [Fact] + public void SetSecret_Update_Existing_Secret() + { + var projectPath = UserSecretHelper.GetTempSecretProject(); + var secretManager = new Program() { Logger = _logger }; + + secretManager.RunInternal("set", "secret1", "value1", "-p", projectPath); + Assert.Equal(1, _logger.Messages.Count); + Assert.Contains("Successfully saved secret1 = value1 to the secret store.", _logger.Messages); + secretManager.RunInternal("set", "secret1", "value2", "-p", projectPath); + Assert.Equal(2, _logger.Messages.Count); + Assert.Contains("Successfully saved secret1 = value2 to the secret store.", _logger.Messages); + + _logger.Messages.Clear(); + + secretManager.RunInternal("list", "-p", projectPath); + Assert.Equal(1, _logger.Messages.Count); + Assert.Contains("secret1 = value2", _logger.Messages); + + UserSecretHelper.DeleteTempSecretProject(projectPath); + } + + [Fact] + public void SetSecret_With_Verbose_Flag() + { + var projectPath = UserSecretHelper.GetTempSecretProject(); + _logger.SetLevel(LogLevel.Debug); + var secretManager = new Program() { Logger = _logger }; + + secretManager.RunInternal("-v", "set", "secret1", "value1", "-p", projectPath); + Assert.Equal(3, _logger.Messages.Count); + Assert.Contains(string.Format("Project file path {0}.", Path.Combine(projectPath, "project.json")), _logger.Messages); + Assert.Contains(string.Format("Secrets file path {0}.", PathHelper.GetSecretsPath(projectPath)), _logger.Messages); + Assert.Contains("Successfully saved secret1 = value1 to the secret store.", _logger.Messages); + _logger.Messages.Clear(); + + secretManager.RunInternal("-v", "list", "-p", projectPath); + + Assert.Equal(3, _logger.Messages.Count); + Assert.Contains(string.Format("Project file path {0}.", Path.Combine(projectPath, "project.json")), _logger.Messages); + Assert.Contains(string.Format("Secrets file path {0}.", PathHelper.GetSecretsPath(projectPath)), _logger.Messages); + Assert.Contains("secret1 = value1", _logger.Messages); + + UserSecretHelper.DeleteTempSecretProject(projectPath); + } + + [Fact] + public void Remove_Non_Existing_Secret() + { + var projectPath = UserSecretHelper.GetTempSecretProject(); + var secretManager = new Program() { Logger = _logger }; + secretManager.RunInternal("remove", "secret1", "-p", projectPath); + Assert.Equal(1, _logger.Messages.Count); + Assert.Contains("Cannot find 'secret1' in the secret store.", _logger.Messages); + } + + [Fact] + public void Remove_Is_Case_Insensitive() + { + var projectPath = UserSecretHelper.GetTempSecretProject(); + var secretManager = new Program() { Logger = _logger }; + secretManager.RunInternal("set", "SeCreT1", "value", "-p", projectPath); + secretManager.RunInternal("list", "-p", projectPath); + Assert.Contains("SeCreT1 = value", _logger.Messages); + secretManager.RunInternal("remove", "secret1", "-p", projectPath); + + Assert.Equal(2, _logger.Messages.Count); + _logger.Messages.Clear(); + secretManager.RunInternal("list", "-p", projectPath); + + Assert.Contains(Resources.Error_No_Secrets_Found, _logger.Messages); + + UserSecretHelper.DeleteTempSecretProject(projectPath); + } + + [Fact] + public void List_Flattens_Nested_Objects() + { + var projectPath = UserSecretHelper.GetTempSecretProject(); + var secretsFile = PathHelper.GetSecretsPath(projectPath); + Directory.CreateDirectory(Path.GetDirectoryName(secretsFile)); + File.WriteAllText(secretsFile, @"{ ""AzureAd"": { ""ClientSecret"": ""abcd郩˙î""} }", Encoding.UTF8); + var secretManager = new Program() { Logger = _logger }; + secretManager.RunInternal("list", "-p", projectPath); + Assert.Equal(1, _logger.Messages.Count); + Assert.Contains("AzureAd:ClientSecret = abcd郩˙î", _logger.Messages); + + UserSecretHelper.DeleteTempSecretProject(projectPath); + } + + [Fact] + public void Set_Flattens_Nested_Objects() + { + var projectPath = UserSecretHelper.GetTempSecretProject(); + var secretsFile = PathHelper.GetSecretsPath(projectPath); + Directory.CreateDirectory(Path.GetDirectoryName(secretsFile)); + File.WriteAllText(secretsFile, @"{ ""AzureAd"": { ""ClientSecret"": ""abcd郩˙î""} }", Encoding.UTF8); + var secretManager = new Program() { Logger = _logger }; + secretManager.RunInternal("set", "AzureAd:ClientSecret", "¡™£¢∞", "-p", projectPath); + Assert.Equal(1, _logger.Messages.Count); + secretManager.RunInternal("list", "-p", projectPath); + + Assert.Equal(2, _logger.Messages.Count); + Assert.Contains("AzureAd:ClientSecret = ¡™£¢∞", _logger.Messages); + var fileContents = File.ReadAllText(secretsFile, Encoding.UTF8); + Assert.Equal(@"{ + ""AzureAd:ClientSecret"": ""¡™£¢∞"" +}", + fileContents, ignoreLineEndingDifferences: true, ignoreWhiteSpaceDifferences: true); + + UserSecretHelper.DeleteTempSecretProject(projectPath); + } + + [Fact] + public void List_Empty_Secrets_File() + { + var projectPath = UserSecretHelper.GetTempSecretProject(); + var secretManager = new Program() { Logger = _logger }; + secretManager.RunInternal("list", "-p", projectPath); + Assert.Equal(1, _logger.Messages.Count); + Assert.Contains(Resources.Error_No_Secrets_Found, _logger.Messages); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void Clear_Secrets(bool fromCurrentDirectory) + { + var projectPath = UserSecretHelper.GetTempSecretProject(); + + var dir = fromCurrentDirectory + ? projectPath + : Path.GetTempPath(); + + var secretManager = new Program(Console.Out, dir) { Logger = _logger }; + + var secrets = new KeyValuePair[] + { + new KeyValuePair("key1", Guid.NewGuid().ToString()), + new KeyValuePair("Facebook:AppId", Guid.NewGuid().ToString()), + new KeyValuePair(@"key-@\/.~123!#$%^&*())-+==", @"key-@\/.~123!#$%^&*())-+=="), + new KeyValuePair("key2", string.Empty) + }; + + foreach (var secret in secrets) + { + var parameters = fromCurrentDirectory ? + new string[] { "set", secret.Key, secret.Value } : + new string[] { "set", secret.Key, secret.Value, "-p", projectPath }; + secretManager.RunInternal(parameters); + } + + Assert.Equal(4, _logger.Messages.Count); + + foreach (var keyValue in secrets) + { + Assert.Contains( + string.Format("Successfully saved {0} = {1} to the secret store.", keyValue.Key, keyValue.Value), + _logger.Messages); + } + + // Verify secrets are persisted. + _logger.Messages.Clear(); + var args = fromCurrentDirectory ? + new string[] { "list" } : + new string[] { "list", "-p", projectPath }; + secretManager.RunInternal(args); + Assert.Equal(4, _logger.Messages.Count); + foreach (var keyValue in secrets) + { + Assert.Contains( + string.Format("{0} = {1}", keyValue.Key, keyValue.Value), + _logger.Messages); + } + + // Clear secrets. + _logger.Messages.Clear(); + args = fromCurrentDirectory ? new string[] { "clear" } : new string[] { "clear", "-p", projectPath }; + secretManager.RunInternal(args); + Assert.Equal(0, _logger.Messages.Count); + + args = fromCurrentDirectory ? new string[] { "list" } : new string[] { "list", "-p", projectPath }; + secretManager.RunInternal(args); + Assert.Equal(1, _logger.Messages.Count); + Assert.Contains(Resources.Error_No_Secrets_Found, _logger.Messages); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/TestLogger.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/TestLogger.cs new file mode 100644 index 0000000000..1176d33218 --- /dev/null +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/TestLogger.cs @@ -0,0 +1,50 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using Microsoft.Extensions.Logging; +using Xunit.Abstractions; + +namespace Microsoft.Extensions.SecretManager.Tools.Tests +{ + public class TestLogger : ILogger + { + private CommandOutputProvider _commandOutputProvider; + private readonly ILogger _wrapped; + private readonly ITestOutputHelper _output; + + public TestLogger(ITestOutputHelper output = null) + { + _commandOutputProvider = new CommandOutputProvider(); + _wrapped = _commandOutputProvider.CreateLogger(""); + _output = output; + } + + public void SetLevel(LogLevel level) + { + _commandOutputProvider.LogLevel = LogLevel.Debug; + } + + public List Messages { get; set; } = new List(); + + public IDisposable BeginScope(TState state) + { + throw new NotImplementedException(); + } + + public bool IsEnabled(LogLevel logLevel) + { + return _wrapped.IsEnabled(logLevel); + } + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + if (IsEnabled(logLevel)) + { + Messages.Add(formatter(state, exception)); + _output?.WriteLine(formatter(state, exception)); + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretHelper.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretHelper.cs new file mode 100644 index 0000000000..87dbddc3e4 --- /dev/null +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretHelper.cs @@ -0,0 +1,47 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using Newtonsoft.Json; + +namespace Microsoft.Extensions.Configuration.UserSecrets.Tests +{ + internal class UserSecretHelper + { + internal static string GetTempSecretProject() + { + string userSecretsId; + return GetTempSecretProject(out userSecretsId); + } + + internal static string GetTempSecretProject(out string userSecretsId) + { + var projectPath = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "usersecretstest", Guid.NewGuid().ToString())); + userSecretsId = Guid.NewGuid().ToString(); + File.WriteAllText( + Path.Combine(projectPath.FullName, "project.json"), + JsonConvert.SerializeObject(new { userSecretsId })); + return projectPath.FullName; + } + + internal static void SetTempSecretInProject(string projectPath, string userSecretsId) + { + File.WriteAllText( + Path.Combine(projectPath, "project.json"), + JsonConvert.SerializeObject(new { userSecretsId })); + } + + internal static void DeleteTempSecretProject(string projectPath) + { + try + { + Directory.Delete(projectPath, true); + } + catch (Exception) + { + // Ignore failures. + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json new file mode 100644 index 0000000000..18868d2684 --- /dev/null +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json @@ -0,0 +1,22 @@ +{ + "buildOptions": { + "warningsAsErrors": true, + "keyFile": "../../tools/Key.snk" + }, + "dependencies": { + "dotnet-test-xunit": "2.2.0-*", + "Microsoft.Extensions.SecretManager.Tools": "1.0.0-*", + "xunit": "2.2.0-*" + }, + "testRunner": "xunit", + "frameworks": { + "netcoreapp1.0": { + "dependencies": { + "Microsoft.NETCore.App": { + "version": "1.0.0", + "type": "platform" + } + } + } + } +} \ No newline at end of file From fb54566ff5ba0d21c86adb3224802bfc6dd9bbeb Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 19 Sep 2016 11:41:35 -0700 Subject: [PATCH 0254/1029] Add dotnet-sql-cache --- DotNetTools.sln | 7 + NuGetPackageVerifier.json | 1 + README.md | 1 + ...t.Extensions.Caching.SqlConfig.Tools.xproj | 17 ++ .../Program.cs | 157 ++++++++++++++++++ .../Properties/AssemblyInfo.cs | 11 ++ .../SqlQueries.cs | 67 ++++++++ .../project.json | 41 +++++ 8 files changed, 302 insertions(+) create mode 100644 src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.xproj create mode 100644 src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs create mode 100644 src/Microsoft.Extensions.Caching.SqlConfig.Tools/Properties/AssemblyInfo.cs create mode 100644 src/Microsoft.Extensions.Caching.SqlConfig.Tools/SqlQueries.cs create mode 100644 src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json diff --git a/DotNetTools.sln b/DotNetTools.sln index e600c724c1..3dbe6b4f4e 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -33,6 +33,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.Secret EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.SecretManager.Tools.Tests", "test\Microsoft.Extensions.SecretManager.Tools.Tests\Microsoft.Extensions.SecretManager.Tools.Tests.xproj", "{7B331122-83B1-4F08-A119-DC846959844C}" EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.Caching.SqlConfig.Tools", "src\Microsoft.Extensions.Caching.SqlConfig.Tools\Microsoft.Extensions.Caching.SqlConfig.Tools.xproj", "{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -75,6 +77,10 @@ Global {7B331122-83B1-4F08-A119-DC846959844C}.Debug|Any CPU.Build.0 = Debug|Any CPU {7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.ActiveCfg = Release|Any CPU {7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.Build.0 = Release|Any CPU + {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -90,5 +96,6 @@ Global {2F48041A-F7D1-478F-9C38-D41F0F05E8CA} = {2876B12E-5841-4792-85A8-2929AEE11885} {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E} = {66517987-2A5A-4330-B130-207039378FD4} {7B331122-83B1-4F08-A119-DC846959844C} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} + {53F3B53D-303A-4DAA-9C38-4F55195FA5B9} = {66517987-2A5A-4330-B130-207039378FD4} EndGlobalSection EndGlobal diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index 932af6fb14..fe8b1557a4 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -6,6 +6,7 @@ "packages": { "Microsoft.DotNet.Watcher.Tools": { }, "Microsoft.DotNet.Watcher.Core": { }, + "Microsoft.Extensions.Caching.SqlConfig.Tools": { }, "Microsoft.Extensions.SecretManager.Tools": { } } }, diff --git a/README.md b/README.md index 64eb8a2cee..e937d4d0d5 100644 --- a/README.md +++ b/README.md @@ -8,5 +8,6 @@ The project contains command-line tools for the .NET Core SDK. - [dotnet-watch](src/Microsoft.DotNet.Watcher.Tools/) - [dotnet-user-secrets](src/Microsoft.Extensions.SecretManager.Tools/) + - [dotnet-sql-cache](src/Microsoft.Extensions.Caching.SqlConfig.Tools/) This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo. diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.xproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.xproj new file mode 100644 index 0000000000..1bba570109 --- /dev/null +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.xproj @@ -0,0 +1,17 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 53f3b53d-303a-4daa-9c38-4f55195fa5b9 + .\obj + .\bin\ + + + 2.0 + + + \ No newline at end of file diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs new file mode 100644 index 0000000000..eb46dcb0a8 --- /dev/null +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs @@ -0,0 +1,157 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Data; +using System.Data.SqlClient; +using Microsoft.Extensions.CommandLineUtils; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Extensions.Caching.SqlConfig.Tools +{ + public class Program + { + private string _connectionString = null; + private string _schemaName = null; + private string _tableName = null; + + private readonly ILogger _logger; + + public Program() + { + var loggerFactory = new LoggerFactory(); + loggerFactory.AddConsole(); + _logger = loggerFactory.CreateLogger(); + } + + public static int Main(string[] args) + { + return new Program().Run(args); + } + + public int Run(string[] args) + { + try + { + var description = "Creates table and indexes in Microsoft SQL Server database " + + "to be used for distributed caching"; + + var app = new CommandLineApplication(); + app.Name = "dotnet-sql-cache"; + app.Description = description; + + app.HelpOption("-?|-h|--help"); + + app.Command("create", command => + { + command.Description = description; + var connectionStringArg = command.Argument( + "[connectionString]", + "The connection string to connect to the database."); + var schemaNameArg = command.Argument("[schemaName]", "Name of the table schema."); + var tableNameArg = command.Argument("[tableName]", "Name of the table to be created."); + command.HelpOption("-?|-h|--help"); + + command.OnExecute(() => + { + if (string.IsNullOrEmpty(connectionStringArg.Value) + || string.IsNullOrEmpty(schemaNameArg.Value) + || string.IsNullOrEmpty(tableNameArg.Value)) + { + _logger.LogWarning("Invalid input"); + app.ShowHelp(); + return 2; + } + + _connectionString = connectionStringArg.Value; + _schemaName = schemaNameArg.Value; + _tableName = tableNameArg.Value; + + return CreateTableAndIndexes(); + }); + }); + + // Show help information if no subcommand/option was specified. + app.OnExecute(() => + { + app.ShowHelp(); + return 2; + }); + + return app.Execute(args); + } + catch (Exception exception) + { + _logger.LogCritical("An error occurred. {ErrorMessage}", exception.Message); + return 1; + } + } + + private int CreateTableAndIndexes() + { + ValidateConnectionString(); + + using (var connection = new SqlConnection(_connectionString)) + { + connection.Open(); + + var sqlQueries = new SqlQueries(_schemaName, _tableName); + var command = new SqlCommand(sqlQueries.TableInfo, connection); + + using (var reader = command.ExecuteReader(CommandBehavior.SingleRow)) + { + if (reader.Read()) + { + _logger.LogWarning( + $"Table with schema '{_schemaName}' and name '{_tableName}' already exists. " + + "Provide a different table name and try again."); + return 1; + } + } + + using (var transaction = connection.BeginTransaction()) + { + try + { + command = new SqlCommand(sqlQueries.CreateTable, connection, transaction); + command.ExecuteNonQuery(); + + command = new SqlCommand( + sqlQueries.CreateNonClusteredIndexOnExpirationTime, + connection, + transaction); + command.ExecuteNonQuery(); + + transaction.Commit(); + + _logger.LogInformation("Table and index were created successfully."); + } + catch (Exception ex) + { + _logger.LogError( + "An error occurred while trying to create the table and index. {ErrorMessage}", + ex.Message); + transaction.Rollback(); + + return 1; + } + } + } + + return 0; + } + + private void ValidateConnectionString() + { + try + { + new SqlConnectionStringBuilder(_connectionString); + } + catch (Exception ex) + { + throw new ArgumentException( + $"Invalid Sql server connection string '{_connectionString}'. {ex.Message}", ex); + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Properties/AssemblyInfo.cs b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..8d8d88195c --- /dev/null +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Properties/AssemblyInfo.cs @@ -0,0 +1,11 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Reflection; +using System.Resources; + +[assembly: AssemblyMetadata("Serviceable", "True")] +[assembly: NeutralResourcesLanguage("en-us")] +[assembly: AssemblyCompany("Microsoft Corporation.")] +[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] +[assembly: AssemblyProduct("Microsoft .NET Extensions")] diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/SqlQueries.cs b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/SqlQueries.cs new file mode 100644 index 0000000000..110ee13caf --- /dev/null +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/SqlQueries.cs @@ -0,0 +1,67 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.Extensions.Caching.SqlConfig.Tools +{ + internal class SqlQueries + { + private const string CreateTableFormat = "CREATE TABLE {0}(" + + // Maximum size of primary key column is 900 bytes (898 bytes from key + 2 additional bytes used by the + // Sql Server). In the case where the key is greater than 898 bytes, then it gets truncated. + // - Add collation to the key column to make it case-sensitive + "Id nvarchar(449) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, " + + "Value varbinary(MAX) NOT NULL, " + + "ExpiresAtTime datetimeoffset NOT NULL, " + + "SlidingExpirationInSeconds bigint NULL," + + "AbsoluteExpiration datetimeoffset NULL, " + + "CONSTRAINT pk_Id PRIMARY KEY (Id))"; + + private const string CreateNonClusteredIndexOnExpirationTimeFormat + = "CREATE NONCLUSTERED INDEX Index_ExpiresAtTime ON {0}(ExpiresAtTime)"; + + private const string TableInfoFormat = + "SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE " + + "FROM INFORMATION_SCHEMA.TABLES " + + "WHERE TABLE_SCHEMA = '{0}' " + + "AND TABLE_NAME = '{1}'"; + + public SqlQueries(string schemaName, string tableName) + { + if (string.IsNullOrEmpty(schemaName)) + { + throw new ArgumentException("Schema name cannot be empty or null"); + } + if (string.IsNullOrEmpty(tableName)) + { + throw new ArgumentException("Table name cannot be empty or null"); + } + + var tableNameWithSchema = string.Format( + "{0}.{1}", DelimitIdentifier(schemaName), DelimitIdentifier(tableName)); + CreateTable = string.Format(CreateTableFormat, tableNameWithSchema); + CreateNonClusteredIndexOnExpirationTime = string.Format( + CreateNonClusteredIndexOnExpirationTimeFormat, + tableNameWithSchema); + TableInfo = string.Format(TableInfoFormat, EscapeLiteral(schemaName), EscapeLiteral(tableName)); + } + + public string CreateTable { get; } + + public string CreateNonClusteredIndexOnExpirationTime { get; } + + public string TableInfo { get; } + + // From EF's SqlServerQuerySqlGenerator + private string DelimitIdentifier(string identifier) + { + return "[" + identifier.Replace("]", "]]") + "]"; + } + + private string EscapeLiteral(string literal) + { + return literal.Replace("'", "''"); + } + } +} diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json new file mode 100644 index 0000000000..b8ffffdc12 --- /dev/null +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json @@ -0,0 +1,41 @@ +{ + "version": "1.0.0-*", + "dependencies": { + "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", + "Microsoft.Extensions.Logging": "1.1.0-*", + "Microsoft.Extensions.Logging.Console": "1.1.0-*", + "System.Data.SqlClient": "4.1.0-*" + }, + "description": "Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching.", + "frameworks": { + "netcoreapp1.0": { + "dependencies": { + "Microsoft.NETCore.App": { + "version": "1.0.0-*", + "type": "platform" + } + } + } + }, + "buildOptions": { + "outputName": "dotnet-sql-cache", + "emitEntryPoint": true, + "warningsAsErrors": true, + "keyFile": "../../tools/Key.snk", + "nowarn": [ + "CS1591" + ], + "xmlDoc": true + }, + "packOptions": { + "repository": { + "type": "git", + "url": "https://github.com/aspnet/DotNetTools" + }, + "tags": [ + "cache", + "distributedcache", + "sqlserver" + ] + } +} \ No newline at end of file From 436ad5fd65e3098e4282d707bfe8c9e602b634fb Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 20 Sep 2016 10:58:28 -0700 Subject: [PATCH 0255/1029] Update Travis badge [ci skip] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e937d4d0d5..f5c04352e2 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ DotNetTools =========== -[![Travis build status](https://img.shields.io/travis/aspnet/dotnet-watch.svg?label=travis-ci&branch=dev&style=flat-square)](https://travis-ci.org/aspnet/dotnet-watch/branches) +[![Travis build status](https://img.shields.io/travis/aspnet/DotNetTools.svg?label=travis-ci&branch=dev&style=flat-square)](https://travis-ci.org/aspnet/DotNetTools/branches) [![AppVeyor build status](https://img.shields.io/appveyor/ci/aspnetci/dnx-watch/dev.svg?label=appveyor&style=flat-square)](https://ci.appveyor.com/project/aspnetci/dnx-watch/branch/dev) The project contains command-line tools for the .NET Core SDK. From 7bafb00f05d579dd4c140f34742e11f8433db559 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 20 Sep 2016 10:16:52 -0700 Subject: [PATCH 0256/1029] Improve error message when project file does not exist. Resolve #171 --- .../Program.cs | 5 +++++ .../Properties/Resources.Designer.cs | 16 ++++++++++++++++ .../Resources.resx | 3 +++ .../SecretManagerTests.cs | 12 ++++++++++++ 4 files changed, 36 insertions(+) diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs index 0da29bd567..b8d3e9f0b9 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs @@ -151,6 +151,11 @@ namespace Microsoft.Extensions.SecretManager.Tools var fileInfo = new PhysicalFileInfo(new FileInfo(projectPath)); + if (!fileInfo.Exists) + { + throw new GracefulException(Resources.FormatError_ProjectPath_NotFound(projectPath)); + } + Logger.LogDebug(Resources.Message_Project_File_Path, fileInfo.PhysicalPath); return ReadUserSecretsId(fileInfo); } diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs b/src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs index c79e6e1fa2..d9ae9fe2c6 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs @@ -58,6 +58,22 @@ namespace Microsoft.Extensions.SecretManager.Tools return GetString("Error_No_Secrets_Found"); } + /// + /// The project file '{path}' does not exist. + /// + internal static string Error_ProjectPath_NotFound + { + get { return GetString("Error_ProjectPath_NotFound"); } + } + + /// + /// The project file '{path}' does not exist. + /// + internal static string FormatError_ProjectPath_NotFound(object path) + { + return string.Format(CultureInfo.CurrentCulture, GetString("Error_ProjectPath_NotFound", "path"), path); + } + /// /// Project file path {project}. /// diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Resources.resx b/src/Microsoft.Extensions.SecretManager.Tools/Resources.resx index 13c953c727..76631dea0d 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Resources.resx +++ b/src/Microsoft.Extensions.SecretManager.Tools/Resources.resx @@ -126,6 +126,9 @@ No secrets configured for this application. + + The project file '{path}' does not exist. + Project file path {project}. diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs index 4618b5a92b..038bb0d464 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs @@ -10,6 +10,7 @@ using Microsoft.Extensions.Configuration.UserSecrets.Tests; using Microsoft.Extensions.Logging; using Xunit; using Xunit.Abstractions; +using Microsoft.Extensions.SecretManager.Tools.Internal; namespace Microsoft.Extensions.SecretManager.Tools.Tests { @@ -22,6 +23,17 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests _logger = new TestLogger(output); } + [Fact] + public void Error_Project_DoesNotExist() + { + var projectPath = Path.Combine(Path.GetTempPath(), "dne", Guid.NewGuid().ToString(), "project.json"); + var secretManager = new Program(Console.Out, Directory.GetCurrentDirectory()) { Logger = _logger }; + + var ex = Assert.Throws(() => secretManager.RunInternal("list", "--project", projectPath)); + + Assert.Equal(ex.Message, Resources.FormatError_ProjectPath_NotFound(projectPath)); + } + [Theory] [InlineData(true)] [InlineData(false)] From 11bbd6df8e363d87b7f5498b8491e085d90be5d1 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 20 Sep 2016 10:42:35 -0700 Subject: [PATCH 0257/1029] Support relative paths to projects. Resolve #170 --- .../Program.cs | 5 ++ .../SecretManagerTests.cs | 67 ++++++++++++------- .../TestLogger.cs | 8 +-- 3 files changed, 51 insertions(+), 29 deletions(-) diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs index b8d3e9f0b9..82422bd189 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs @@ -144,6 +144,11 @@ namespace Microsoft.Extensions.SecretManager.Tools { var projectPath = options.Project ?? _workingDirectory; + if (!Path.IsPathRooted(projectPath)) + { + projectPath = Path.Combine(_workingDirectory, projectPath); + } + if (!projectPath.EndsWith("project.json", StringComparison.OrdinalIgnoreCase)) { projectPath = Path.Combine(projectPath, "project.json"); diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs index 038bb0d464..4675988131 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs @@ -14,24 +14,54 @@ using Microsoft.Extensions.SecretManager.Tools.Internal; namespace Microsoft.Extensions.SecretManager.Tools.Tests { - public class SecretManagerTests + public class SecretManagerTests : IDisposable { private TestLogger _logger; + private Stack _disposables = new Stack(); public SecretManagerTests(ITestOutputHelper output) { _logger = new TestLogger(output); } + private string GetTempSecretProject() + { + var projectPath = UserSecretHelper.GetTempSecretProject(); + _disposables.Push(() => UserSecretHelper.DeleteTempSecretProject(projectPath)); + return projectPath; + } + + public void Dispose() + { + while (_disposables.Count > 0) + { + _disposables.Pop().Invoke(); + } + } + [Fact] public void Error_Project_DoesNotExist() { - var projectPath = Path.Combine(Path.GetTempPath(), "dne", Guid.NewGuid().ToString(), "project.json"); + var projectPath = Path.Combine(GetTempSecretProject(), "does_not_exist", "project.json"); var secretManager = new Program(Console.Out, Directory.GetCurrentDirectory()) { Logger = _logger }; var ex = Assert.Throws(() => secretManager.RunInternal("list", "--project", projectPath)); - Assert.Equal(ex.Message, Resources.FormatError_ProjectPath_NotFound(projectPath)); + Assert.Equal(Resources.FormatError_ProjectPath_NotFound(projectPath), ex.Message); + } + + [Fact] + public void SupportsRelativePaths() + { + var projectPath = GetTempSecretProject(); + var cwd = Path.Combine(projectPath, "nested1"); + Directory.CreateDirectory(cwd); + var secretManager = new Program(Console.Out, cwd) { Logger = _logger, CommandOutputProvider = _logger.CommandOutputProvider }; + secretManager.CommandOutputProvider.LogLevel = LogLevel.Debug; + + secretManager.RunInternal("list", "-p", "../", "--verbose"); + + Assert.Contains(Resources.FormatMessage_Project_File_Path(Path.Combine(projectPath, "project.json")), _logger.Messages); } [Theory] @@ -47,8 +77,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests new KeyValuePair("key2", string.Empty) }; - var projectPath = UserSecretHelper.GetTempSecretProject(); - + var projectPath = GetTempSecretProject(); var dir = fromCurrentDirectory ? projectPath : Path.GetTempPath(); @@ -102,14 +131,12 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests secretManager.RunInternal(args); Assert.Equal(1, _logger.Messages.Count); Assert.Contains(Resources.Error_No_Secrets_Found, _logger.Messages); - - UserSecretHelper.DeleteTempSecretProject(projectPath); } [Fact] public void SetSecret_Update_Existing_Secret() { - var projectPath = UserSecretHelper.GetTempSecretProject(); + var projectPath = GetTempSecretProject(); var secretManager = new Program() { Logger = _logger }; secretManager.RunInternal("set", "secret1", "value1", "-p", projectPath); @@ -124,14 +151,12 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests secretManager.RunInternal("list", "-p", projectPath); Assert.Equal(1, _logger.Messages.Count); Assert.Contains("secret1 = value2", _logger.Messages); - - UserSecretHelper.DeleteTempSecretProject(projectPath); } [Fact] public void SetSecret_With_Verbose_Flag() { - var projectPath = UserSecretHelper.GetTempSecretProject(); + var projectPath = GetTempSecretProject(); _logger.SetLevel(LogLevel.Debug); var secretManager = new Program() { Logger = _logger }; @@ -148,14 +173,12 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests Assert.Contains(string.Format("Project file path {0}.", Path.Combine(projectPath, "project.json")), _logger.Messages); Assert.Contains(string.Format("Secrets file path {0}.", PathHelper.GetSecretsPath(projectPath)), _logger.Messages); Assert.Contains("secret1 = value1", _logger.Messages); - - UserSecretHelper.DeleteTempSecretProject(projectPath); } [Fact] public void Remove_Non_Existing_Secret() { - var projectPath = UserSecretHelper.GetTempSecretProject(); + var projectPath = GetTempSecretProject(); var secretManager = new Program() { Logger = _logger }; secretManager.RunInternal("remove", "secret1", "-p", projectPath); Assert.Equal(1, _logger.Messages.Count); @@ -165,7 +188,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests [Fact] public void Remove_Is_Case_Insensitive() { - var projectPath = UserSecretHelper.GetTempSecretProject(); + var projectPath = GetTempSecretProject(); var secretManager = new Program() { Logger = _logger }; secretManager.RunInternal("set", "SeCreT1", "value", "-p", projectPath); secretManager.RunInternal("list", "-p", projectPath); @@ -177,14 +200,12 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests secretManager.RunInternal("list", "-p", projectPath); Assert.Contains(Resources.Error_No_Secrets_Found, _logger.Messages); - - UserSecretHelper.DeleteTempSecretProject(projectPath); } [Fact] public void List_Flattens_Nested_Objects() { - var projectPath = UserSecretHelper.GetTempSecretProject(); + var projectPath = GetTempSecretProject(); var secretsFile = PathHelper.GetSecretsPath(projectPath); Directory.CreateDirectory(Path.GetDirectoryName(secretsFile)); File.WriteAllText(secretsFile, @"{ ""AzureAd"": { ""ClientSecret"": ""abcd郩˙î""} }", Encoding.UTF8); @@ -192,14 +213,12 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests secretManager.RunInternal("list", "-p", projectPath); Assert.Equal(1, _logger.Messages.Count); Assert.Contains("AzureAd:ClientSecret = abcd郩˙î", _logger.Messages); - - UserSecretHelper.DeleteTempSecretProject(projectPath); } [Fact] public void Set_Flattens_Nested_Objects() { - var projectPath = UserSecretHelper.GetTempSecretProject(); + var projectPath = GetTempSecretProject(); var secretsFile = PathHelper.GetSecretsPath(projectPath); Directory.CreateDirectory(Path.GetDirectoryName(secretsFile)); File.WriteAllText(secretsFile, @"{ ""AzureAd"": { ""ClientSecret"": ""abcd郩˙î""} }", Encoding.UTF8); @@ -215,14 +234,12 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests ""AzureAd:ClientSecret"": ""¡™£¢∞"" }", fileContents, ignoreLineEndingDifferences: true, ignoreWhiteSpaceDifferences: true); - - UserSecretHelper.DeleteTempSecretProject(projectPath); } [Fact] public void List_Empty_Secrets_File() { - var projectPath = UserSecretHelper.GetTempSecretProject(); + var projectPath = GetTempSecretProject(); var secretManager = new Program() { Logger = _logger }; secretManager.RunInternal("list", "-p", projectPath); Assert.Equal(1, _logger.Messages.Count); @@ -234,7 +251,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests [InlineData(false)] public void Clear_Secrets(bool fromCurrentDirectory) { - var projectPath = UserSecretHelper.GetTempSecretProject(); + var projectPath = GetTempSecretProject(); var dir = fromCurrentDirectory ? projectPath diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/TestLogger.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/TestLogger.cs index 1176d33218..94df0ce5b2 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/TestLogger.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/TestLogger.cs @@ -10,20 +10,20 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests { public class TestLogger : ILogger { - private CommandOutputProvider _commandOutputProvider; private readonly ILogger _wrapped; private readonly ITestOutputHelper _output; public TestLogger(ITestOutputHelper output = null) { - _commandOutputProvider = new CommandOutputProvider(); - _wrapped = _commandOutputProvider.CreateLogger(""); + CommandOutputProvider = new CommandOutputProvider(); + _wrapped = CommandOutputProvider.CreateLogger(""); _output = output; } + public CommandOutputProvider CommandOutputProvider { get;} public void SetLevel(LogLevel level) { - _commandOutputProvider.LogLevel = LogLevel.Debug; + CommandOutputProvider.LogLevel = level; } public List Messages { get; set; } = new List(); From f90594a6470ab2d212039098f815745259b4045e Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 6 Sep 2016 15:26:21 -0700 Subject: [PATCH 0258/1029] Add support for '--' argument separator Also refactors command line parsing into a separate class. --- .gitignore | 3 +- DotNetTools.sln | 9 +- .../DotNetWatcher.cs | 23 +---- .../project.json | 1 + .../CommandLineOptions.cs | 54 ++++++++++++ src/Microsoft.DotNet.Watcher.Tools/Program.cs | 83 ++++++++++--------- .../Properties/AssemblyInfo.cs | 3 - .../Properties/InternalsVisibleTo.cs | 6 ++ src/Microsoft.DotNet.Watcher.Tools/README.md | 4 +- .../CommandLineOptionsTests.cs | 46 ++++++++++ ...Microsoft.DotNet.Watcher.Tools.Tests.xproj | 19 +++++ .../project.json | 22 +++++ 12 files changed, 211 insertions(+), 62 deletions(-) create mode 100644 src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs create mode 100644 src/Microsoft.DotNet.Watcher.Tools/Properties/InternalsVisibleTo.cs create mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs create mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.xproj create mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/project.json diff --git a/.gitignore b/.gitignore index 79f4ca4258..33889157be 100644 --- a/.gitignore +++ b/.gitignore @@ -29,4 +29,5 @@ project.lock.json .build/ /.vs/ testWorkDir/ - +*.nuget.props +*.nuget.targets \ No newline at end of file diff --git a/DotNetTools.sln b/DotNetTools.sln index 3dbe6b4f4e..8852cbde1a 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 VisualStudioVersion = 14.0.25420.1 @@ -33,6 +33,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.Secret EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.SecretManager.Tools.Tests", "test\Microsoft.Extensions.SecretManager.Tools.Tests\Microsoft.Extensions.SecretManager.Tools.Tests.xproj", "{7B331122-83B1-4F08-A119-DC846959844C}" EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Watcher.Tools.Tests", "test\Microsoft.DotNet.Watcher.Tools.Tests\Microsoft.DotNet.Watcher.Tools.Tests.xproj", "{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}" +EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.Caching.SqlConfig.Tools", "src\Microsoft.Extensions.Caching.SqlConfig.Tools\Microsoft.Extensions.Caching.SqlConfig.Tools.xproj", "{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}" EndProject Global @@ -81,6 +83,10 @@ Global {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.Build.0 = Debug|Any CPU {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.ActiveCfg = Release|Any CPU {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.Build.0 = Release|Any CPU + {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -97,5 +103,6 @@ Global {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E} = {66517987-2A5A-4330-B130-207039378FD4} {7B331122-83B1-4F08-A119-DC846959844C} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {53F3B53D-303A-4DAA-9C38-4F55195FA5B9} = {66517987-2A5A-4330-B130-207039378FD4} + {8A2E6961-6B12-4A8E-8215-3E7301D52EAC} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} EndGlobalSection EndGlobal diff --git a/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs index 92577d59fe..2fe63625d2 100644 --- a/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs @@ -2,9 +2,11 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; +using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Watcher.Core.Internal; using Microsoft.Extensions.Logging; @@ -33,7 +35,7 @@ namespace Microsoft.DotNet.Watcher.Core _logger = _loggerFactory.CreateLogger(nameof(DotNetWatcher)); } - public async Task WatchAsync(string projectFile, string[] dotnetArguments, CancellationToken cancellationToken) + public async Task WatchAsync(string projectFile, IEnumerable dotnetArguments, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(projectFile)) { @@ -48,24 +50,7 @@ namespace Microsoft.DotNet.Watcher.Core throw new ArgumentNullException(nameof(cancellationToken)); } - // If any argument has spaces then quote it because we're going to convert everything - // to string - for (var i = 0; i < dotnetArguments.Length; i++) - { - var arg = dotnetArguments[i]; - foreach (char c in arg) - { - if (c == ' ' || - c == '\t') - { - arg = $"\"{arg}\""; - break; - } - } - dotnetArguments[i] = arg; - } - - var dotnetArgumentsAsString = string.Join(" ", dotnetArguments); + var dotnetArgumentsAsString = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(dotnetArguments); var workingDir = Path.GetDirectoryName(projectFile); diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json index 53730690fc..2f3f041420 100644 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ b/src/Microsoft.DotNet.Watcher.Core/project.json @@ -17,6 +17,7 @@ }, "dependencies": { "Microsoft.DotNet.ProjectModel": "1.0.0-*", + "Microsoft.DotNet.Cli.Utils": "1.0.0-*", "Microsoft.Extensions.FileProviders.Abstractions": "1.1.0-*", "Microsoft.Extensions.FileProviders.Physical": "1.1.0-*", "Microsoft.Extensions.Logging.Abstractions": "1.1.0-*", diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs new file mode 100644 index 0000000000..03ab69567c --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs @@ -0,0 +1,54 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using Microsoft.Extensions.CommandLineUtils; + +namespace Microsoft.DotNet.Watcher.Tools +{ + internal class CommandLineOptions + { + public bool IsHelp { get; private set; } + public IList RemainingArguments { get; private set; } + public static CommandLineOptions Parse(string[] args, TextWriter consoleOutput) + { + if (args == null) + { + throw new ArgumentNullException(nameof(args)); + } + + var app = new CommandLineApplication(throwOnUnexpectedArg: false) + { + Name = "dotnet watch", + FullName = "Microsoft DotNet File Watcher", + Out = consoleOutput, + AllowArgumentSeparator = true + }; + + app.HelpOption("-?|-h|--help"); + + app.OnExecute(() => + { + if (app.RemainingArguments.Count == 0) + { + app.ShowHelp(); + } + + return 0; + }); + + if (app.Execute(args) != 0) + { + return null; + } + + return new CommandLineOptions + { + RemainingArguments = app.RemainingArguments, + IsHelp = app.IsShowingInformation + }; + } + } +} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index 5b0cde0b71..d3f0631134 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -6,7 +6,6 @@ using System.IO; using System.Threading; using System.Threading.Tasks; using Microsoft.DotNet.Watcher.Core; -using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Logging; namespace Microsoft.DotNet.Watcher.Tools @@ -14,9 +13,24 @@ namespace Microsoft.DotNet.Watcher.Tools public class Program { private readonly ILoggerFactory _loggerFactory; + private readonly CancellationToken _cancellationToken; + private readonly TextWriter _out; - public Program() + public Program(TextWriter consoleOutput, CancellationToken cancellationToken) { + if (consoleOutput == null) + { + throw new ArgumentNullException(nameof(consoleOutput)); + } + + if (cancellationToken == null) + { + throw new ArgumentNullException(nameof(cancellationToken)); + } + + _cancellationToken = cancellationToken; + _out = consoleOutput; + _loggerFactory = new LoggerFactory(); var logVar = Environment.GetEnvironmentVariable("DOTNET_WATCH_LOG_LEVEL"); @@ -44,49 +58,44 @@ namespace Microsoft.DotNet.Watcher.Tools ev.Cancel = false; }; - return new Program().MainInternal(args, ctrlCTokenSource.Token); + int exitCode; + try + { + exitCode = new Program(Console.Out, ctrlCTokenSource.Token) + .MainInternalAsync(args) + .GetAwaiter() + .GetResult(); + } + catch (TaskCanceledException) + { + // swallow when only exception is the CTRL+C exit cancellation task + exitCode = 0; + } + return exitCode; } } - private int MainInternal(string[] args, CancellationToken cancellationToken) + private async Task MainInternalAsync(string[] args) { - var app = new CommandLineApplication(); - app.Name = "dotnet-watch"; - app.FullName = "Microsoft dotnet File Watcher"; - - app.HelpOption("-?|-h|--help"); - - app.OnExecute(() => + var options = CommandLineOptions.Parse(args, _out); + if (options == null) { - var projectToWatch = Path.Combine(Directory.GetCurrentDirectory(), ProjectModel.Project.FileName); - var watcher = DotNetWatcher.CreateDefault(_loggerFactory); - - try - { - watcher.WatchAsync(projectToWatch, args, cancellationToken).Wait(); - } - catch (AggregateException ex) - { - if (ex.InnerExceptions.Count != 1 || !(ex.InnerException is TaskCanceledException)) - { - throw; - } - } - - return 0; - }); - - if (args == null || - args.Length == 0 || - args[0].Equals("--help", StringComparison.OrdinalIgnoreCase) || - args[0].Equals("-h", StringComparison.OrdinalIgnoreCase) || - args[0].Equals("-?", StringComparison.OrdinalIgnoreCase)) - { - app.ShowHelp(); + // invalid args syntax return 1; } - return app.Execute(); + if (options.IsHelp) + { + return 2; + } + + var projectToWatch = Path.Combine(Directory.GetCurrentDirectory(), ProjectModel.Project.FileName); + + await DotNetWatcher + .CreateDefault(_loggerFactory) + .WatchAsync(projectToWatch, options.RemainingArguments, _cancellationToken); + + return 0; } } } diff --git a/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs b/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs index 35b4b58d45..df3730569e 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs @@ -3,12 +3,9 @@ using System.Reflection; using System.Resources; -using System.Runtime.CompilerServices; [assembly: AssemblyMetadata("Serviceable", "True")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: AssemblyCompany("Microsoft Corporation.")] [assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] [assembly: AssemblyProduct("Microsoft .NET")] - -[assembly: InternalsVisibleTo("Microsoft.DotNet.Watcher.Tools.Tests, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Properties/InternalsVisibleTo.cs b/src/Microsoft.DotNet.Watcher.Tools/Properties/InternalsVisibleTo.cs new file mode 100644 index 0000000000..ea9ec15282 --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/Properties/InternalsVisibleTo.cs @@ -0,0 +1,6 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Microsoft.DotNet.Watcher.Tools.Tests, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/README.md b/src/Microsoft.DotNet.Watcher.Tools/README.md index b244177440..8c47b9c58c 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/README.md +++ b/src/Microsoft.DotNet.Watcher.Tools/README.md @@ -18,7 +18,9 @@ Add `Microsoft.DotNet.Watcher.Tools` to the `tools` section of your `project.jso ### How To Use - dotnet watch [dotnet arguments] + dotnet watch [-?|-h|--help] + + dotnet watch [[--] ...] Add `watch` after `dotnet` in the command that you want to run: diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs new file mode 100644 index 0000000000..306cddaacd --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs @@ -0,0 +1,46 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; +using System.Linq; +using System.Text; +using Xunit; + +namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests +{ + public class CommandLineOptionsTests + { + [Theory] + [InlineData(new object[] { new[] { "-h" } })] + [InlineData(new object[] { new[] { "-?" } })] + [InlineData(new object[] { new[] { "--help" } })] + [InlineData(new object[] { new[] { "--help", "--bogus" } })] + [InlineData(new object[] { new[] { "--" } })] + [InlineData(new object[] { new string[0] })] + public void HelpArgs(string[] args) + { + var stdout = new StringBuilder(); + + var options = CommandLineOptions.Parse(args, new StringWriter(stdout)); + + Assert.True(options.IsHelp); + Assert.Contains("Usage: dotnet watch ", stdout.ToString()); + } + + [Theory] + [InlineData(new[] { "run" }, new[] { "run" })] + [InlineData(new[] { "run", "--", "subarg" }, new[] { "run", "--", "subarg" })] + [InlineData(new[] { "--", "run", "--", "subarg" }, new[] { "run", "--", "subarg" })] + [InlineData(new[] { "--unrecognized-arg" }, new[] { "--unrecognized-arg" })] + public void ParsesRemainingArgs(string[] args, string[] expected) + { + var stdout = new StringBuilder(); + + var options = CommandLineOptions.Parse(args, new StringWriter(stdout)); + + Assert.Equal(expected, options.RemainingArguments.ToArray()); + Assert.False(options.IsHelp); + Assert.Empty(stdout.ToString()); + } + } +} diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.xproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.xproj new file mode 100644 index 0000000000..3a1a6e45b7 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.xproj @@ -0,0 +1,19 @@ + + + + 14.0.25420 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 8a2e6961-6b12-4a8e-8215-3e7301d52eac + Microsoft.DotNet.Watcher.Tools.Tests + .\obj + .\bin\ + + + + 2.0 + + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json new file mode 100644 index 0000000000..bcdb3e2ae6 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json @@ -0,0 +1,22 @@ +{ + "buildOptions": { + "warningsAsErrors": true, + "keyFile": "../../tools/Key.snk" + }, + "dependencies": { + "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", + "dotnet-test-xunit": "2.2.0-*", + "xunit": "2.2.0-*" + }, + "frameworks": { + "netcoreapp1.0": { + "dependencies": { + "Microsoft.NETCore.App": { + "version": "1.0.0", + "type": "platform" + } + } + } + }, + "testRunner": "xunit" +} From 61dc862e4db1e5d802ab8a5cb1e614a0457222c4 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 26 Sep 2016 12:04:12 -0700 Subject: [PATCH 0259/1029] Merge Microsoft.DotNet.Watcher{.Core} into {.Tools} History: in the days of DNX, there was a plan to share code between dnx-watch and Visual Studio tooling to watch the system. We split the package into two pieces with this intention. Since then, dotnet-cli has replaced DNX and MSBuild will replace project.json. The shared watch code isn't necessary, nor is it an API we want to support. --- DotNetTools.sln | 18 +++------- NuGetPackageVerifier.json | 1 - .../Microsoft.DotNet.Watcher.Core.xproj | 17 ---------- .../Properties/AssemblyInfo.cs | 11 ------- .../project.json | 33 ------------------- .../CommandLineOptions.cs | 2 +- .../CommandOutputLogger.cs | 2 +- .../CommandOutputProvider.cs | 2 +- .../DotNetWatcher.cs | 4 +-- .../Internal/FileWatcher/DotnetFileWatcher.cs | 2 +- .../FileWatcher/FileWatcherFactory.cs | 2 +- .../FileWatcher/IFileSystemWatcher.cs | 2 +- .../FileWatcher/PollingFileWatcher.cs | 2 +- .../Internal/IFileWatcher.cs | 2 +- .../Internal/IProcessWatcher.cs | 2 +- .../Internal/IProject.cs | 2 +- .../Internal/IProjectProvider.cs | 2 +- .../Internal/Implementation/FileWatcher.cs | 2 +- .../Internal/Implementation/ProcessWatcher.cs | 3 +- .../Internal/Implementation/Project.cs | 2 +- .../Implementation/ProjectProvider.cs | 2 +- .../Internal}/IncludeContextExtensions.cs | 2 +- .../Internal/ProjectWatcher.cs | 2 +- .../Microsoft.DotNet.Watcher.Tools.xproj | 3 ++ src/Microsoft.DotNet.Watcher.Tools/Program.cs | 3 +- .../project.json | 8 +++-- .../FileWatcherTests.cs | 2 +- .../WaitForFileToChange.cs | 2 +- .../project.json | 2 +- 29 files changed, 37 insertions(+), 102 deletions(-) delete mode 100644 src/Microsoft.DotNet.Watcher.Core/Microsoft.DotNet.Watcher.Core.xproj delete mode 100644 src/Microsoft.DotNet.Watcher.Core/Properties/AssemblyInfo.cs delete mode 100644 src/Microsoft.DotNet.Watcher.Core/project.json rename src/{Microsoft.DotNet.Watcher.Core => Microsoft.DotNet.Watcher.Tools}/DotNetWatcher.cs (98%) rename src/{Microsoft.DotNet.Watcher.Core => Microsoft.DotNet.Watcher.Tools}/Internal/FileWatcher/DotnetFileWatcher.cs (98%) rename src/{Microsoft.DotNet.Watcher.Core => Microsoft.DotNet.Watcher.Tools}/Internal/FileWatcher/FileWatcherFactory.cs (95%) rename src/{Microsoft.DotNet.Watcher.Core => Microsoft.DotNet.Watcher.Tools}/Internal/FileWatcher/IFileSystemWatcher.cs (88%) rename src/{Microsoft.DotNet.Watcher.Core => Microsoft.DotNet.Watcher.Tools}/Internal/FileWatcher/PollingFileWatcher.cs (99%) rename src/{Microsoft.DotNet.Watcher.Core => Microsoft.DotNet.Watcher.Tools}/Internal/IFileWatcher.cs (87%) rename src/{Microsoft.DotNet.Watcher.Core => Microsoft.DotNet.Watcher.Tools}/Internal/IProcessWatcher.cs (90%) rename src/{Microsoft.DotNet.Watcher.Core => Microsoft.DotNet.Watcher.Tools}/Internal/IProject.cs (88%) rename src/{Microsoft.DotNet.Watcher.Core => Microsoft.DotNet.Watcher.Tools}/Internal/IProjectProvider.cs (86%) rename src/{Microsoft.DotNet.Watcher.Core => Microsoft.DotNet.Watcher.Tools}/Internal/Implementation/FileWatcher.cs (98%) rename src/{Microsoft.DotNet.Watcher.Core => Microsoft.DotNet.Watcher.Tools}/Internal/Implementation/ProcessWatcher.cs (97%) rename src/{Microsoft.DotNet.Watcher.Core => Microsoft.DotNet.Watcher.Tools}/Internal/Implementation/Project.cs (98%) rename src/{Microsoft.DotNet.Watcher.Core => Microsoft.DotNet.Watcher.Tools}/Internal/Implementation/ProjectProvider.cs (98%) rename src/{Microsoft.DotNet.Watcher.Core => Microsoft.DotNet.Watcher.Tools/Internal}/IncludeContextExtensions.cs (94%) rename src/{Microsoft.DotNet.Watcher.Core => Microsoft.DotNet.Watcher.Tools}/Internal/ProjectWatcher.cs (98%) diff --git a/DotNetTools.sln b/DotNetTools.sln index 8852cbde1a..f5b20b98f9 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -1,4 +1,3 @@ - Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 VisualStudioVersion = 14.0.25420.1 @@ -7,8 +6,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66517987-2A5 EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Watcher.Tools", "src\Microsoft.DotNet.Watcher.Tools\Microsoft.DotNet.Watcher.Tools.xproj", "{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Watcher.Core", "src\Microsoft.DotNet.Watcher.Core\Microsoft.DotNet.Watcher.Core.xproj", "{D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8321E0D1-9A47-4D2F-AED8-3AE636D44E35}" ProjectSection(SolutionItems) = preProject global.json = global.json @@ -47,10 +44,6 @@ Global {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Debug|Any CPU.Build.0 = Debug|Any CPU {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Release|Any CPU.ActiveCfg = Release|Any CPU {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Release|Any CPU.Build.0 = Release|Any CPU - {D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}.Release|Any CPU.Build.0 = Release|Any CPU {16BADE2F-1184-4518-8A70-B68A19D0805B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {16BADE2F-1184-4518-8A70-B68A19D0805B}.Debug|Any CPU.Build.0 = Debug|Any CPU {16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -79,21 +72,20 @@ Global {7B331122-83B1-4F08-A119-DC846959844C}.Debug|Any CPU.Build.0 = Debug|Any CPU {7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.ActiveCfg = Release|Any CPU {7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.Build.0 = Release|Any CPU - {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.Build.0 = Release|Any CPU {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Debug|Any CPU.Build.0 = Debug|Any CPU {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Release|Any CPU.ActiveCfg = Release|Any CPU {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Release|Any CPU.Build.0 = Release|Any CPU + {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46} = {66517987-2A5A-4330-B130-207039378FD4} - {D3DA3BBB-E206-404F-AEE6-17FB9B6F1221} = {66517987-2A5A-4330-B130-207039378FD4} {16BADE2F-1184-4518-8A70-B68A19D0805B} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {2876B12E-5841-4792-85A8-2929AEE11885} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {4F0D8A80-221F-4BCB-822E-44A0655F537E} = {2876B12E-5841-4792-85A8-2929AEE11885} @@ -102,7 +94,7 @@ Global {2F48041A-F7D1-478F-9C38-D41F0F05E8CA} = {2876B12E-5841-4792-85A8-2929AEE11885} {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E} = {66517987-2A5A-4330-B130-207039378FD4} {7B331122-83B1-4F08-A119-DC846959844C} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} - {53F3B53D-303A-4DAA-9C38-4F55195FA5B9} = {66517987-2A5A-4330-B130-207039378FD4} {8A2E6961-6B12-4A8E-8215-3E7301D52EAC} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} + {53F3B53D-303A-4DAA-9C38-4F55195FA5B9} = {66517987-2A5A-4330-B130-207039378FD4} EndGlobalSection EndGlobal diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index fe8b1557a4..6f028d94a6 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -5,7 +5,6 @@ ], "packages": { "Microsoft.DotNet.Watcher.Tools": { }, - "Microsoft.DotNet.Watcher.Core": { }, "Microsoft.Extensions.Caching.SqlConfig.Tools": { }, "Microsoft.Extensions.SecretManager.Tools": { } } diff --git a/src/Microsoft.DotNet.Watcher.Core/Microsoft.DotNet.Watcher.Core.xproj b/src/Microsoft.DotNet.Watcher.Core/Microsoft.DotNet.Watcher.Core.xproj deleted file mode 100644 index c8b26f14d5..0000000000 --- a/src/Microsoft.DotNet.Watcher.Core/Microsoft.DotNet.Watcher.Core.xproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - d3da3bbb-e206-404f-aee6-17fb9b6f1221 - .\obj - .\bin\ - - - 2.0 - - - \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Core/Properties/AssemblyInfo.cs b/src/Microsoft.DotNet.Watcher.Core/Properties/AssemblyInfo.cs deleted file mode 100644 index 540e9029bc..0000000000 --- a/src/Microsoft.DotNet.Watcher.Core/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Reflection; -using System.Resources; - -[assembly: AssemblyMetadata("Serviceable", "True")] -[assembly: NeutralResourcesLanguage("en-US")] -[assembly: AssemblyCompany("Microsoft Corporation.")] -[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] -[assembly: AssemblyProduct("Microsoft .NET")] \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Core/project.json b/src/Microsoft.DotNet.Watcher.Core/project.json deleted file mode 100644 index 2f3f041420..0000000000 --- a/src/Microsoft.DotNet.Watcher.Core/project.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "version": "1.0.0-*", - "description": "Core logic for the dotnet-watch command line tool.", - "packOptions": { - "tags": [ - "dotnet", - "watch" - ] - }, - "buildOptions": { - "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk", - "nowarn": [ - "CS1591" - ], - "xmlDoc": true - }, - "dependencies": { - "Microsoft.DotNet.ProjectModel": "1.0.0-*", - "Microsoft.DotNet.Cli.Utils": "1.0.0-*", - "Microsoft.Extensions.FileProviders.Abstractions": "1.1.0-*", - "Microsoft.Extensions.FileProviders.Physical": "1.1.0-*", - "Microsoft.Extensions.Logging.Abstractions": "1.1.0-*", - "Microsoft.Extensions.FileSystemGlobbing": "1.1.0-*", - "Microsoft.Extensions.Process.Sources": { - "type": "build", - "version": "1.1.0-*" - } - }, - "frameworks": { - "netstandard1.6": {} - } -} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs index 03ab69567c..4d7c998622 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.IO; using Microsoft.Extensions.CommandLineUtils; -namespace Microsoft.DotNet.Watcher.Tools +namespace Microsoft.DotNet.Watcher { internal class CommandLineOptions { diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandOutputLogger.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandOutputLogger.cs index 9ad0149db1..aeb90f45c2 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandOutputLogger.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandOutputLogger.cs @@ -5,7 +5,7 @@ using System; using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Logging; -namespace Microsoft.DotNet.Watcher.Tools +namespace Microsoft.DotNet.Watcher { /// /// Logger to print formatted command output. diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs index 34d2149009..7d9c2fd808 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs @@ -4,7 +4,7 @@ using System.Runtime.InteropServices; using Microsoft.Extensions.Logging; -namespace Microsoft.DotNet.Watcher.Tools +namespace Microsoft.DotNet.Watcher { public class CommandOutputProvider : ILoggerProvider { diff --git a/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs similarity index 98% rename from src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs rename to src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs index 2fe63625d2..d159af747f 100644 --- a/src/Microsoft.DotNet.Watcher.Core/DotNetWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs @@ -7,10 +7,10 @@ using System.IO; using System.Threading; using System.Threading.Tasks; using Microsoft.DotNet.Cli.Utils; -using Microsoft.DotNet.Watcher.Core.Internal; +using Microsoft.DotNet.Watcher.Internal; using Microsoft.Extensions.Logging; -namespace Microsoft.DotNet.Watcher.Core +namespace Microsoft.DotNet.Watcher { public class DotNetWatcher { diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/DotnetFileWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/DotnetFileWatcher.cs similarity index 98% rename from src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/DotnetFileWatcher.cs rename to src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/DotnetFileWatcher.cs index 8f2e44b5e7..e76fa088f6 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/DotnetFileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/DotnetFileWatcher.cs @@ -4,7 +4,7 @@ using System; using System.IO; -namespace Microsoft.DotNet.Watcher.Core.Internal +namespace Microsoft.DotNet.Watcher.Internal { internal class DotnetFileWatcher : IFileSystemWatcher { diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/FileWatcherFactory.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/FileWatcherFactory.cs similarity index 95% rename from src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/FileWatcherFactory.cs rename to src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/FileWatcherFactory.cs index 7d782a0db7..248342571f 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/FileWatcherFactory.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/FileWatcherFactory.cs @@ -3,7 +3,7 @@ using System; -namespace Microsoft.DotNet.Watcher.Core.Internal +namespace Microsoft.DotNet.Watcher.Internal { public static class FileWatcherFactory { diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/IFileSystemWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/IFileSystemWatcher.cs similarity index 88% rename from src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/IFileSystemWatcher.cs rename to src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/IFileSystemWatcher.cs index c944bb9d64..4bfc6bac6d 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/IFileSystemWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/IFileSystemWatcher.cs @@ -3,7 +3,7 @@ using System; -namespace Microsoft.DotNet.Watcher.Core.Internal +namespace Microsoft.DotNet.Watcher.Internal { public interface IFileSystemWatcher : IDisposable { diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/PollingFileWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs similarity index 99% rename from src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/PollingFileWatcher.cs rename to src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs index a6ed82ce1c..1920eecb90 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/FileWatcher/PollingFileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs @@ -7,7 +7,7 @@ using System.Diagnostics; using System.IO; using System.Threading; -namespace Microsoft.DotNet.Watcher.Core.Internal +namespace Microsoft.DotNet.Watcher.Internal { internal class PollingFileWatcher : IFileSystemWatcher { diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/IFileWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/IFileWatcher.cs similarity index 87% rename from src/Microsoft.DotNet.Watcher.Core/Internal/IFileWatcher.cs rename to src/Microsoft.DotNet.Watcher.Tools/Internal/IFileWatcher.cs index ab1f255003..1e43363789 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/IFileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/IFileWatcher.cs @@ -3,7 +3,7 @@ using System; -namespace Microsoft.DotNet.Watcher.Core.Internal +namespace Microsoft.DotNet.Watcher.Internal { public interface IFileWatcher : IDisposable { diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/IProcessWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/IProcessWatcher.cs similarity index 90% rename from src/Microsoft.DotNet.Watcher.Core/Internal/IProcessWatcher.cs rename to src/Microsoft.DotNet.Watcher.Tools/Internal/IProcessWatcher.cs index 86960b28b3..e80bd7c0a9 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/IProcessWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/IProcessWatcher.cs @@ -5,7 +5,7 @@ using System; using System.Threading; using System.Threading.Tasks; -namespace Microsoft.DotNet.Watcher.Core.Internal +namespace Microsoft.DotNet.Watcher.Internal { public interface IProcessWatcher { diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/IProject.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/IProject.cs similarity index 88% rename from src/Microsoft.DotNet.Watcher.Core/Internal/IProject.cs rename to src/Microsoft.DotNet.Watcher.Tools/Internal/IProject.cs index a2a2389f06..ca1dfb670a 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/IProject.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/IProject.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; -namespace Microsoft.DotNet.Watcher.Core.Internal +namespace Microsoft.DotNet.Watcher.Internal { public interface IProject { diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/IProjectProvider.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/IProjectProvider.cs similarity index 86% rename from src/Microsoft.DotNet.Watcher.Core/Internal/IProjectProvider.cs rename to src/Microsoft.DotNet.Watcher.Tools/Internal/IProjectProvider.cs index bcbf63aaae..30b2a94ee9 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/IProjectProvider.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/IProjectProvider.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.DotNet.Watcher.Core.Internal +namespace Microsoft.DotNet.Watcher.Internal { public interface IProjectProvider { diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/FileWatcher.cs similarity index 98% rename from src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs rename to src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/FileWatcher.cs index e0dbcabed5..79036c28de 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/FileWatcher.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; -namespace Microsoft.DotNet.Watcher.Core.Internal +namespace Microsoft.DotNet.Watcher.Internal { public class FileWatcher : IFileWatcher { diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/ProcessWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/ProcessWatcher.cs similarity index 97% rename from src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/ProcessWatcher.cs rename to src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/ProcessWatcher.cs index 4fa8872d14..466ef9be17 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/ProcessWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/ProcessWatcher.cs @@ -7,7 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Internal; -namespace Microsoft.DotNet.Watcher.Core.Internal +namespace Microsoft.DotNet.Watcher.Internal { public class ProcessWatcher : IProcessWatcher { @@ -55,6 +55,5 @@ namespace Microsoft.DotNet.Watcher.Core.Internal return exitCode; }); } - } } \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/Project.cs similarity index 98% rename from src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs rename to src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/Project.cs index 11df0238c1..10d8624df3 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/Project.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/Project.cs @@ -8,7 +8,7 @@ using System.Linq; using Microsoft.DotNet.ProjectModel.Files; using Microsoft.DotNet.ProjectModel.Graph; -namespace Microsoft.DotNet.Watcher.Core.Internal +namespace Microsoft.DotNet.Watcher.Internal { internal class Project : IProject { diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/ProjectProvider.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/ProjectProvider.cs similarity index 98% rename from src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/ProjectProvider.cs rename to src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/ProjectProvider.cs index a03bae0cf6..6d1cf3d99e 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/ProjectProvider.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/ProjectProvider.cs @@ -7,7 +7,7 @@ using System.Linq; using System.Text; using Microsoft.DotNet.ProjectModel; -namespace Microsoft.DotNet.Watcher.Core.Internal +namespace Microsoft.DotNet.Watcher.Internal { public class ProjectProvider : IProjectProvider { diff --git a/src/Microsoft.DotNet.Watcher.Core/IncludeContextExtensions.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/IncludeContextExtensions.cs similarity index 94% rename from src/Microsoft.DotNet.Watcher.Core/IncludeContextExtensions.cs rename to src/Microsoft.DotNet.Watcher.Tools/Internal/IncludeContextExtensions.cs index 2f422c777d..d01703999d 100644 --- a/src/Microsoft.DotNet.Watcher.Core/IncludeContextExtensions.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/IncludeContextExtensions.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.DotNet.ProjectModel.Files; -namespace Microsoft.DotNet.Watcher.Core +namespace Microsoft.DotNet.Watcher.Internal { internal static class IncludeContextExtensions { diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/ProjectWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectWatcher.cs similarity index 98% rename from src/Microsoft.DotNet.Watcher.Core/Internal/ProjectWatcher.cs rename to src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectWatcher.cs index e94afb7dd4..6b5fce3ab5 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/ProjectWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectWatcher.cs @@ -7,7 +7,7 @@ using System.IO; using System.Threading; using System.Threading.Tasks; -namespace Microsoft.DotNet.Watcher.Core.Internal +namespace Microsoft.DotNet.Watcher.Internal { public class ProjectWatcher : IDisposable { diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.xproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.xproj index 8d14e52973..f6e8a5813a 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.xproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.xproj @@ -10,6 +10,9 @@ .\obj .\bin\ + + Microsoft.DotNet.Watcher + 2.0 diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index d3f0631134..d96726f258 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -5,10 +5,9 @@ using System; using System.IO; using System.Threading; using System.Threading.Tasks; -using Microsoft.DotNet.Watcher.Core; using Microsoft.Extensions.Logging; -namespace Microsoft.DotNet.Watcher.Tools +namespace Microsoft.DotNet.Watcher { public class Program { diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index e9cf189495..3779fdc757 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -18,11 +18,15 @@ "xmlDoc": true }, "dependencies": { - "Microsoft.DotNet.Watcher.Core": "1.0.0-*", "System.Runtime.InteropServices.RuntimeInformation": "4.0.0", + "Microsoft.DotNet.Cli.Utils": "1.0.0-*", "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", "Microsoft.Extensions.Logging": "1.1.0-*", - "Microsoft.Extensions.Logging.Console": "1.1.0-*" + "Microsoft.Extensions.Logging.Console": "1.1.0-*", + "Microsoft.Extensions.Process.Sources": { + "type": "build", + "version": "1.1.0-*" + } }, "frameworks": { "netcoreapp1.0": { diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs index e9be4869a1..f627a5bd0d 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; -using Microsoft.DotNet.Watcher.Core.Internal; +using Microsoft.DotNet.Watcher.Internal; using Xunit; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/WaitForFileToChange.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/WaitForFileToChange.cs index 38ced6b437..995e61a738 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/WaitForFileToChange.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/WaitForFileToChange.cs @@ -4,7 +4,7 @@ using System; using System.IO; using System.Threading; -using Microsoft.DotNet.Watcher.Core.Internal; +using Microsoft.DotNet.Watcher.Internal; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index 76af431397..b2aa208cba 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -11,7 +11,7 @@ "type": "build", "version": "1.1.0-*" }, - "Microsoft.DotNet.Watcher.Core": "1.0.0-*", + "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", "Newtonsoft.Json": "9.0.1", "System.Threading.Thread": "4.0.0", "xunit": "2.2.0-*" From c88aa0042a8ae3457bb6731fcbbc6721d4b8c335 Mon Sep 17 00:00:00 2001 From: Kevin Dockx Date: Wed, 28 Sep 2016 18:37:21 +0200 Subject: [PATCH 0260/1029] Fix for issue #29 (Honor JsonProperty when serializing a JsonPatchDocument) (#35) * Fix for issue #29 (Honor JsonProperty when serializing a JsonPatchDocument) --- .../Helpers/ExpressionHelpers.cs | 26 ++- ...nPatchDocumentJsonPropertyAttributeTest.cs | 148 ++++++++++++++++++ .../JsonPropertyDTO.cs | 13 ++ .../JsonPropertyWithAnotherNameDTO.cs | 10 ++ .../JsonPropertyWithInheritanceDTO.cs | 19 +++ 5 files changed, 214 insertions(+), 2 deletions(-) create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyDTO.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithAnotherNameDTO.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithInheritanceDTO.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpressionHelpers.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpressionHelpers.cs index 92880eb0e1..d9b516cc0e 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpressionHelpers.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpressionHelpers.cs @@ -1,9 +1,12 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Newtonsoft.Json; using System; using System.Globalization; +using System.Linq; using System.Linq.Expressions; +using System.Reflection; namespace Microsoft.AspNetCore.JsonPatch.Helpers { @@ -51,11 +54,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Helpers if (ContinueWithSubPath(memberExpression.Expression.NodeType, false)) { var left = GetPath(memberExpression.Expression, false); - return left + "/" + memberExpression.Member.Name; + // Get property name, respecting JsonProperty attribute + return left + "/" + GetPropertyNameFromMemberExpression(memberExpression); } else { - return memberExpression.Member.Name; + // Get property name, respecting JsonProperty attribute + return GetPropertyNameFromMemberExpression(memberExpression); } case ExpressionType.Parameter: // Fits "x => x" (the whole document which is "" as JSON pointer) @@ -65,6 +70,23 @@ namespace Microsoft.AspNetCore.JsonPatch.Helpers } } + private static string GetPropertyNameFromMemberExpression(MemberExpression memberExpression) + { + // if there's a JsonProperty attribute, we must return the PropertyName + // from the attribute rather than the member name + var jsonPropertyAttribute = + memberExpression.Member.GetCustomAttribute( + typeof(JsonPropertyAttribute), true); + + if (jsonPropertyAttribute == null) + { + return memberExpression.Member.Name; + } + // get value + var castedAttribute = (JsonPropertyAttribute)jsonPropertyAttribute; + return castedAttribute.PropertyName; + } + private static bool ContinueWithSubPath(ExpressionType expressionType, bool firstTime) { if (firstTime) diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs new file mode 100644 index 0000000000..ef7d53c21a --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs @@ -0,0 +1,148 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Newtonsoft.Json; +using System.Linq; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch +{ + public class JsonPatchDocumentJsonPropertyAttributeTest + { + [Fact] + public void Add_WithExpression_RespectsJsonPropertyName_ForModelProperty() + { + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(p => p.Name, "John"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + // serialized value should have "AnotherName" as path + // deserialize to a JsonPatchDocument to check + var deserialized = + JsonConvert.DeserializeObject>(serialized); + + // get path + var pathToCheck = deserialized.Operations.First().path; + Assert.Equal(pathToCheck, "/anothername"); + } + + [Fact] + public void Add_WithExpression_RespectsJsonPropertyName_WhenApplyingToDifferentlyTypedClassWithPropertyMatchingJsonPropertyName() + { + var patchDocToSerialize = new JsonPatchDocument(); + patchDocToSerialize.Add(p => p.Name, "John"); + + // the patchdoc will deserialize to "anothername". We should thus be able to apply + // it to a class that HAS that other property name. + var doc = new JsonPropertyWithAnotherNameDTO() + { + AnotherName = "InitialValue" + }; + + var serialized = JsonConvert.SerializeObject(patchDocToSerialize); + var deserialized = + JsonConvert.DeserializeObject> + (serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(doc.AnotherName, "John"); + } + + [Fact] + public void Add_WithExpression_RespectsJsonPropertyName_WhenApplyingToSameTypedClassWithMatchingJsonPropertyName() + { + var patchDocToSerialize = new JsonPatchDocument(); + patchDocToSerialize.Add(p => p.Name, "John"); + + // the patchdoc will deserialize to "anothername". As JsonPropertyDTO has + // a JsonProperty signifying that "Name" should be deseriallized from "AnotherName", + // we should be able to apply the patchDoc. + + var doc = new JsonPropertyDTO() + { + Name = "InitialValue" + }; + + var serialized = JsonConvert.SerializeObject(patchDocToSerialize); + var deserialized = + JsonConvert.DeserializeObject> + (serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(doc.Name, "John"); + } + + [Fact] + public void Add_OnApplyFromJson_RespectsJsonPropertyNameOnJsonDocument() + { + var doc = new JsonPropertyDTO() + { + Name = "InitialValue" + }; + + // serialization should serialize to "AnotherName" + var serialized = "[{\"value\":\"Kevin\",\"path\":\"/AnotherName\",\"op\":\"add\"}]"; + var deserialized = + JsonConvert.DeserializeObject>(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal("Kevin", doc.Name); + } + + [Fact] + public void Remove_OnApplyFromJson_RespectsJsonPropertyNameOnJsonDocument() + { + var doc = new JsonPropertyDTO() + { + Name = "InitialValue" + }; + + // serialization should serialize to "AnotherName" + var serialized = "[{\"path\":\"/AnotherName\",\"op\":\"remove\"}]"; + var deserialized = + JsonConvert.DeserializeObject>(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal(null, doc.Name); + } + + [Fact] + public void Add_OnApplyFromJson_RespectsInheritedJsonPropertyNameOnJsonDocument() + { + var doc = new JsonPropertyWithInheritanceDTO() + { + Name = "InitialName" + }; + + // serialization should serialize to "AnotherName" + var serialized = "[{\"value\":\"Kevin\",\"path\":\"/AnotherName\",\"op\":\"add\"}]"; + var deserialized = + JsonConvert.DeserializeObject>(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal("Kevin", doc.Name); + } + + [Fact] + public void Add_WithExpression_RespectsJsonPropertyName_ForInheritedModelProperty() + { + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(p => p.Name, "John"); + + var serialized = JsonConvert.SerializeObject(patchDoc); + // serialized value should have "AnotherName" as path + // deserialize to a JsonPatchDocument to check + var deserialized = + JsonConvert.DeserializeObject>(serialized); + + // get path + var pathToCheck = deserialized.Operations.First().path; + Assert.Equal(pathToCheck, "/anothername"); + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyDTO.cs new file mode 100644 index 0000000000..c926d9f5fd --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyDTO.cs @@ -0,0 +1,13 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Newtonsoft.Json; + +namespace Microsoft.AspNetCore.JsonPatch +{ + public class JsonPropertyDTO + { + [JsonProperty("AnotherName")] + public string Name { get; set; } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithAnotherNameDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithAnotherNameDTO.cs new file mode 100644 index 0000000000..9b61e09005 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithAnotherNameDTO.cs @@ -0,0 +1,10 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.AspNetCore.JsonPatch +{ + public class JsonPropertyWithAnotherNameDTO + { + public string AnotherName { get; set; } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithInheritanceDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithInheritanceDTO.cs new file mode 100644 index 0000000000..fa69425ea9 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithInheritanceDTO.cs @@ -0,0 +1,19 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.AspNetCore.JsonPatch +{ + public class JsonPropertyWithInheritanceDTO : JsonPropertyWithInheritanceBaseDTO + { + public override string Name { get; set; } + } + + public abstract class JsonPropertyWithInheritanceBaseDTO + { + [JsonProperty("AnotherName")] + public abstract string Name { get; set; } + } +} From c13a8affc0662e32edd3914c290c5c9631dbad96 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 28 Sep 2016 11:50:43 -0700 Subject: [PATCH 0261/1029] Updating partner package versions --- .../project.json | 10 +++------- src/Microsoft.Extensions.WebEncoders/project.json | 3 ++- .../project.json | 2 +- .../project.json | 2 +- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/project.json b/src/Microsoft.AspNetCore.Html.Abstractions/project.json index 7d42a7746d..da6f399828 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/project.json +++ b/src/Microsoft.AspNetCore.Html.Abstractions/project.json @@ -19,14 +19,10 @@ "xmlDoc": true }, "dependencies": { - "System.Text.Encodings.Web": "4.0.0-*" + "NETStandard.Library": "1.6.1-*", + "System.Text.Encodings.Web": "4.3.0-*" }, "frameworks": { - "netstandard1.0": { - "dependencies": { - "System.Collections": "4.0.11-*", - "System.Resources.ResourceManager": "4.0.1-*" - } - } + "netstandard1.0": {} } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.WebEncoders/project.json b/src/Microsoft.Extensions.WebEncoders/project.json index 1e765f8b80..852787db64 100644 --- a/src/Microsoft.Extensions.WebEncoders/project.json +++ b/src/Microsoft.Extensions.WebEncoders/project.json @@ -22,7 +22,8 @@ "dependencies": { "Microsoft.Extensions.DependencyInjection.Abstractions": "1.1.0-*", "Microsoft.Extensions.Options": "1.1.0-*", - "System.Text.Encodings.Web": "4.0.0-*" + "NETStandard.Library": "1.6.1-*", + "System.Text.Encodings.Web": "4.3.0-*" }, "frameworks": { "netstandard1.0": {} diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index 8c2d135d8a..8e5e79eeb2 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -15,7 +15,7 @@ "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { - "version": "1.0.0-*", + "version": "1.1.0-*", "type": "platform" } } diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index 6ed331d6ec..4c9ee42471 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -14,7 +14,7 @@ "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { - "version": "1.0.0-*", + "version": "1.1.0-*", "type": "platform" } }, From 9e8aee24788a48b0d3277a85cebb3a228be8f9dd Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 28 Sep 2016 11:51:01 -0700 Subject: [PATCH 0262/1029] Updating partner package versions --- src/Microsoft.AspNetCore.JsonPatch/project.json | 15 ++++----------- .../project.json | 4 ++-- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index 44daeef0e9..5180ee7e23 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -21,22 +21,15 @@ ] }, "dependencies": { + "NETStandard.Library": "1.6.1-*", "Newtonsoft.Json": "9.0.1" }, "frameworks": { "netstandard1.1": { "dependencies": { - "Microsoft.CSharp": "4.0.1-*", - "System.Collections.Concurrent": "4.0.12-*", - "System.ComponentModel.TypeConverter": "4.1.0-*", - "System.Diagnostics.Debug": "4.0.11-*", - "System.Globalization": "4.0.11-*", - "System.Linq": "4.1.0-*", - "System.Reflection.Extensions": "4.0.1-*", - "System.Resources.ResourceManager": "4.0.1-*", - "System.Runtime.Extensions": "4.1.0-*", - "System.Runtime.Serialization.Primitives": "4.1.1-*", - "System.Text.Encoding.Extensions": "4.0.11-*" + "Microsoft.CSharp": "4.3.0-*", + "System.ComponentModel.TypeConverter": "4.3.0-*", + "System.Runtime.Serialization.Primitives": "4.3.0-*" } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index acc8390c6d..9da14bf59e 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -14,10 +14,10 @@ "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { - "version": "1.0.0-*", + "version": "1.1.0-*", "type": "platform" }, - "System.Diagnostics.TraceSource": "4.0.0-*" + "System.Diagnostics.TraceSource": "4.3.0-*" } }, "net451": { From 3b1f650d3be8bd4dcf5a22a07179b4778deb6bf4 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 20 Sep 2016 15:50:04 -0700 Subject: [PATCH 0263/1029] Add custom tool for packaging as "CLI" package types. Resolves #157 --- DotNetTools.sln | 9 ++ NuGetPackageVerifier.json | 53 +++++-- makefile.shade | 20 ++- .../Microsoft.DotNet.Watcher.Tools.nuspec | 30 ++++ .../project.json | 23 +-- ....Extensions.Caching.SqlConfig.Tools.nuspec | 29 ++++ .../project.json | 37 ++--- ...soft.Extensions.SecretManager.Tools.nuspec | 33 ++++ .../project.json | 19 +-- tools/NuGetPackager/NuGetPackager.xproj | 19 +++ tools/NuGetPackager/PackCommand.cs | 150 ++++++++++++++++++ tools/NuGetPackager/Program.cs | 50 ++++++ tools/NuGetPackager/project.json | 22 +++ 13 files changed, 427 insertions(+), 67 deletions(-) create mode 100644 src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec create mode 100644 src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec create mode 100644 tools/NuGetPackager/NuGetPackager.xproj create mode 100644 tools/NuGetPackager/PackCommand.cs create mode 100644 tools/NuGetPackager/Program.cs create mode 100644 tools/NuGetPackager/project.json diff --git a/DotNetTools.sln b/DotNetTools.sln index f5b20b98f9..c68103961f 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -34,6 +34,10 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Watcher.To EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.Caching.SqlConfig.Tools", "src\Microsoft.Extensions.Caching.SqlConfig.Tools\Microsoft.Extensions.Caching.SqlConfig.Tools.xproj", "{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{59E02BDF-98DE-4D64-B576-2D0299D5E052}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NuGetPackager", "tools\NuGetPackager\NuGetPackager.xproj", "{8B781D87-1FC3-4A34-9089-2BDF6B562B85}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -80,6 +84,10 @@ Global {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.Build.0 = Debug|Any CPU {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.ActiveCfg = Release|Any CPU {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.Build.0 = Release|Any CPU + {8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -96,5 +104,6 @@ Global {7B331122-83B1-4F08-A119-DC846959844C} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {8A2E6961-6B12-4A8E-8215-3E7301D52EAC} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {53F3B53D-303A-4DAA-9C38-4F55195FA5B9} = {66517987-2A5A-4330-B130-207039378FD4} + {8B781D87-1FC3-4A34-9089-2BDF6B562B85} = {59E02BDF-98DE-4D64-B576-2D0299D5E052} EndGlobalSection EndGlobal diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index 6f028d94a6..a8c79faf4d 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -1,17 +1,38 @@ -{ - "adx": { // Packages written by the ADX team and that ship on NuGet.org - "rules": [ - "AdxVerificationCompositeRule" - ], - "packages": { - "Microsoft.DotNet.Watcher.Tools": { }, - "Microsoft.Extensions.Caching.SqlConfig.Tools": { }, - "Microsoft.Extensions.SecretManager.Tools": { } - } - }, - "Default": { // Rules to run for packages not listed in any other set. - "rules": [ - "DefaultCompositeRule" - ] - } +{ + "adx": { + "rules": [ + "AdxVerificationCompositeRule" + ], + "packages": { + "Microsoft.DotNet.Watcher.Tools": { + "nowarn": { + "DOC_MISSING": { + "lib/netcoreapp1.0/dotnet-watch.dll": "xmldocs not required for DotnetCliTool packages" + } + }, + "packageTypes": ["DotnetCliTool"] + }, + "Microsoft.Extensions.Caching.SqlConfig.Tools": { + "nowarn": { + "DOC_MISSING": { + "lib/netcoreapp1.0/dotnet-sql-cache.dll": "xmldocs not required for DotnetCliTool packages" + } + }, + "packageTypes": ["DotnetCliTool"] + }, + "Microsoft.Extensions.SecretManager.Tools": { + "nowarn": { + "DOC_MISSING": { + "lib/netcoreapp1.0/dotnet-user-secrets.dll": "xmldocs not required for DotnetCliTool packages" + } + }, + "packageTypes": ["DotnetCliTool"] + } + } + }, + "Default": { + "rules": [ + "DefaultCompositeRule" + ] + } } \ No newline at end of file diff --git a/makefile.shade b/makefile.shade index 2493f0fcd3..83ca855489 100644 --- a/makefile.shade +++ b/makefile.shade @@ -1,7 +1,25 @@ +use namespace="System.IO" + +default BASE_DIR_LOCAL='${Directory.GetCurrentDirectory()}' +default BUILD_DIR_LOCAL='${Path.Combine(BASE_DIR_LOCAL, "artifacts", "build")}' + var VERSION='0.1' var FULL_VERSION='0.1' var AUTHORS='Microsoft Open Technologies, Inc.' -BuildQuality = "preview3"; use-standard-lifecycle -k-standard-goals \ No newline at end of file +k-standard-goals + +#build-pack .build-compile target='compile' + @{ + if (Directory.Exists("src") && !IsLinux) + { + Directory.CreateDirectory(BUILD_DIR_LOCAL); + Dotnet("run -p tools/NuGetPackager -- -c " + E("Configuration") + + " -o artifacts/build/ "+ + "-n src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec " + + "-n src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec " + + "-n src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec "); + } + } \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec new file mode 100644 index 0000000000..21ccd58d3d --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec @@ -0,0 +1,30 @@ + + + + Microsoft.DotNet.Watcher.Tools + $version$ + Microsoft + Microsoft + false + Command line tool to watch for source file changes during development and restart the dotnet command. + dotnet,watch + true + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index 3779fdc757..0fb7148fb5 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -11,14 +11,9 @@ "outputName": "dotnet-watch", "warningsAsErrors": true, "emitEntryPoint": true, - "keyFile": "../../tools/Key.snk", - "nowarn": [ - "CS1591" - ], - "xmlDoc": true + "keyFile": "../../tools/Key.snk" }, "dependencies": { - "System.Runtime.InteropServices.RuntimeInformation": "4.0.0", "Microsoft.DotNet.Cli.Utils": "1.0.0-*", "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", "Microsoft.Extensions.Logging": "1.1.0-*", @@ -26,16 +21,14 @@ "Microsoft.Extensions.Process.Sources": { "type": "build", "version": "1.1.0-*" - } + }, + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0" + }, + "System.Runtime.InteropServices.RuntimeInformation": "4.0.0" }, "frameworks": { - "netcoreapp1.0": { - "dependencies": { - "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.0.0" - } - } - } + "netcoreapp1.0": {} } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec new file mode 100644 index 0000000000..82ab8374f4 --- /dev/null +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec @@ -0,0 +1,29 @@ + + + + Microsoft.Extensions.Caching.SqlConfig.Tools + $version$ + Microsoft + Microsoft + false + Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching. + cache,distributedcache,sqlserver + true + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json index b8ffffdc12..5d6700047d 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json @@ -1,32 +1,12 @@ { "version": "1.0.0-*", - "dependencies": { - "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", - "Microsoft.Extensions.Logging": "1.1.0-*", - "Microsoft.Extensions.Logging.Console": "1.1.0-*", - "System.Data.SqlClient": "4.1.0-*" - }, - "description": "Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching.", - "frameworks": { - "netcoreapp1.0": { - "dependencies": { - "Microsoft.NETCore.App": { - "version": "1.0.0-*", - "type": "platform" - } - } - } - }, "buildOptions": { "outputName": "dotnet-sql-cache", "emitEntryPoint": true, "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk", - "nowarn": [ - "CS1591" - ], - "xmlDoc": true + "keyFile": "../../tools/Key.snk" }, + "description": "Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching.", "packOptions": { "repository": { "type": "git", @@ -37,5 +17,18 @@ "distributedcache", "sqlserver" ] + }, + "dependencies": { + "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", + "Microsoft.Extensions.Logging": "1.1.0-*", + "Microsoft.Extensions.Logging.Console": "1.1.0-*", + "Microsoft.NETCore.App": { + "version": "1.0.0-*", + "type": "platform" + }, + "System.Data.SqlClient": "4.1.0-*" + }, + "frameworks": { + "netcoreapp1.0": {} } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec new file mode 100644 index 0000000000..18d5b244e8 --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec @@ -0,0 +1,33 @@ + + + + + Microsoft.Extensions.SecretManager.Tools + $version$ + Microsoft + Microsoft + false + Command line tool to manage user secrets for Microsoft.Extensions.Configuration. + configuration,secrets,usersecrets + true + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index bd470ffdc8..f057bf19a6 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -4,11 +4,7 @@ "outputName": "dotnet-user-secrets", "emitEntryPoint": true, "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk", - "nowarn": [ - "CS1591" - ], - "xmlDoc": true + "keyFile": "../../tools/Key.snk" }, "description": "Command line tool to manage user secrets for Microsoft.Extensions.Configuration.", "packOptions": { @@ -26,18 +22,15 @@ "Microsoft.Extensions.Configuration.UserSecrets": "1.1.0-*", "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", "Microsoft.Extensions.Logging": "1.1.0-*", + "Microsoft.NETCore.App": { + "version": "1.0.0", + "type": "platform" + }, "Newtonsoft.Json": "9.0.1", "System.Runtime.InteropServices.RuntimeInformation": "4.0.0", "System.Runtime.Serialization.Primitives": "4.1.1" }, "frameworks": { - "netcoreapp1.0": { - "dependencies": { - "Microsoft.NETCore.App": { - "version": "1.0.0", - "type": "platform" - } - } - } + "netcoreapp1.0": {} } } \ No newline at end of file diff --git a/tools/NuGetPackager/NuGetPackager.xproj b/tools/NuGetPackager/NuGetPackager.xproj new file mode 100644 index 0000000000..57c243c965 --- /dev/null +++ b/tools/NuGetPackager/NuGetPackager.xproj @@ -0,0 +1,19 @@ + + + + 14.0.25420 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 8b781d87-1fc3-4a34-9089-2bdf6b562b85 + NuGetPackager + .\obj + .\bin\ + + + + 2.0 + + + \ No newline at end of file diff --git a/tools/NuGetPackager/PackCommand.cs b/tools/NuGetPackager/PackCommand.cs new file mode 100644 index 0000000000..687d0e0d64 --- /dev/null +++ b/tools/NuGetPackager/PackCommand.cs @@ -0,0 +1,150 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.DotNet.ProjectModel.Utilities; +using NuGet.Frameworks; +using NuGet.Versioning; + +namespace NuGetPackager +{ + internal class PackCommand + { + private readonly string _baseDir; + + public PackCommand(string baseDir) + { + _baseDir = baseDir; + } + + public async Task PackAsync(string nuspec, string config, string outputDir) + { + var project = ProjectContext.Create(Path.GetDirectoryName(nuspec), FrameworkConstants.CommonFrameworks.NetCoreApp10); + var props = "configuration=" + config; + var idx = 0; + foreach (var depVersion in GetDependencies(project).OrderBy(p => p.Item1).Select(p => p.Item2)) + { + props += $";dep_{++idx}={depVersion}"; + } + + var buildCommand = Command.CreateDotNet("build", + new[] { project.ProjectFile.ProjectFilePath, "--configuration", config }, + configuration: config); + + if (buildCommand.Execute().ExitCode != 0) + { + throw new GracefulException("Build failed"); + } + + Directory.CreateDirectory(outputDir); + + var version = project.ProjectFile.Version.ToNormalizedString(); + await Nuget("pack", + nuspec, + "-Verbosity", "detailed", + "-OutputDirectory", outputDir, + "-Version", version, + "-Properties", props); + } + + private IEnumerable> GetDependencies(ProjectContext context) + { + // copied from https://github.com/dotnet/cli/blob/da0e365264e0ab555cdde978bdfd2e504bada49a/src/dotnet/commands/dotnet-pack/PackageGenerator.cs + var project = context.RootProject; + + foreach (var dependency in project.Dependencies) + { + if (dependency.Type.Equals(LibraryDependencyType.Build)) + { + continue; + } + + // TODO: Efficiency + var dependencyDescription = context.LibraryManager.GetLibraries().First(l => l.RequestedRanges.Contains(dependency)); + + // REVIEW: Can we get this far with unresolved dependencies + if (!dependencyDescription.Resolved) + { + continue; + } + + if (dependencyDescription.Identity.Type == LibraryType.Project && + ((ProjectDescription)dependencyDescription).Project.EmbedInteropTypes) + { + continue; + } + + VersionRange dependencyVersion = null; + + if (dependency.VersionRange == null || + dependency.VersionRange.IsFloating) + { + dependencyVersion = new VersionRange(dependencyDescription.Identity.Version); + } + else + { + dependencyVersion = dependency.VersionRange; + } + + Reporter.Verbose.WriteLine($"Adding dependency {dependency.Name.Yellow()} {VersionUtility.RenderVersion(dependencyVersion).Yellow()}"); + + yield return new Tuple(dependency.Name, dependencyVersion.MinVersion.ToString()); + } + } + + private static string GetLockFileVersion(ProjectContext project, string name) => + project + .LockFile + .PackageLibraries + .First(l => l.Name.Equals(name)) + .Version + .ToNormalizedString(); + + private async Task Nuget(params string[] args) + { + var pInfo = new ProcessStartInfo + { + Arguments = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args), + FileName = await GetNugetExePath() + }; + Console.WriteLine("command: ".Bold().Blue() + pInfo.FileName); + Console.WriteLine("arguments: ".Bold().Blue() + pInfo.Arguments); + + Process.Start(pInfo).WaitForExit(); + } + + private async Task GetNugetExePath() + { + if (Environment.GetEnvironmentVariable("KOREBUILD_NUGET_EXE") != null) + { + return Environment.GetEnvironmentVariable("KOREBUILD_NUGET_EXE"); + } + + var nugetPath = Path.Combine(_baseDir, ".build", "nuget.3.5.0-rc1.exe"); + if (File.Exists(nugetPath)) + { + return nugetPath; + } + + Console.WriteLine("log : Downloading nuget.exe 3.5.0-rc1".Bold().Black()); + + var response = await new HttpClient().GetAsync("https://dist.nuget.org/win-x86-commandline/v3.5.0-rc1/NuGet.exe"); + using (var file = new FileStream(nugetPath, FileMode.CreateNew)) + { + response.EnsureSuccessStatusCode(); + await response.Content.LoadIntoBufferAsync(); + await response.Content.CopyToAsync(file); + } + return nugetPath; + } + } +} \ No newline at end of file diff --git a/tools/NuGetPackager/Program.cs b/tools/NuGetPackager/Program.cs new file mode 100644 index 0000000000..a553decce6 --- /dev/null +++ b/tools/NuGetPackager/Program.cs @@ -0,0 +1,50 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; +using System.Linq; +using Microsoft.Extensions.CommandLineUtils; +using Microsoft.DotNet.Cli.Utils; + +namespace NuGetPackager +{ + /// + /// This replaces the "dotnet-pack" command, which doesn't not yet support "package types" + /// and probably won't in time for the next release. + /// TODO remove this once CLI supports package type + /// + public class Program + { + public static int Main(string[] args) + { + var app = new CommandLineApplication(); + var optOutput = app.Option("-o|--output-dir ", "Output dir", CommandOptionType.SingleValue); + var optConfig = app.Option("-c|--configuration ", "Config", CommandOptionType.SingleValue); + var optsNuspec = app.Option("-n|--nuspec ", "nuspec", CommandOptionType.MultipleValue); + + app.OnExecute(async () => + { + if (!optsNuspec.Values.Any()) + { + Reporter.Error.WriteLine("Missing values for --nuspec"); + return 1; + } + + var config = optConfig.HasValue() + ? optConfig.Value() + : "Debug"; + var output = optOutput.Value() ?? Directory.GetCurrentDirectory(); + + var packer = new PackCommand(Directory.GetCurrentDirectory()); + foreach (var nuspec in optsNuspec.Values) + { + await packer.PackAsync(nuspec, config, output); + } + + return 0; + }); + + return app.Execute(args); + } + } +} \ No newline at end of file diff --git a/tools/NuGetPackager/project.json b/tools/NuGetPackager/project.json new file mode 100644 index 0000000000..146561308a --- /dev/null +++ b/tools/NuGetPackager/project.json @@ -0,0 +1,22 @@ +{ + "version": "1.0.0-*", + "buildOptions": { + "emitEntryPoint": true + }, + + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0" + }, + "Microsoft.DotNet.ProjectModel": "1.0.0-*", + "Microsoft.DotNet.Cli.Utils": "1.0.0-*", + "Microsoft.Extensions.CommandLineUtils": "1.1.0-*" + }, + + "frameworks": { + "netcoreapp1.0": { + "imports": "dnxcore50" + } + } +} \ No newline at end of file From 07444de002ddf6882c646214274bc498c7171fd1 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 30 Sep 2016 15:04:11 -0700 Subject: [PATCH 0264/1029] React to aspnet/BuildTools#105 --- NuGetPackageVerifier.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index a8c79faf4d..aa4710b372 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -5,7 +5,7 @@ ], "packages": { "Microsoft.DotNet.Watcher.Tools": { - "nowarn": { + "exclusions": { "DOC_MISSING": { "lib/netcoreapp1.0/dotnet-watch.dll": "xmldocs not required for DotnetCliTool packages" } @@ -13,7 +13,7 @@ "packageTypes": ["DotnetCliTool"] }, "Microsoft.Extensions.Caching.SqlConfig.Tools": { - "nowarn": { + "exclusions": { "DOC_MISSING": { "lib/netcoreapp1.0/dotnet-sql-cache.dll": "xmldocs not required for DotnetCliTool packages" } @@ -21,7 +21,7 @@ "packageTypes": ["DotnetCliTool"] }, "Microsoft.Extensions.SecretManager.Tools": { - "nowarn": { + "exclusions": { "DOC_MISSING": { "lib/netcoreapp1.0/dotnet-user-secrets.dll": "xmldocs not required for DotnetCliTool packages" } From 756843786e7bcc8055c04598cb033bb30628cbb7 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 30 Sep 2016 15:44:33 -0700 Subject: [PATCH 0265/1029] Ensure absolute path used in output dir --- tools/NuGetPackager/Program.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/NuGetPackager/Program.cs b/tools/NuGetPackager/Program.cs index a553decce6..d73a31a39d 100644 --- a/tools/NuGetPackager/Program.cs +++ b/tools/NuGetPackager/Program.cs @@ -35,6 +35,11 @@ namespace NuGetPackager : "Debug"; var output = optOutput.Value() ?? Directory.GetCurrentDirectory(); + if (!Path.IsPathRooted(output)) + { + output = Path.Combine(Directory.GetCurrentDirectory(), output); + } + var packer = new PackCommand(Directory.GetCurrentDirectory()); foreach (var nuspec in optsNuspec.Values) { From 4647a8a4bd58f690658046fc539158539ca7eafc Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 28 Sep 2016 11:50:14 -0700 Subject: [PATCH 0266/1029] Updating partner package versions --- .../Microsoft.DotNet.Watcher.Tools.nuspec | 1 - src/Microsoft.DotNet.Watcher.Tools/project.json | 5 ++--- .../project.json | 4 ++-- .../Microsoft.Extensions.SecretManager.Tools.nuspec | 3 +-- src/Microsoft.Extensions.SecretManager.Tools/project.json | 7 +++---- .../project.json | 5 ++--- test/Microsoft.DotNet.Watcher.Tools.Tests/project.json | 8 ++++---- .../project.json | 2 +- test/TestApps/AppWithDeps/project.json | 2 +- test/TestApps/Dependency/project.json | 2 +- test/TestApps/GlobbingApp/project.json | 2 +- test/TestApps/NoDepsApp/project.json | 2 +- 12 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec index 21ccd58d3d..53b80837cd 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec @@ -19,7 +19,6 @@ - diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index 0fb7148fb5..e54d7b3774 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -24,9 +24,8 @@ }, "Microsoft.NETCore.App": { "type": "platform", - "version": "1.0.0" - }, - "System.Runtime.InteropServices.RuntimeInformation": "4.0.0" + "version": "1.1.0-*" + } }, "frameworks": { "netcoreapp1.0": {} diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json index 5d6700047d..b860143998 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json @@ -23,10 +23,10 @@ "Microsoft.Extensions.Logging": "1.1.0-*", "Microsoft.Extensions.Logging.Console": "1.1.0-*", "Microsoft.NETCore.App": { - "version": "1.0.0-*", + "version": "1.1.0-*", "type": "platform" }, - "System.Data.SqlClient": "4.1.0-*" + "System.Data.SqlClient": "4.3.0-*" }, "frameworks": { "netcoreapp1.0": {} diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec index 18d5b244e8..2ddab547bf 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec @@ -21,8 +21,7 @@ - - + diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index f057bf19a6..77d376be2d 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -19,16 +19,15 @@ ] }, "dependencies": { - "Microsoft.Extensions.Configuration.UserSecrets": "1.1.0-*", "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", + "Microsoft.Extensions.Configuration.UserSecrets": "1.1.0-*", "Microsoft.Extensions.Logging": "1.1.0-*", "Microsoft.NETCore.App": { - "version": "1.0.0", + "version": "1.1.0-*", "type": "platform" }, "Newtonsoft.Json": "9.0.1", - "System.Runtime.InteropServices.RuntimeInformation": "4.0.0", - "System.Runtime.Serialization.Primitives": "4.1.1" + "System.Runtime.Serialization.Primitives": "4.3.0-*" }, "frameworks": { "netcoreapp1.0": {} diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index b2aa208cba..7242cbab37 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -6,14 +6,13 @@ "dependencies": { "dotnet-test-xunit": "2.2.0-*", "Microsoft.AspNetCore.Testing": "1.1.0-*", + "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", "Microsoft.Extensions.DependencyInjection": "1.1.0-*", "Microsoft.Extensions.Process.Sources": { "type": "build", "version": "1.1.0-*" }, - "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", "Newtonsoft.Json": "9.0.1", - "System.Threading.Thread": "4.0.0", "xunit": "2.2.0-*" }, "frameworks": { @@ -21,7 +20,7 @@ "dependencies": { "Microsoft.NETCore.App": { "type": "platform", - "version": "1.0.0" + "version": "1.1.0-*" } } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json index bcdb3e2ae6..a084f633f2 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json @@ -1,22 +1,22 @@ -{ +{ "buildOptions": { "warningsAsErrors": true, "keyFile": "../../tools/Key.snk" }, "dependencies": { - "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", "dotnet-test-xunit": "2.2.0-*", + "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", "xunit": "2.2.0-*" }, "frameworks": { "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { - "version": "1.0.0", + "version": "1.1.0-*", "type": "platform" } } } }, "testRunner": "xunit" -} +} \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json index 18868d2684..537709e5c8 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json @@ -13,7 +13,7 @@ "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { - "version": "1.0.0", + "version": "1.1.0-*", "type": "platform" } } diff --git a/test/TestApps/AppWithDeps/project.json b/test/TestApps/AppWithDeps/project.json index d197767c64..8b1c2f6bab 100644 --- a/test/TestApps/AppWithDeps/project.json +++ b/test/TestApps/AppWithDeps/project.json @@ -12,7 +12,7 @@ "dependencies": { "Microsoft.NETCore.App": { "type": "platform", - "version": "1.0.0" + "version": "1.1.0-*" } } } diff --git a/test/TestApps/Dependency/project.json b/test/TestApps/Dependency/project.json index 49853f2561..f697b65d49 100644 --- a/test/TestApps/Dependency/project.json +++ b/test/TestApps/Dependency/project.json @@ -1,6 +1,6 @@ { "dependencies": { - "NETStandard.Library": "1.6.0" + "NETStandard.Library": "1.6.1-*" }, "frameworks": { "netstandard1.5": {} diff --git a/test/TestApps/GlobbingApp/project.json b/test/TestApps/GlobbingApp/project.json index 99e2421e43..6418c6d199 100644 --- a/test/TestApps/GlobbingApp/project.json +++ b/test/TestApps/GlobbingApp/project.json @@ -16,7 +16,7 @@ "dependencies": { "Microsoft.NETCore.App": { "type": "platform", - "version": "1.0.0" + "version": "1.1.0-*" } } } diff --git a/test/TestApps/NoDepsApp/project.json b/test/TestApps/NoDepsApp/project.json index 327fafbef0..4972d51a39 100644 --- a/test/TestApps/NoDepsApp/project.json +++ b/test/TestApps/NoDepsApp/project.json @@ -7,7 +7,7 @@ "dependencies": { "Microsoft.NETCore.App": { "type": "platform", - "version": "1.0.0" + "version": "1.1.0-*" } } } From 40ff75d53600d29f62fbc1b408a48395a07e8e4a Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 3 Oct 2016 13:08:07 -0700 Subject: [PATCH 0267/1029] Create replacement API for Microsoft.DotNet.ProjectModel --- DotNetTools.sln | 14 ++ NuGet.config | 1 + NuGetPackageVerifier.json | 6 + global.json | 2 +- makefile.shade | 6 + .../DotNet/DotNetProjectContext.cs | 102 +++++++++ .../DotNet/IncludeContextExtensions.cs | 25 +++ .../IProjectContext.cs | 28 +++ .../Internal/DotNetCoreSdk.cs | 11 + .../Internal/DotNetCoreSdkResolver.cs | 129 ++++++++++++ ...soft.Extensions.ProjectModel.Sources.xproj | 18 ++ .../MsBuild/MsBuildContext.cs | 39 ++++ .../MsBuild/MsBuildExtensions.cs | 14 ++ .../MsBuild/MsBuildProjectContext.cs | 59 ++++++ .../MsBuild/MsBuildProjectContextBuilder.cs | 198 ++++++++++++++++++ .../project.json | 7 + ...Microsoft.DotNet.Watcher.Tools.Tests.xproj | 4 +- ...rosoft.Extensions.ProjectModel.Tests.xproj | 21 ++ .../MsBuild/DotNetCoreSdkResolverTest.cs | 57 +++++ .../MsBuild/MsBuildFixture.cs | 38 ++++ .../MsBuildProjectContextBuilderTest.cs | 77 +++++++ .../Utilities/TemporaryFileProvider.cs | 29 +++ .../project.json | 31 +++ 23 files changed, 914 insertions(+), 2 deletions(-) create mode 100644 src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetProjectContext.cs create mode 100644 src/Microsoft.Extensions.ProjectModel.Sources/DotNet/IncludeContextExtensions.cs create mode 100644 src/Microsoft.Extensions.ProjectModel.Sources/IProjectContext.cs create mode 100644 src/Microsoft.Extensions.ProjectModel.Sources/Internal/DotNetCoreSdk.cs create mode 100644 src/Microsoft.Extensions.ProjectModel.Sources/Internal/DotNetCoreSdkResolver.cs create mode 100644 src/Microsoft.Extensions.ProjectModel.Sources/Microsoft.Extensions.ProjectModel.Sources.xproj create mode 100644 src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildContext.cs create mode 100644 src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildExtensions.cs create mode 100644 src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContext.cs create mode 100644 src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContextBuilder.cs create mode 100644 src/Microsoft.Extensions.ProjectModel.Sources/project.json create mode 100644 test/Microsoft.Extensions.ProjectModel.Tests/Microsoft.Extensions.ProjectModel.Tests.xproj create mode 100644 test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/DotNetCoreSdkResolverTest.cs create mode 100644 test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildFixture.cs create mode 100644 test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs create mode 100644 test/Microsoft.Extensions.ProjectModel.Tests/Utilities/TemporaryFileProvider.cs create mode 100644 test/Microsoft.Extensions.ProjectModel.Tests/project.json diff --git a/DotNetTools.sln b/DotNetTools.sln index c68103961f..44d6a3dac3 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -38,6 +38,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{59E02BDF EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NuGetPackager", "tools\NuGetPackager\NuGetPackager.xproj", "{8B781D87-1FC3-4A34-9089-2BDF6B562B85}" EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.ProjectModel.Sources", "src\Microsoft.Extensions.ProjectModel.Sources\Microsoft.Extensions.ProjectModel.Sources.xproj", "{99D6CE89-7302-4C3A-83EB-D534C24644D2}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.ProjectModel.Tests", "test\Microsoft.Extensions.ProjectModel.Tests\Microsoft.Extensions.ProjectModel.Tests.xproj", "{1A66A831-4F06-46D9-B483-70A4E75A2F7F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -88,6 +92,14 @@ Global {8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Debug|Any CPU.Build.0 = Debug|Any CPU {8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Release|Any CPU.ActiveCfg = Release|Any CPU {8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Release|Any CPU.Build.0 = Release|Any CPU + {99D6CE89-7302-4C3A-83EB-D534C24644D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {99D6CE89-7302-4C3A-83EB-D534C24644D2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {99D6CE89-7302-4C3A-83EB-D534C24644D2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {99D6CE89-7302-4C3A-83EB-D534C24644D2}.Release|Any CPU.Build.0 = Release|Any CPU + {1A66A831-4F06-46D9-B483-70A4E75A2F7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1A66A831-4F06-46D9-B483-70A4E75A2F7F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1A66A831-4F06-46D9-B483-70A4E75A2F7F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1A66A831-4F06-46D9-B483-70A4E75A2F7F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -105,5 +117,7 @@ Global {8A2E6961-6B12-4A8E-8215-3E7301D52EAC} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {53F3B53D-303A-4DAA-9C38-4F55195FA5B9} = {66517987-2A5A-4330-B130-207039378FD4} {8B781D87-1FC3-4A34-9089-2BDF6B562B85} = {59E02BDF-98DE-4D64-B576-2D0299D5E052} + {99D6CE89-7302-4C3A-83EB-D534C24644D2} = {66517987-2A5A-4330-B130-207039378FD4} + {1A66A831-4F06-46D9-B483-70A4E75A2F7F} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} EndGlobalSection EndGlobal diff --git a/NuGet.config b/NuGet.config index 0fd623ffdd..18b373abe1 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,6 +1,7 @@  + diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index aa4710b372..d0e3b370e2 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -30,6 +30,12 @@ } } }, + "adx-nonshipping": { + "rules": [], + "packages": { + "Microsoft.Extensions.ProjectModel.Sources": {} + } + }, "Default": { "rules": [ "DefaultCompositeRule" diff --git a/global.json b/global.json index 553b2244a3..1920b5a762 100644 --- a/global.json +++ b/global.json @@ -1,3 +1,3 @@ { - "projects": [ "src"] + "projects": [ "src", "test"] } diff --git a/makefile.shade b/makefile.shade index 83ca855489..f957f23173 100644 --- a/makefile.shade +++ b/makefile.shade @@ -21,5 +21,11 @@ k-standard-goals "-n src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec " + "-n src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec " + "-n src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec "); + + DotnetPack("src/Microsoft.Extensions.ProjectModel.Sources/project.json", BUILD_DIR_LOCAL, E("Configuration"), E("KOREBUILD_DOTNET_PACK_OPTIONS") + " --no-build"); + foreach (var nupkg in Files.Include(Path.Combine(BUILD_DIR_LOCAL, "*/" + E("Configuration") + "/*.nupkg"))) + { + File.Copy(nupkg, Path.Combine(BUILD_DIR_LOCAL, Path.GetFileName(nupkg)), true); + } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetProjectContext.cs new file mode 100644 index 0000000000..53d8b3939f --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetProjectContext.cs @@ -0,0 +1,102 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using Microsoft.DotNet.ProjectModel; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using NuGet.Frameworks; + +namespace Microsoft.Extensions.ProjectModel +{ + internal class DotNetProjectContext : IProjectContext + { + private readonly ProjectContext _projectContext; + private readonly OutputPaths _paths; + private readonly Lazy _rawProject; + private readonly CommonCompilerOptions _compilerOptions; + + public DotNetProjectContext(ProjectContext projectContext, string configuration, string outputPath) + { + if (projectContext == null) + { + throw new ArgumentNullException(nameof(projectContext)); + } + + if (string.IsNullOrEmpty(configuration)) + { + throw new ArgumentNullException(nameof(configuration)); + } + + _rawProject = new Lazy(() => + { + using (var stream = new FileStream(projectContext.ProjectFile.ProjectFilePath, FileMode.Open, FileAccess.Read)) + using (var streamReader = new StreamReader(stream)) + using (var jsonReader = new JsonTextReader(streamReader)) + { + return JObject.Load(jsonReader); + } + }); + + Configuration = configuration; + _projectContext = projectContext; + + _paths = projectContext.GetOutputPaths(configuration, buidBasePath: null, outputPath: outputPath); + _compilerOptions = _projectContext.ProjectFile.GetCompilerOptions(TargetFramework, Configuration); + + // Workaround https://github.com/dotnet/cli/issues/3164 + IsClassLibrary = !(_compilerOptions.EmitEntryPoint + ?? projectContext.ProjectFile.GetCompilerOptions(null, configuration).EmitEntryPoint.GetValueOrDefault()); + } + + public bool IsClassLibrary { get; } + + public NuGetFramework TargetFramework => _projectContext.TargetFramework; + public string Config => _paths.RuntimeFiles.Config; + public string DepsJson => _paths.RuntimeFiles.DepsJson; + public string RuntimeConfigJson => _paths.RuntimeFiles.RuntimeConfigJson; + public string PackagesDirectory => _projectContext.PackagesDirectory; + + public string AssemblyFullPath => + !IsClassLibrary && (_projectContext.IsPortable || TargetFramework.IsDesktop()) + ? _paths.RuntimeFiles.Executable + : _paths.RuntimeFiles.Assembly; + + public string Configuration { get; } + public string ProjectFullPath => _projectContext.ProjectFile.ProjectFilePath; + public string ProjectName => _projectContext.ProjectFile.Name; + // TODO read from xproj if available + public string RootNamespace => _projectContext.ProjectFile.Name; + public string TargetDirectory => _paths.RuntimeOutputPath; + public string Platform => _compilerOptions.Platform; + + public IEnumerable CompilationItems + => _compilerOptions.CompileInclude.ResolveFiles(); + + public IEnumerable EmbededItems + => _compilerOptions.EmbedInclude.ResolveFiles(); + + /// + /// Returns string values of top-level keys in the project.json file + /// + /// + /// + /// + public string FindProperty(string propertyName) => FindProperty(propertyName); + + public TProperty FindProperty(string propertyName) + { + foreach (var item in _rawProject.Value) + { + if (item.Key.Equals(propertyName, StringComparison.OrdinalIgnoreCase)) + { + return item.Value.Value(); + } + } + + return default(TProperty); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/IncludeContextExtensions.cs b/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/IncludeContextExtensions.cs new file mode 100644 index 0000000000..938d84ed5c --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/IncludeContextExtensions.cs @@ -0,0 +1,25 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.DotNet.ProjectModel.Files; + +namespace Microsoft.Extensions.ProjectModel +{ + internal static class IncludeContextExtensions + { + public static IEnumerable ResolveFiles(this IncludeContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + return IncludeFilesResolver + .GetIncludeFiles(context, "/", diagnostics: null) + .Select(f => f.SourcePath); + } + } +} diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/IProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.Sources/IProjectContext.cs new file mode 100644 index 0000000000..64af21c0db --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.Sources/IProjectContext.cs @@ -0,0 +1,28 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using NuGet.Frameworks; + +namespace Microsoft.Extensions.ProjectModel +{ + public interface IProjectContext + { + string ProjectName { get; } + string Configuration { get; } + string Platform { get; } + string ProjectFullPath { get; } + string RootNamespace { get; } + bool IsClassLibrary { get; } + NuGetFramework TargetFramework { get; } + string Config { get; } + string DepsJson { get; } + string RuntimeConfigJson { get; } + string PackagesDirectory { get; } + string TargetDirectory { get; } + string AssemblyFullPath { get; } + IEnumerable CompilationItems { get; } + IEnumerable EmbededItems { get; } + string FindProperty(string propertyName); + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/Internal/DotNetCoreSdk.cs b/src/Microsoft.Extensions.ProjectModel.Sources/Internal/DotNetCoreSdk.cs new file mode 100644 index 0000000000..40dd59d6d9 --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.Sources/Internal/DotNetCoreSdk.cs @@ -0,0 +1,11 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Extensions.ProjectModel.Internal +{ + internal class DotNetCoreSdk + { + public string BasePath { get; set; } + public string Version { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/Internal/DotNetCoreSdkResolver.cs b/src/Microsoft.Extensions.ProjectModel.Sources/Internal/DotNetCoreSdkResolver.cs new file mode 100644 index 0000000000..684654674f --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.Sources/Internal/DotNetCoreSdkResolver.cs @@ -0,0 +1,129 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.DotNet.Cli.Utils; +using Newtonsoft.Json; +using NuGet.Versioning; + +namespace Microsoft.Extensions.ProjectModel.Internal +{ + internal class DotNetCoreSdkResolver + { + private readonly string _installationDir; + + /// + /// Represents a resolver that uses the currently executing to find the .NET Core SDK installation + /// + public static readonly DotNetCoreSdkResolver DefaultResolver = new DotNetCoreSdkResolver(Path.GetDirectoryName(new Muxer().MuxerPath)); + + /// + /// Instantiates a resolver that locates the SDK + /// + /// The directory containing dotnet muxer, aka DOTNET_HOME + public DotNetCoreSdkResolver(string installationDir) + { + _installationDir = installationDir; + } + + /// + /// Find the latest SDK installation (uses SemVer 1.0 to determine what is "latest") + /// + /// Path to SDK root directory + public DotNetCoreSdk ResolveLatest() + { + var latest = FindInstalled() + .Select(d => new { path = d, version = SemanticVersion.Parse(Path.GetFileName(d)) }) + .OrderByDescending(sdk => sdk.version) + .FirstOrDefault(); + + if (latest == null) + { + throw CreateSdkNotInstalledException(); + } + + return new DotNetCoreSdk + { + BasePath = latest.path, + Version = latest.version.ToFullString() + }; + } + + public DotNetCoreSdk ResolveProjectSdk(string projectDir) + { + var sdkVersion = ResolveGlobalJsonSdkVersion(projectDir); + if (string.IsNullOrEmpty(sdkVersion)) + { + return ResolveLatest(); + } + + var sdk = FindInstalled() + .Where(p => Path.GetFileName(p).Equals(sdkVersion, StringComparison.OrdinalIgnoreCase)) + .Select(d => new { path = d, version = SemanticVersion.Parse(Path.GetFileName(d)) }) + .FirstOrDefault(); + + if (sdk == null) + { + throw CreateSdkNotInstalledException(); + } + + return new DotNetCoreSdk + { + BasePath = sdk.path, + Version = sdk.version.ToFullString() + }; + } + + private Exception CreateSdkNotInstalledException() + { + return new DirectoryNotFoundException($"Could not find an installation of the .NET Core SDK in '{_installationDir}'"); + } + + private IEnumerable FindInstalled() + => Directory.EnumerateDirectories(Path.Combine(_installationDir, "sdk")); + + private string ResolveGlobalJsonSdkVersion(string start) + { + var dir = new DirectoryInfo(start); + FileInfo fileInfo = null; + while (dir != null) + { + var candidate = Path.Combine(dir.FullName, "global.json"); + if (File.Exists(candidate)) + { + fileInfo = new FileInfo(candidate); + break; + } + dir = dir.Parent; + } + if (fileInfo == null) + { + return null; + } + try + { + var contents = File.ReadAllText(fileInfo.FullName); + var globalJson = JsonConvert.DeserializeObject(contents); + return globalJson?.sdk?.version; + } + catch (JsonException) + { + // TODO log + return null; + } + } + + private class GlobalJsonStub + { + public GlobalJsonSdkStub sdk { get; set; } + + public class GlobalJsonSdkStub + { + public string version { get; set; } + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/Microsoft.Extensions.ProjectModel.Sources.xproj b/src/Microsoft.Extensions.ProjectModel.Sources/Microsoft.Extensions.ProjectModel.Sources.xproj new file mode 100644 index 0000000000..772d9c1c91 --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.Sources/Microsoft.Extensions.ProjectModel.Sources.xproj @@ -0,0 +1,18 @@ + + + + 14.0.25420 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 99d6ce89-7302-4c3a-83eb-d534c24644d2 + Microsoft.Extensions.ProjectModel + .\obj + .\bin\ + + + 2.0 + + + \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildContext.cs b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildContext.cs new file mode 100644 index 0000000000..4b50ca089e --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildContext.cs @@ -0,0 +1,39 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using Microsoft.Extensions.ProjectModel.Internal; + +namespace Microsoft.Extensions.ProjectModel +{ + /// + /// Represents the msbuild context used to parse a project model + /// + internal class MsBuildContext + { + public string MsBuildExecutableFullPath { get; private set; } + public string ExtensionsPath { get; private set; } + + public static MsBuildContext FromCurrentDotNetSdk() + { + var sdk = DotNetCoreSdkResolver.DefaultResolver.ResolveLatest(); + return FromDotNetSdk(sdk); + } + + public static MsBuildContext FromDotNetSdk(DotNetCoreSdk sdk) + { + if (sdk == null) + { + throw new ArgumentNullException(nameof(sdk)); + } + + return new MsBuildContext + { + // might change... See https://github.com/Microsoft/msbuild/issues/1136 + MsBuildExecutableFullPath = Path.Combine(sdk.BasePath, "MSBuild.exe"), + ExtensionsPath = sdk.BasePath + }; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildExtensions.cs b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildExtensions.cs new file mode 100644 index 0000000000..eef3bef01c --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildExtensions.cs @@ -0,0 +1,14 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Linq; + +namespace Microsoft.Build.Execution +{ + internal static class MsBuildExtensions + { + public static string FindProperty(this ProjectInstance projectInstance, string propertyName, StringComparison comparer) + => projectInstance.Properties.FirstOrDefault(p => p.Name.Equals(propertyName, comparer))?.EvaluatedValue; + } +} diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContext.cs new file mode 100644 index 0000000000..d8ca3020bb --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContext.cs @@ -0,0 +1,59 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using Microsoft.Build.Execution; +using NuGet.Frameworks; +using System.Linq; + +namespace Microsoft.Extensions.ProjectModel +{ + internal class MsBuildProjectContext : IProjectContext + { + private const string CompileItemName = "Compile"; + private const string EmbedItemName = "EmbeddedResource"; + private const string FullPathMetadataName = "FullPath"; + + private readonly ProjectInstance _project; + private readonly string _name; + + public MsBuildProjectContext(string name, string configuration, ProjectInstance project) + { + _project = project; + + Configuration = configuration; + _name = name; + } + + public string FindProperty(string propertyName) + { + return _project.GetProperty(propertyName)?.EvaluatedValue; + } + + public string ProjectName => FindProperty("ProjectName") ?? _name; + public string Configuration { get; } + + public NuGetFramework TargetFramework => NuGetFramework.Parse(FindProperty("NuGetTargetMoniker")); + public bool IsClassLibrary => FindProperty("OutputType").Equals("Library", StringComparison.OrdinalIgnoreCase); + + // TODO get from actual properties according to TFM + public string Config => AssemblyFullPath + ".config"; + public string DepsJson => Path.Combine(TargetDirectory, Path.GetFileNameWithoutExtension(AssemblyFullPath) + ".deps.json"); + public string RuntimeConfigJson => Path.Combine(TargetDirectory, Path.GetFileNameWithoutExtension(AssemblyFullPath) + ".runtimeconfig.json"); + + public string PackagesDirectory => FindProperty("NuGetPackageRoot"); + public string AssemblyFullPath => FindProperty("TargetPath"); + public string Platform => FindProperty("Platform"); + public string ProjectFullPath => _project.FullPath; + public string RootNamespace => FindProperty("RootNamespace") ?? ProjectName; + public string TargetDirectory => FindProperty("TargetDir"); + + public IEnumerable CompilationItems + => _project.GetItems(CompileItemName).Select(i => i.GetMetadataValue(FullPathMetadataName)); + + public IEnumerable EmbededItems + => _project.GetItems(EmbedItemName).Select(i => i.GetMetadataValue(FullPathMetadataName)); + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContextBuilder.cs b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContextBuilder.cs new file mode 100644 index 0000000000..63551e8aa6 --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContextBuilder.cs @@ -0,0 +1,198 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Xml; +using Microsoft.Build.Construction; +using Microsoft.Build.Evaluation; +using Microsoft.Build.Execution; +using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.FileProviders.Physical; +using Microsoft.Build.Framework; +using NuGet.Frameworks; + +namespace Microsoft.Extensions.ProjectModel +{ + internal class MsBuildProjectContextBuilder + { + private string _configuration; + private IFileInfo _fileInfo; + private string[] _buildTargets; + private Dictionary _globalProperties = new Dictionary(); + + public MsBuildProjectContextBuilder() + { + Initialize(); + } + + public MsBuildProjectContextBuilder WithBuildTargets(string[] targets) + { + if (targets == null) + { + throw new ArgumentNullException(nameof(targets)); + } + + _buildTargets = targets; + return this; + } + + public MsBuildProjectContextBuilder WithConfiguration(string configuration) + { + _configuration = configuration; + WithProperty("Configuration", configuration); + return this; + } + + public MsBuildProjectContextBuilder WithDesignTimeBuild() + { + // don't to expensive things + WithProperty("DesignTimeBuild", "true"); + WithProperty("_ResolveReferenceDependencies", "true"); + WithProperty("BuildProjectReferences", "false"); + return this; + } + + public MsBuildProjectContextBuilder WithMsBuild(MsBuildContext context) + { + /* + Workaround https://github.com/Microsoft/msbuild/issues/999 + Error: System.TypeInitializationException : The type initializer for 'BuildEnvironmentHelperSingleton' threw an exception. + Could not determine a valid location to MSBuild. Try running this process from the Developer Command Prompt for Visual Studio. + */ + + Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", context.MsBuildExecutableFullPath); + return WithProperty("MSBuildExtensionsPath", context.ExtensionsPath); + } + + public MsBuildProjectContextBuilder WithProperty(string property, string value) + { + _globalProperties[property] = value; + return this; + } + + public MsBuildProjectContextBuilder WithProjectFile(string filePath) + { + if (string.IsNullOrEmpty(filePath)) + { + throw new ArgumentNullException(nameof(filePath)); + } + + var fileInfo = new PhysicalFileInfo(new FileInfo(filePath)); + return WithProjectFile(fileInfo); + } + + public MsBuildProjectContextBuilder WithProjectFile(IFileInfo fileInfo) + { + _fileInfo = fileInfo; + return this; + } + + public MsBuildProjectContextBuilder WithTargetFramework(NuGetFramework framework) + => WithTargetFramework(framework.GetShortFolderName()); + + public MsBuildProjectContextBuilder WithTargetFramework(string framework) + => WithProperty("TargetFramework", framework); + + public virtual MsBuildProjectContext Build(bool ignoreBuildErrors = false) + { + var projectCollection = CreateProjectCollection(); + var project = CreateProject(_fileInfo, _configuration, _globalProperties, projectCollection); + var projectInstance = CreateProjectInstance(project, _buildTargets, ignoreBuildErrors); + + var name = Path.GetFileNameWithoutExtension(_fileInfo.Name); + return new MsBuildProjectContext(name, _configuration, projectInstance); + } + + protected virtual void Initialize() + { + WithBuildTargets(new[] { "ResolveReferences" }); + WithMsBuild(MsBuildContext.FromCurrentDotNetSdk()); + WithProperty("_ResolveReferenceDependencies", "true"); + } + + protected virtual ProjectCollection CreateProjectCollection() => new ProjectCollection(); + + protected virtual Project CreateProject(IFileInfo fileInfo, + string configuration, + IDictionary globalProps, + ProjectCollection projectCollection) + { + using (var stream = fileInfo.CreateReadStream()) + { + var xmlReader = XmlReader.Create(stream); + + var xml = ProjectRootElement.Create(xmlReader, projectCollection, preserveFormatting: true); + xml.FullPath = fileInfo.PhysicalPath; + + return new Project(xml, globalProps, toolsVersion: null, projectCollection: projectCollection); + } + } + + protected virtual ProjectInstance CreateProjectInstance(Project project, string[] targets, bool ignoreErrors) + { + var projectInstance = project.CreateProjectInstance(); + if (targets.Length == 0) + { + return projectInstance; + } + + var logger = new InMemoryLogger(); + projectInstance.Build(targets, new[] { logger }); + + if (!ignoreErrors && logger.Errors.Count > 0) + { + throw CreateBuildFailedException(project.FullPath, logger.Errors); + } + + return projectInstance; + } + + private Exception CreateBuildFailedException(string filePath, IList errors) + { + var sb = new StringBuilder(); + sb.AppendLine($"Building '{filePath}' failed."); + + for (var i = 0; i < errors.Count; i++) + { + sb.Append(i).Append(" :").AppendLine(errors[i].Message); + } + + throw new InvalidOperationException(sb.ToString()); + } + + private class InMemoryLogger : ILogger + { + private readonly Stack _onShutdown = new Stack(); + + internal IList Errors = new List(); + + public string Parameters { get; set; } + public LoggerVerbosity Verbosity { get; set; } + + public void Initialize(IEventSource eventSource) + { + eventSource.ErrorRaised += OnError; + _onShutdown.Push(() => + { + eventSource.ErrorRaised -= OnError; + }); + } + + private void OnError(object sender, BuildErrorEventArgs e) + { + Errors.Add(e); + } + + public void Shutdown() + { + while (_onShutdown.Count > 0) + { + _onShutdown.Pop()?.Invoke(); + } + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/project.json b/src/Microsoft.Extensions.ProjectModel.Sources/project.json new file mode 100644 index 0000000000..23d8c31849 --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.Sources/project.json @@ -0,0 +1,7 @@ +{ + "version": "1.0.0-*", + "shared": "**/*.cs", + "frameworks": { + "netstandard1.0": {} + } +} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.xproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.xproj index 3a1a6e45b7..58c2a08157 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.xproj +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.xproj @@ -11,9 +11,11 @@ .\obj .\bin\ - 2.0 + + + \ No newline at end of file diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/Microsoft.Extensions.ProjectModel.Tests.xproj b/test/Microsoft.Extensions.ProjectModel.Tests/Microsoft.Extensions.ProjectModel.Tests.xproj new file mode 100644 index 0000000000..a056486759 --- /dev/null +++ b/test/Microsoft.Extensions.ProjectModel.Tests/Microsoft.Extensions.ProjectModel.Tests.xproj @@ -0,0 +1,21 @@ + + + + 14.0.25420 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 1a66a831-4f06-46d9-b483-70a4e75a2f7f + Microsoft.Extensions.ProjectModel + .\obj + .\bin\ + + + 2.0 + + + + + + \ No newline at end of file diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/DotNetCoreSdkResolverTest.cs b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/DotNetCoreSdkResolverTest.cs new file mode 100644 index 0000000000..344cb20777 --- /dev/null +++ b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/DotNetCoreSdkResolverTest.cs @@ -0,0 +1,57 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using Microsoft.Extensions.ProjectModel.Internal; +using Xunit; + +namespace Microsoft.Extensions.ProjectModel +{ + public class DotNetCoreSdkResolverTest : IDisposable + { + private readonly string _fakeInstallDir; + public DotNetCoreSdkResolverTest() + { + _fakeInstallDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(_fakeInstallDir); + Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk")); + } + + [Fact] + public void ResolveLatest() + { + var project = Path.Combine(_fakeInstallDir, "project"); + Directory.CreateDirectory(project); + Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk", "1.0.1")); + Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk", "1.0.0")); + Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk", "1.0.0-beta1")); + var sdk = new DotNetCoreSdkResolver(_fakeInstallDir).ResolveLatest(); + Assert.Equal("1.0.1", sdk.Version); + Assert.Equal(Path.Combine(_fakeInstallDir, "sdk", "1.0.1"), sdk.BasePath); + } + + [Fact] + public void ResolveProjectSdk() + { + var project = Path.Combine(_fakeInstallDir, "project"); + Directory.CreateDirectory(project); + Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk", "1.0.0")); + Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk", "1.0.0-abc-123")); + Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk", "1.0.0-xyz-123")); + File.WriteAllText(Path.Combine(_fakeInstallDir, "global.json"), @"{ + ""sdk"": { + ""version"": ""1.0.0-abc-123"" + } + }"); + var sdk = new DotNetCoreSdkResolver(_fakeInstallDir).ResolveProjectSdk(project); + Assert.Equal("1.0.0-abc-123", sdk.Version); + Assert.Equal(Path.Combine(_fakeInstallDir, "sdk", "1.0.0-abc-123"), sdk.BasePath); + } + + public void Dispose() + { + Directory.Delete(_fakeInstallDir, recursive: true); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildFixture.cs b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildFixture.cs new file mode 100644 index 0000000000..9a7ae4d6ee --- /dev/null +++ b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildFixture.cs @@ -0,0 +1,38 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using Microsoft.Extensions.ProjectModel.Internal; +using NuGet.Versioning; + +namespace Microsoft.Extensions.ProjectModel +{ + public class MsBuildFixture + { + private readonly SemanticVersion _minMsBuildVersion = SemanticVersion.Parse("1.0.0-preview3-00000"); + + internal MsBuildContext GetMsBuildContext() + { + // for CI + var sdk = DotNetCoreSdkResolver.DefaultResolver.ResolveLatest(); + + // for dev work in VS + if (SemanticVersion.Parse(sdk.Version) < _minMsBuildVersion) + { + var home = Environment.GetEnvironmentVariable("USERPROFILE") + ?? Environment.GetEnvironmentVariable("HOME"); + var dotnetHome = Path.Combine(home, ".dotnet"); + var resovler = new DotNetCoreSdkResolver(dotnetHome); + sdk = resovler.ResolveLatest(); + } + + if (SemanticVersion.Parse(sdk.Version) < _minMsBuildVersion) + { + throw new InvalidOperationException($"Version of .NET Core SDK found in '{sdk.BasePath}' is not new enough for these tests."); + } + + return MsBuildContext.FromDotNetSdk(sdk); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs new file mode 100644 index 0000000000..41cfba10c7 --- /dev/null +++ b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs @@ -0,0 +1,77 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; +using System.Linq; +using NuGet.Frameworks; +using Xunit; + +namespace Microsoft.Extensions.ProjectModel +{ + public class MsBuildProjectContextBuilderTest : IClassFixture + { + private const string SkipReason = "CI doesn't yet have a new enough version of .NET Core SDK"; + + private readonly MsBuildFixture _fixture; + + public MsBuildProjectContextBuilderTest(MsBuildFixture fixture) + { + _fixture = fixture; + } + + [Fact(Skip = SkipReason)] + public void ExecutesDesignTimeBuild() + { + using (var fileProvider = new TemporaryFileProvider()) + { + // TODO When .NET Core SDK is available, detect and add to this test project + // fileProvider.Add("test.nuget.targets", "Import .NET Core SDK here"); + fileProvider.Add("test.csproj", @" + + + + + Microsoft.TestProject + TestProject + Library + .NETCoreApp + v1.0 + + + + + + + + +"); + fileProvider.Add("One.cs", "public class Abc {}"); + fileProvider.Add("Two.cs", "public class Abc2 {}"); + fileProvider.Add("Excluded.cs", "public class Abc {}"); + + var testContext = _fixture.GetMsBuildContext(); + + var expectedCompileItems = new[] { "One.cs", "Two.cs" }.Select(p => Path.Combine(fileProvider.Root, p)).ToArray(); + var builder = new MsBuildProjectContextBuilder() + .WithMsBuild(testContext) + .WithDesignTimeBuild() + // In latest version of MSBuild, setting this property causes evaluation errors when SDK is not available + //.WithConfiguration("Debug") + .WithProjectFile(fileProvider.GetFileInfo("test.csproj")); + + // TODO remove ignoreBuildErrors flag + // this always throws because Microsoft.NETCore.SDK is not available. + var context = builder.Build(ignoreBuildErrors: true); + + Assert.False(fileProvider.GetFileInfo("bin").Exists); + Assert.False(fileProvider.GetFileInfo("obj").Exists); + Assert.Equal(expectedCompileItems, context.CompilationItems.OrderBy(i => i).ToArray()); + Assert.Equal(Path.Combine(fileProvider.Root, "bin", "Debug", "test.dll"), context.AssemblyFullPath); + Assert.True(context.IsClassLibrary); + Assert.Equal("TestProject", context.ProjectName); + Assert.Equal(FrameworkConstants.CommonFrameworks.NetCoreApp10, context.TargetFramework); + Assert.Equal("Microsoft.TestProject", context.RootNamespace); + } + } + } +} diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/Utilities/TemporaryFileProvider.cs b/test/Microsoft.Extensions.ProjectModel.Tests/Utilities/TemporaryFileProvider.cs new file mode 100644 index 0000000000..9e21d6a371 --- /dev/null +++ b/test/Microsoft.Extensions.ProjectModel.Tests/Utilities/TemporaryFileProvider.cs @@ -0,0 +1,29 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Text; +using Microsoft.Extensions.FileProviders; + +namespace Microsoft.Extensions.ProjectModel +{ + internal class TemporaryFileProvider : PhysicalFileProvider + { + public TemporaryFileProvider() + :base(Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "tmpfiles", Guid.NewGuid().ToString())).FullName) + { + } + + public void Add(string filename, string contents) + { + File.WriteAllText(Path.Combine(this.Root, filename), contents, Encoding.UTF8); + } + + public new void Dispose() + { + base.Dispose(); + Directory.Delete(Root, recursive: true); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/project.json b/test/Microsoft.Extensions.ProjectModel.Tests/project.json new file mode 100644 index 0000000000..6b0b647c3e --- /dev/null +++ b/test/Microsoft.Extensions.ProjectModel.Tests/project.json @@ -0,0 +1,31 @@ +{ + "buildOptions": { + "warningsAsErrors": true, + "keyFile": "../../tools/Key.snk" + }, + "dependencies": { + "NuGet.Frameworks": "3.5.0-*", + "Microsoft.DotNet.Cli.Utils": "1.0.0-*", + "Microsoft.DotNet.ProjectModel": "1.0.0-*", + "Microsoft.Build.Runtime": "15.1.298-preview5", + "Microsoft.Extensions.FileProviders.Physical": "1.1.0-*", + "Microsoft.Extensions.ProjectModel.Sources": { + "type": "build", + "version": "1.0.0-*" + }, + "System.Runtime.InteropServices.RuntimeInformation": "4.0.0", + "dotnet-test-xunit": "2.2.0-*", + "xunit": "2.2.0-*" + }, + "frameworks": { + "netcoreapp1.0": { + "dependencies": { + "Microsoft.NETCore.App": { + "version": "1.0.0", + "type": "platform" + } + } + } + }, + "testRunner": "xunit" +} From dde022961cb903d0dbcff07ec2f2731dda1244f5 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 5 Oct 2016 10:08:37 -0700 Subject: [PATCH 0268/1029] Add MSBuildProjectFinder and update ProjectModel to handle latest MSBuild updates --- .../MsBuild/MsBuildProjectContextBuilder.cs | 40 +++++++--- .../MsBuild/MsBuildProjectFinder.cs | 72 ++++++++++++++++++ .../MsBuildProjectContextBuilderTest.cs | 55 ++++++++++---- .../MsBuild/MsBuildProjectFinderTest.cs | 73 +++++++++++++++++++ .../project.json | 6 +- .../MsBuild => Shared}/MsBuildFixture.cs | 6 +- 6 files changed, 223 insertions(+), 29 deletions(-) create mode 100644 src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectFinder.cs create mode 100644 test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectFinderTest.cs rename test/{Microsoft.Extensions.ProjectModel.Tests/MsBuild => Shared}/MsBuildFixture.cs (83%) diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContextBuilder.cs b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContextBuilder.cs index 63551e8aa6..2216860816 100644 --- a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContextBuilder.cs +++ b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContextBuilder.cs @@ -9,9 +9,10 @@ using System.Xml; using Microsoft.Build.Construction; using Microsoft.Build.Evaluation; using Microsoft.Build.Execution; +using Microsoft.Build.Framework; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.FileProviders.Physical; -using Microsoft.Build.Framework; +using Microsoft.Extensions.ProjectModel.Internal; using NuGet.Frameworks; namespace Microsoft.Extensions.ProjectModel @@ -22,6 +23,7 @@ namespace Microsoft.Extensions.ProjectModel private IFileInfo _fileInfo; private string[] _buildTargets; private Dictionary _globalProperties = new Dictionary(); + private bool _explicitMsBuild; public MsBuildProjectContextBuilder() { @@ -46,7 +48,7 @@ namespace Microsoft.Extensions.ProjectModel return this; } - public MsBuildProjectContextBuilder WithDesignTimeBuild() + public MsBuildProjectContextBuilder AsDesignTimeBuild() { // don't to expensive things WithProperty("DesignTimeBuild", "true"); @@ -55,16 +57,12 @@ namespace Microsoft.Extensions.ProjectModel return this; } - public MsBuildProjectContextBuilder WithMsBuild(MsBuildContext context) + // should be needed in most cases, but can be used to override + public MsBuildProjectContextBuilder UseMsBuild(MsBuildContext context) { - /* - Workaround https://github.com/Microsoft/msbuild/issues/999 - Error: System.TypeInitializationException : The type initializer for 'BuildEnvironmentHelperSingleton' threw an exception. - Could not determine a valid location to MSBuild. Try running this process from the Developer Command Prompt for Visual Studio. - */ - - Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", context.MsBuildExecutableFullPath); - return WithProperty("MSBuildExtensionsPath", context.ExtensionsPath); + _explicitMsBuild = true; + SetMsBuildContext(context); + return this; } public MsBuildProjectContextBuilder WithProperty(string property, string value) @@ -86,6 +84,13 @@ namespace Microsoft.Extensions.ProjectModel public MsBuildProjectContextBuilder WithProjectFile(IFileInfo fileInfo) { + if (!_explicitMsBuild) + { + var projectDir = Path.GetDirectoryName(fileInfo.PhysicalPath); + var sdk = DotNetCoreSdkResolver.DefaultResolver.ResolveProjectSdk(projectDir); + SetMsBuildContext(MsBuildContext.FromDotNetSdk(sdk)); + } + _fileInfo = fileInfo; return this; } @@ -109,7 +114,6 @@ namespace Microsoft.Extensions.ProjectModel protected virtual void Initialize() { WithBuildTargets(new[] { "ResolveReferences" }); - WithMsBuild(MsBuildContext.FromCurrentDotNetSdk()); WithProperty("_ResolveReferenceDependencies", "true"); } @@ -163,6 +167,18 @@ namespace Microsoft.Extensions.ProjectModel throw new InvalidOperationException(sb.ToString()); } + private void SetMsBuildContext(MsBuildContext context) + { + /* + Workaround https://github.com/Microsoft/msbuild/issues/999 + Error: System.TypeInitializationException : The type initializer for 'BuildEnvironmentHelperSingleton' threw an exception. + Could not determine a valid location to MSBuild. Try running this process from the Developer Command Prompt for Visual Studio. + */ + + Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", context.MsBuildExecutableFullPath); + WithProperty("MSBuildExtensionsPath", context.ExtensionsPath); + } + private class InMemoryLogger : ILogger { private readonly Stack _onShutdown = new Stack(); diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectFinder.cs b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectFinder.cs new file mode 100644 index 0000000000..3b43918631 --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectFinder.cs @@ -0,0 +1,72 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +// TODO if this becomes a true API instead of .Sources package, put strings into resource file + +namespace Microsoft.Extensions.ProjectModel +{ + internal class MsBuildProjectFinder + { + private readonly string _directory; + + public MsBuildProjectFinder(string directory) + { + if (string.IsNullOrEmpty(directory)) + { + throw new ArgumentException("Value cannot be null or empty", nameof(directory)); + } + + _directory = directory; + } + + public string FindMsBuildProject(string project = null) + { + var projectPath = project ?? _directory; + + if (!Path.IsPathRooted(projectPath)) + { + projectPath = Path.Combine(_directory, projectPath); + } + + if (Directory.Exists(projectPath)) + { + var projects = FindProjectFiles(projectPath).ToList(); + if (projects.Count > 1) + { + throw MultipleProjectsFound(projectPath); + } + + if (projects.Count == 0) + { + throw NoProjectsFound(projectPath); + } + + return projects[0]; + } + + if (!File.Exists(projectPath)) + { + throw FileDoesNotExist(projectPath); + } + + return projectPath; + } + + protected virtual Exception FileDoesNotExist(string filePath) + => new InvalidOperationException($"No file was found at '{filePath}'."); + + protected virtual Exception MultipleProjectsFound(string directory) + => new InvalidOperationException($"Multiple MSBuild project files found in '{directory}'."); + + protected virtual Exception NoProjectsFound(string directory) + => new InvalidOperationException($"Could not find a MSBuild project file in '{directory}'."); + + protected virtual IEnumerable FindProjectFiles(string directory) + => Directory.EnumerateFileSystemEntries(directory, "*.*proj", SearchOption.TopDirectoryOnly); + } +} \ No newline at end of file diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs index 41cfba10c7..118842ebc3 100644 --- a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs +++ b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs @@ -3,8 +3,11 @@ using System.IO; using System.Linq; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.Extensions.ProjectModel.Tests; using NuGet.Frameworks; using Xunit; +using Xunit.Abstractions; namespace Microsoft.Extensions.ProjectModel { @@ -13,10 +16,12 @@ namespace Microsoft.Extensions.ProjectModel private const string SkipReason = "CI doesn't yet have a new enough version of .NET Core SDK"; private readonly MsBuildFixture _fixture; + private readonly ITestOutputHelper _output; - public MsBuildProjectContextBuilderTest(MsBuildFixture fixture) + public MsBuildProjectContextBuilderTest(MsBuildFixture fixture, ITestOutputHelper output) { _fixture = fixture; + _output = output; } [Fact(Skip = SkipReason)] @@ -24,8 +29,17 @@ namespace Microsoft.Extensions.ProjectModel { using (var fileProvider = new TemporaryFileProvider()) { - // TODO When .NET Core SDK is available, detect and add to this test project - // fileProvider.Add("test.nuget.targets", "Import .NET Core SDK here"); + // TODO remove when SDK becomes available on other feeds + fileProvider.Add("NuGet.config", @" + + + + + + + +"); + fileProvider.Add("test.csproj", @" @@ -34,14 +48,23 @@ namespace Microsoft.Extensions.ProjectModel Microsoft.TestProject TestProject Library - .NETCoreApp - v1.0 + netcoreapp1.0 + bin\$(Configuration) + + + 1.0.0-* + + + 1.0.1 + + + "); @@ -51,22 +74,28 @@ namespace Microsoft.Extensions.ProjectModel var testContext = _fixture.GetMsBuildContext(); + var muxer = Path.Combine(testContext.ExtensionsPath, "../..", "dotnet.exe"); + var result = Command + .Create(muxer, new[] { "restore3", Path.Combine(fileProvider.Root, "test.csproj") }) + .OnErrorLine(l => _output.WriteLine(l)) + .OnOutputLine(l => _output.WriteLine(l)) + .Execute(); + Assert.Equal(0, result.ExitCode); + var expectedCompileItems = new[] { "One.cs", "Two.cs" }.Select(p => Path.Combine(fileProvider.Root, p)).ToArray(); var builder = new MsBuildProjectContextBuilder() - .WithMsBuild(testContext) - .WithDesignTimeBuild() - // In latest version of MSBuild, setting this property causes evaluation errors when SDK is not available - //.WithConfiguration("Debug") + .AsDesignTimeBuild() + .UseMsBuild(testContext) + .WithTargetFramework(FrameworkConstants.CommonFrameworks.NetCoreApp10) + .WithConfiguration("Debug") .WithProjectFile(fileProvider.GetFileInfo("test.csproj")); - // TODO remove ignoreBuildErrors flag - // this always throws because Microsoft.NETCore.SDK is not available. - var context = builder.Build(ignoreBuildErrors: true); + var context = builder.Build(); Assert.False(fileProvider.GetFileInfo("bin").Exists); Assert.False(fileProvider.GetFileInfo("obj").Exists); Assert.Equal(expectedCompileItems, context.CompilationItems.OrderBy(i => i).ToArray()); - Assert.Equal(Path.Combine(fileProvider.Root, "bin", "Debug", "test.dll"), context.AssemblyFullPath); + Assert.Equal(Path.Combine(fileProvider.Root, "bin", "Debug", "netcoreapp1.0", "test.dll"), context.AssemblyFullPath); Assert.True(context.IsClassLibrary); Assert.Equal("TestProject", context.ProjectName); Assert.Equal(FrameworkConstants.CommonFrameworks.NetCoreApp10, context.TargetFramework); diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectFinderTest.cs b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectFinderTest.cs new file mode 100644 index 0000000000..3d4155cfc5 --- /dev/null +++ b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectFinderTest.cs @@ -0,0 +1,73 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using Xunit; + +namespace Microsoft.Extensions.ProjectModel.MsBuild +{ + public class MsBuildProjectFinderTest + { + [Theory] + [InlineData(".csproj")] + [InlineData(".vbproj")] + [InlineData(".fsproj")] + public void FindsSingleProject(string extension) + { + using (var files = new TemporaryFileProvider()) + { + var filename = "TestProject" + extension; + files.Add(filename, ""); + + var finder = new MsBuildProjectFinder(files.Root); + + Assert.Equal(Path.Combine(files.Root, filename), finder.FindMsBuildProject()); + } + } + + [Fact] + public void ThrowsWhenNoFile() + { + using (var files = new TemporaryFileProvider()) + { + var finder = new MsBuildProjectFinder(files.Root); + + Assert.Throws(() => finder.FindMsBuildProject()); + } + } + + [Fact] + public void ThrowsWhenMultipleFile() + { + using (var files = new TemporaryFileProvider()) + { + files.Add("Test1.csproj", ""); + files.Add("Test2.csproj", ""); + var finder = new MsBuildProjectFinder(files.Root); + + Assert.Throws(() => finder.FindMsBuildProject()); + } + } + + [Fact] + public void ThrowsWhenFileDoesNotExist() + { + using (var files = new TemporaryFileProvider()) + { + var finder = new MsBuildProjectFinder(files.Root); + + Assert.Throws(() => finder.FindMsBuildProject("test.csproj")); + } + } + + [Fact] + public void ThrowsWhenRootDoesNotExist() + { + var files = new TemporaryFileProvider(); + var finder = new MsBuildProjectFinder(files.Root); + files.Dispose(); + Assert.Throws(() => finder.FindMsBuildProject()); + } + } +} diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/project.json b/test/Microsoft.Extensions.ProjectModel.Tests/project.json index 6b0b647c3e..2e1015de5a 100644 --- a/test/Microsoft.Extensions.ProjectModel.Tests/project.json +++ b/test/Microsoft.Extensions.ProjectModel.Tests/project.json @@ -1,7 +1,10 @@ { "buildOptions": { "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk" + "keyFile": "../../tools/Key.snk", + "compile": { + "include": "../Shared/*.cs" + } }, "dependencies": { "NuGet.Frameworks": "3.5.0-*", @@ -13,7 +16,6 @@ "type": "build", "version": "1.0.0-*" }, - "System.Runtime.InteropServices.RuntimeInformation": "4.0.0", "dotnet-test-xunit": "2.2.0-*", "xunit": "2.2.0-*" }, diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildFixture.cs b/test/Shared/MsBuildFixture.cs similarity index 83% rename from test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildFixture.cs rename to test/Shared/MsBuildFixture.cs index 9a7ae4d6ee..b8d1b8c237 100644 --- a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildFixture.cs +++ b/test/Shared/MsBuildFixture.cs @@ -6,12 +6,14 @@ using System.IO; using Microsoft.Extensions.ProjectModel.Internal; using NuGet.Versioning; -namespace Microsoft.Extensions.ProjectModel +namespace Microsoft.Extensions.ProjectModel.Tests { public class MsBuildFixture { - private readonly SemanticVersion _minMsBuildVersion = SemanticVersion.Parse("1.0.0-preview3-00000"); + // TODO remove this when preview3 stabilizies + private readonly SemanticVersion _minMsBuildVersion = SemanticVersion.Parse("1.0.0-preview3-003748"); + // TODO remove when our CI updates to using MSBuild or when Microsoft/msbuild#4213 is resolved internal MsBuildContext GetMsBuildContext() { // for CI From a15b73af6835a1b6d0bed8e77788fc059d20f010 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 6 Oct 2016 12:10:11 -0700 Subject: [PATCH 0269/1029] Pin to RTM versions of DotNet packages --- test/Microsoft.Extensions.ProjectModel.Tests/project.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/project.json b/test/Microsoft.Extensions.ProjectModel.Tests/project.json index 2e1015de5a..58c314075e 100644 --- a/test/Microsoft.Extensions.ProjectModel.Tests/project.json +++ b/test/Microsoft.Extensions.ProjectModel.Tests/project.json @@ -7,9 +7,9 @@ } }, "dependencies": { - "NuGet.Frameworks": "3.5.0-*", - "Microsoft.DotNet.Cli.Utils": "1.0.0-*", - "Microsoft.DotNet.ProjectModel": "1.0.0-*", + "NuGet.Frameworks": "3.5.0-rc1-final", + "Microsoft.DotNet.Cli.Utils": "1.0.0-preview2-003121", + "Microsoft.DotNet.ProjectModel": "1.0.0-rc3-003121", "Microsoft.Build.Runtime": "15.1.298-preview5", "Microsoft.Extensions.FileProviders.Physical": "1.1.0-*", "Microsoft.Extensions.ProjectModel.Sources": { From 74a067fdc3594113d6fecc6e587f8f7bc7a55a8e Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 6 Oct 2016 12:34:50 -0700 Subject: [PATCH 0270/1029] React to aspnet/Configuration#525 --- .../SecretManagerTests.cs | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs index 4675988131..f9b8f62961 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs @@ -26,11 +26,16 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests private string GetTempSecretProject() { - var projectPath = UserSecretHelper.GetTempSecretProject(); + string id; + return GetTempSecretProject(out id); + } + + private string GetTempSecretProject(out string userSecretsId) + { + var projectPath = UserSecretHelper.GetTempSecretProject(out userSecretsId); _disposables.Push(() => UserSecretHelper.DeleteTempSecretProject(projectPath)); return projectPath; } - public void Dispose() { while (_disposables.Count > 0) @@ -156,14 +161,15 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests [Fact] public void SetSecret_With_Verbose_Flag() { - var projectPath = GetTempSecretProject(); + string id; + var projectPath = GetTempSecretProject(out id); _logger.SetLevel(LogLevel.Debug); var secretManager = new Program() { Logger = _logger }; secretManager.RunInternal("-v", "set", "secret1", "value1", "-p", projectPath); Assert.Equal(3, _logger.Messages.Count); Assert.Contains(string.Format("Project file path {0}.", Path.Combine(projectPath, "project.json")), _logger.Messages); - Assert.Contains(string.Format("Secrets file path {0}.", PathHelper.GetSecretsPath(projectPath)), _logger.Messages); + Assert.Contains(string.Format("Secrets file path {0}.", PathHelper.GetSecretsPathFromSecretsId(id)), _logger.Messages); Assert.Contains("Successfully saved secret1 = value1 to the secret store.", _logger.Messages); _logger.Messages.Clear(); @@ -171,7 +177,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests Assert.Equal(3, _logger.Messages.Count); Assert.Contains(string.Format("Project file path {0}.", Path.Combine(projectPath, "project.json")), _logger.Messages); - Assert.Contains(string.Format("Secrets file path {0}.", PathHelper.GetSecretsPath(projectPath)), _logger.Messages); + Assert.Contains(string.Format("Secrets file path {0}.", PathHelper.GetSecretsPathFromSecretsId(id)), _logger.Messages); Assert.Contains("secret1 = value1", _logger.Messages); } @@ -205,8 +211,9 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests [Fact] public void List_Flattens_Nested_Objects() { - var projectPath = GetTempSecretProject(); - var secretsFile = PathHelper.GetSecretsPath(projectPath); + string id; + var projectPath = GetTempSecretProject(out id); + var secretsFile = PathHelper.GetSecretsPathFromSecretsId(id); Directory.CreateDirectory(Path.GetDirectoryName(secretsFile)); File.WriteAllText(secretsFile, @"{ ""AzureAd"": { ""ClientSecret"": ""abcd郩˙î""} }", Encoding.UTF8); var secretManager = new Program() { Logger = _logger }; @@ -218,8 +225,9 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests [Fact] public void Set_Flattens_Nested_Objects() { - var projectPath = GetTempSecretProject(); - var secretsFile = PathHelper.GetSecretsPath(projectPath); + string id; + var projectPath = GetTempSecretProject(out id); + var secretsFile = PathHelper.GetSecretsPathFromSecretsId(id); Directory.CreateDirectory(Path.GetDirectoryName(secretsFile)); File.WriteAllText(secretsFile, @"{ ""AzureAd"": { ""ClientSecret"": ""abcd郩˙î""} }", Encoding.UTF8); var secretManager = new Program() { Logger = _logger }; From 4214884b3e420755fc62180ee1cf84d578cbaea0 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Thu, 6 Oct 2016 12:38:19 -0700 Subject: [PATCH 0271/1029] Fix xml doc warning. --- .../DotNet/DotNetProjectContext.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetProjectContext.cs index 53d8b3939f..d28d100515 100644 --- a/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetProjectContext.cs +++ b/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetProjectContext.cs @@ -82,7 +82,6 @@ namespace Microsoft.Extensions.ProjectModel /// Returns string values of top-level keys in the project.json file /// /// - /// /// public string FindProperty(string propertyName) => FindProperty(propertyName); From 92a8d6d3bd44265ebf1741bf106b938b452ace79 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 6 Oct 2016 13:03:05 -0700 Subject: [PATCH 0272/1029] Add API for multi-tfm projects (#184) Project builder supports auto-detecting the framework --- .../MsBuild/MsBuildProjectContext.cs | 14 ++- .../MsBuild/MsBuildProjectContextBuilder.cs | 101 +++++++++++++++--- .../MsBuildProjectContextBuilderTest.cs | 100 +++++++++++------ 3 files changed, 165 insertions(+), 50 deletions(-) diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContext.cs index d8ca3020bb..b11c6b48d9 100644 --- a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContext.cs +++ b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContext.cs @@ -35,7 +35,19 @@ namespace Microsoft.Extensions.ProjectModel public string ProjectName => FindProperty("ProjectName") ?? _name; public string Configuration { get; } - public NuGetFramework TargetFramework => NuGetFramework.Parse(FindProperty("NuGetTargetMoniker")); + public NuGetFramework TargetFramework + { + get + { + var tfm = FindProperty("NuGetTargetMoniker") ?? FindProperty("TargetFramework"); + if (tfm == null) + { + return null; + } + return NuGetFramework.Parse(tfm); + } + } + public bool IsClassLibrary => FindProperty("OutputType").Equals("Library", StringComparison.OrdinalIgnoreCase); // TODO get from actual properties according to TFM diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContextBuilder.cs b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContextBuilder.cs index 2216860816..20d1f6cdc4 100644 --- a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContextBuilder.cs +++ b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContextBuilder.cs @@ -14,6 +14,7 @@ using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.FileProviders.Physical; using Microsoft.Extensions.ProjectModel.Internal; using NuGet.Frameworks; +using System.Linq; namespace Microsoft.Extensions.ProjectModel { @@ -23,13 +24,37 @@ namespace Microsoft.Extensions.ProjectModel private IFileInfo _fileInfo; private string[] _buildTargets; private Dictionary _globalProperties = new Dictionary(); - private bool _explicitMsBuild; + private MsBuildContext _msbuildContext; public MsBuildProjectContextBuilder() { Initialize(); } + public virtual MsBuildProjectContextBuilder Clone() + { + var builder = new MsBuildProjectContextBuilder() + .WithProperties(_globalProperties) + .WithBuildTargets(_buildTargets); + + if (_msbuildContext != null) + { + builder.UseMsBuild(_msbuildContext); + } + + if (_fileInfo != null) + { + builder.WithProjectFile(_fileInfo); + } + + if (_configuration != null) + { + builder.WithConfiguration(_configuration); + } + + return builder; + } + public MsBuildProjectContextBuilder WithBuildTargets(string[] targets) { if (targets == null) @@ -60,8 +85,27 @@ namespace Microsoft.Extensions.ProjectModel // should be needed in most cases, but can be used to override public MsBuildProjectContextBuilder UseMsBuild(MsBuildContext context) { - _explicitMsBuild = true; - SetMsBuildContext(context); + _msbuildContext = context; + + /* + Workaround https://github.com/Microsoft/msbuild/issues/999 + Error: System.TypeInitializationException : The type initializer for 'BuildEnvironmentHelperSingleton' threw an exception. + Could not determine a valid location to MSBuild. Try running this process from the Developer Command Prompt for Visual Studio. + */ + + Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", context.MsBuildExecutableFullPath); + WithProperty("MSBuildExtensionsPath", context.ExtensionsPath); + + return this; + } + + public MsBuildProjectContextBuilder WithProperties(IDictionary properties) + { + foreach (var prop in properties) + { + _globalProperties[prop.Key] = prop.Value; + } + return this; } @@ -84,11 +128,11 @@ namespace Microsoft.Extensions.ProjectModel public MsBuildProjectContextBuilder WithProjectFile(IFileInfo fileInfo) { - if (!_explicitMsBuild) + if (_msbuildContext == null) { var projectDir = Path.GetDirectoryName(fileInfo.PhysicalPath); var sdk = DotNetCoreSdkResolver.DefaultResolver.ResolveProjectSdk(projectDir); - SetMsBuildContext(MsBuildContext.FromDotNetSdk(sdk)); + UseMsBuild(MsBuildContext.FromDotNetSdk(sdk)); } _fileInfo = fileInfo; @@ -105,12 +149,41 @@ namespace Microsoft.Extensions.ProjectModel { var projectCollection = CreateProjectCollection(); var project = CreateProject(_fileInfo, _configuration, _globalProperties, projectCollection); + if (project.GetProperty("TargetFramework") == null) + { + var frameworks = GetAvailableTargetFrameworks(project).ToList(); + if (frameworks.Count > 1) + { + throw new InvalidOperationException($"Multiple frameworks are available. Either use {nameof(WithTargetFramework)} or {nameof(BuildAllTargetFrameworks)}"); + } + + if (frameworks.Count == 0) + { + throw new InvalidOperationException($"No frameworks are available. Either use {nameof(WithTargetFramework)} or {nameof(BuildAllTargetFrameworks)}"); + } + + project.SetGlobalProperty("TargetFramework", frameworks.Single()); + } + var projectInstance = CreateProjectInstance(project, _buildTargets, ignoreBuildErrors); var name = Path.GetFileNameWithoutExtension(_fileInfo.Name); return new MsBuildProjectContext(name, _configuration, projectInstance); } + public IEnumerable BuildAllTargetFrameworks() + { + var projectCollection = CreateProjectCollection(); + var project = CreateProject(_fileInfo, _configuration, _globalProperties, projectCollection); + + foreach (var framework in GetAvailableTargetFrameworks(project)) + { + var builder = Clone(); + builder.WithTargetFramework(framework); + yield return builder.Build(); + } + } + protected virtual void Initialize() { WithBuildTargets(new[] { "ResolveReferences" }); @@ -167,22 +240,20 @@ namespace Microsoft.Extensions.ProjectModel throw new InvalidOperationException(sb.ToString()); } - private void SetMsBuildContext(MsBuildContext context) + private IEnumerable GetAvailableTargetFrameworks(Project project) { - /* - Workaround https://github.com/Microsoft/msbuild/issues/999 - Error: System.TypeInitializationException : The type initializer for 'BuildEnvironmentHelperSingleton' threw an exception. - Could not determine a valid location to MSBuild. Try running this process from the Developer Command Prompt for Visual Studio. - */ - - Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", context.MsBuildExecutableFullPath); - WithProperty("MSBuildExtensionsPath", context.ExtensionsPath); + var frameworks = project.GetProperty("TargetFrameworks")?.EvaluatedValue; + if (string.IsNullOrEmpty(frameworks)) + { + return Enumerable.Empty(); + } + return frameworks.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); } private class InMemoryLogger : ILogger { private readonly Stack _onShutdown = new Stack(); - + internal IList Errors = new List(); public string Parameters { get; set; } diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs index 118842ebc3..1f840b9be6 100644 --- a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs +++ b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.IO; using System.Linq; using Microsoft.DotNet.Cli.Utils; @@ -11,26 +12,59 @@ using Xunit.Abstractions; namespace Microsoft.Extensions.ProjectModel { - public class MsBuildProjectContextBuilderTest : IClassFixture + public class MsBuildProjectContextBuilderTest : IClassFixture, IDisposable { private const string SkipReason = "CI doesn't yet have a new enough version of .NET Core SDK"; private readonly MsBuildFixture _fixture; private readonly ITestOutputHelper _output; + private readonly TemporaryFileProvider _files; public MsBuildProjectContextBuilderTest(MsBuildFixture fixture, ITestOutputHelper output) { _fixture = fixture; _output = output; + _files = new TemporaryFileProvider(); + } + + public void Dispose() + { + _files.Dispose(); + } + + [Fact(Skip = SkipReason)] + public void BuildsAllTargetFrameworks() + { + + _files.Add("test.proj", @" + + + net451;netstandard1.3 + + +"); + var contexts = new MsBuildProjectContextBuilder() + .WithBuildTargets(Array.Empty()) + .WithProjectFile(_files.GetFileInfo("test.proj")) + .BuildAllTargetFrameworks() + .ToList(); + + Assert.Collection(contexts, + context => + { + Assert.Equal(FrameworkConstants.CommonFrameworks.Net451, context.TargetFramework); + }, + context => + { + Assert.Equal(FrameworkConstants.CommonFrameworks.NetStandard13, context.TargetFramework); + }); } [Fact(Skip = SkipReason)] public void ExecutesDesignTimeBuild() { - using (var fileProvider = new TemporaryFileProvider()) - { - // TODO remove when SDK becomes available on other feeds - fileProvider.Add("NuGet.config", @" + // TODO remove when SDK becomes available on other feeds + _files.Add("NuGet.config", @" @@ -40,7 +74,7 @@ namespace Microsoft.Extensions.ProjectModel "); - fileProvider.Add("test.csproj", @" + _files.Add("test.csproj", @" @@ -68,39 +102,37 @@ namespace Microsoft.Extensions.ProjectModel "); - fileProvider.Add("One.cs", "public class Abc {}"); - fileProvider.Add("Two.cs", "public class Abc2 {}"); - fileProvider.Add("Excluded.cs", "public class Abc {}"); + _files.Add("One.cs", "public class Abc {}"); + _files.Add("Two.cs", "public class Abc2 {}"); + _files.Add("Excluded.cs", "public class Abc {}"); - var testContext = _fixture.GetMsBuildContext(); + var testContext = _fixture.GetMsBuildContext(); - var muxer = Path.Combine(testContext.ExtensionsPath, "../..", "dotnet.exe"); - var result = Command - .Create(muxer, new[] { "restore3", Path.Combine(fileProvider.Root, "test.csproj") }) - .OnErrorLine(l => _output.WriteLine(l)) - .OnOutputLine(l => _output.WriteLine(l)) - .Execute(); - Assert.Equal(0, result.ExitCode); + var muxer = Path.Combine(testContext.ExtensionsPath, "../..", "dotnet.exe"); + var result = Command + .Create(muxer, new[] { "restore3", Path.Combine(_files.Root, "test.csproj") }) + .OnErrorLine(l => _output.WriteLine(l)) + .OnOutputLine(l => _output.WriteLine(l)) + .Execute(); + Assert.Equal(0, result.ExitCode); - var expectedCompileItems = new[] { "One.cs", "Two.cs" }.Select(p => Path.Combine(fileProvider.Root, p)).ToArray(); - var builder = new MsBuildProjectContextBuilder() - .AsDesignTimeBuild() - .UseMsBuild(testContext) - .WithTargetFramework(FrameworkConstants.CommonFrameworks.NetCoreApp10) - .WithConfiguration("Debug") - .WithProjectFile(fileProvider.GetFileInfo("test.csproj")); + var expectedCompileItems = new[] { "One.cs", "Two.cs" }.Select(p => Path.Combine(_files.Root, p)).ToArray(); - var context = builder.Build(); + var context = new MsBuildProjectContextBuilder() + .AsDesignTimeBuild() + .UseMsBuild(testContext) + .WithConfiguration("Debug") + .WithProjectFile(_files.GetFileInfo("test.csproj")) + .Build(); - Assert.False(fileProvider.GetFileInfo("bin").Exists); - Assert.False(fileProvider.GetFileInfo("obj").Exists); - Assert.Equal(expectedCompileItems, context.CompilationItems.OrderBy(i => i).ToArray()); - Assert.Equal(Path.Combine(fileProvider.Root, "bin", "Debug", "netcoreapp1.0", "test.dll"), context.AssemblyFullPath); - Assert.True(context.IsClassLibrary); - Assert.Equal("TestProject", context.ProjectName); - Assert.Equal(FrameworkConstants.CommonFrameworks.NetCoreApp10, context.TargetFramework); - Assert.Equal("Microsoft.TestProject", context.RootNamespace); - } + Assert.False(_files.GetFileInfo("bin").Exists); + Assert.False(_files.GetFileInfo("obj").Exists); + Assert.Equal(expectedCompileItems, context.CompilationItems.OrderBy(i => i).ToArray()); + Assert.Equal(Path.Combine(_files.Root, "bin", "Debug", "netcoreapp1.0", "test.dll"), context.AssemblyFullPath); + Assert.True(context.IsClassLibrary); + Assert.Equal("TestProject", context.ProjectName); + Assert.Equal(FrameworkConstants.CommonFrameworks.NetCoreApp10, context.TargetFramework); + Assert.Equal("Microsoft.TestProject", context.RootNamespace); } } } From f9412e7707f3927ae87295af2a7537eae20fc6b6 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 6 Oct 2016 13:37:26 -0700 Subject: [PATCH 0273/1029] Remove unnecessary workaround. Resolves #165. --- .../Internal/SecretsStore.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs index 7863fb725a..b25a757500 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs @@ -28,11 +28,6 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal _secretsFilePath = PathHelper.GetSecretsPathFromSecretsId(userSecretsId); logger.LogDebug(Resources.Message_Secret_File_Path, _secretsFilePath); - // workaround https://github.com/aspnet/Configuration/issues/478 - // TODO remove when tool upgrades to use 1.1.0 - Directory.CreateDirectory(Path.GetDirectoryName(_secretsFilePath)); - //end workaround - _secrets = new ConfigurationBuilder() .AddJsonFile(_secretsFilePath, optional: true) .Build() From 393c25988ae2a57b6be4235ee4848212c3dcd861 Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Wed, 21 Sep 2016 22:56:55 -0700 Subject: [PATCH 0274/1029] [Fixes #33] Dictionary operations fail due to contract issues --- .../Adapters/ObjectAdapter.cs | 853 ++---------------- .../Helpers/ActualPropertyPathResult.cs | 22 - .../ExpandoObjectDictionaryExtensions.cs | 77 -- .../Helpers/ObjectTreeAnalyisResult.cs | 209 ----- .../Helpers/RemovedPropertyTypeResult.cs | 38 - .../{Helpers => Internal}/ConversionResult.cs | 10 +- .../Internal/ConversionResultProvider.cs | 24 + .../Internal/DictionaryAdapter.cs | 111 +++ .../Internal/ExpandoObjectAdapter.cs | 143 +++ .../ExpandoObjectDictionaryExtensions.cs | 26 + .../ExpressionHelpers.cs | 11 +- .../Internal/IAdapter.cs | 44 + .../Internal/ListAdapter.cs | 299 ++++++ .../Internal/ObjectVisitor.cs | 76 ++ .../Internal/ParsedPath.cs | 40 + .../{Helpers => Internal}/PathHelpers.cs | 2 +- .../Internal/PocoAdapter.cs | 205 +++++ .../JsonPatchDocument.cs | 10 +- .../JsonPatchDocumentOfT.cs | 10 +- .../Properties/Resources.Designer.cs | 132 +-- .../Resources.resx | 34 +- .../project.json | 12 +- .../DictionaryAdapterTest.cs | 176 ++++ .../Dynamic/AddOperationTests.cs | 43 +- .../Dynamic/AddTypedOperationTests.cs | 6 +- .../Dynamic/RemoveOperationTests.cs | 10 +- .../Dynamic/RemoveTypedOperationTests.cs | 10 +- .../Dynamic/ReplaceOperationTests.cs | 10 +- .../ListAdapterTest.cs | 302 +++++++ .../NestedDTO.cs | 2 +- .../NestedObjectTests.cs | 54 +- .../ObjectAdapterTests.cs | 667 ++++++++++++-- .../ObjectVisitorTest.cs | 230 +++++ .../ObjectVisitorTest.cs~RF1ad82e13.TMP | 119 +++ .../ObjectVisitorTest.cs~RF1ae034c3.TMP | 131 +++ .../SimpleDTO.cs | 2 +- .../SimpleDTOWithNestedDTO.cs | 2 +- .../TestErrorLogger.cs | 2 +- 38 files changed, 2796 insertions(+), 1358 deletions(-) delete mode 100644 src/Microsoft.AspNetCore.JsonPatch/Helpers/ActualPropertyPathResult.cs delete mode 100644 src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpandoObjectDictionaryExtensions.cs delete mode 100644 src/Microsoft.AspNetCore.JsonPatch/Helpers/ObjectTreeAnalyisResult.cs delete mode 100644 src/Microsoft.AspNetCore.JsonPatch/Helpers/RemovedPropertyTypeResult.cs rename src/Microsoft.AspNetCore.JsonPatch/{Helpers => Internal}/ConversionResult.cs (64%) create mode 100644 src/Microsoft.AspNetCore.JsonPatch/Internal/ConversionResultProvider.cs create mode 100644 src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapter.cs create mode 100644 src/Microsoft.AspNetCore.JsonPatch/Internal/ExpandoObjectAdapter.cs create mode 100644 src/Microsoft.AspNetCore.JsonPatch/Internal/ExpandoObjectDictionaryExtensions.cs rename src/Microsoft.AspNetCore.JsonPatch/{Helpers => Internal}/ExpressionHelpers.cs (95%) create mode 100644 src/Microsoft.AspNetCore.JsonPatch/Internal/IAdapter.cs create mode 100644 src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs create mode 100644 src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs create mode 100644 src/Microsoft.AspNetCore.JsonPatch/Internal/ParsedPath.cs rename src/Microsoft.AspNetCore.JsonPatch/{Helpers => Internal}/PathHelpers.cs (95%) create mode 100644 src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs~RF1ad82e13.TMP create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs~RF1ae034c3.TMP diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs index b70ff697c3..ee01fbeba7 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs @@ -1,14 +1,11 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; using Microsoft.AspNetCore.JsonPatch.Exceptions; using Microsoft.AspNetCore.JsonPatch.Helpers; +using Microsoft.AspNetCore.JsonPatch.Internal; using Microsoft.AspNetCore.JsonPatch.Operations; -using Newtonsoft.Json; using Newtonsoft.Json.Serialization; namespace Microsoft.AspNetCore.JsonPatch.Adapters @@ -127,7 +124,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters string path, object value, object objectToApplyTo, - Operation operationToReport) + Operation operation) { if (path == null) { @@ -139,228 +136,30 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters throw new ArgumentNullException(nameof(objectToApplyTo)); } - if (operationToReport == null) + if (operation == null) { - throw new ArgumentNullException(nameof(operationToReport)); + throw new ArgumentNullException(nameof(operation)); } - // first up: if the path ends in a numeric value, we're inserting in a list and - // that value represents the position; if the path ends in "-", we're appending - // to the list. + var parsedPath = new ParsedPath(path); + var visitor = new ObjectVisitor(parsedPath, ContractResolver); - // get path result - var pathResult = GetActualPropertyPath( - path, - objectToApplyTo, - operationToReport); - if (pathResult == null) + IAdapter adapter; + var target = objectToApplyTo; + string errorMessage; + if (!visitor.TryVisit(ref target, out adapter, out errorMessage)) { + var error = CreatePathNotFoundError(objectToApplyTo, path, operation, errorMessage); + ReportError(error); return; } - var appendList = pathResult.ExecuteAtEnd; - var positionAsInteger = pathResult.NumericEnd; - var actualPathToProperty = pathResult.PathToProperty; - - var treeAnalysisResult = new ObjectTreeAnalysisResult( - objectToApplyTo, - actualPathToProperty, - ContractResolver); - - if (!treeAnalysisResult.IsValidPathForAdd) + if (!adapter.TryAdd(target, parsedPath.LastSegment, ContractResolver, value, out errorMessage)) { - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatPropertyCannotBeAdded(path))); + var error = CreateOperationFailedError(objectToApplyTo, path, operation, errorMessage); + ReportError(error); return; } - - if (treeAnalysisResult.UseDynamicLogic) - { - var container = treeAnalysisResult.Container; - if (container.ContainsCaseInsensitiveKey(treeAnalysisResult.PropertyPathInParent)) - { - // Existing property. - // If it's not an array, we need to check if the value fits the property type - // - // If it's an array, we need to check if the value fits in that array type, - // and add it at the correct position (if allowed). - if (appendList || positionAsInteger > -1) - { - // get the actual type - var propertyValue = container.GetValueForCaseInsensitiveKey(treeAnalysisResult.PropertyPathInParent); - var typeOfPathProperty = propertyValue.GetType(); - - if (!IsNonStringArray(typeOfPathProperty)) - { - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatInvalidIndexForArrayProperty(operationToReport.op, path))); - return; - } - - // now, get the generic type of the enumerable - var genericTypeOfArray = GetIListType(typeOfPathProperty); - var conversionResult = ConvertToActualType(genericTypeOfArray, value); - if (!conversionResult.CanBeConverted) - { - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatInvalidValueForProperty(value, path))); - return; - } - - // get value (it can be cast, we just checked that) - var array = treeAnalysisResult.Container.GetValueForCaseInsensitiveKey( - treeAnalysisResult.PropertyPathInParent) as IList; - - if (appendList) - { - array.Add(conversionResult.ConvertedInstance); - treeAnalysisResult.Container.SetValueForCaseInsensitiveKey( - treeAnalysisResult.PropertyPathInParent, array); - } - else - { - // specified index must not be greater than - // the amount of items in the array - if (positionAsInteger > array.Count) - { - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatInvalidIndexForArrayProperty( - operationToReport.op, - path))); - return; - } - - array.Insert(positionAsInteger, conversionResult.ConvertedInstance); - treeAnalysisResult.Container.SetValueForCaseInsensitiveKey( - treeAnalysisResult.PropertyPathInParent, array); - } - } - else - { - // get the actual type - var typeOfPathProperty = treeAnalysisResult.Container - .GetValueForCaseInsensitiveKey(treeAnalysisResult.PropertyPathInParent).GetType(); - - // can the value be converted to the actual type? - var conversionResult = ConvertToActualType(typeOfPathProperty, value); - if (conversionResult.CanBeConverted) - { - treeAnalysisResult.Container.SetValueForCaseInsensitiveKey( - treeAnalysisResult.PropertyPathInParent, - conversionResult.ConvertedInstance); - } - else - { - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatInvalidValueForProperty(conversionResult.ConvertedInstance, path))); - return; - } - } - } - else - { - // New property - add it. - treeAnalysisResult.Container.Add(treeAnalysisResult.PropertyPathInParent, value); - } - } - else - { - // If it's an array, add to that array. If it's not, we replace. - - // is the path an array (but not a string (= char[]))? In this case, - // the path must end with "/position" or "/-", which we already determined before. - - var patchProperty = treeAnalysisResult.JsonPatchProperty; - - if (appendList || positionAsInteger > -1) - { - if (!IsNonStringArray(patchProperty.Property.PropertyType)) - { - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatInvalidIndexForArrayProperty(operationToReport.op, path))); - return; - } - - // now, get the generic type of the IList<> from Property type. - var genericTypeOfArray = GetIListType(patchProperty.Property.PropertyType); - var conversionResult = ConvertToActualType(genericTypeOfArray, value); - if (!conversionResult.CanBeConverted) - { - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatInvalidValueForProperty(conversionResult.ConvertedInstance, path))); - return; - } - - if (!patchProperty.Property.Readable) - { - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatCannotReadProperty(path))); - return; - } - - var array = (IList)patchProperty.Property.ValueProvider.GetValue(patchProperty.Parent); - if (appendList) - { - array.Add(conversionResult.ConvertedInstance); - } - else if (positionAsInteger <= array.Count) - { - array.Insert(positionAsInteger, conversionResult.ConvertedInstance); - } - else - { - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatInvalidIndexForArrayProperty(operationToReport.op, path))); - return; - } - } - else - { - var conversionResultTuple = ConvertToActualType( - patchProperty.Property.PropertyType, - value); - - if (!conversionResultTuple.CanBeConverted) - { - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatInvalidValueForProperty(value, path))); - return; - } - - if (!patchProperty.Property.Writable) - { - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatCannotUpdateProperty(path))); - return; - } - - patchProperty.Property.ValueProvider.SetValue( - patchProperty.Parent, - conversionResultTuple.ConvertedInstance); - } - } } /// @@ -398,30 +197,19 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters throw new ArgumentNullException(nameof(objectToApplyTo)); } - var valueAtFromLocationResult = GetValueAtLocation(operation.from, objectToApplyTo, operation); - - if (valueAtFromLocationResult.HasError) + object propertyValue; + // Get value at 'from' location and add that value to the 'path' location + if (TryGetValue(operation.from, objectToApplyTo, operation, out propertyValue)) { - // Error has already been logged in GetValueAtLocation. We - // must return, because remove / add should not be allowed to continue - return; + // remove that value + Remove(operation.from, objectToApplyTo, operation); + + // add that value to the path location + Add(operation.path, + propertyValue, + objectToApplyTo, + operation); } - - // remove that value - var removeResult = Remove(operation.from, objectToApplyTo, operation); - - if (removeResult.HasError) - { - // Return => error has already been logged in remove method. We must - // return, because add should not be allowed to continue - return; - } - - // add that value to the path location - Add(operation.path, - valueAtFromLocationResult.PropertyValue, - objectToApplyTo, - operation); } /// @@ -453,240 +241,33 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters Remove(operation.path, objectToApplyTo, operation); } - /// /// Remove is used by various operations (eg: remove, move, ...), yet through different operations; /// This method allows code reuse yet reporting the correct operation on error. The return value /// contains the type of the item that has been removed (and a bool possibly signifying an error) - /// This can be used by other methods, like replace, to ensure that we can pass in the correctly + /// This can be used by other methods, like replace, to ensure that we can pass in the correctly /// typed value to whatever method follows. /// - private RemovedPropertyTypeResult Remove(string path, object objectToApplyTo, Operation operationToReport) + private void Remove(string path, object objectToApplyTo, Operation operationToReport) { - // get path result - var pathResult = GetActualPropertyPath( - path, - objectToApplyTo, - operationToReport); + var parsedPath = new ParsedPath(path); + var visitor = new ObjectVisitor(parsedPath, ContractResolver); - if (pathResult == null) + IAdapter adapter; + var target = objectToApplyTo; + string errorMessage; + if (!visitor.TryVisit(ref target, out adapter, out errorMessage)) { - return new RemovedPropertyTypeResult(null, true); + var error = CreatePathNotFoundError(objectToApplyTo, path, operationToReport, errorMessage); + ReportError(error); + return; } - var removeFromList = pathResult.ExecuteAtEnd; - var positionAsInteger = pathResult.NumericEnd; - var actualPathToProperty = pathResult.PathToProperty; - - var treeAnalysisResult = new ObjectTreeAnalysisResult( - objectToApplyTo, - actualPathToProperty, - ContractResolver); - - if (!treeAnalysisResult.IsValidPathForRemove) + if (!adapter.TryRemove(target, parsedPath.LastSegment, ContractResolver, out errorMessage)) { - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatPropertyCannotBeRemoved(path))); - return new RemovedPropertyTypeResult(null, true); - } - - if (treeAnalysisResult.UseDynamicLogic) - { - // if it's not an array, we can remove the property from - // the dictionary. If it's an array, we need to check the position first. - if (removeFromList || positionAsInteger > -1) - { - var propertyValue = treeAnalysisResult.Container - .GetValueForCaseInsensitiveKey(treeAnalysisResult.PropertyPathInParent); - - // we cannot continue when the value is null, because to be able to - // continue we need to be able to check if the array is a non-string array - if (propertyValue == null) - { - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatCannotDeterminePropertyType(path))); - return new RemovedPropertyTypeResult(null, true); - } - - var typeOfPathProperty = propertyValue.GetType(); - - if (!IsNonStringArray(typeOfPathProperty)) - { - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatInvalidIndexForArrayProperty(operationToReport.op, path))); - return new RemovedPropertyTypeResult(null, true); - } - - // now, get the generic type of the enumerable (we'll return this type) - var genericTypeOfArray = GetIListType(typeOfPathProperty); - - // get the array - var array = (IList)treeAnalysisResult.Container.GetValueForCaseInsensitiveKey( - treeAnalysisResult.PropertyPathInParent); - - if (array.Count == 0) - { - // if the array is empty, we should throw an error - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatInvalidIndexForArrayProperty( - operationToReport.op, - path))); - return new RemovedPropertyTypeResult(null, true); - } - - if (removeFromList) - { - array.RemoveAt(array.Count - 1); - treeAnalysisResult.Container.SetValueForCaseInsensitiveKey( - treeAnalysisResult.PropertyPathInParent, array); - - // return the type of the value that has been removed. - return new RemovedPropertyTypeResult(genericTypeOfArray, false); - } - else - { - if (positionAsInteger >= array.Count) - { - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatInvalidIndexForArrayProperty( - operationToReport.op, - path))); - return new RemovedPropertyTypeResult(null, true); - } - - array.RemoveAt(positionAsInteger); - treeAnalysisResult.Container.SetValueForCaseInsensitiveKey( - treeAnalysisResult.PropertyPathInParent, array); - - // return the type of the value that has been removed. - return new RemovedPropertyTypeResult(genericTypeOfArray, false); - } - } - else - { - // get the property - var getResult = treeAnalysisResult.Container.GetValueForCaseInsensitiveKey( - treeAnalysisResult.PropertyPathInParent); - - // remove the property - treeAnalysisResult.Container.RemoveValueForCaseInsensitiveKey( - treeAnalysisResult.PropertyPathInParent); - - // value is not null, we can determine the type - if (getResult != null) - { - var actualType = getResult.GetType(); - return new RemovedPropertyTypeResult(actualType, false); - } - else - { - return new RemovedPropertyTypeResult(null, false); - } - } - } - else - { - // not dynamic - var patchProperty = treeAnalysisResult.JsonPatchProperty; - - if (removeFromList || positionAsInteger > -1) - { - if (!IsNonStringArray(patchProperty.Property.PropertyType)) - { - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatInvalidIndexForArrayProperty(operationToReport.op, path))); - return new RemovedPropertyTypeResult(null, true); - } - - // now, get the generic type of the IList<> from Property type. - var genericTypeOfArray = GetIListType(patchProperty.Property.PropertyType); - - if (!patchProperty.Property.Readable) - { - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatCannotReadProperty(path))); - return new RemovedPropertyTypeResult(null, true); - } - - var array = (IList)patchProperty.Property.ValueProvider - .GetValue(patchProperty.Parent); - - if (array.Count == 0) - { - // if the array is empty, we should throw an error - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatInvalidIndexForArrayProperty( - operationToReport.op, - path))); - return new RemovedPropertyTypeResult(null, true); - } - - if (removeFromList) - { - array.RemoveAt(array.Count - 1); - - // return the type of the value that has been removed - return new RemovedPropertyTypeResult(genericTypeOfArray, false); - } - else - { - if (positionAsInteger >= array.Count) - { - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatInvalidIndexForArrayProperty( - operationToReport.op, - path))); - return new RemovedPropertyTypeResult(null, true); - } - - array.RemoveAt(positionAsInteger); - - // return the type of the value that has been removed - return new RemovedPropertyTypeResult(genericTypeOfArray, false); - } - } - else - { - if (!patchProperty.Property.Writable) - { - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatCannotUpdateProperty(path))); - return new RemovedPropertyTypeResult(null, true); - } - - // setting the value to "null" will use the default value in case of value types, and - // null in case of reference types - object value = null; - - if (patchProperty.Property.PropertyType.GetTypeInfo().IsValueType - && Nullable.GetUnderlyingType(patchProperty.Property.PropertyType) == null) - { - value = Activator.CreateInstance(patchProperty.Property.PropertyType); - } - - patchProperty.Property.ValueProvider.SetValue(patchProperty.Parent, value); - return new RemovedPropertyTypeResult(patchProperty.Property.PropertyType, false); - } + var error = CreateOperationFailedError(objectToApplyTo, path, operationToReport, errorMessage); + ReportError(error); + return; } } @@ -722,37 +303,25 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters throw new ArgumentNullException(nameof(objectToApplyTo)); } - var removeResult = Remove(operation.path, objectToApplyTo, operation); + var parsedPath = new ParsedPath(operation.path); + var visitor = new ObjectVisitor(parsedPath, ContractResolver); - if (removeResult.HasError) + IAdapter adapter; + var target = objectToApplyTo; + string errorMessage; + if (!visitor.TryVisit(ref target, out adapter, out errorMessage)) { - // return => error has already been logged in remove method + var error = CreatePathNotFoundError(objectToApplyTo, operation.path, operation, errorMessage); + ReportError(error); return; } - if (!removeResult.HasError && removeResult.ActualType == null) + if (!adapter.TryReplace(target, parsedPath.LastSegment, ContractResolver, operation.value, out errorMessage)) { - // the remove operation completed succesfully, but we could not determine the type. - LogError(new JsonPatchError( - objectToApplyTo, - operation, - Resources.FormatCannotDeterminePropertyType(operation.from))); + var error = CreateOperationFailedError(objectToApplyTo, operation.path, operation, errorMessage); + ReportError(error); return; } - - var conversionResult = ConvertToActualType(removeResult.ActualType, operation.value); - - if (!conversionResult.CanBeConverted) - { - // invalid value for path - LogError(new JsonPatchError( - objectToApplyTo, - operation, - Resources.FormatInvalidValueForProperty(operation.value, operation.path))); - return; - } - - Add(operation.path, conversionResult.ConvertedInstance, objectToApplyTo, operation); } /// @@ -789,36 +358,26 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters throw new ArgumentNullException(nameof(objectToApplyTo)); } - // get value at from location and add that value to the path location - var valueAtFromLocationResult = GetValueAtLocation(operation.from, objectToApplyTo, operation); - - if (valueAtFromLocationResult.HasError) + object propertyValue; + // Get value at 'from' location and add that value to the 'path' location + if (TryGetValue(operation.from, objectToApplyTo, operation, out propertyValue)) { - // Return, error has already been logged in GetValueAtLocation - return; + Add(operation.path, + propertyValue, + objectToApplyTo, + operation); } - - Add(operation.path, - valueAtFromLocationResult.PropertyValue, - objectToApplyTo, - operation); } - /// - /// Method is used by Copy and Move to avoid duplicate code - /// - /// Location where value should be - /// Object to inspect for the desired value - /// Operation to report in case of an error - /// GetValueResult containing value and a bool signifying a possible error - private GetValueResult GetValueAtLocation( - string location, + private bool TryGetValue( + string fromLocation, object objectToGetValueFrom, - Operation operationToReport) + Operation operation, + out object propertyValue) { - if (location == null) + if (fromLocation == null) { - throw new ArgumentNullException(nameof(location)); + throw new ArgumentNullException(nameof(fromLocation)); } if (objectToGetValueFrom == null) @@ -826,280 +385,62 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters throw new ArgumentNullException(nameof(objectToGetValueFrom)); } - if (operationToReport == null) + if (operation == null) { - throw new ArgumentNullException(nameof(operationToReport)); + throw new ArgumentNullException(nameof(operation)); } - // get path result - var pathResult = GetActualPropertyPath( - location, - objectToGetValueFrom, - operationToReport); + propertyValue = null; - if (pathResult == null) + var parsedPath = new ParsedPath(fromLocation); + var visitor = new ObjectVisitor(parsedPath, ContractResolver); + + IAdapter adapter; + var target = objectToGetValueFrom; + string errorMessage; + if (!visitor.TryVisit(ref target, out adapter, out errorMessage)) { - return new GetValueResult(null, true); + var error = CreatePathNotFoundError(objectToGetValueFrom, fromLocation, operation, errorMessage); + ReportError(error); + return false; } - var getAtEndOfList = pathResult.ExecuteAtEnd; - var positionAsInteger = pathResult.NumericEnd; - var actualPathToProperty = pathResult.PathToProperty; - - var treeAnalysisResult = new ObjectTreeAnalysisResult( - objectToGetValueFrom, - actualPathToProperty, - ContractResolver); - - if (treeAnalysisResult.UseDynamicLogic) + if (!adapter.TryGet(target, parsedPath.LastSegment, ContractResolver, out propertyValue, out errorMessage)) { - // if it's not an array, we can remove the property from - // the dictionary. If it's an array, we need to check the position first. - if (getAtEndOfList || positionAsInteger > -1) - { - var propertyValue = treeAnalysisResult.Container - .GetValueForCaseInsensitiveKey(treeAnalysisResult.PropertyPathInParent); - - // we cannot continue when the value is null, because to be able to - // continue we need to be able to check if the array is a non-string array - if (propertyValue == null) - { - LogError(new JsonPatchError( - objectToGetValueFrom, - operationToReport, - Resources.FormatCannotDeterminePropertyType(location))); - return new GetValueResult(null, true); - } - - var typeOfPathProperty = propertyValue.GetType(); - - if (!IsNonStringArray(typeOfPathProperty)) - { - LogError(new JsonPatchError( - objectToGetValueFrom, - operationToReport, - Resources.FormatInvalidIndexForArrayProperty(operationToReport.op, location))); - return new GetValueResult(null, true); - } - - // get the array - var array = (IList)treeAnalysisResult.Container.GetValueForCaseInsensitiveKey( - treeAnalysisResult.PropertyPathInParent); - - if (positionAsInteger >= array.Count) - { - LogError(new JsonPatchError( - objectToGetValueFrom, - operationToReport, - Resources.FormatInvalidIndexForArrayProperty( - operationToReport.op, - location))); - return new GetValueResult(null, true); - } - - if (getAtEndOfList) - { - return new GetValueResult(array[array.Count - 1], false); - } - else - { - return new GetValueResult(array[positionAsInteger], false); - } - } - else - { - // get the property - var propertyValueAtLocation = treeAnalysisResult.Container.GetValueForCaseInsensitiveKey( - treeAnalysisResult.PropertyPathInParent); - - return new GetValueResult(propertyValueAtLocation, false); - } + var error = CreateOperationFailedError(objectToGetValueFrom, fromLocation, operation, errorMessage); + ReportError(error); + return false; } - else - { - // not dynamic - var patchProperty = treeAnalysisResult.JsonPatchProperty; - if (getAtEndOfList || positionAsInteger > -1) - { - if (!IsNonStringArray(patchProperty.Property.PropertyType)) - { - LogError(new JsonPatchError( - objectToGetValueFrom, - operationToReport, - Resources.FormatInvalidIndexForArrayProperty(operationToReport.op, location))); - return new GetValueResult(null, true); - } - - if (!patchProperty.Property.Readable) - { - LogError(new JsonPatchError( - objectToGetValueFrom, - operationToReport, - Resources.FormatCannotReadProperty(location))); - return new GetValueResult(null, true); - } - - var array = (IList)patchProperty.Property.ValueProvider - .GetValue(patchProperty.Parent); - - if (positionAsInteger >= array.Count) - { - LogError(new JsonPatchError( - objectToGetValueFrom, - operationToReport, - Resources.FormatInvalidIndexForArrayProperty( - operationToReport.op, - location))); - return new GetValueResult(null, true); - } - - if (getAtEndOfList) - { - return new GetValueResult(array[array.Count - 1], false); - } - else - { - return new GetValueResult(array[positionAsInteger], false); - } - } - else - { - if (!patchProperty.Property.Readable) - { - LogError(new JsonPatchError( - objectToGetValueFrom, - operationToReport, - Resources.FormatCannotReadProperty( - location))); - return new GetValueResult(null, true); - } - - var propertyValueAtLocation = patchProperty.Property.ValueProvider - .GetValue(patchProperty.Parent); - - return new GetValueResult(propertyValueAtLocation, false); - } - } + return true; } - private bool IsNonStringArray(Type type) - { - if (GetIListType(type) != null) - { - return true; - } - - return (!(type == typeof(string)) && typeof(IList).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo())); - } - - private void LogError(JsonPatchError jsonPatchError) + private void ReportError(JsonPatchError error) { if (LogErrorAction != null) { - LogErrorAction(jsonPatchError); + LogErrorAction(error); } else { - throw new JsonPatchException(jsonPatchError); + throw new JsonPatchException(error); } } - private ConversionResult ConvertToActualType(Type propertyType, object value) + private JsonPatchError CreateOperationFailedError(object target, string path, Operation operation, string errorMessage) { - try - { - var o = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(value), propertyType); - - return new ConversionResult(true, o); - } - catch (Exception) - { - return new ConversionResult(false, null); - } + return new JsonPatchError( + target, + operation, + errorMessage ?? Resources.FormatCannotPerformOperation(operation.op, path)); } - private Type GetIListType(Type type) + private JsonPatchError CreatePathNotFoundError(object target, string path, Operation operation, string errorMessage) { - if (IsGenericListType(type)) - { - return type.GetTypeInfo().GenericTypeArguments[0]; - } - - foreach (Type interfaceType in type.GetTypeInfo().ImplementedInterfaces) - { - if (IsGenericListType(interfaceType)) - { - return interfaceType.GetTypeInfo().GenericTypeArguments[0]; - } - } - - return null; - } - - private bool IsGenericListType(Type type) - { - if (type.GetTypeInfo().IsGenericType && - type.GetGenericTypeDefinition() == typeof(IList<>)) - { - return true; - } - - return false; - } - - private ActualPropertyPathResult GetActualPropertyPath( - string propertyPath, - object objectToApplyTo, - Operation operationToReport) - { - if (propertyPath == null) - { - throw new ArgumentNullException(nameof(propertyPath)); - } - - if (objectToApplyTo == null) - { - throw new ArgumentNullException(nameof(objectToApplyTo)); - } - - if (operationToReport == null) - { - throw new ArgumentNullException(nameof(operationToReport)); - } - - if (propertyPath.EndsWith("/-")) - { - return new ActualPropertyPathResult(-1, propertyPath.Substring(0, propertyPath.Length - 2), true); - } - else - { - var possibleIndex = propertyPath.Substring(propertyPath.LastIndexOf("/") + 1); - int castedIndex = -1; - if (int.TryParse(possibleIndex, out castedIndex)) - { - // has numeric end. - if (castedIndex > -1) - { - var pathToProperty = propertyPath.Substring( - 0, - propertyPath.LastIndexOf('/' + castedIndex.ToString())); - - return new ActualPropertyPathResult(castedIndex, pathToProperty, false); - } - else - { - // negative position - invalid path - LogError(new JsonPatchError( - objectToApplyTo, - operationToReport, - Resources.FormatNegativeIndexForArrayProperty(operationToReport.op, propertyPath))); - return null; - } - } - - return new ActualPropertyPathResult(-1, propertyPath, false); - } + return new JsonPatchError( + target, + operation, + errorMessage ?? Resources.FormatTargetLocationNotFound(operation.op, path)); } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ActualPropertyPathResult.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ActualPropertyPathResult.cs deleted file mode 100644 index 1967bf6d90..0000000000 --- a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ActualPropertyPathResult.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.JsonPatch.Helpers -{ - internal class ActualPropertyPathResult - { - public int NumericEnd { get; private set; } - public string PathToProperty { get; set; } - public bool ExecuteAtEnd { get; set; } - - public ActualPropertyPathResult( - int numericEnd, - string pathToProperty, - bool executeAtEnd) - { - NumericEnd = numericEnd; - PathToProperty = pathToProperty; - ExecuteAtEnd = executeAtEnd; - } - } -} diff --git a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpandoObjectDictionaryExtensions.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpandoObjectDictionaryExtensions.cs deleted file mode 100644 index aa9fa2158b..0000000000 --- a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpandoObjectDictionaryExtensions.cs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; - -namespace Microsoft.AspNetCore.JsonPatch.Helpers -{ - // Helper methods to allow case-insensitive key search - internal static class ExpandoObjectDictionaryExtensions - { - internal static void SetValueForCaseInsensitiveKey( - this IDictionary propertyDictionary, - string key, - object value) - { - foreach (KeyValuePair kvp in propertyDictionary) - { - if (string.Equals(kvp.Key, key, StringComparison.OrdinalIgnoreCase)) - { - propertyDictionary[kvp.Key] = value; - break; - } - } - } - - internal static void RemoveValueForCaseInsensitiveKey( - this IDictionary propertyDictionary, - string key) - { - string realKey = null; - foreach (KeyValuePair kvp in propertyDictionary) - { - if (string.Equals(kvp.Key, key, StringComparison.OrdinalIgnoreCase)) - { - realKey = kvp.Key; - break; - } - } - - if (realKey != null) - { - propertyDictionary.Remove(realKey); - } - } - - internal static object GetValueForCaseInsensitiveKey( - this IDictionary propertyDictionary, - string key) - { - foreach (KeyValuePair kvp in propertyDictionary) - { - if (string.Equals(kvp.Key, key, StringComparison.OrdinalIgnoreCase)) - { - return kvp.Value; - } - } - - throw new ArgumentException(Resources.FormatDictionaryKeyNotFound(key)); - } - - internal static bool ContainsCaseInsensitiveKey( - this IDictionary propertyDictionary, - string key) - { - foreach (KeyValuePair kvp in propertyDictionary) - { - if (string.Equals(kvp.Key, key, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - } - - return false; - } - } -} diff --git a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ObjectTreeAnalyisResult.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/ObjectTreeAnalyisResult.cs deleted file mode 100644 index 782859ad5f..0000000000 --- a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ObjectTreeAnalyisResult.cs +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using Newtonsoft.Json.Serialization; - -namespace Microsoft.AspNetCore.JsonPatch.Helpers -{ - internal class ObjectTreeAnalysisResult - { - // either the property is part of the container dictionary, - // or we have a direct reference to a JsonPatchProperty instance - - public bool UseDynamicLogic { get; private set; } - - public bool IsValidPathForAdd { get; private set; } - - public bool IsValidPathForRemove { get; private set; } - - public IDictionary Container { get; private set; } - - public string PropertyPathInParent { get; private set; } - - public JsonPatchProperty JsonPatchProperty { get; private set; } - - public ObjectTreeAnalysisResult( - object objectToSearch, - string propertyPath, - IContractResolver contractResolver) - { - // construct the analysis result. - - // split the propertypath, and if necessary, remove the first - // empty item (that's the case when it starts with a "/") - var propertyPathTree = propertyPath.Split( - new char[] { '/' }, - StringSplitOptions.RemoveEmptyEntries); - - // we've now got a split up property tree "base/property/otherproperty/..." - int lastPosition = 0; - object targetObject = objectToSearch; - for (int i = 0; i < propertyPathTree.Length; i++) - { - lastPosition = i; - - // if the current target object is an ExpandoObject (IDictionary), - // we cannot use the ContractResolver. - var dictionary = targetObject as IDictionary; - if (dictionary != null) - { - // find the value in the dictionary - if (dictionary.ContainsCaseInsensitiveKey(propertyPathTree[i])) - { - var possibleNewTargetObject = dictionary.GetValueForCaseInsensitiveKey(propertyPathTree[i]); - - // unless we're at the last item, we should set the targetobject - // to the new object. If we're at the last item, we need to stop - if (i != propertyPathTree.Length - 1) - { - targetObject = possibleNewTargetObject; - } - } - else - { - break; - } - } - else - { - // if the current part of the path is numeric, this means we're trying - // to get the propertyInfo of a specific object in an array. To allow - // for this, the previous value (targetObject) must be an IEnumerable, and - // the position must exist. - - int numericValue = -1; - if (int.TryParse(propertyPathTree[i], out numericValue)) - { - var element = GetElementAtFromObject(targetObject, numericValue); - if (element != null) - { - targetObject = element; - } - else - { - break; - } - } - else - { - var jsonContract = (JsonObjectContract)contractResolver.ResolveContract(targetObject.GetType()); - - // does the property exist? - var attemptedProperty = jsonContract - .Properties - .FirstOrDefault(p => string.Equals(p.PropertyName, propertyPathTree[i], StringComparison.OrdinalIgnoreCase)); - - if (attemptedProperty != null) - { - // unless we're at the last item, we should continue searching. - // If we're at the last item, we need to stop - if ((i != propertyPathTree.Length - 1)) - { - targetObject = attemptedProperty.ValueProvider.GetValue(targetObject); - } - } - else - { - // property cannot be found, and we're not working with dynamics. - // Stop, and return invalid path. - break; - } - } - } - } - - if (propertyPathTree.Length - lastPosition != 1) - { - IsValidPathForAdd = false; - IsValidPathForRemove = false; - return; - } - - // two things can happen now. The targetproperty can be an IDictionary - in that - // case, it's valid for add if there's 1 item left in the propertyPathTree. - // - // it can also be a property info. In that case, if there's nothing left in the path - // tree we're at the end, if there's one left we can try and set that. - if (targetObject is IDictionary) - { - UseDynamicLogic = true; - - Container = (IDictionary)targetObject; - IsValidPathForAdd = true; - PropertyPathInParent = propertyPathTree[propertyPathTree.Length - 1]; - - // to be able to remove this property, it must exist - IsValidPathForRemove = Container.ContainsCaseInsensitiveKey(PropertyPathInParent); - } - else if (targetObject is IList) - { - UseDynamicLogic = false; - - int index; - if (!Int32.TryParse(propertyPathTree[propertyPathTree.Length - 1], out index)) - { - // We only support indexing into a list - IsValidPathForAdd = false; - IsValidPathForRemove = false; - return; - } - - IsValidPathForAdd = true; - IsValidPathForRemove = ((IList)targetObject).Count > index; - PropertyPathInParent = propertyPathTree[propertyPathTree.Length - 1]; - } - else - { - UseDynamicLogic = false; - - var property = propertyPathTree[propertyPathTree.Length - 1]; - var jsonContract = (JsonObjectContract)contractResolver.ResolveContract(targetObject.GetType()); - var attemptedProperty = jsonContract - .Properties - .FirstOrDefault(p => string.Equals(p.PropertyName, property, StringComparison.OrdinalIgnoreCase)); - - if (attemptedProperty == null) - { - IsValidPathForAdd = false; - IsValidPathForRemove = false; - } - else - { - IsValidPathForAdd = true; - IsValidPathForRemove = true; - JsonPatchProperty = new JsonPatchProperty(attemptedProperty, targetObject); - PropertyPathInParent = property; - } - } - } - - private object GetElementAtFromObject(object targetObject, int numericValue) - { - if (numericValue > -1) - { - // Check if the targetobject is an IEnumerable, - // and if the position is valid. - if (targetObject is IEnumerable) - { - var indexable = ((IEnumerable)targetObject).Cast(); - - if (indexable.Count() >= numericValue) - { - return indexable.ElementAt(numericValue); - } - else { return null; } - } - else { return null; } - } - else - { - return null; - } - } - - } -} diff --git a/src/Microsoft.AspNetCore.JsonPatch/Helpers/RemovedPropertyTypeResult.cs b/src/Microsoft.AspNetCore.JsonPatch/Helpers/RemovedPropertyTypeResult.cs deleted file mode 100644 index c548f55c6e..0000000000 --- a/src/Microsoft.AspNetCore.JsonPatch/Helpers/RemovedPropertyTypeResult.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; - -namespace Microsoft.AspNetCore.JsonPatch.Helpers -{ - /// - /// Return value for Remove operation. The combination tells us what to do next (if this operation - /// is called from inside another operation, eg: Replace, Copy. - /// - /// Possible combo: - /// - ActualType contains type: operation succesfully completed, can continue when called from inside - /// another operation - /// - ActualType null and HasError true: operation not completed succesfully, should not be allowed to continue - /// - ActualType null and HasError false: operation completed succesfully, but we should not be allowed to - /// continue when called from inside another method as we could not verify the type of the removed property. - /// This happens when the value of an item in an ExpandoObject dictionary is null. - /// - internal class RemovedPropertyTypeResult - { - /// - /// The type of the removed property (value) - /// - public Type ActualType { get; private set; } - - /// - /// HasError: true when an error occurred, the operation didn't complete succesfully - /// - public bool HasError { get; set; } - - public RemovedPropertyTypeResult(Type actualType, bool hasError) - { - ActualType = actualType; - HasError = hasError; - } - } -} diff --git a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ConversionResult.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ConversionResult.cs similarity index 64% rename from src/Microsoft.AspNetCore.JsonPatch/Helpers/ConversionResult.cs rename to src/Microsoft.AspNetCore.JsonPatch/Internal/ConversionResult.cs index 00a7513d44..77181eb18d 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ConversionResult.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ConversionResult.cs @@ -1,17 +1,17 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.JsonPatch.Helpers +namespace Microsoft.AspNetCore.JsonPatch.Internal { - internal class ConversionResult + public class ConversionResult { - public bool CanBeConverted { get; private set; } - public object ConvertedInstance { get; private set; } - public ConversionResult(bool canBeConverted, object convertedInstance) { CanBeConverted = canBeConverted; ConvertedInstance = convertedInstance; } + + public bool CanBeConverted { get; } + public object ConvertedInstance { get; } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ConversionResultProvider.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ConversionResultProvider.cs new file mode 100644 index 0000000000..bdf4122394 --- /dev/null +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ConversionResultProvider.cs @@ -0,0 +1,24 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Newtonsoft.Json; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + public static class ConversionResultProvider + { + public static ConversionResult ConvertTo(object value, Type typeToConvertTo) + { + try + { + var deserialized = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(value), typeToConvertTo); + return new ConversionResult(true, deserialized); + } + catch + { + return new ConversionResult(canBeConverted: false, convertedInstance: null); + } + } + } +} diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapter.cs new file mode 100644 index 0000000000..4c7651e475 --- /dev/null +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapter.cs @@ -0,0 +1,111 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections; +using Newtonsoft.Json.Serialization; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + public class DictionaryAdapter : IAdapter + { + public bool TryAdd( + object target, + string segment, + IContractResolver contractResolver, + object value, + out string errorMessage) + { + var dictionary = (IDictionary)target; + + // As per JsonPatch spec, if a key already exists, adding should replace the existing value + dictionary[segment] = value; + + errorMessage = null; + return true; + } + + public bool TryGet( + object target, + string segment, + IContractResolver contractResolver, + out object value, + out string errorMessage) + { + var dictionary = (IDictionary)target; + + value = dictionary[segment]; + errorMessage = null; + return true; + } + + public bool TryRemove( + object target, + string segment, + IContractResolver contractResolver, + out string errorMessage) + { + var dictionary = (IDictionary)target; + + // As per JsonPatch spec, the target location must exist for remove to be successful + if (!dictionary.Contains(segment)) + { + errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); + return false; + } + + dictionary.Remove(segment); + errorMessage = null; + return true; + } + + public bool TryReplace( + object target, + string segment, + IContractResolver contractResolver, + object value, + out string errorMessage) + { + var dictionary = (IDictionary)target; + + // As per JsonPatch spec, the target location must exist for remove to be successful + if (!dictionary.Contains(segment)) + { + errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); + return false; + } + + dictionary[segment] = value; + errorMessage = null; + return true; + } + + public bool TryTraverse( + object target, + string segment, + IContractResolver contractResolver, + out object nextTarget, + out string errorMessage) + { + var dictionary = target as IDictionary; + if (dictionary == null) + { + nextTarget = null; + errorMessage = null; + return false; + } + + if (dictionary.Contains(segment)) + { + nextTarget = dictionary[segment]; + errorMessage = null; + return true; + } + else + { + nextTarget = null; + errorMessage = null; + return false; + } + } + } +} diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ExpandoObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ExpandoObjectAdapter.cs new file mode 100644 index 0000000000..681b5309e6 --- /dev/null +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ExpandoObjectAdapter.cs @@ -0,0 +1,143 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Dynamic; +using Newtonsoft.Json.Serialization; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + public class ExpandoObjectAdapter : IAdapter + { + public bool TryAdd( + object target, + string segment, + IContractResolver contractResolver, + object value, + out string errorMessage) + { + var dictionary = (IDictionary)target; + + var key = dictionary.GetKeyUsingCaseInsensitiveSearch(segment); + + // As per JsonPatch spec, if a key already exists, adding should replace the existing value + dictionary[key] = ConvertValue(dictionary, key, value); + + errorMessage = null; + return true; + } + + public bool TryGet( + object target, + string segment, + IContractResolver contractResolver, + out object value, + out string errorMessage) + { + var dictionary = (IDictionary)target; + + var key = dictionary.GetKeyUsingCaseInsensitiveSearch(segment); + value = dictionary[key]; + + errorMessage = null; + return true; + } + + public bool TryRemove( + object target, + string segment, + IContractResolver contractResolver, + out string errorMessage) + { + var dictionary = (IDictionary)target; + + var key = dictionary.GetKeyUsingCaseInsensitiveSearch(segment); + + // As per JsonPatch spec, the target location must exist for remove to be successful + if (!dictionary.ContainsKey(key)) + { + errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); + return false; + } + + dictionary.Remove(key); + + errorMessage = null; + return true; + } + + public bool TryReplace( + object target, + string segment, + IContractResolver contractResolver, + object value, + out string errorMessage) + { + var dictionary = (IDictionary)target; + + var key = dictionary.GetKeyUsingCaseInsensitiveSearch(segment); + + // As per JsonPatch spec, the target location must exist for remove to be successful + if (!dictionary.ContainsKey(key)) + { + errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); + return false; + } + + dictionary[key] = ConvertValue(dictionary, key, value); + + errorMessage = null; + return true; + } + + public bool TryTraverse( + object target, + string segment, + IContractResolver contractResolver, + out object nextTarget, + out string errorMessage) + { + var expandoObject = target as ExpandoObject; + if (expandoObject == null) + { + errorMessage = null; + nextTarget = null; + return false; + } + + var dictionary = (IDictionary)expandoObject; + + var key = dictionary.GetKeyUsingCaseInsensitiveSearch(segment); + + if (dictionary.ContainsKey(key)) + { + nextTarget = dictionary[key]; + errorMessage = null; + return true; + } + else + { + nextTarget = null; + errorMessage = null; + return false; + } + } + + private object ConvertValue(IDictionary dictionary, string key, object newValue) + { + object existingValue = null; + if (dictionary.TryGetValue(key, out existingValue)) + { + if (existingValue != null) + { + var conversionResult = ConversionResultProvider.ConvertTo(newValue, existingValue.GetType()); + if (conversionResult.CanBeConverted) + { + return conversionResult.ConvertedInstance; + } + } + } + return newValue; + } + } +} diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ExpandoObjectDictionaryExtensions.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ExpandoObjectDictionaryExtensions.cs new file mode 100644 index 0000000000..8bb60dd2a7 --- /dev/null +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ExpandoObjectDictionaryExtensions.cs @@ -0,0 +1,26 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + // Helper methods to allow case-insensitive key search + public static class ExpandoObjectDictionaryExtensions + { + internal static string GetKeyUsingCaseInsensitiveSearch( + this IDictionary propertyDictionary, + string key) + { + foreach (var keyInDictionary in propertyDictionary.Keys) + { + if (string.Equals(key, keyInDictionary, StringComparison.OrdinalIgnoreCase)) + { + return keyInDictionary; + } + } + return key; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpressionHelpers.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ExpressionHelpers.cs similarity index 95% rename from src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpressionHelpers.cs rename to src/Microsoft.AspNetCore.JsonPatch/Internal/ExpressionHelpers.cs index d9b516cc0e..c978330e5c 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Helpers/ExpressionHelpers.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ExpressionHelpers.cs @@ -1,16 +1,15 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Newtonsoft.Json; using System; using System.Globalization; -using System.Linq; using System.Linq.Expressions; using System.Reflection; +using Newtonsoft.Json; -namespace Microsoft.AspNetCore.JsonPatch.Helpers +namespace Microsoft.AspNetCore.JsonPatch.Internal { - internal static class ExpressionHelpers + public static class ExpressionHelpers { public static string GetPath(Expression> expr) where TModel : class { @@ -59,7 +58,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Helpers } else { - // Get property name, respecting JsonProperty attribute + // Get property name, respecting JsonProperty attribute return GetPropertyNameFromMemberExpression(memberExpression); } case ExpressionType.Parameter: @@ -73,7 +72,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Helpers private static string GetPropertyNameFromMemberExpression(MemberExpression memberExpression) { // if there's a JsonProperty attribute, we must return the PropertyName - // from the attribute rather than the member name + // from the attribute rather than the member name var jsonPropertyAttribute = memberExpression.Member.GetCustomAttribute( typeof(JsonPropertyAttribute), true); diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/IAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/IAdapter.cs new file mode 100644 index 0000000000..1866b42ed4 --- /dev/null +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/IAdapter.cs @@ -0,0 +1,44 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Newtonsoft.Json.Serialization; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + public interface IAdapter + { + bool TryTraverse( + object target, + string segment, + IContractResolver contractResolver, + out object nextTarget, + out string errorMessage); + + bool TryAdd( + object target, + string segment, + IContractResolver contractResolver, + object value, + out string errorMessage); + + bool TryRemove( + object target, + string segment, + IContractResolver contractResolver, + out string errorMessage); + + bool TryGet( + object target, + string segment, + IContractResolver contractResolver, + out object value, + out string errorMessage); + + bool TryReplace( + object target, + string segment, + IContractResolver contractResolver, + object value, + out string errorMessage); + } +} diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs new file mode 100644 index 0000000000..c3da14fe5a --- /dev/null +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs @@ -0,0 +1,299 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections; +using System.Collections.Generic; +using Microsoft.Extensions.Internal; +using Newtonsoft.Json.Serialization; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + public class ListAdapter : IAdapter + { + public bool TryAdd( + object target, + string segment, + IContractResolver contractResolver, + object value, + out string errorMessage) + { + var list = (IList)target; + + Type typeArgument = null; + if (!TryGetListTypeArgument(list, out typeArgument, out errorMessage)) + { + return false; + } + + PositionInfo positionInfo; + if (!TryGetPositionInfo(list, segment, out positionInfo, out errorMessage)) + { + return false; + } + + object convertedValue = null; + if (!TryConvertValue(value, typeArgument, segment, out convertedValue, out errorMessage)) + { + return false; + } + + if (positionInfo.Type == PositionType.EndOfList) + { + list.Add(convertedValue); + } + else + { + list.Insert(positionInfo.Index, convertedValue); + } + + errorMessage = null; + return true; + } + + public bool TryGet( + object target, + string segment, + IContractResolver contractResolver, + out object value, + out string errorMessage) + { + var list = (IList)target; + + Type typeArgument = null; + if (!TryGetListTypeArgument(list, out typeArgument, out errorMessage)) + { + value = null; + return false; + } + + PositionInfo positionInfo; + if (!TryGetPositionInfo(list, segment, out positionInfo, out errorMessage)) + { + value = null; + return false; + } + + if (positionInfo.Type == PositionType.EndOfList) + { + value = list[list.Count - 1]; + } + else + { + value = list[positionInfo.Index]; + } + + errorMessage = null; + return true; + } + + public bool TryRemove( + object target, + string segment, + IContractResolver contractResolver, + out string errorMessage) + { + var list = (IList)target; + + Type typeArgument = null; + if (!TryGetListTypeArgument(list, out typeArgument, out errorMessage)) + { + return false; + } + + PositionInfo positionInfo; + if (!TryGetPositionInfo(list, segment, out positionInfo, out errorMessage)) + { + return false; + } + + if (positionInfo.Type == PositionType.EndOfList) + { + list.RemoveAt(list.Count - 1); + } + else + { + list.RemoveAt(positionInfo.Index); + } + + errorMessage = null; + return true; + } + + public bool TryReplace( + object target, + string segment, + IContractResolver contractResolver, + object value, + out string errorMessage) + { + var list = (IList)target; + + Type typeArgument = null; + if (!TryGetListTypeArgument(list, out typeArgument, out errorMessage)) + { + return false; + } + + PositionInfo positionInfo; + if (!TryGetPositionInfo(list, segment, out positionInfo, out errorMessage)) + { + return false; + } + + object convertedValue = null; + if (!TryConvertValue(value, typeArgument, segment, out convertedValue, out errorMessage)) + { + return false; + } + + if (positionInfo.Type == PositionType.EndOfList) + { + list[list.Count - 1] = convertedValue; + } + else + { + list[positionInfo.Index] = convertedValue; + } + + errorMessage = null; + return true; + } + + public bool TryTraverse( + object target, + string segment, + IContractResolver contractResolver, + out object value, + out string errorMessage) + { + var list = target as IList; + if (list == null) + { + value = null; + errorMessage = null; + return false; + } + + int index = -1; + if (!int.TryParse(segment, out index)) + { + value = null; + errorMessage = Resources.FormatInvalidIndexValue(segment); + return false; + } + + if (index < 0 || index >= list.Count) + { + value = null; + errorMessage = Resources.FormatIndexOutOfBounds(segment); + return false; + } + + value = list[index]; + errorMessage = null; + return true; + } + + private bool TryConvertValue( + object originalValue, + Type listTypeArgument, + string segment, + out object convertedValue, + out string errorMessage) + { + var conversionResult = ConversionResultProvider.ConvertTo(originalValue, listTypeArgument); + if (!conversionResult.CanBeConverted) + { + convertedValue = null; + errorMessage = Resources.FormatInvalidValueForProperty(originalValue); + return false; + } + + convertedValue = conversionResult.ConvertedInstance; + errorMessage = null; + return true; + } + + private bool TryGetListTypeArgument(IList list, out Type listTypeArgument, out string errorMessage) + { + // Arrays are not supported as they have fixed size and operations like Add, Insert do not make sense + var listType = list.GetType(); + if (listType.IsArray) + { + errorMessage = Resources.FormatPatchNotSupportedForArrays(listType.FullName); + listTypeArgument = null; + return false; + } + else + { + var genericList = ClosedGenericMatcher.ExtractGenericInterface(listType, typeof(IList<>)); + if (genericList == null) + { + errorMessage = Resources.FormatPatchNotSupportedForNonGenericLists(listType.FullName); + listTypeArgument = null; + return false; + } + else + { + listTypeArgument = genericList.GenericTypeArguments[0]; + errorMessage = null; + return true; + } + } + } + + private bool TryGetPositionInfo(IList list, string segment, out PositionInfo positionInfo, out string errorMessage) + { + if (segment == "-") + { + positionInfo = new PositionInfo(PositionType.EndOfList, -1); + errorMessage = null; + return true; + } + + int position = -1; + if (int.TryParse(segment, out position)) + { + if (position >= 0 && position < list.Count) + { + positionInfo = new PositionInfo(PositionType.Index, position); + errorMessage = null; + return true; + } + else + { + positionInfo = default(PositionInfo); + errorMessage = Resources.FormatIndexOutOfBounds(segment); + return false; + } + } + else + { + positionInfo = default(PositionInfo); + errorMessage = Resources.FormatInvalidIndexValue(segment); + return false; + } + } + + private struct PositionInfo + { + public PositionInfo(PositionType type, int index) + { + Type = type; + Index = index; + } + + public PositionType Type { get; } + public int Index { get; } + } + + private enum PositionType + { + Index, // valid index + EndOfList, // '-' + Invalid, // Ex: not an integer + OutOfBounds + } + } +} diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs new file mode 100644 index 0000000000..b604f65a17 --- /dev/null +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs @@ -0,0 +1,76 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections; +using System.Dynamic; +using Newtonsoft.Json.Serialization; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + public class ObjectVisitor + { + private readonly IContractResolver _contractResolver; + private readonly ParsedPath _path; + + public ObjectVisitor(ParsedPath path, IContractResolver contractResolver) + { + if (contractResolver == null) + { + throw new ArgumentNullException(nameof(contractResolver)); + } + + _path = path; + _contractResolver = contractResolver; + } + + public bool TryVisit(ref object target, out IAdapter adapter, out string errorMessage) + { + if (target == null) + { + adapter = null; + errorMessage = null; + return false; + } + + adapter = SelectAdapater(target); + + // Traverse until the penultimate segment to get the target object and adapter + for (var i = 0; i < _path.Segments.Count - 1; i++) + { + object next; + if (!adapter.TryTraverse(target, _path.Segments[i], _contractResolver, out next, out errorMessage)) + { + adapter = null; + return false; + } + + target = next; + adapter = SelectAdapater(target); + } + + errorMessage = null; + return true; + } + + private IAdapter SelectAdapater(object targetObject) + { + if (targetObject is ExpandoObject) + { + return new ExpandoObjectAdapter(); + } + else if (targetObject is IDictionary) + { + return new DictionaryAdapter(); + } + else if (targetObject is IList) + { + return new ListAdapter(); + } + else + { + return new PocoAdapter(); + } + } + } +} diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ParsedPath.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ParsedPath.cs new file mode 100644 index 0000000000..fe786b86c1 --- /dev/null +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ParsedPath.cs @@ -0,0 +1,40 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + public struct ParsedPath + { + private static readonly string[] Empty = null; + + private readonly string[] _segments; + + public ParsedPath(string path) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + _segments = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + } + + public string LastSegment + { + get + { + if (_segments == null || _segments.Length == 0) + { + return null; + } + + return _segments[_segments.Length - 1]; + } + } + + public IReadOnlyList Segments => _segments ?? Empty; + } +} diff --git a/src/Microsoft.AspNetCore.JsonPatch/Helpers/PathHelpers.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/PathHelpers.cs similarity index 95% rename from src/Microsoft.AspNetCore.JsonPatch/Helpers/PathHelpers.cs rename to src/Microsoft.AspNetCore.JsonPatch/Internal/PathHelpers.cs index 99bb2f1536..7ef8fe7baf 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Helpers/PathHelpers.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/PathHelpers.cs @@ -3,7 +3,7 @@ using Microsoft.AspNetCore.JsonPatch.Exceptions; -namespace Microsoft.AspNetCore.JsonPatch.Helpers +namespace Microsoft.AspNetCore.JsonPatch.Internal { internal static class PathHelpers { diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs new file mode 100644 index 0000000000..0755e132e1 --- /dev/null +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs @@ -0,0 +1,205 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Linq; +using System.Reflection; +using Newtonsoft.Json.Serialization; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + public class PocoAdapter : IAdapter + { + public bool TryAdd( + object target, + string segment, + IContractResolver contractResolver, + object value, + out string errorMessage) + { + JsonProperty jsonProperty = null; + if (!TryGetJsonProperty(target, contractResolver, segment, out jsonProperty)) + { + errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); + return false; + } + + if (!jsonProperty.Writable) + { + errorMessage = Resources.FormatCannotUpdateProperty(segment); + return false; + } + + object convertedValue = null; + if (!TryConvertValue(value, jsonProperty.PropertyType, out convertedValue)) + { + errorMessage = Resources.FormatInvalidValueForProperty(value); + return false; + } + + jsonProperty.ValueProvider.SetValue(target, convertedValue); + + errorMessage = null; + return true; + } + + public bool TryGet( + object target, + string segment, + IContractResolver contractResolver, + out object value, + out string errorMessage) + { + JsonProperty jsonProperty = null; + if (!TryGetJsonProperty(target, contractResolver, segment, out jsonProperty)) + { + errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); + value = null; + return false; + } + + if (!jsonProperty.Readable) + { + errorMessage = Resources.FormatCannotReadProperty(segment); + value = null; + return false; + } + + value = jsonProperty.ValueProvider.GetValue(target); + errorMessage = null; + return true; + } + + public bool TryRemove( + object target, + string segment, + IContractResolver contractResolver, + out string errorMessage) + { + JsonProperty jsonProperty = null; + if (!TryGetJsonProperty(target, contractResolver, segment, out jsonProperty)) + { + errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); + return false; + } + + if (!jsonProperty.Writable) + { + errorMessage = Resources.FormatCannotUpdateProperty(segment); + return false; + } + + // Setting the value to "null" will use the default value in case of value types, and + // null in case of reference types + object value = null; + if (jsonProperty.PropertyType.GetTypeInfo().IsValueType + && Nullable.GetUnderlyingType(jsonProperty.PropertyType) == null) + { + value = Activator.CreateInstance(jsonProperty.PropertyType); + } + + jsonProperty.ValueProvider.SetValue(target, value); + + errorMessage = null; + return true; + } + + public bool TryReplace( + object target, + string segment, + IContractResolver + contractResolver, + object value, + out string errorMessage) + { + JsonProperty jsonProperty = null; + if (!TryGetJsonProperty(target, contractResolver, segment, out jsonProperty)) + { + errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); + return false; + } + + if (!jsonProperty.Writable) + { + errorMessage = Resources.FormatCannotUpdateProperty(segment); + return false; + } + + object convertedValue = null; + if (!TryConvertValue(value, jsonProperty.PropertyType, out convertedValue)) + { + errorMessage = Resources.FormatInvalidValueForProperty(value); + return false; + } + + jsonProperty.ValueProvider.SetValue(target, convertedValue); + + errorMessage = null; + return true; + } + + public bool TryTraverse( + object target, + string segment, + IContractResolver contractResolver, + out object value, + out string errorMessage) + { + if (target == null) + { + value = null; + errorMessage = null; + return false; + } + + JsonProperty jsonProperty = null; + if (TryGetJsonProperty(target, contractResolver, segment, out jsonProperty)) + { + value = jsonProperty.ValueProvider.GetValue(target); + errorMessage = null; + return true; + } + + value = null; + errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); + return false; + } + + private bool TryGetJsonProperty( + object target, + IContractResolver contractResolver, + string segment, + out JsonProperty jsonProperty) + { + var jsonObjectContract = contractResolver.ResolveContract(target.GetType()) as JsonObjectContract; + if (jsonObjectContract != null) + { + var pocoProperty = jsonObjectContract + .Properties + .FirstOrDefault(p => string.Equals(p.PropertyName, segment, StringComparison.OrdinalIgnoreCase)); + + if (pocoProperty != null) + { + jsonProperty = pocoProperty; + return true; + } + } + + jsonProperty = null; + return false; + } + + private bool TryConvertValue(object value, Type propertyType, out object convertedValue) + { + var conversionResult = ConversionResultProvider.ConvertTo(value, propertyType); + if (!conversionResult.CanBeConverted) + { + convertedValue = null; + return false; + } + + convertedValue = conversionResult.ConvertedInstance; + return true; + } + } +} diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs index c9c34459a9..72e93e0302 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using Microsoft.AspNetCore.JsonPatch.Adapters; using Microsoft.AspNetCore.JsonPatch.Converters; -using Microsoft.AspNetCore.JsonPatch.Helpers; +using Microsoft.AspNetCore.JsonPatch.Internal; using Microsoft.AspNetCore.JsonPatch.Operations; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; @@ -13,7 +13,7 @@ using Newtonsoft.Json.Serialization; namespace Microsoft.AspNetCore.JsonPatch { // Implementation details: the purpose of this type of patch document is to allow creation of such - // documents for cases where there's no class/DTO to work on. Typical use case: backend not built in + // documents for cases where there's no class/DTO to work on. Typical use case: backend not built in // .NET or architecture doesn't contain a shared DTO layer. [JsonConverter(typeof(JsonPatchDocumentConverter))] public class JsonPatchDocument : IJsonPatchDocument @@ -145,7 +145,7 @@ namespace Microsoft.AspNetCore.JsonPatch } /// - /// Apply this JsonPatchDocument + /// Apply this JsonPatchDocument /// /// Object to apply the JsonPatchDocument to public void ApplyTo(object objectToApplyTo) @@ -159,7 +159,7 @@ namespace Microsoft.AspNetCore.JsonPatch } /// - /// Apply this JsonPatchDocument + /// Apply this JsonPatchDocument /// /// Object to apply the JsonPatchDocument to /// Action to log errors @@ -174,7 +174,7 @@ namespace Microsoft.AspNetCore.JsonPatch } /// - /// Apply this JsonPatchDocument + /// Apply this JsonPatchDocument /// /// Object to apply the JsonPatchDocument to /// IObjectAdapter instance to use when applying diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs index 530b414060..afb5eb3ff1 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Linq.Expressions; using Microsoft.AspNetCore.JsonPatch.Adapters; using Microsoft.AspNetCore.JsonPatch.Converters; -using Microsoft.AspNetCore.JsonPatch.Helpers; +using Microsoft.AspNetCore.JsonPatch.Internal; using Microsoft.AspNetCore.JsonPatch.Operations; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; @@ -502,7 +502,7 @@ namespace Microsoft.AspNetCore.JsonPatch /// Copy from a property to a location in a list /// /// - /// source location + /// source location /// target location /// position /// @@ -623,7 +623,7 @@ namespace Microsoft.AspNetCore.JsonPatch } /// - /// Apply this JsonPatchDocument + /// Apply this JsonPatchDocument /// /// Object to apply the JsonPatchDocument to public void ApplyTo(TModel objectToApplyTo) @@ -637,7 +637,7 @@ namespace Microsoft.AspNetCore.JsonPatch } /// - /// Apply this JsonPatchDocument + /// Apply this JsonPatchDocument /// /// Object to apply the JsonPatchDocument to /// Action to log errors @@ -652,7 +652,7 @@ namespace Microsoft.AspNetCore.JsonPatch } /// - /// Apply this JsonPatchDocument + /// Apply this JsonPatchDocument /// /// Object to apply the JsonPatchDocument to /// IObjectAdapter instance to use when applying diff --git a/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs index 70f76f1fa3..9e00cc2f00 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs @@ -26,6 +26,22 @@ namespace Microsoft.AspNetCore.JsonPatch return string.Format(CultureInfo.CurrentCulture, GetString("CannotDeterminePropertyType"), p0); } + /// + /// The '{0}' operation at path '{1}' could not be performed. + /// + internal static string CannotPerformOperation + { + get { return GetString("CannotPerformOperation"); } + } + + /// + /// The '{0}' operation at path '{1}' could not be performed. + /// + internal static string FormatCannotPerformOperation(object p0, object p1) + { + return string.Format(CultureInfo.CurrentCulture, GetString("CannotPerformOperation"), p0, p1); + } + /// /// The property at '{0}' could not be read. /// @@ -59,35 +75,35 @@ namespace Microsoft.AspNetCore.JsonPatch } /// - /// The key '{0}' was not found. + /// The index value provided by path segment '{0}' is out of bounds of the array size. /// - internal static string DictionaryKeyNotFound + internal static string IndexOutOfBounds { - get { return GetString("DictionaryKeyNotFound"); } + get { return GetString("IndexOutOfBounds"); } } /// - /// The key '{0}' was not found. + /// The index value provided by path segment '{0}' is out of bounds of the array size. /// - internal static string FormatDictionaryKeyNotFound(object p0) + internal static string FormatIndexOutOfBounds(object p0) { - return string.Format(CultureInfo.CurrentCulture, GetString("DictionaryKeyNotFound"), p0); + return string.Format(CultureInfo.CurrentCulture, GetString("IndexOutOfBounds"), p0); } /// - /// For operation '{0}' on array property at path '{1}', the index is larger than the array size. + /// The path segment '{0}' is invalid for an array index. /// - internal static string InvalidIndexForArrayProperty + internal static string InvalidIndexValue { - get { return GetString("InvalidIndexForArrayProperty"); } + get { return GetString("InvalidIndexValue"); } } /// - /// For operation '{0}' on array property at path '{1}', the index is larger than the array size. + /// The path segment '{0}' is invalid for an array index. /// - internal static string FormatInvalidIndexForArrayProperty(object p0, object p1) + internal static string FormatInvalidIndexValue(object p0) { - return string.Format(CultureInfo.CurrentCulture, GetString("InvalidIndexForArrayProperty"), p0, p1); + return string.Format(CultureInfo.CurrentCulture, GetString("InvalidIndexValue"), p0); } /// @@ -106,22 +122,6 @@ namespace Microsoft.AspNetCore.JsonPatch return string.Format(CultureInfo.CurrentCulture, GetString("InvalidJsonPatchDocument"), p0); } - /// - /// For operation '{0}', the provided path is invalid for array property at path '{1}'. - /// - internal static string InvalidPathForArrayProperty - { - get { return GetString("InvalidPathForArrayProperty"); } - } - - /// - /// For operation '{0}', the provided path is invalid for array property at path '{1}'. - /// - internal static string FormatInvalidPathForArrayProperty(object p0, object p1) - { - return string.Format(CultureInfo.CurrentCulture, GetString("InvalidPathForArrayProperty"), p0, p1); - } - /// /// The provided string '{0}' is an invalid path. /// @@ -139,7 +139,7 @@ namespace Microsoft.AspNetCore.JsonPatch } /// - /// The value '{0}' is invalid for property at path '{1}'. + /// The value '{0}' is invalid for target location. /// internal static string InvalidValueForProperty { @@ -147,27 +147,11 @@ namespace Microsoft.AspNetCore.JsonPatch } /// - /// The value '{0}' is invalid for property at path '{1}'. + /// The value '{0}' is invalid for target location. /// - internal static string FormatInvalidValueForProperty(object p0, object p1) + internal static string FormatInvalidValueForProperty(object p0) { - return string.Format(CultureInfo.CurrentCulture, GetString("InvalidValueForProperty"), p0, p1); - } - - /// - /// For operation '{0}' on array property at path '{1}', the index is negative. - /// - internal static string NegativeIndexForArrayProperty - { - get { return GetString("NegativeIndexForArrayProperty"); } - } - - /// - /// For operation '{0}' on array property at path '{1}', the index is negative. - /// - internal static string FormatNegativeIndexForArrayProperty(object p0, object p1) - { - return string.Format(CultureInfo.CurrentCulture, GetString("NegativeIndexForArrayProperty"), p0, p1); + return string.Format(CultureInfo.CurrentCulture, GetString("InvalidValueForProperty"), p0); } /// @@ -187,51 +171,67 @@ namespace Microsoft.AspNetCore.JsonPatch } /// - /// The property at path '{0}' could not be added. + /// The type '{0}' which is an array is not supported for json patch operations as it has a fixed size. /// - internal static string PropertyCannotBeAdded + internal static string PatchNotSupportedForArrays { - get { return GetString("PropertyCannotBeAdded"); } + get { return GetString("PatchNotSupportedForArrays"); } } /// - /// The property at path '{0}' could not be added. + /// The type '{0}' which is an array is not supported for json patch operations as it has a fixed size. /// - internal static string FormatPropertyCannotBeAdded(object p0) + internal static string FormatPatchNotSupportedForArrays(object p0) { - return string.Format(CultureInfo.CurrentCulture, GetString("PropertyCannotBeAdded"), p0); + return string.Format(CultureInfo.CurrentCulture, GetString("PatchNotSupportedForArrays"), p0); } /// - /// The property at path '{0}' could not be removed. + /// The type '{0}' which is a non generic list is not supported for json patch operations. Only generic list types are supported. /// - internal static string PropertyCannotBeRemoved + internal static string PatchNotSupportedForNonGenericLists { - get { return GetString("PropertyCannotBeRemoved"); } + get { return GetString("PatchNotSupportedForNonGenericLists"); } } /// - /// The property at path '{0}' could not be removed. + /// The type '{0}' which is a non generic list is not supported for json patch operations. Only generic list types are supported. /// - internal static string FormatPropertyCannotBeRemoved(object p0) + internal static string FormatPatchNotSupportedForNonGenericLists(object p0) { - return string.Format(CultureInfo.CurrentCulture, GetString("PropertyCannotBeRemoved"), p0); + return string.Format(CultureInfo.CurrentCulture, GetString("PatchNotSupportedForNonGenericLists"), p0); } /// - /// Property does not exist at path '{0}'. + /// The target location specified by path segment '{0}' was not found. /// - internal static string PropertyDoesNotExist + internal static string TargetLocationAtPathSegmentNotFound { - get { return GetString("PropertyDoesNotExist"); } + get { return GetString("TargetLocationAtPathSegmentNotFound"); } } /// - /// Property does not exist at path '{0}'. + /// The target location specified by path segment '{0}' was not found. /// - internal static string FormatPropertyDoesNotExist(object p0) + internal static string FormatTargetLocationAtPathSegmentNotFound(object p0) { - return string.Format(CultureInfo.CurrentCulture, GetString("PropertyDoesNotExist"), p0); + return string.Format(CultureInfo.CurrentCulture, GetString("TargetLocationAtPathSegmentNotFound"), p0); + } + + /// + /// For operation '{0}', the target location specified by path '{1}' was not found. + /// + internal static string TargetLocationNotFound + { + get { return GetString("TargetLocationNotFound"); } + } + + /// + /// For operation '{0}', the target location specified by path '{1}' was not found. + /// + internal static string FormatTargetLocationNotFound(object p0, object p1) + { + return string.Format(CultureInfo.CurrentCulture, GetString("TargetLocationNotFound"), p0, p1); } /// diff --git a/src/Microsoft.AspNetCore.JsonPatch/Resources.resx b/src/Microsoft.AspNetCore.JsonPatch/Resources.resx index 59ae2b59c3..a7b50520ac 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Resources.resx +++ b/src/Microsoft.AspNetCore.JsonPatch/Resources.resx @@ -120,44 +120,44 @@ The type of the property at path '{0}' could not be determined. + + The '{0}' operation at path '{1}' could not be performed. + The property at '{0}' could not be read. The property at path '{0}' could not be updated. - - The key '{0}' was not found. + + The index value provided by path segment '{0}' is out of bounds of the array size. - - For operation '{0}' on array property at path '{1}', the index is larger than the array size. + + The path segment '{0}' is invalid for an array index. The type '{0}' was malformed and could not be parsed. - - For operation '{0}', the provided path is invalid for array property at path '{1}'. - The provided string '{0}' is an invalid path. - The value '{0}' is invalid for property at path '{1}'. - - - For operation '{0}' on array property at path '{1}', the index is negative. + The value '{0}' is invalid for target location. '{0}' must be of type '{1}'. - - The property at path '{0}' could not be added. + + The type '{0}' which is an array is not supported for json patch operations as it has a fixed size. - - The property at path '{0}' could not be removed. + + The type '{0}' which is a non generic list is not supported for json patch operations. Only generic list types are supported. - - Property does not exist at path '{0}'. + + The target location specified by path segment '{0}' was not found. + + + For operation '{0}', the target location specified by path '{1}' was not found. The test operation is not supported. diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index 5180ee7e23..c9beba3639 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -22,14 +22,18 @@ }, "dependencies": { "NETStandard.Library": "1.6.1-*", - "Newtonsoft.Json": "9.0.1" + "Newtonsoft.Json": "9.0.1", + "Microsoft.Extensions.ClosedGenericMatcher.Sources": { + "type": "build", + "version": "1.1.0-*" + } }, "frameworks": { - "netstandard1.1": { + "net451": {}, + "netstandard1.3": { "dependencies": { "Microsoft.CSharp": "4.3.0-*", - "System.ComponentModel.TypeConverter": "4.3.0-*", - "System.Runtime.Serialization.Primitives": "4.3.0-*" + "System.Reflection.TypeExtensions": "4.1.0-*" } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs new file mode 100644 index 0000000000..6a88bd6cc7 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs @@ -0,0 +1,176 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using Moq; +using Newtonsoft.Json.Serialization; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + public class DictionaryAdapterTest + { + [Fact] + public void Add_KeyWhichAlreadyExists_ReplacesExistingValue() + { + // Arrange + var nameKey = "Name"; + var dictionary = new Dictionary(StringComparer.Ordinal); + dictionary[nameKey] = "Mike"; + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new Mock(MockBehavior.Strict); + string message = null; + + // Act + var addStatus = dictionaryAdapter.TryAdd(dictionary, nameKey, resolver.Object, "James", out message); + + // Assert + Assert.True(addStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Equal(1, dictionary.Count); + Assert.Equal("James", dictionary[nameKey]); + } + + [Fact] + public void Get_UsingCaseSensitiveKey_FailureScenario() + { + // Arrange + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new Mock(MockBehavior.Strict); + string message = null; + var nameKey = "Name"; + var dictionary = new Dictionary(StringComparer.Ordinal); + + // Act + var addStatus = dictionaryAdapter.TryAdd(dictionary, nameKey, resolver.Object, "James", out message); + + // Assert + Assert.True(addStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Equal(1, dictionary.Count); + Assert.Equal("James", dictionary[nameKey]); + + // Act + object outValue = null; + addStatus = dictionaryAdapter.TryGet(dictionary, nameKey.ToUpper(), resolver.Object, out outValue, out message); + + // Assert + Assert.True(addStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Null(outValue); + } + + [Fact] + public void Get_UsingCaseSensitiveKey_SuccessScenario() + { + // Arrange + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new Mock(MockBehavior.Strict); + string message = null; + var nameKey = "Name"; + var dictionary = new Dictionary(StringComparer.Ordinal); + + // Act + var addStatus = dictionaryAdapter.TryAdd(dictionary, nameKey, resolver.Object, "James", out message); + + // Assert + Assert.True(addStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Equal(1, dictionary.Count); + Assert.Equal("James", dictionary[nameKey]); + + // Act + object outValue = null; + addStatus = dictionaryAdapter.TryGet(dictionary, nameKey, resolver.Object, out outValue, out message); + + // Assert + Assert.True(addStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Equal("James", outValue?.ToString()); + } + + [Fact] + public void ReplacingExistingItem() + { + // Arrange + var nameKey = "Name"; + var dictionary = new Dictionary(StringComparer.Ordinal); + dictionary.Add(nameKey, "Mike"); + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new Mock(MockBehavior.Strict); + string message = null; + + // Act + var replaceStatus = dictionaryAdapter.TryReplace(dictionary, nameKey, resolver.Object, "James", out message); + + // Assert + Assert.True(replaceStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Equal(1, dictionary.Count); + Assert.Equal("James", dictionary[nameKey]); + } + + [Fact] + public void Replace_NonExistingKey_Fails() + { + // Arrange + var nameKey = "Name"; + var dictionary = new Dictionary(StringComparer.Ordinal); + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new Mock(MockBehavior.Strict); + string message = null; + + // Act + var replaceStatus = dictionaryAdapter.TryReplace(dictionary, nameKey, resolver.Object, "Mike", out message); + + // Assert + Assert.False(replaceStatus); + Assert.Equal( + string.Format("The target location specified by path segment '{0}' was not found.", nameKey), + message); + Assert.Equal(0, dictionary.Count); + } + + [Fact] + public void Remove_NonExistingKey_Fails() + { + // Arrange + var nameKey = "Name"; + var dictionary = new Dictionary(StringComparer.Ordinal); + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new Mock(MockBehavior.Strict); + string message = null; + + // Act + var removeStatus = dictionaryAdapter.TryRemove(dictionary, nameKey, resolver.Object, out message); + + // Assert + Assert.False(removeStatus); + Assert.Equal( + string.Format("The target location specified by path segment '{0}' was not found.", nameKey), + message); + Assert.Equal(0, dictionary.Count); + } + + [Fact] + public void Remove_RemovesFromDictionary() + { + // Arrange + var nameKey = "Name"; + var dictionary = new Dictionary(StringComparer.Ordinal); + dictionary[nameKey] = "James"; + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new Mock(MockBehavior.Strict); + string message = null; + + // Act + var removeStatus = dictionaryAdapter.TryRemove(dictionary, nameKey, resolver.Object, out message); + + //Assert + Assert.True(removeStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Equal(0, dictionary.Count); + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs index cb5f090d0f..cbd44a7ef9 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs @@ -32,7 +32,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "The property at path '/NewInt' could not be added.", + string.Format("The target location specified by path segment '{0}' was not found.", "NewInt"), exception.Message); } @@ -76,7 +76,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "The property at path '/Nested/NewInt' could not be added.", + string.Format("The target location specified by path segment '{0}' was not found.", "NewInt"), exception.Message); } @@ -101,7 +101,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "The property at path '/Nested/NewInt' could not be added.", + string.Format("The target location specified by path segment '{0}' was not found.", "NewInt"), exception.Message); } @@ -214,7 +214,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "The property at path '/ComplexProperty' could not be added.", + string.Format("The target location specified by path segment '{0}' was not found.", "ComplexProperty"), exception.Message); } @@ -238,7 +238,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "The property at path '/StringProperty' could not be updated.", + string.Format("The property at path '{0}' could not be updated.", "StringProperty"), exception.Message); } @@ -336,7 +336,10 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "The property at path '/DynamicProperty/OtherProperty/IntProperty' could not be added.", + string.Format( + "For operation '{0}', the target location specified by path '{1}' was not found.", + "add", + "/DynamicProperty/OtherProperty/IntProperty"), exception.Message); } @@ -374,7 +377,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "The property at path '/baz/bat' could not be added.", + string.Format("The target location specified by path segment '{0}' was not found.", "baz"), exception.Message); } @@ -434,7 +437,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "For operation 'add' on array property at path '/IntegerList/-1', the index is negative.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), exception.Message); } @@ -478,30 +481,10 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "For operation 'add' on array property at path '/IntegerList/4', the index is larger than the array size.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "4"), exception.Message); } - [Fact] - public void AddToListAtEndWithSerialization() - { - var doc = new - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); - patchDoc.Add("IntegerList/3", 4); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 2, 3, 4 }, doc.IntegerList); - } - [Fact] public void AddToListAtBeginning() { @@ -542,7 +525,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "For operation 'add' on array property at path '/IntegerList/-1', the index is negative.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), exception.Message); } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs index 098e97d850..f28d877ea4 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs @@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "For operation 'add' on array property at path '/IntegerList/-1', the index is negative.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), exception.Message); } @@ -85,7 +85,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "The property at path '/ListOfSimpleDTO/-1/IntegerList/0' could not be added.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), exception.Message); } @@ -114,7 +114,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "The property at path '/ListOfSimpleDTO/20/IntegerList/0' could not be added.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "20"), exception.Message); } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs index b436bb4d23..6e903bf2ec 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs @@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "The property at path '/Test' could not be updated.", + string.Format("The property at path '{0}' could not be updated.", "Test"), exception.Message); } @@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "The property at path '/NonExisting' could not be removed.", + string.Format("The target location specified by path segment '{0}' was not found.", "NonExisting"), exception.Message); } @@ -250,7 +250,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "For operation 'remove' on array property at path '/SimpleDTO/IntegerList/3', the index is larger than the array size.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), exception.Message); } @@ -275,8 +275,8 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "For operation 'remove' on array property at path '/SimpleDTO/IntegerList/-1', the index is negative.", - exception.Message); + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), + exception.Message); } [Fact] diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs index d716dafe9a..126706eef2 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs @@ -70,7 +70,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "For operation 'remove' on array property at path '/IntegerList/3', the index is larger than the array size.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), exception.Message); } @@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "For operation 'remove' on array property at path '/IntegerList/-1', the index is negative.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), exception.Message); } @@ -187,8 +187,8 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "For operation 'remove' on array property at path '/SimpleDTO/IntegerList/3', the index is larger than the array size.", - exception.Message); + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), + exception.Message); } [Fact] @@ -214,7 +214,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); }); Assert.Equal( - "For operation 'remove' on array property at path '/SimpleDTO/IntegerList/-1', the index is negative.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), exception.Message); } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs index 8dff9b6a98..b8e7196068 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Dynamic; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using Xunit; namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic @@ -25,7 +26,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic JsonPatchDocument patchDoc = new JsonPatchDocument(); patchDoc.Replace("GuidValue", newGuid); - // serialize & deserialize + // serialize & deserialize var serialized = JsonConvert.SerializeObject(patchDoc); var deserizalized = JsonConvert.DeserializeObject(serialized); @@ -45,7 +46,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic JsonPatchDocument patchDoc = new JsonPatchDocument(); patchDoc.Replace("GuidValue", newGuid); - // serialize & deserialize + // serialize & deserialize var serialized = JsonConvert.SerializeObject(patchDoc); var deserizalized = JsonConvert.DeserializeObject(serialized); @@ -70,7 +71,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic JsonPatchDocument patchDoc = new JsonPatchDocument(); patchDoc.Replace("nestedobject/GuidValue", newGuid); - // serialize & deserialize + // serialize & deserialize var serialized = JsonConvert.SerializeObject(patchDoc); var deserizalized = JsonConvert.DeserializeObject(serialized); @@ -98,7 +99,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic JsonPatchDocument patchDoc = new JsonPatchDocument(); patchDoc.Replace("SimpleDTO", newDTO); - // serialize & deserialize + // serialize & deserialize var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); @@ -201,6 +202,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic var deserialized = JsonConvert.DeserializeObject(serialized); deserialized.ApplyTo(doc); + Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs new file mode 100644 index 0000000000..ee331a2b30 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs @@ -0,0 +1,302 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections; +using System.Collections.Generic; +using Moq; +using Newtonsoft.Json.Serialization; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + public class ListAdapterTest + { + [Fact] + public void Patch_OnArrayObject_Fails() + { + // Arrange + var resolver = new Mock(MockBehavior.Strict); + var targetObject = new[] { 20, 30 }; + var listAdapter = new ListAdapter(); + string message = null; + + // Act + var addStatus = listAdapter.TryAdd(targetObject, "0", resolver.Object, "40", out message); + + // Assert + Assert.False(addStatus); + Assert.Equal( + string.Format( + "The type '{0}' which is an array is not supported for json patch operations as it has a fixed size.", + targetObject.GetType().FullName), + message); + } + + [Fact] + public void Patch_OnNonGenericListObject_Fails() + { + // Arrange + var resolver = new Mock(MockBehavior.Strict); + var targetObject = new ArrayList(); + targetObject.Add(20); + targetObject.Add(30); + var listAdapter = new ListAdapter(); + string message = null; + + // Act + var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, "40", out message); + + // Assert + Assert.False(addStatus); + Assert.Equal( + string.Format( + "The type '{0}' which is a non generic list is not supported for json patch operations. Only generic list types are supported.", + targetObject.GetType().FullName), + message); + } + + [Theory] + [InlineData("-1")] + [InlineData("-2")] + [InlineData("2")] + [InlineData("3")] + public void Patch_WithOutOfBoundsIndex_Fails(string position) + { + // Arrange + var resolver = new Mock(MockBehavior.Strict); + var targetObject = new List() { "James", "Mike" }; + var listAdapter = new ListAdapter(); + string message = null; + + // Act + var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, "40", out message); + + // Assert + Assert.False(addStatus); + Assert.Equal( + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", position), + message); + } + + [Theory] + [InlineData("_")] + [InlineData("blah")] + public void Patch_WithInvalidPositionFormat_Fails(string position) + { + // Arrange + var resolver = new Mock(MockBehavior.Strict); + var targetObject = new List() { "James", "Mike" }; + var listAdapter = new ListAdapter(); + string message = null; + + // Act + var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, "40", out message); + + // Assert + Assert.False(addStatus); + Assert.Equal( + string.Format("The path segment '{0}' is invalid for an array index.", position), + message); + } + + public static TheoryData, List> AppendAtEndOfListData + { + get + { + return new TheoryData, List>() + { + { + new List() { }, + new List() { 20 } + }, + { + new List() { 5, 10 }, + new List() { 5, 10, 20 } + } + }; + } + } + + [Theory] + [MemberData(nameof(AppendAtEndOfListData))] + public void Add_Appends_AtTheEnd(List targetObject, List expected) + { + // Arrange + var resolver = new Mock(MockBehavior.Strict); + var listAdapter = new ListAdapter(); + string message = null; + + // Act + var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, "20", out message); + + // Assert + Assert.True(addStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Equal(expected.Count, targetObject.Count); + Assert.Equal(expected, targetObject); + } + + [Fact] + public void Add_NullObject_ToReferenceTypeListWorks() + { + // Arrange + var resolver = new Mock(MockBehavior.Strict); + var listAdapter = new ListAdapter(); + var targetObject = new List() { "James", "Mike" }; + string message = null; + + // Act + var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, value: null, errorMessage: out message); + + // Assert + Assert.True(addStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Equal(3, targetObject.Count); + Assert.Equal(new List() { "James", "Mike", null }, targetObject); + } + + [Fact] + public void Add_NonCompatibleType_Fails() + { + // Arrange + var resolver = new Mock(MockBehavior.Strict); + var targetObject = (new List() { 10, 20 }).AsReadOnly(); + var listAdapter = new ListAdapter(); + string message = null; + + // Act + var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, "James", out message); + + // Assert + Assert.False(addStatus); + Assert.Equal(string.Format("The value '{0}' is invalid for target location.", "James"), message); + } + + public static TheoryData AddingDifferentComplexTypeWorksData + { + get + { + return new TheoryData() + { + { + new List() { }, + "a", + "-", + new List() { "a" } + }, + { + new List() { "a", "b" }, + "c", + "-", + new List() { "a", "b", "c" } + }, + { + new List() { "a", "b" }, + "c", + "0", + new List() { "c", "a", "b" } + }, + { + new List() { "a", "b" }, + "c", + "1", + new List() { "a", "c", "b" } + } + }; + } + } + + [Theory] + [MemberData(nameof(AddingDifferentComplexTypeWorksData))] + public void Add_DifferentComplexTypeWorks(IList targetObject, object value, string position, IList expected) + { + // Arrange + var resolver = new Mock(MockBehavior.Strict); + var listAdapter = new ListAdapter(); + string message = null; + + // Act + var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, value, out message); + + // Assert + Assert.True(addStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Equal(expected.Count, targetObject.Count); + Assert.Equal(expected, targetObject); + } + + [Fact] + public void Replace_NonCompatibleType_Fails() + { + // Arrange + var resolver = new Mock(MockBehavior.Strict); + var targetObject = (new List() { 10, 20 }).AsReadOnly(); + var listAdapter = new ListAdapter(); + string message = null; + + // Act + var replaceStatus = listAdapter.TryReplace(targetObject, "-", resolver.Object, "James", out message); + + // Assert + Assert.False(replaceStatus); + Assert.Equal( + string.Format("The value '{0}' is invalid for target location.", "James"), + message); + } + + [Fact] + public void Replace_ReplacesValue_AtTheEnd() + { + // Arrange + var resolver = new Mock(MockBehavior.Strict); + var targetObject = new List() { 10, 20 }; + var listAdapter = new ListAdapter(); + string message = null; + + // Act + var replaceStatus = listAdapter.TryReplace(targetObject, "-", resolver.Object, "30", out message); + + // Assert + Assert.True(replaceStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Equal(new List() { 10, 30 }, targetObject); + } + + public static TheoryData> ReplacesValuesAtPositionData + { + get + { + return new TheoryData>() + { + { + "0", + new List() { 30, 20 } + }, + { + "1", + new List() { 10, 30 } + } + }; + } + } + + [Theory] + [MemberData(nameof(ReplacesValuesAtPositionData))] + public void Replace_ReplacesValue_AtGivenPosition(string position, List expected) + { + // Arrange + var resolver = new Mock(MockBehavior.Strict); + var targetObject = new List() { 10, 20 }; + var listAdapter = new ListAdapter(); + string message = null; + + // Act + var replaceStatus = listAdapter.TryReplace(targetObject, position, resolver.Object, "30", out message); + + // Assert + Assert.True(replaceStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Equal(expected, targetObject); + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/NestedDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/NestedDTO.cs index aa767557c3..90be5152cb 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/NestedDTO.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/NestedDTO.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.JsonPatch.Test +namespace Microsoft.AspNetCore.JsonPatch { public class NestedDTO { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs index 6215da6bcd..345ffe2201 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs @@ -7,7 +7,7 @@ using Microsoft.AspNetCore.JsonPatch.Exceptions; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNetCore.JsonPatch.Test +namespace Microsoft.AspNetCore.JsonPatch { public class NestedObjectTests { @@ -386,8 +386,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Act & Assert var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); Assert.Equal( - "For operation 'add' on array property at path '/simpledto/integerlist/4', the index is " + - "larger than the array size.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "4"), exception.Message); } @@ -417,8 +416,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test deserialized.ApplyTo(doc); }); Assert.Equal( - "For operation 'add' on array property at path '/simpledto/integerlist/4', the index is " + - "larger than the array size.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "4"), exception.Message); } @@ -445,8 +443,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test //Assert Assert.Equal( - "For operation 'add' on array property at path '/simpledto/integerlist/4', the index is larger than " + - "the array size.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "4"), logger.ErrorMessage); } @@ -470,7 +467,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Act & Assert var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); Assert.Equal( - "For operation 'add' on array property at path '/simpledto/integerlist/-1', the index is negative.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), exception.Message); } @@ -499,7 +496,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test deserialized.ApplyTo(doc); }); Assert.Equal( - "For operation 'add' on array property at path '/simpledto/integerlist/-1', the index is negative.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), exception.Message); } @@ -527,7 +524,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test //Assert Assert.Equal( - "For operation 'add' on array property at path '/simpledto/integerlist/-1', the index is negative.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), logger.ErrorMessage); } @@ -697,8 +694,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Act & Assert var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); Assert.Equal( - "For operation 'remove' on array property at path '/simpledto/integerlist/3', the index is " + - "larger than the array size.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), exception.Message); } @@ -727,8 +723,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test deserialized.ApplyTo(doc); }); Assert.Equal( - "For operation 'remove' on array property at path '/simpledto/integerlist/3', the index is " + - "larger than the array size.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), exception.Message); } @@ -754,8 +749,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Assert Assert.Equal( - "For operation 'remove' on array property at path '/simpledto/integerlist/3', the index is " + - "larger than the array size.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), logger.ErrorMessage); } @@ -777,7 +771,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Act & Assert var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); - Assert.Equal("For operation 'remove' on array property at path '/simpledto/integerlist/-1', the index is negative.", exception.Message); + Assert.Equal( + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), + exception.Message); } [Fact] @@ -804,7 +800,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Test { deserialized.ApplyTo(doc); }); - Assert.Equal("For operation 'remove' on array property at path '/simpledto/integerlist/-1', the index is negative.", exception.Message); + Assert.Equal( + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), + exception.Message); } [Fact] @@ -829,7 +827,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Test patchDoc.ApplyTo(doc, logger.LogErrorMessage); // Assert - Assert.Equal("For operation 'remove' on array property at path '/simpledto/integerlist/-1', the index is negative.", logger.ErrorMessage); + Assert.Equal( + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), + logger.ErrorMessage); } [Fact] @@ -1239,8 +1239,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Act & Assert var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); Assert.Equal( - "For operation 'replace' on array property at path '/simpledto/integerlist/3', the index is " + - "larger than the array size.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), exception.Message); } @@ -1269,8 +1268,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test deserialized.ApplyTo(doc); }); Assert.Equal( - "For operation 'replace' on array property at path '/simpledto/integerlist/3', the index is " + - "larger than the array size.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), exception.Message); } @@ -1298,8 +1296,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Assert Assert.Equal( - "For operation 'replace' on array property at path '/simpledto/integerlist/3', the index is " + - "larger than the array size.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), logger.ErrorMessage); } @@ -1321,7 +1318,8 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Act & Assert var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); - Assert.Equal("For operation 'replace' on array property at path '/simpledto/integerlist/-1', the index is negative.", + Assert.Equal( + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), exception.Message); } @@ -1347,7 +1345,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Act & Assert var exception = Assert.Throws(() => { deserialized.ApplyTo(doc); }); Assert.Equal( - "For operation 'replace' on array property at path '/simpledto/integerlist/-1', the index is negative.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), exception.Message); } @@ -1375,7 +1373,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Assert Assert.Equal( - "For operation 'replace' on array property at path '/simpledto/integerlist/-1', the index is negative.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), logger.ErrorMessage); } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs index 98a72e1bf8..88693fdbd5 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs @@ -8,7 +8,7 @@ using Microsoft.AspNetCore.JsonPatch.Exceptions; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNetCore.JsonPatch.Test +namespace Microsoft.AspNetCore.JsonPatch.Adapters { public class ObjectAdapterTests { @@ -157,8 +157,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Act & Assert var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); Assert.Equal( - "For operation 'add' on array property at path '/integerlist/4', the index is " + - "larger than the array size.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "4"), exception.Message); } @@ -181,8 +180,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Act & Assert var exception = Assert.Throws(() => { deserialized.ApplyTo(doc); }); Assert.Equal( - "For operation 'add' on array property at path '/integerlist/4', the index is " + - "larger than the array size.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "4"), exception.Message); } @@ -206,54 +204,10 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Assert Assert.Equal( - "For operation 'add' on array property at path '/integerlist/4', the index is " + - "larger than the array size.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "4"), logger.ErrorMessage); } - [Fact] - public void AddToListAtEnd() - { - // Arrange - var doc = new SimpleDTO() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.IntegerList, 4, 3); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2, 3, 4 }, doc.IntegerList); - } - - [Fact] - public void AddToListAtEndWithSerialization() - { - // Arrange - var doc = new SimpleDTO() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.IntegerList, 4, 3); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2, 3, 4 }, doc.IntegerList); - } - [Fact] public void AddToListAtBeginning() { @@ -313,7 +267,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Act & Assert var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); Assert.Equal( - "For operation 'add' on array property at path '/integerlist/-1', the index is negative.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), exception.Message); } @@ -336,7 +290,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Act & Assert var exception = Assert.Throws(() => { deserialized.ApplyTo(doc); }); Assert.Equal( - "For operation 'add' on array property at path '/integerlist/-1', the index is negative.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), exception.Message); } @@ -359,7 +313,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Assert Assert.Equal( - "For operation 'add' on array property at path '/integerlist/-1', the index is negative.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), logger.ErrorMessage); } @@ -508,8 +462,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Act & Assert var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); Assert.Equal( - "For operation 'remove' on array property at path '/integerlist/3', the index is " + - "larger than the array size.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), exception.Message); } @@ -532,8 +485,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Act & Assert var exception = Assert.Throws(() => { deserialized.ApplyTo(doc); }); Assert.Equal( - "For operation 'remove' on array property at path '/integerlist/3', the index is " + - "larger than the array size.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), exception.Message); } @@ -557,8 +509,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Assert Assert.Equal( - "For operation 'remove' on array property at path '/integerlist/3', the index is " + - "larger than the array size.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), logger.ErrorMessage); } @@ -577,7 +528,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Act & Assert var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); - Assert.Equal("For operation 'remove' on array property at path '/integerlist/-1', the index is negative.", exception.Message); + Assert.Equal( + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), + exception.Message); } [Fact] @@ -598,7 +551,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Act & Assert var exception = Assert.Throws(() => { deserialized.ApplyTo(doc); }); - Assert.Equal("For operation 'remove' on array property at path '/integerlist/-1', the index is negative.", exception.Message); + Assert.Equal( + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), + exception.Message); } [Fact] @@ -621,7 +576,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Test // Assert - Assert.Equal("For operation 'remove' on array property at path '/integerlist/-1', the index is negative.", logger.ErrorMessage); + Assert.Equal( + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), + logger.ErrorMessage); } [Fact] @@ -1123,8 +1080,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test patchDoc.ApplyTo(doc); }); Assert.Equal( - "For operation 'replace' on array property at path '/integerlist/3', the index is " + - "larger than the array size.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), exception.Message); } @@ -1149,8 +1105,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test deserialized.ApplyTo(doc); }); Assert.Equal( - "For operation 'replace' on array property at path '/integerlist/3', the index is " + - "larger than the array size.", + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), exception.Message); } @@ -1172,7 +1127,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Test { patchDoc.ApplyTo(doc); }); - Assert.Equal("For operation 'replace' on array property at path '/integerlist/-1', the index is negative.", exception.Message); + Assert.Equal( + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), + exception.Message); } [Fact] @@ -1196,7 +1153,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Test { deserialized.ApplyTo(doc); }); - Assert.Equal("For operation 'replace' on array property at path '/integerlist/-1', the index is negative.", exception.Message); + Assert.Equal( + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), + exception.Message); } [Fact] @@ -1733,5 +1692,577 @@ namespace Microsoft.AspNetCore.JsonPatch.Test Assert.Equal(0, doc.IntegerValue); Assert.Equal(new List() { 1, 2, 3, 5 }, doc.IntegerList); } + + private class Class6 + { + public IDictionary DictionaryOfStringToInteger { get; } = new Dictionary(); + } + + [Fact] + public void Add_WhenDictionary_ValueIsNonObject_Succeeds() + { + // Arrange + var model = new Class6(); + model.DictionaryOfStringToInteger["one"] = 1; + model.DictionaryOfStringToInteger["two"] = 2; + var patchDocument = new JsonPatchDocument(); + patchDocument.Add("/DictionaryOfStringToInteger/three", 3); + + // Act + patchDocument.ApplyTo(model); + + // Assert + Assert.Equal(3, model.DictionaryOfStringToInteger.Count); + Assert.Equal(1, model.DictionaryOfStringToInteger["one"]); + Assert.Equal(2, model.DictionaryOfStringToInteger["two"]); + Assert.Equal(3, model.DictionaryOfStringToInteger["three"]); + } + + [Fact] + public void Remove_WhenDictionary_ValueIsNonObject_Succeeds() + { + // Arrange + var model = new Class6(); + model.DictionaryOfStringToInteger["one"] = 1; + model.DictionaryOfStringToInteger["two"] = 2; + var patchDocument = new JsonPatchDocument(); + patchDocument.Remove("/DictionaryOfStringToInteger/two"); + + // Act + patchDocument.ApplyTo(model); + + // Assert + Assert.Equal(1, model.DictionaryOfStringToInteger.Count); + Assert.Equal(1, model.DictionaryOfStringToInteger["one"]); + } + + [Fact] + public void Replace_WhenDictionary_ValueIsNonObject_Succeeds() + { + // Arrange + var model = new Class6(); + model.DictionaryOfStringToInteger["one"] = 1; + model.DictionaryOfStringToInteger["two"] = 2; + var patchDocument = new JsonPatchDocument(); + patchDocument.Replace("/DictionaryOfStringToInteger/two", 20); + + // Act + patchDocument.ApplyTo(model); + + // Assert + Assert.Equal(2, model.DictionaryOfStringToInteger.Count); + Assert.Equal(1, model.DictionaryOfStringToInteger["one"]); + Assert.Equal(20, model.DictionaryOfStringToInteger["two"]); + } + + private class Customer + { + public string Name { get; set; } + public Address Address { get; set; } + } + + private class Address + { + public string City { get; set; } + } + + private class Class8 + { + public IDictionary DictionaryOfStringToCustomer { get; } = new Dictionary(); + } + + [Fact] + public void Replace_WhenDictionary_ValueAPocoType_Succeeds() + { + // Arrange + var key1 = "key1"; + var value1 = new Customer() { Name = "Jamesss" }; + var key2 = "key2"; + var value2 = new Customer() { Name = "Mike" }; + var model = new Class8(); + model.DictionaryOfStringToCustomer[key1] = value1; + model.DictionaryOfStringToCustomer[key2] = value2; + var patchDocument = new JsonPatchDocument(); + patchDocument.Replace($"/DictionaryOfStringToCustomer/{key1}/Name", "James"); + + // Act + patchDocument.ApplyTo(model); + + // Assert + Assert.Equal(2, model.DictionaryOfStringToCustomer.Count); + var actualValue1 = model.DictionaryOfStringToCustomer[key1]; + Assert.NotNull(actualValue1); + Assert.Equal("James", actualValue1.Name); + } + + [Fact] + public void Replace_WhenDictionary_ValueAPocoType_Succeeds_WithSerialization() + { + // Arrange + var key1 = "key1"; + var value1 = new Customer() { Name = "Jamesss" }; + var key2 = "key2"; + var value2 = new Customer() { Name = "Mike" }; + var model = new Class8(); + model.DictionaryOfStringToCustomer[key1] = value1; + model.DictionaryOfStringToCustomer[key2] = value2; + var patchDocument = new JsonPatchDocument(); + patchDocument.Replace($"/DictionaryOfStringToCustomer/{key1}/Name", "James"); + var serialized = JsonConvert.SerializeObject(patchDocument); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + patchDocument.ApplyTo(model); + + // Assert + Assert.Equal(2, model.DictionaryOfStringToCustomer.Count); + var actualValue1 = model.DictionaryOfStringToCustomer[key1]; + Assert.NotNull(actualValue1); + Assert.Equal("James", actualValue1.Name); + } + + [Fact] + public void Replace_DeepNested_DictionaryValue_Succeeds() + { + // Arrange + var key1 = "key1"; + var value1 = new Customer() { Name = "Jamesss" }; + var key2 = "key2"; + var value2 = new Customer() { Name = "Mike" }; + var model = new Class8(); + model.DictionaryOfStringToCustomer[key1] = value1; + model.DictionaryOfStringToCustomer[key2] = value2; + var patchDocument = new JsonPatchDocument(); + patchDocument.Replace($"/DictionaryOfStringToCustomer/{key1}/Name", "James"); + + // Act + patchDocument.ApplyTo(model); + + // Assert + Assert.Equal(2, model.DictionaryOfStringToCustomer.Count); + var actualValue1 = model.DictionaryOfStringToCustomer[key1]; + Assert.NotNull(actualValue1); + Assert.Equal("James", actualValue1.Name); + } + + [Fact] + public void Replace_DeepNested_DictionaryValue_Succeeds_WithSerialization() + { + // Arrange + var key1 = "key1"; + var value1 = new Customer() { Name = "James", Address = new Address { City = "Redmond" } }; + var key2 = "key2"; + var value2 = new Customer() { Name = "Mike", Address = new Address { City = "Seattle" } }; + var model = new Class8(); + model.DictionaryOfStringToCustomer[key1] = value1; + model.DictionaryOfStringToCustomer[key2] = value2; + var patchDocument = new JsonPatchDocument(); + patchDocument.Replace($"/DictionaryOfStringToCustomer/{key1}/Address/City", "Bellevue"); + var serialized = JsonConvert.SerializeObject(patchDocument); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + patchDocument.ApplyTo(model); + + // Assert + Assert.Equal(2, model.DictionaryOfStringToCustomer.Count); + var actualValue1 = model.DictionaryOfStringToCustomer[key1]; + Assert.NotNull(actualValue1); + Assert.Equal("James", actualValue1.Name); + var address = actualValue1.Address; + Assert.NotNull(address); + Assert.Equal("Bellevue", address.City); + } + + class Class9 + { + public List StringList { get; set; } = new List(); + } + + [Fact] + public void AddToNonIntegerListAtEnd() + { + // Arrange + var model = new Class9() + { + StringList = new List() + }; + model.StringList.Add("string1"); + model.StringList.Add("string2"); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add("/StringList/0", "string3"); + + // Act + patchDoc.ApplyTo(model); + + // Assert + Assert.Equal(new List() { "string3", "string1", "string2" }, model.StringList); + } + + [Fact] + public void AddMember_OnPOCO_WithNullPropertyValue_ShouldAddPropertyValue() + { + // Arrange + var doc = new SimpleDTO() + { + StringProperty = null + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.StringProperty, "B"); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal("B", doc.StringProperty); + } + + private class Class1 + { + public IDictionary USStates { get; set; } = new Dictionary(); + } + + [Fact] + public void AddMember_OnDictionaryProperty_ShouldAddKeyValueMember() + { + // Arrange + var expected = "Washington"; + var model = new Class1(); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add("/USStates/WA", expected); + + // Act + patchDoc.ApplyTo(model); + + // Assert + Assert.Equal(1, model.USStates.Count); + Assert.Equal(expected, model.USStates["WA"]); + } + + [Fact] + public void AddMember_OnDictionaryProperty_ShouldAddKeyValueMember_WithSerialization() + { + // Arrange + var expected = "Washington"; + var model = new Class1(); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add("/USStates/WA", expected); + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(model); + + // Assert + Assert.Equal(1, model.USStates.Count); + Assert.Equal(expected, model.USStates["WA"]); + } + + private class Class2 + { + public Class1 Class1Property { get; set; } = new Class1(); + } + + [Fact] + public void AddMember_OnDictionaryPropertyDeeplyNested_ShouldAddKeyValueMember() + { + // Arrange + var expected = "Washington"; + var model = new Class2(); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add("/Class1Property/USStates/WA", expected); + + // Act + patchDoc.ApplyTo(model); + + // Assert + Assert.Equal(1, model.Class1Property.USStates.Count); + Assert.Equal(expected, model.Class1Property.USStates["WA"]); + } + + [Fact] + public void AddMember_OnDictionaryPropertyDeeplyNested_ShouldAddKeyValueMember_WithSerialization() + { + // Arrange + var expected = "Washington"; + var model = new Class2(); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add("/Class1Property/USStates/WA", expected); + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(model); + + // Assert + Assert.Equal(1, model.Class1Property.USStates.Count); + Assert.Equal(expected, model.Class1Property.USStates["WA"]); + } + + [Fact] + public void AddMember_OnDictionaryObjectDirectly_ShouldAddKeyValueMember() + { + // Arrange + var expected = "Washington"; + var model = new Dictionary(); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add("/WA", expected); + + // Act + patchDoc.ApplyTo(model); + + // Assert + Assert.Equal(1, model.Count); + Assert.Equal(expected, model["WA"]); + } + + [Fact] + public void AddMember_OnDictionaryObjectDirectly_ShouldAddKeyValueMember_WithSerialization() + { + // Arrange + var expected = "Washington"; + var model = new Dictionary(); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add("/WA", expected); + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>>(serialized); + + // Act + deserialized.ApplyTo(model); + + // Assert + Assert.Equal(1, model.Count); + Assert.Equal(expected, model["WA"]); + } + + [Fact] + public void AddElement_ToListDirectly_ShouldAppendValue() + { + // Arrange + var model = new List() { 1, 2, 3 }; + var patchDoc = new JsonPatchDocument(); + patchDoc.Add("/-", value: 4); + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>>(serialized); + + // Act + deserialized.ApplyTo(model); + + // Assert + Assert.Equal(new List() { 1, 2, 3, 4 }, model); + } + + [Fact] + public void AddElement_ToListDirectly_ShouldAppendValue_WithSerialization() + { + // Arrange + var model = new List() { 1, 2, 3 }; + var patchDoc = new JsonPatchDocument(); + patchDoc.Add("/-", value: 4); + + // Act + patchDoc.ApplyTo(model); + + // Assert + Assert.Equal(new List() { 1, 2, 3, 4 }, model); + } + + [Fact] + public void AddElement_ToListDirectly_ShouldAddValue_AtSuppliedPosition() + { + // Arrange + var model = new List() { 1, 2, 3 }; + var patchDoc = new JsonPatchDocument(); + patchDoc.Add("/0", value: 4); + + // Act + patchDoc.ApplyTo(model); + + // Assert + Assert.Equal(new List() { 4, 1, 2, 3 }, model); + } + + [Fact] + public void AddElement_ToListDirectly_ShouldAddValue_AtSuppliedPosition_WithSerialization() + { + // Arrange + var model = new List() { 1, 2, 3 }; + var patchDoc = new JsonPatchDocument(); + patchDoc.Add("/0", value: 4); + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>>(serialized); + + // Act + deserialized.ApplyTo(model); + + // Assert + Assert.Equal(new List() { 4, 1, 2, 3 }, model); + } + + class ListOnDictionary + { + public IDictionary> NamesAndBadgeIds { get; set; } = new Dictionary>(); + } + + [Fact] + public void AddElement_ToList_OnDictionary_ShouldAddValue_AtSuppliedPosition() + { + // Arrange + var model = new ListOnDictionary(); + model.NamesAndBadgeIds["James"] = new List(); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add("/NamesAndBadgeIds/James/-", 200); + + // Act + patchDoc.ApplyTo(model); + + // Assert + var list = model.NamesAndBadgeIds["James"]; + Assert.NotNull(list); + Assert.Equal(new List() { 200 }, list); + } + + [Fact] + public void AddElement_ToList_OnPOCO_ShouldAddValue_AtSuppliedPosition() + { + // Arrange + var doc = new SimpleDTO() + { + IntegerIList = new List() { 1, 2, 3 } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.IntegerIList, 4, 0); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerIList); + } + + class Class3 + { + public SimpleDTO SimpleDTOProperty { get; set; } = new SimpleDTO(); + } + + [Fact] + public void AddElement_ToDeeplyNestedListProperty_OnPOCO_ShouldAddValue_AtSuppliedPosition() + { + // Arrange + var model = new Class3() + { + SimpleDTOProperty = new SimpleDTO() + { + IntegerIList = new List() { 1, 2, 3 } + } + }; + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleDTOProperty.IntegerIList, value: 4, position: 0); + + // Act + patchDoc.ApplyTo(model); + + // Assert + Assert.Equal(new List() { 4, 1, 2, 3 }, model.SimpleDTOProperty.IntegerIList); + } + + [Fact] + public void AddElement_ToDeeplyNestedListProperty_OnPOCO_ShouldAddValue_AtSuppliedPosition_WithSerialization() + { + // Arrange + var model = new Class3() + { + SimpleDTOProperty = new SimpleDTO() + { + IntegerIList = new List() { 1, 2, 3 } + } + }; + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleDTOProperty.IntegerIList, value: 4, position: 0); + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(model); + + // Assert + Assert.Equal(new List() { 4, 1, 2, 3 }, model.SimpleDTOProperty.IntegerIList); + } + + class Class4 + { + public int IntegerProperty { get; set; } + } + + [Fact] + public void Remove_OnNonReferenceType_POCOProperty_ShouldSetDefaultValue() + { + // Arrange + var model = new Class4() + { + IntegerProperty = 10 + }; + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.IntegerProperty); + + // Act + patchDoc.ApplyTo(model); + + // Assert + Assert.Equal(0, model.IntegerProperty); + } + + [Fact] + public void Remove_OnNonReferenceType_POCOProperty_ShouldSetDefaultValue_WithSerialization() + { + // Arrange + var doc = new SimpleDTO() + { + StringProperty = "A" + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.StringProperty); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal(null, doc.StringProperty); + } + + class ClassWithPrivateProperties + { + public string Name { get; set; } + private int Age { get; set; } = 45; + } + + [Fact] + public void Add_OnPrivateProperties_FailesWithException() + { + // Arrange + var doc = new ClassWithPrivateProperties() + { + Name = "James" + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add("/Age", 30); + + // Act & Assert + var exception = Assert.Throws(() => patchDoc.ApplyTo(doc)); + Assert.Equal( + string.Format("The target location specified by path segment '{0}' was not found.", "Age"), + exception.Message); + } } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs new file mode 100644 index 0000000000..a03b830e02 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs @@ -0,0 +1,230 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Dynamic; +using Newtonsoft.Json.Serialization; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + public class ObjectVisitorTest + { + private class Class1 + { + public string Name { get; set; } + public IList States { get; set; } = new List(); + public IDictionary Countries = new Dictionary(); + public dynamic Items { get; set; } = new ExpandoObject(); + } + + private class Class1Nested + { + public List Customers { get; set; } = new List(); + } + + public static IEnumerable ReturnsListAdapterData + { + get + { + var model = new Class1(); + yield return new object[] { model, "/States/-", model.States }; + yield return new object[] { model.States, "/-", model.States }; + + var nestedModel = new Class1Nested(); + nestedModel.Customers.Add(new Class1()); + yield return new object[] { nestedModel, "/Customers/0/States/-", nestedModel.Customers[0].States }; + yield return new object[] { nestedModel, "/Customers/0/States/0", nestedModel.Customers[0].States }; + yield return new object[] { nestedModel.Customers, "/0/States/-", nestedModel.Customers[0].States }; + yield return new object[] { nestedModel.Customers[0], "/States/-", nestedModel.Customers[0].States }; + } + } + + [Theory] + [MemberData(nameof(ReturnsListAdapterData))] + public void Visit_ValidPathToArray_ReturnsListAdapter(object targetObject, string path, object expectedTargetObject) + { + // Arrange + var visitor = new ObjectVisitor(new ParsedPath(path), new DefaultContractResolver()); + IAdapter adapter = null; + string message = null; + + // Act + var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + + // Assert + Assert.True(visitStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Same(expectedTargetObject, targetObject); + Assert.IsType(adapter); + } + + public static IEnumerable ReturnsDictionaryAdapterData + { + get + { + var model = new Class1(); + yield return new object[] { model, "/Countries/USA", model.Countries }; + yield return new object[] { model.Countries, "/USA", model.Countries }; + + var nestedModel = new Class1Nested(); + nestedModel.Customers.Add(new Class1()); + yield return new object[] { nestedModel, "/Customers/0/Countries/USA", nestedModel.Customers[0].Countries }; + yield return new object[] { nestedModel.Customers, "/0/Countries/USA", nestedModel.Customers[0].Countries }; + yield return new object[] { nestedModel.Customers[0], "/Countries/USA", nestedModel.Customers[0].Countries }; + } + } + + [Theory] + [MemberData(nameof(ReturnsDictionaryAdapterData))] + public void Visit_ValidPathToDictionary_ReturnsDictionaryAdapter(object targetObject, string path, object expectedTargetObject) + { + // Arrange + var visitor = new ObjectVisitor(new ParsedPath(path), new DefaultContractResolver()); + IAdapter adapter = null; + string message = null; + + // Act + var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + + // Assert + Assert.True(visitStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Same(expectedTargetObject, targetObject); + Assert.IsType(adapter); + } + + public static IEnumerable ReturnsExpandoAdapterData + { + get + { + var model = new Class1(); + yield return new object[] { model, "/Items/Name", model.Items }; + yield return new object[] { model.Items, "/Name", model.Items }; + + var nestedModel = new Class1Nested(); + nestedModel.Customers.Add(new Class1()); + yield return new object[] { nestedModel, "/Customers/0/Items/Name", nestedModel.Customers[0].Items }; + yield return new object[] { nestedModel.Customers, "/0/Items/Name", nestedModel.Customers[0].Items }; + yield return new object[] { nestedModel.Customers[0], "/Items/Name", nestedModel.Customers[0].Items }; + } + } + + [Theory] + [MemberData(nameof(ReturnsExpandoAdapterData))] + public void Visit_ValidPathToExpandoObject_ReturnsExpandoAdapter(object targetObject, string path, object expectedTargetObject) + { + // Arrange + var visitor = new ObjectVisitor(new ParsedPath(path), new DefaultContractResolver()); + IAdapter adapter = null; + string message = null; + + // Act + var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + + // Assert + Assert.True(visitStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Same(expectedTargetObject, targetObject); + Assert.IsType(adapter); + } + + public static IEnumerable ReturnsPocoAdapterData + { + get + { + var model = new Class1(); + yield return new object[] { model, "/Name", model }; + + var nestedModel = new Class1Nested(); + nestedModel.Customers.Add(new Class1()); + yield return new object[] { nestedModel, "/Customers/0/Name", nestedModel.Customers[0] }; + yield return new object[] { nestedModel.Customers, "/0/Name", nestedModel.Customers[0] }; + yield return new object[] { nestedModel.Customers[0], "/Name", nestedModel.Customers[0] }; + } + } + + [Theory] + [MemberData(nameof(ReturnsPocoAdapterData))] + public void Visit_ValidPath_ReturnsExpandoAdapter(object targetObject, string path, object expectedTargetObject) + { + // Arrange + var visitor = new ObjectVisitor(new ParsedPath(path), new DefaultContractResolver()); + IAdapter adapter = null; + string message = null; + + // Act + var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + + // Assert + Assert.True(visitStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Same(expectedTargetObject, targetObject); + Assert.IsType(adapter); + } + + [Theory] + [InlineData("0")] + [InlineData("-1")] + public void Visit_InvalidIndexToArray_Fails(string position) + { + // Arrange + var visitor = new ObjectVisitor(new ParsedPath($"/Customers/{position}/States/-"), new DefaultContractResolver()); + var automobileDepartment = new Class1Nested(); + object targetObject = automobileDepartment; + IAdapter adapter = null; + string message = null; + + // Act + var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + + // Assert + Assert.False(visitStatus); + Assert.Equal( + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", position), + message); + } + + [Theory] + [InlineData("-")] + [InlineData("foo")] + public void Visit_InvalidIndexFormatToArray_Fails(string position) + { + // Arrange + var visitor = new ObjectVisitor(new ParsedPath($"/Customers/{position}/States/-"), new DefaultContractResolver()); + var automobileDepartment = new Class1Nested(); + object targetObject = automobileDepartment; + IAdapter adapter = null; + string message = null; + + // Act + var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + + // Assert + Assert.False(visitStatus); + Assert.Equal(string.Format( + "The path segment '{0}' is invalid for an array index.", position), + message); + } + + // The adapter takes care of the responsibility of validating the final segment + [Fact] + public void Visit_DoesNotValidate_FinalPathSegment() + { + // Arrange + var visitor = new ObjectVisitor(new ParsedPath($"/NonExisting"), new DefaultContractResolver()); + var model = new Class1(); + object targetObject = model; + IAdapter adapter = null; + string message = null; + + // Act + var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + + // Assert + Assert.True(visitStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.IsType(adapter); + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs~RF1ad82e13.TMP b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs~RF1ad82e13.TMP new file mode 100644 index 0000000000..694c33c633 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs~RF1ad82e13.TMP @@ -0,0 +1,119 @@ +using System.Collections.Generic; +using Newtonsoft.Json.Serialization; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + public class ObjectVisitorTest + { + private class Class1 + { + public IList States { get; set; } = new List(); + public IDictionary Countries = new Dictionary(); + } + + [Fact] + public void Visit_ValidPathToArray_ReturnsListAdapter() + { + // Arrange + var visitor = new ObjectVisitor(new ParsedPath("/States/-"), new DefaultContractResolver()); + var model = new Class1(); + object targetObject = model; + IAdapter adapter = null; + string message = null; + + // Act + var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + + // Assert + Assert.True(visitStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Same(model.States, targetObject); + Assert.IsType(adapter); + } + + [Fact] + public void Visit_ValidPathToDictionary_ReturnsDictionaryAdapter() + { + // Arrange + var visitor = new ObjectVisitor(new ParsedPath("/Countries/USA"), new DefaultContractResolver()); + var model = new Class1(); + object targetObject = model; + IAdapter adapter = null; + string message = null; + + // Act + var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + + // Assert + Assert.True(visitStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Same(model.Countries, targetObject); + Assert.IsType(adapter); + } + + private class AutomobileDepartment + { + public List Customers { get; set; } = new List(); + } + + [Fact] + public void Visit_ValidPathToArray_ReturnsListAdapter_ForDeepNestedPath() + { + // Arrange + var visitor = new ObjectVisitor(new ParsedPath("/Customers/0/States/-"), new DefaultContractResolver()); + var customer = new Class1(); + var automobileDepartment = new AutomobileDepartment(); + automobileDepartment.Customers.Add(customer); + object targetObject = automobileDepartment; + IAdapter adapter = null; + string message = null; + + // Act + var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + + // Assert + Assert.True(visitStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Same(customer.States, targetObject); + Assert.IsType(adapter); + } + + [Fact] + public void Visit_InvalidPathToArray_Fails() + { + // Arrange + var invalidIndex = 2; + var visitor = new ObjectVisitor(new ParsedPath($"/Customers/{invalidIndex}/States/-"), new DefaultContractResolver()); + var automobileDepartment = new AutomobileDepartment(); + object targetObject = automobileDepartment; + IAdapter adapter = null; + string message = null; + + // Act + var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + + // Assert + Assert.False(visitStatus); + Assert.Equal(string.Format(ErrorMessageFormats.IndexOutOfBounds, invalidIndex), message); + } + + [Fact] + public void Visit_DoesNotValidate_FinalPathSegment() + { + // Arrange + var visitor = new ObjectVisitor(new ParsedPath($"/NonExisting"), new DefaultContractResolver()); + var model = new Class1(); + object targetObject = model; + IAdapter adapter = null; + string message = null; + + // Act + var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + + // Assert + Assert.False(visitStatus); + Assert.Equal(string.Format(ErrorMessageFormats.TargetLocationAtPathSegmentNotFound, "NonExisting"), message); + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs~RF1ae034c3.TMP b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs~RF1ae034c3.TMP new file mode 100644 index 0000000000..88139198ac --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs~RF1ae034c3.TMP @@ -0,0 +1,131 @@ +using System.Collections.Generic; +using Newtonsoft.Json.Serialization; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + public class ObjectVisitorTest + { + private class Class1 + { + public IList States { get; set; } = new List(); + public IDictionary Countries = new Dictionary(); + } + + public static IEnumerable ReturnsListAdapterData + { + get + { + var model = new Class1(); + yield return new object[] { model, "/States/-", model.States }; + + yield return new object[] { model.States, "/-", model.States }; + } + } + + [Theory] + [MemberData(nameof(ReturnsListAdapterData))] + public void Visit_ValidPathToArray_ReturnsListAdapter(object targetObject, string path, object expectedTargetObject) + { + // Arrange + var visitor = new ObjectVisitor(new ParsedPath(path), new DefaultContractResolver()); + IAdapter adapter = null; + string message = null; + + // Act + var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + + // Assert + Assert.True(visitStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Same(expectedTargetObject, targetObject); + Assert.IsType(adapter); + } + + [Fact] + public void Visit_ValidPathToDictionary_ReturnsDictionaryAdapter() + { + // Arrange + var visitor = new ObjectVisitor(new ParsedPath("/Countries/USA"), new DefaultContractResolver()); + var model = new Class1(); + object targetObject = model; + IAdapter adapter = null; + string message = null; + + // Act + var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + + // Assert + Assert.True(visitStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Same(model.Countries, targetObject); + Assert.IsType(adapter); + } + + private class AutomobileDepartment + { + public List Customers { get; set; } = new List(); + } + + [Fact] + public void Visit_ValidPathToArray_ReturnsListAdapter_ForDeepNestedPath() + { + // Arrange + var visitor = new ObjectVisitor(new ParsedPath("/Customers/0/States/-"), new DefaultContractResolver()); + var customer = new Class1(); + var automobileDepartment = new AutomobileDepartment(); + automobileDepartment.Customers.Add(customer); + object targetObject = automobileDepartment; + IAdapter adapter = null; + string message = null; + + // Act + var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + + // Assert + Assert.True(visitStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Same(customer.States, targetObject); + Assert.IsType(adapter); + } + + [Fact] + public void Visit_InvalidPathToArray_Fails() + { + // Arrange + var invalidIndex = 2; + var visitor = new ObjectVisitor(new ParsedPath($"/Customers/{invalidIndex}/States/-"), new DefaultContractResolver()); + var automobileDepartment = new AutomobileDepartment(); + object targetObject = automobileDepartment; + IAdapter adapter = null; + string message = null; + + // Act + var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + + // Assert + Assert.False(visitStatus); + Assert.Equal(string.Format(ErrorMessageFormats.IndexOutOfBounds, invalidIndex), message); + } + + // The adapter takes care of the responsibility of validating the final segment + [Fact] + public void Visit_DoesNotValidate_FinalPathSegment() + { + // Arrange + var visitor = new ObjectVisitor(new ParsedPath($"/NonExisting"), new DefaultContractResolver()); + var model = new Class1(); + object targetObject = model; + IAdapter adapter = null; + string message = null; + + // Act + var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + + // Assert + Assert.True(visitStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.IsType(adapter); + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTO.cs index 1206cd108f..6dc1f173de 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTO.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTO.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; -namespace Microsoft.AspNetCore.JsonPatch.Test +namespace Microsoft.AspNetCore.JsonPatch { public class SimpleDTO { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTO.cs index dbded242ee..879d820277 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTO.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTO.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; -namespace Microsoft.AspNetCore.JsonPatch.Test +namespace Microsoft.AspNetCore.JsonPatch { public class SimpleDTOWithNestedDTO { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/TestErrorLogger.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/TestErrorLogger.cs index 6db8a42684..2cd6a4453e 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/TestErrorLogger.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/TestErrorLogger.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.JsonPatch.Test +namespace Microsoft.AspNetCore.JsonPatch { public class TestErrorLogger where T : class { From 3b7f9b4043c978e1ce1d1d9d974be36f05b8e985 Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Fri, 7 Oct 2016 11:28:07 -0700 Subject: [PATCH 0275/1029] Fixed version of System.Reflection.TypeExtensions package --- src/Microsoft.AspNetCore.JsonPatch/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index c9beba3639..5b998272ff 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -33,7 +33,7 @@ "netstandard1.3": { "dependencies": { "Microsoft.CSharp": "4.3.0-*", - "System.Reflection.TypeExtensions": "4.1.0-*" + "System.Reflection.TypeExtensions": "4.3.0-*" } } } From c20b9ae8940ef90237ee2fb5fc9fc83d16a864aa Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 10 Oct 2016 11:30:12 -0700 Subject: [PATCH 0276/1029] Add PackageLockFile to IProjectContext (#187) --- .../DotNet/DotNetProjectContext.cs | 1 + .../IProjectContext.cs | 1 + .../MsBuild/MsBuildProjectContext.cs | 13 ++++++++++++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetProjectContext.cs index d28d100515..7de51a2b53 100644 --- a/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetProjectContext.cs +++ b/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetProjectContext.cs @@ -58,6 +58,7 @@ namespace Microsoft.Extensions.ProjectModel public string DepsJson => _paths.RuntimeFiles.DepsJson; public string RuntimeConfigJson => _paths.RuntimeFiles.RuntimeConfigJson; public string PackagesDirectory => _projectContext.PackagesDirectory; + public string PackageLockFile => Path.Combine(Path.GetDirectoryName(ProjectFullPath), "project.lock.json"); public string AssemblyFullPath => !IsClassLibrary && (_projectContext.IsPortable || TargetFramework.IsDesktop()) diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/IProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.Sources/IProjectContext.cs index 64af21c0db..163c033bcb 100644 --- a/src/Microsoft.Extensions.ProjectModel.Sources/IProjectContext.cs +++ b/src/Microsoft.Extensions.ProjectModel.Sources/IProjectContext.cs @@ -18,6 +18,7 @@ namespace Microsoft.Extensions.ProjectModel string Config { get; } string DepsJson { get; } string RuntimeConfigJson { get; } + string PackageLockFile { get; } string PackagesDirectory { get; } string TargetDirectory { get; } string AssemblyFullPath { get; } diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContext.cs index b11c6b48d9..4e9a6f89c0 100644 --- a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContext.cs +++ b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContext.cs @@ -54,8 +54,19 @@ namespace Microsoft.Extensions.ProjectModel public string Config => AssemblyFullPath + ".config"; public string DepsJson => Path.Combine(TargetDirectory, Path.GetFileNameWithoutExtension(AssemblyFullPath) + ".deps.json"); public string RuntimeConfigJson => Path.Combine(TargetDirectory, Path.GetFileNameWithoutExtension(AssemblyFullPath) + ".runtimeconfig.json"); - public string PackagesDirectory => FindProperty("NuGetPackageRoot"); + public string PackageLockFile + { + get + { + var restoreOutputPath = FindProperty("RestoreOutputPath"); + if (string.IsNullOrEmpty(restoreOutputPath)) + { + restoreOutputPath = Path.Combine(Path.GetDirectoryName(ProjectFullPath), "obj"); + } + return Path.Combine(restoreOutputPath, "project.assets.json"); + } + } public string AssemblyFullPath => FindProperty("TargetPath"); public string Platform => FindProperty("Platform"); public string ProjectFullPath => _project.FullPath; From f7932b57a6de2a98db23cf0d7616c3b6815a9113 Mon Sep 17 00:00:00 2001 From: Prafull Bhosale Date: Thu, 6 Oct 2016 16:54:43 -0700 Subject: [PATCH 0277/1029] Add Dependency Resolution Apis to ProjectContext Abstractions --- .../DotNet/DotNetDependencyProvider.cs | 98 ++++++++++ .../DotNet/DotNetProjectContext.cs | 33 ++++ .../IProjectContext.cs | 3 + .../MsBuild/MsBuildProjectContext.cs | 51 +++++- .../MsBuild/MsBuildProjectContextBuilder.cs | 10 +- .../MsBuildProjectDependencyProvider.cs | 126 +++++++++++++ .../Resolution/Dependency.cs | 26 +++ .../Resolution/DependencyDescription.cs | 51 ++++++ .../Resolution/DependencyType.cs | 20 ++ .../Resolution/ResolvedReference.cs | 21 +++ .../DotNet/DotNetDependencyProviderTests.cs | 88 +++++++++ .../MsBuildProjectContextBuilderTest.cs | 1 + .../MsBuildProjectDependencyProviderTests.cs | 171 ++++++++++++++++++ 13 files changed, 685 insertions(+), 14 deletions(-) create mode 100644 src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetDependencyProvider.cs create mode 100644 src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectDependencyProvider.cs create mode 100644 src/Microsoft.Extensions.ProjectModel.Sources/Resolution/Dependency.cs create mode 100644 src/Microsoft.Extensions.ProjectModel.Sources/Resolution/DependencyDescription.cs create mode 100644 src/Microsoft.Extensions.ProjectModel.Sources/Resolution/DependencyType.cs create mode 100644 src/Microsoft.Extensions.ProjectModel.Sources/Resolution/ResolvedReference.cs create mode 100644 test/Microsoft.Extensions.ProjectModel.Tests/DotNet/DotNetDependencyProviderTests.cs create mode 100644 test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectDependencyProviderTests.cs diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetDependencyProvider.cs b/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetDependencyProvider.cs new file mode 100644 index 0000000000..429a2a6a68 --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetDependencyProvider.cs @@ -0,0 +1,98 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.IO; +using Microsoft.DotNet.ProjectModel; +using Microsoft.Extensions.ProjectModel.Resolution; +using Microsoft.DotNet.Cli.Utils; + +namespace Microsoft.Extensions.ProjectModel +{ + internal class DotNetDependencyProvider + { + private ProjectContext _context; + private List _packageDependencies; + private List _resolvedReferences; + private string _configuration; + + public DotNetDependencyProvider(ProjectContext context, string configuration = Constants.DefaultConfiguration) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + _configuration = configuration; + _context = context; + DiscoverDependencies(); + } + + public IEnumerable GetPackageDependencies() + { + return _packageDependencies; + } + + public IEnumerable GetResolvedReferences() + { + return _resolvedReferences; + } + + private void DiscoverDependencies() + { + var exporter = _context.CreateExporter(_configuration); + + if (exporter == null) + { + throw new InvalidOperationException($"Couldn't create a library exporter for configuration {_configuration}"); + } + + var framework = _context.TargetFramework; + if (framework == null) + { + throw new InvalidOperationException("Couldn't resolve dependencies when target framework is not specified."); + } + + var exports = exporter.GetAllExports(); + var nugetPackages = new Dictionary(StringComparer.OrdinalIgnoreCase); + _resolvedReferences = new List(); + + foreach (var export in exports) + { + var library = export.Library; + + var description = new DependencyDescription( + library.Identity.Name, + library.Identity.Version.ToString(), + export.Library.Path, + framework.DotNetFrameworkName, + library.Identity.Type.Value, + library.Resolved); + + foreach (var dependency in export.Library.Dependencies) + { + var dep = new Dependency(dependency.Name, version: string.Empty); + description.AddDependency(dep); + } + + var itemSpec = $"{framework.DotNetFrameworkName}/{library.Identity.Name}/{library.Identity.Version.ToString()}"; + nugetPackages[itemSpec] = description; + + if (library.Resolved) + { + foreach (var asset in export.CompilationAssemblies) + { + var resolvedRef = new ResolvedReference( + name: Path.GetFileNameWithoutExtension(asset.FileName), + resolvedPath: asset.ResolvedPath); + _resolvedReferences.Add(resolvedRef); + } + } + } + + _packageDependencies = nugetPackages.Values.ToList(); + } + } +} diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetProjectContext.cs index 7de51a2b53..b2b9851ea8 100644 --- a/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetProjectContext.cs +++ b/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetProjectContext.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using Microsoft.DotNet.ProjectModel; +using Microsoft.Extensions.ProjectModel.Resolution; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NuGet.Frameworks; @@ -17,6 +18,10 @@ namespace Microsoft.Extensions.ProjectModel private readonly OutputPaths _paths; private readonly Lazy _rawProject; private readonly CommonCompilerOptions _compilerOptions; + private readonly Lazy _dependencyProvider; + + private IEnumerable _packageDependencies; + private IEnumerable _compilationAssemblies; public DotNetProjectContext(ProjectContext projectContext, string configuration, string outputPath) { @@ -49,6 +54,8 @@ namespace Microsoft.Extensions.ProjectModel // Workaround https://github.com/dotnet/cli/issues/3164 IsClassLibrary = !(_compilerOptions.EmitEntryPoint ?? projectContext.ProjectFile.GetCompilerOptions(null, configuration).EmitEntryPoint.GetValueOrDefault()); + + _dependencyProvider = new Lazy(() => new DotNetDependencyProvider(_projectContext)); } public bool IsClassLibrary { get; } @@ -79,6 +86,32 @@ namespace Microsoft.Extensions.ProjectModel public IEnumerable EmbededItems => _compilerOptions.EmbedInclude.ResolveFiles(); + public IEnumerable PackageDependencies + { + get + { + if (_packageDependencies == null) + { + _packageDependencies = _dependencyProvider.Value.GetPackageDependencies(); + } + + return _packageDependencies; + } + } + + public IEnumerable CompilationAssemblies + { + get + { + if (_compilationAssemblies == null) + { + _compilationAssemblies = _dependencyProvider.Value.GetResolvedReferences(); + } + + return _compilationAssemblies; + } + } + /// /// Returns string values of top-level keys in the project.json file /// diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/IProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.Sources/IProjectContext.cs index 163c033bcb..ce7731fac6 100644 --- a/src/Microsoft.Extensions.ProjectModel.Sources/IProjectContext.cs +++ b/src/Microsoft.Extensions.ProjectModel.Sources/IProjectContext.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using Microsoft.Extensions.ProjectModel.Resolution; using NuGet.Frameworks; namespace Microsoft.Extensions.ProjectModel @@ -25,5 +26,7 @@ namespace Microsoft.Extensions.ProjectModel IEnumerable CompilationItems { get; } IEnumerable EmbededItems { get; } string FindProperty(string propertyName); + IEnumerable PackageDependencies { get;} + IEnumerable CompilationAssemblies { get; } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContext.cs index 4e9a6f89c0..dc2369065e 100644 --- a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContext.cs +++ b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContext.cs @@ -7,6 +7,7 @@ using System.IO; using Microsoft.Build.Execution; using NuGet.Frameworks; using System.Linq; +using Microsoft.Extensions.ProjectModel.Resolution; namespace Microsoft.Extensions.ProjectModel { @@ -16,23 +17,28 @@ namespace Microsoft.Extensions.ProjectModel private const string EmbedItemName = "EmbeddedResource"; private const string FullPathMetadataName = "FullPath"; - private readonly ProjectInstance _project; - private readonly string _name; + private readonly MsBuildProjectDependencyProvider _dependencyProvider; + private IEnumerable _packageDependencies; + private IEnumerable _compilationAssemblies; + + protected ProjectInstance Project { get; } + protected string Name { get; } public MsBuildProjectContext(string name, string configuration, ProjectInstance project) { - _project = project; + Project = project; Configuration = configuration; - _name = name; + Name = name; + _dependencyProvider = new MsBuildProjectDependencyProvider(Project); } public string FindProperty(string propertyName) { - return _project.GetProperty(propertyName)?.EvaluatedValue; + return Project.GetProperty(propertyName)?.EvaluatedValue; } - public string ProjectName => FindProperty("ProjectName") ?? _name; + public string ProjectName => FindProperty("ProjectName") ?? Name; public string Configuration { get; } public NuGetFramework TargetFramework @@ -69,14 +75,41 @@ namespace Microsoft.Extensions.ProjectModel } public string AssemblyFullPath => FindProperty("TargetPath"); public string Platform => FindProperty("Platform"); - public string ProjectFullPath => _project.FullPath; + public string ProjectFullPath => Project.FullPath; public string RootNamespace => FindProperty("RootNamespace") ?? ProjectName; public string TargetDirectory => FindProperty("TargetDir"); public IEnumerable CompilationItems - => _project.GetItems(CompileItemName).Select(i => i.GetMetadataValue(FullPathMetadataName)); + => Project.GetItems(CompileItemName).Select(i => i.GetMetadataValue(FullPathMetadataName)); public IEnumerable EmbededItems - => _project.GetItems(EmbedItemName).Select(i => i.GetMetadataValue(FullPathMetadataName)); + => Project.GetItems(EmbedItemName).Select(i => i.GetMetadataValue(FullPathMetadataName)); + + public IEnumerable PackageDependencies + { + get + { + if (_packageDependencies == null) + { + _packageDependencies = _dependencyProvider.GetPackageDependencies(); + } + + return _packageDependencies; + } + } + + public IEnumerable CompilationAssemblies + { + get + { + if (_compilationAssemblies == null) + { + _compilationAssemblies = _dependencyProvider.GetResolvedReferences(); + } + + return _compilationAssemblies; + } + } + } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContextBuilder.cs b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContextBuilder.cs index 20d1f6cdc4..8033dd0012 100644 --- a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContextBuilder.cs +++ b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContextBuilder.cs @@ -20,10 +20,10 @@ namespace Microsoft.Extensions.ProjectModel { internal class MsBuildProjectContextBuilder { - private string _configuration; - private IFileInfo _fileInfo; - private string[] _buildTargets; - private Dictionary _globalProperties = new Dictionary(); + protected string _configuration; + protected IFileInfo _fileInfo; + protected string[] _buildTargets; + protected Dictionary _globalProperties = new Dictionary(); private MsBuildContext _msbuildContext; public MsBuildProjectContextBuilder() @@ -186,7 +186,7 @@ namespace Microsoft.Extensions.ProjectModel protected virtual void Initialize() { - WithBuildTargets(new[] { "ResolveReferences" }); + WithBuildTargets(new[] { "ResolveReferences", "ResolvePackageDependenciesDesignTime" }); WithProperty("_ResolveReferenceDependencies", "true"); } diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectDependencyProvider.cs b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectDependencyProvider.cs new file mode 100644 index 0000000000..8c4345e158 --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectDependencyProvider.cs @@ -0,0 +1,126 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.Build.Execution; +using Microsoft.Extensions.ProjectModel.Resolution; + +namespace Microsoft.Extensions.ProjectModel +{ + internal class MsBuildProjectDependencyProvider + { + private const string PackageDependencyItemType = "_DependenciesDesignTime"; + private const string ResolvedReferenceItemType = "ReferencePath"; + + private readonly ProjectInstance _projectInstance; + public MsBuildProjectDependencyProvider(ProjectInstance projectInstance) + { + if (projectInstance == null) + { + throw new ArgumentNullException(nameof(projectInstance)); + } + _projectInstance = projectInstance; + } + + public IEnumerable GetPackageDependencies() + { + var packageItems = _projectInstance.GetItems(PackageDependencyItemType); + var packageInfo = new Dictionary(StringComparer.OrdinalIgnoreCase); + if (packageItems != null) + { + foreach (var packageItem in packageItems) + { + var packageDependency = CreateDependencyDescriptionFromItem(packageItem); + if (packageDependency != null) + { + packageInfo[packageItem.EvaluatedInclude] = packageDependency; + } + } + + // 2nd pass to populate dependencies; + + PopulateDependencies(packageInfo, packageItems); + } + + return packageInfo.Values; + } + + + public IEnumerable GetResolvedReferences() + { + var refItems = _projectInstance.GetItems(ResolvedReferenceItemType); + + var resolvedReferences = refItems + ?.Select(refItem => CreateResolvedReferenceFromProjectItem(refItem)) + .Where(resolvedReference => resolvedReference != null); + + return resolvedReferences; + } + + private static ResolvedReference CreateResolvedReferenceFromProjectItem(ProjectItemInstance item) + { + var resolvedPath = item.EvaluatedInclude; + + if (string.IsNullOrEmpty(resolvedPath)) + { + return null; + } + + var name = Path.GetFileNameWithoutExtension(resolvedPath); + return new ResolvedReference(name, resolvedPath); + } + + private static DependencyDescription CreateDependencyDescriptionFromItem(ProjectItemInstance item) + { + // For type == Target, we do not get Name in the metadata. This is a special node where the dependencies are + // the direct dependencies of the project. + var itemSpec = item.EvaluatedInclude; + var name = item.HasMetadata("Name") ? item.GetMetadataValue("Name") : itemSpec; + + if (string.IsNullOrEmpty(name)) + { + return null; + } + + var version = item.GetMetadataValue("Version"); + var path = item.GetMetadataValue("Path"); + var type = item.GetMetadataValue("Type"); + var resolved = item.GetMetadataValue("Resolved"); + + bool isResolved; + isResolved = bool.TryParse(resolved, out isResolved) ? isResolved : false; + var framework = itemSpec.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries).First(); + + return new DependencyDescription(name, version, path, framework, type, isResolved); + } + + private static void PopulateDependencies(Dictionary dependencies, ICollection items) + { + foreach (var item in items) + { + var depSpecs = item.GetMetadataValue("Dependencies") + ?.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + DependencyDescription currentDescription = null; + if (depSpecs == null || !dependencies.TryGetValue(item.EvaluatedInclude, out currentDescription)) + { + return; + } + + var prefix = item.EvaluatedInclude.Split('/').FirstOrDefault(); + foreach (var depSpec in depSpecs) + { + var spec = $"{prefix}/{depSpec}"; + DependencyDescription dependency = null; + if (dependencies.TryGetValue(spec, out dependency)) + { + var dep = new Dependency(dependency.Name, dependency.Version); + currentDescription.AddDependency(dep); + } + } + } + } + } +} diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/Resolution/Dependency.cs b/src/Microsoft.Extensions.ProjectModel.Sources/Resolution/Dependency.cs new file mode 100644 index 0000000000..7722da1762 --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.Sources/Resolution/Dependency.cs @@ -0,0 +1,26 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.Extensions.ProjectModel.Resolution +{ + public class Dependency + { + public Dependency(string name, string version) + { + if (string.IsNullOrEmpty(name)) + { + throw new ArgumentNullException(nameof(name)); + } + + Name = name; + Version = version; + } + public string Name { get; } + public string Version { get; } + } +} diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/Resolution/DependencyDescription.cs b/src/Microsoft.Extensions.ProjectModel.Sources/Resolution/DependencyDescription.cs new file mode 100644 index 0000000000..25dc5249f7 --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.Sources/Resolution/DependencyDescription.cs @@ -0,0 +1,51 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.Extensions.ProjectModel.Resolution +{ + public class DependencyDescription + { + private readonly List _dependencies; + + public DependencyDescription(string name, string version, string path, string framework, string type, bool isResolved) + { + if (string.IsNullOrEmpty(name)) + { + throw new ArgumentNullException(nameof(name)); + } + + if (string.IsNullOrEmpty(framework)) + { + throw new ArgumentNullException(nameof(framework)); + } + + Name = name; + Version = version; + TargetFramework = framework; + Resolved = isResolved; + Path = path; + DependencyType dt; + Type = Enum.TryParse(type, ignoreCase: true , result: out dt) ? dt : DependencyType.Unknown; + + _dependencies = new List(); + } + + public string TargetFramework { get; } + public string Name { get; } + public string Path { get; } + public string Version { get; } + public DependencyType Type { get; } + public bool Resolved { get; } + public IEnumerable Dependencies => _dependencies; + + public void AddDependency(Dependency dependency) + { + _dependencies.Add(dependency); + } + } +} diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/Resolution/DependencyType.cs b/src/Microsoft.Extensions.ProjectModel.Sources/Resolution/DependencyType.cs new file mode 100644 index 0000000000..4f49efa9b1 --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.Sources/Resolution/DependencyType.cs @@ -0,0 +1,20 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.Extensions.ProjectModel.Resolution +{ + public enum DependencyType + { + Target, + Package, + Assembly, + Project, + AnalyzerAssembly, + Unknown + } +} diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/Resolution/ResolvedReference.cs b/src/Microsoft.Extensions.ProjectModel.Sources/Resolution/ResolvedReference.cs new file mode 100644 index 0000000000..4833d86071 --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.Sources/Resolution/ResolvedReference.cs @@ -0,0 +1,21 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.Extensions.ProjectModel.Resolution +{ + public class ResolvedReference + { + public ResolvedReference(string name,string resolvedPath) + { + Name = name; + ResolvedPath = resolvedPath; + } + public string ResolvedPath { get; } + public string Name { get; } + } +} diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/DotNet/DotNetDependencyProviderTests.cs b/test/Microsoft.Extensions.ProjectModel.Tests/DotNet/DotNetDependencyProviderTests.cs new file mode 100644 index 0000000000..ccb96e4303 --- /dev/null +++ b/test/Microsoft.Extensions.ProjectModel.Tests/DotNet/DotNetDependencyProviderTests.cs @@ -0,0 +1,88 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Linq; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.ProjectModel; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.Extensions.ProjectModel.DotNet +{ + public class DotNetDependencyProviderTests + { + private const string projectJson = @" +{ + ""buildOptions"": { + }, + ""dependencies"": { + ""Microsoft.AspNetCore.Mvc"": ""1.0.0-*"", + }, + ""frameworks"": { + ""netcoreapp1.0"": { + ""dependencies"": { + ""Microsoft.NETCore.App"": { + ""version"": ""1.0.0"", + ""type"": ""platform"" + } + } + } + }, +} +"; + private readonly ITestOutputHelper _output; + + public DotNetDependencyProviderTests(ITestOutputHelper output) + { + _output = output; + } + + [Fact] + public void BuildProjectDependencies() + { + using (var fileProvider = new TemporaryFileProvider()) + { + Directory.CreateDirectory(Path.Combine(fileProvider.Root, "demo")); + fileProvider.Add($"demo{Path.DirectorySeparatorChar}project.json", projectJson); + fileProvider.Add($"demo{Path.DirectorySeparatorChar}First.cs", "namespace demo { class First{} }"); + + var muxer = new Muxer().MuxerPath; + + var result = Command + .Create(muxer, new[] { "restore", Path.Combine(fileProvider.Root, "demo") }) + .OnErrorLine(l => _output.WriteLine(l)) + .OnOutputLine(l => _output.WriteLine(l)) + .Execute(); + + Assert.Equal(0, result.ExitCode); + var oldContext = ProjectContext + .CreateContextForEachFramework(Path.Combine(fileProvider.Root, "demo", "project.json")) + .First(); + + var context = new DotNetProjectContext(oldContext, "Debug", Path.Combine(fileProvider.Root, "demo", "bin")); + + var home = Environment.GetEnvironmentVariable("USERPROFILE") + ?? Environment.GetEnvironmentVariable("HOME"); + var nugetPackageRoot = Path.Combine(home, ".nuget", "packages"); + var expectedPackagePath = Path.Combine(nugetPackageRoot, "Microsoft.AspNetCore.Mvc", "1.0.0"); + var expectedReferencePath = Path.Combine(expectedPackagePath, "lib", "netstandard1.6", "Microsoft.AspNetCore.Mvc.dll"); + + var assembly = context + .CompilationAssemblies + .Where(asm => asm.Name.Equals("Microsoft.AspNetCore.Mvc", StringComparison.OrdinalIgnoreCase)) + .First(); + + Assert.Equal(expectedReferencePath, assembly.ResolvedPath); + + var mvcPackage = context + .PackageDependencies + .Where(package => package.Name.Equals("Microsoft.AspNetCore.Mvc", StringComparison.OrdinalIgnoreCase)) + .First(); + + Assert.Equal(expectedPackagePath, mvcPackage.Path); + } + } + } +} diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs index 1f840b9be6..4dfeab0d99 100644 --- a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs +++ b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs @@ -102,6 +102,7 @@ namespace Microsoft.Extensions.ProjectModel "); + _files.Add("One.cs", "public class Abc {}"); _files.Add("Two.cs", "public class Abc2 {}"); _files.Add("Excluded.cs", "public class Abc {}"); diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectDependencyProviderTests.cs b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectDependencyProviderTests.cs new file mode 100644 index 0000000000..9caea9c562 --- /dev/null +++ b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectDependencyProviderTests.cs @@ -0,0 +1,171 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Linq; +using Microsoft.Extensions.ProjectModel.Tests; +using Xunit; +using Xunit.Abstractions; +using System.IO; +using Microsoft.DotNet.Cli.Utils; +using NuGet.Frameworks; + +namespace Microsoft.Extensions.ProjectModel.MsBuild +{ + public class MsBuildProjectDependencyProviderTests: IClassFixture + { + private const string NugetConfigTxt = @" + + + + + + + + +"; + + private const string RootProjectTxt = @" + + + + + Microsoft.TestProject + TestProject + Library + netcoreapp1.0 + bin\$(Configuration) + + + + + + + + + 1.0.0-* + + + 1.0.0-* + + + 1.0.1 + + + + + + + + + + +"; + + private const string LibraryProjectTxt = @" + + + + + Microsoft.Library + Library1 + Library + netcoreapp1.0 + bin\$(Configuration) + + + + + + + + + 1.0.0-* + + + 1.0.1 + + + + +"; + private readonly MsBuildFixture _fixture; + private readonly ITestOutputHelper _output; + + public MsBuildProjectDependencyProviderTests(MsBuildFixture fixture, ITestOutputHelper output) + { + _fixture = fixture; + _output = output; + } + + [Fact(Skip = "CI doesn't yet have a new enough version of .NET Core SDK")] + public void BuildDependenciesForProject() + { + using (var fileProvider = new TemporaryFileProvider()) + { + Directory.CreateDirectory(Path.Combine(fileProvider.Root, "Root")); + Directory.CreateDirectory(Path.Combine(fileProvider.Root, "Library1")); + // TODO remove when SDK becomes available on other feeds + fileProvider.Add("NuGet.config", NugetConfigTxt); + + // Add Root Project + fileProvider.Add($"Root{Path.DirectorySeparatorChar}test.csproj", RootProjectTxt); + fileProvider.Add($"Root{Path.DirectorySeparatorChar}One.cs", "public class Abc {}"); + fileProvider.Add($"Root{Path.DirectorySeparatorChar}Two.cs", "public class Abc2 {}"); + fileProvider.Add($"Root{Path.DirectorySeparatorChar}Excluded.cs", "public class Abc {}"); + + // Add Class Library project + fileProvider.Add($"Library1{Path.DirectorySeparatorChar}library.csproj", LibraryProjectTxt); + fileProvider.Add($"Library1{Path.DirectorySeparatorChar}Three.cs", "public class Abc3 {}"); + + var testContext = _fixture.GetMsBuildContext(); + + var muxer = Path.Combine(testContext.ExtensionsPath, "../..", "dotnet.exe"); + var result = Command + .Create(muxer, new[] { "restore3", Path.Combine(fileProvider.Root, "Library1","Library1.csproj") }) + .OnErrorLine(l => _output.WriteLine(l)) + .OnOutputLine(l => _output.WriteLine(l)) + .Execute(); + + Assert.Equal(0, result.ExitCode); + + result = Command + .Create(muxer, new[] { "restore3", Path.Combine(fileProvider.Root, "Root", "test.csproj") }) + .OnErrorLine(l => _output.WriteLine(l)) + .OnOutputLine(l => _output.WriteLine(l)) + .Execute(); + + Assert.Equal(0, result.ExitCode); + + var builder = new MsBuildProjectContextBuilder() + .AsDesignTimeBuild() + .UseMsBuild(testContext) + .WithTargetFramework(FrameworkConstants.CommonFrameworks.NetCoreApp10) + .WithConfiguration("Debug") + .WithProjectFile(fileProvider.GetFileInfo(Path.Combine("Root", "test.csproj"))); + + var context = builder.Build(); + + var compilationAssemblies = context.CompilationAssemblies; + var lib1Dll = compilationAssemblies + .Where(assembly => assembly.Name.Equals("Library1", StringComparison.OrdinalIgnoreCase)) + .FirstOrDefault(); + + Assert.NotNull(lib1Dll); + var expectedPath = Path.Combine(fileProvider.Root, "Root", "bin", "Debug", "netcoreapp1.0", "lib1.dll"); + Assert.Equal(expectedPath, lib1Dll.ResolvedPath, ignoreCase: true); + + // This reference doesn't resolve so should not be available here. + Assert.False(compilationAssemblies.Any(assembly => assembly.Name.Equals("xyz", StringComparison.OrdinalIgnoreCase))); + + var packageDependencies = context.PackageDependencies; + var mvcPackage = packageDependencies + .Where(p => p.Name.Equals("Microsoft.AspNetCore.Mvc", StringComparison.OrdinalIgnoreCase)) + .FirstOrDefault(); + Assert.NotNull(mvcPackage); + + Assert.True(mvcPackage.Dependencies.Any(dependency => dependency.Name.Equals("Microsoft.Extensions.DependencyInjection", StringComparison.OrdinalIgnoreCase))); + } + } + } +} From 78e35d3c6f07da3cd2b4722a227798957c7d6064 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 10 Oct 2016 13:11:31 -0700 Subject: [PATCH 0278/1029] Split ProjectModel into separate packages (#188) --- DotNetTools.sln | 28 ++++++++++++++----- NuGetPackageVerifier.json | 4 ++- makefile.shade | 7 ++++- .../IProjectContext.cs | 0 ...ns.ProjectModel.Abstractions.Sources.xproj | 19 +++++++++++++ .../Resolution/Dependency.cs | 0 .../Resolution/DependencyDescription.cs | 0 .../Resolution/DependencyType.cs | 0 .../Resolution/ResolvedReference.cs | 0 .../project.json | 0 .../DotNetDependencyProvider.cs | 0 .../DotNetProjectContext.cs | 0 .../IncludeContextExtensions.cs | 0 ...ensions.ProjectModel.DotNet.Sources.xproj} | 5 ++-- .../project.json | 7 +++++ .../Internal/DotNetCoreSdk.cs | 0 .../Internal/DotNetCoreSdkResolver.cs | 0 ...ensions.ProjectModel.MsBuild.Sources.xproj | 19 +++++++++++++ .../MsBuildContext.cs | 0 .../MsBuildExtensions.cs | 0 .../MsBuildProjectContext.cs | 0 .../MsBuildProjectContextBuilder.cs | 0 .../MsBuildProjectDependencyProvider.cs | 0 .../MsBuildProjectFinder.cs | 0 .../project.json | 7 +++++ .../project.json | 10 ++++++- 26 files changed, 94 insertions(+), 12 deletions(-) rename src/{Microsoft.Extensions.ProjectModel.Sources => Microsoft.Extensions.ProjectModel.Abstractions.Sources}/IProjectContext.cs (100%) create mode 100644 src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Microsoft.Extensions.ProjectModel.Abstractions.Sources.xproj rename src/{Microsoft.Extensions.ProjectModel.Sources => Microsoft.Extensions.ProjectModel.Abstractions.Sources}/Resolution/Dependency.cs (100%) rename src/{Microsoft.Extensions.ProjectModel.Sources => Microsoft.Extensions.ProjectModel.Abstractions.Sources}/Resolution/DependencyDescription.cs (100%) rename src/{Microsoft.Extensions.ProjectModel.Sources => Microsoft.Extensions.ProjectModel.Abstractions.Sources}/Resolution/DependencyType.cs (100%) rename src/{Microsoft.Extensions.ProjectModel.Sources => Microsoft.Extensions.ProjectModel.Abstractions.Sources}/Resolution/ResolvedReference.cs (100%) rename src/{Microsoft.Extensions.ProjectModel.Sources => Microsoft.Extensions.ProjectModel.Abstractions.Sources}/project.json (100%) rename src/{Microsoft.Extensions.ProjectModel.Sources/DotNet => Microsoft.Extensions.ProjectModel.DotNet.Sources}/DotNetDependencyProvider.cs (100%) rename src/{Microsoft.Extensions.ProjectModel.Sources/DotNet => Microsoft.Extensions.ProjectModel.DotNet.Sources}/DotNetProjectContext.cs (100%) rename src/{Microsoft.Extensions.ProjectModel.Sources/DotNet => Microsoft.Extensions.ProjectModel.DotNet.Sources}/IncludeContextExtensions.cs (100%) rename src/{Microsoft.Extensions.ProjectModel.Sources/Microsoft.Extensions.ProjectModel.Sources.xproj => Microsoft.Extensions.ProjectModel.DotNet.Sources/Microsoft.Extensions.ProjectModel.DotNet.Sources.xproj} (85%) create mode 100644 src/Microsoft.Extensions.ProjectModel.DotNet.Sources/project.json rename src/{Microsoft.Extensions.ProjectModel.Sources => Microsoft.Extensions.ProjectModel.MsBuild.Sources}/Internal/DotNetCoreSdk.cs (100%) rename src/{Microsoft.Extensions.ProjectModel.Sources => Microsoft.Extensions.ProjectModel.MsBuild.Sources}/Internal/DotNetCoreSdkResolver.cs (100%) create mode 100644 src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/Microsoft.Extensions.ProjectModel.MsBuild.Sources.xproj rename src/{Microsoft.Extensions.ProjectModel.Sources/MsBuild => Microsoft.Extensions.ProjectModel.MsBuild.Sources}/MsBuildContext.cs (100%) rename src/{Microsoft.Extensions.ProjectModel.Sources/MsBuild => Microsoft.Extensions.ProjectModel.MsBuild.Sources}/MsBuildExtensions.cs (100%) rename src/{Microsoft.Extensions.ProjectModel.Sources/MsBuild => Microsoft.Extensions.ProjectModel.MsBuild.Sources}/MsBuildProjectContext.cs (100%) rename src/{Microsoft.Extensions.ProjectModel.Sources/MsBuild => Microsoft.Extensions.ProjectModel.MsBuild.Sources}/MsBuildProjectContextBuilder.cs (100%) rename src/{Microsoft.Extensions.ProjectModel.Sources/MsBuild => Microsoft.Extensions.ProjectModel.MsBuild.Sources}/MsBuildProjectDependencyProvider.cs (100%) rename src/{Microsoft.Extensions.ProjectModel.Sources/MsBuild => Microsoft.Extensions.ProjectModel.MsBuild.Sources}/MsBuildProjectFinder.cs (100%) create mode 100644 src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/project.json diff --git a/DotNetTools.sln b/DotNetTools.sln index 44d6a3dac3..d1de4da4d0 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -38,10 +38,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{59E02BDF EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NuGetPackager", "tools\NuGetPackager\NuGetPackager.xproj", "{8B781D87-1FC3-4A34-9089-2BDF6B562B85}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.ProjectModel.Sources", "src\Microsoft.Extensions.ProjectModel.Sources\Microsoft.Extensions.ProjectModel.Sources.xproj", "{99D6CE89-7302-4C3A-83EB-D534C24644D2}" -EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.ProjectModel.Tests", "test\Microsoft.Extensions.ProjectModel.Tests\Microsoft.Extensions.ProjectModel.Tests.xproj", "{1A66A831-4F06-46D9-B483-70A4E75A2F7F}" EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.ProjectModel.Abstractions.Sources", "src\Microsoft.Extensions.ProjectModel.Abstractions.Sources\Microsoft.Extensions.ProjectModel.Abstractions.Sources.xproj", "{8A97D718-0681-43C5-A70B-535DBBDF4FA1}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.ProjectModel.DotNet.Sources", "src\Microsoft.Extensions.ProjectModel.DotNet.Sources\Microsoft.Extensions.ProjectModel.DotNet.Sources.xproj", "{1F643A36-A1FC-4502-9D03-75837F20E1A4}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.ProjectModel.MsBuild.Sources", "src\Microsoft.Extensions.ProjectModel.MsBuild.Sources\Microsoft.Extensions.ProjectModel.MsBuild.Sources.xproj", "{7362AE32-7753-4E7C-86D0-DCA86AF413FA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -92,14 +96,22 @@ Global {8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Debug|Any CPU.Build.0 = Debug|Any CPU {8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Release|Any CPU.ActiveCfg = Release|Any CPU {8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Release|Any CPU.Build.0 = Release|Any CPU - {99D6CE89-7302-4C3A-83EB-D534C24644D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {99D6CE89-7302-4C3A-83EB-D534C24644D2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {99D6CE89-7302-4C3A-83EB-D534C24644D2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {99D6CE89-7302-4C3A-83EB-D534C24644D2}.Release|Any CPU.Build.0 = Release|Any CPU {1A66A831-4F06-46D9-B483-70A4E75A2F7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1A66A831-4F06-46D9-B483-70A4E75A2F7F}.Debug|Any CPU.Build.0 = Debug|Any CPU {1A66A831-4F06-46D9-B483-70A4E75A2F7F}.Release|Any CPU.ActiveCfg = Release|Any CPU {1A66A831-4F06-46D9-B483-70A4E75A2F7F}.Release|Any CPU.Build.0 = Release|Any CPU + {8A97D718-0681-43C5-A70B-535DBBDF4FA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8A97D718-0681-43C5-A70B-535DBBDF4FA1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8A97D718-0681-43C5-A70B-535DBBDF4FA1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8A97D718-0681-43C5-A70B-535DBBDF4FA1}.Release|Any CPU.Build.0 = Release|Any CPU + {1F643A36-A1FC-4502-9D03-75837F20E1A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1F643A36-A1FC-4502-9D03-75837F20E1A4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1F643A36-A1FC-4502-9D03-75837F20E1A4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1F643A36-A1FC-4502-9D03-75837F20E1A4}.Release|Any CPU.Build.0 = Release|Any CPU + {7362AE32-7753-4E7C-86D0-DCA86AF413FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7362AE32-7753-4E7C-86D0-DCA86AF413FA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7362AE32-7753-4E7C-86D0-DCA86AF413FA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7362AE32-7753-4E7C-86D0-DCA86AF413FA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -117,7 +129,9 @@ Global {8A2E6961-6B12-4A8E-8215-3E7301D52EAC} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {53F3B53D-303A-4DAA-9C38-4F55195FA5B9} = {66517987-2A5A-4330-B130-207039378FD4} {8B781D87-1FC3-4A34-9089-2BDF6B562B85} = {59E02BDF-98DE-4D64-B576-2D0299D5E052} - {99D6CE89-7302-4C3A-83EB-D534C24644D2} = {66517987-2A5A-4330-B130-207039378FD4} {1A66A831-4F06-46D9-B483-70A4E75A2F7F} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} + {8A97D718-0681-43C5-A70B-535DBBDF4FA1} = {66517987-2A5A-4330-B130-207039378FD4} + {1F643A36-A1FC-4502-9D03-75837F20E1A4} = {66517987-2A5A-4330-B130-207039378FD4} + {7362AE32-7753-4E7C-86D0-DCA86AF413FA} = {66517987-2A5A-4330-B130-207039378FD4} EndGlobalSection EndGlobal diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index d0e3b370e2..7a340ecaad 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -33,7 +33,9 @@ "adx-nonshipping": { "rules": [], "packages": { - "Microsoft.Extensions.ProjectModel.Sources": {} + "Microsoft.Extensions.ProjectModel.Abstractions.Sources": {}, + "Microsoft.Extensions.ProjectModel.DotNet.Sources": {}, + "Microsoft.Extensions.ProjectModel.MsBuild.Sources": {} } }, "Default": { diff --git a/makefile.shade b/makefile.shade index f957f23173..d8d56a527e 100644 --- a/makefile.shade +++ b/makefile.shade @@ -22,7 +22,12 @@ k-standard-goals "-n src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec " + "-n src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec "); - DotnetPack("src/Microsoft.Extensions.ProjectModel.Sources/project.json", BUILD_DIR_LOCAL, E("Configuration"), E("KOREBUILD_DOTNET_PACK_OPTIONS") + " --no-build"); + var projectModel = Files.Include("src/Microsoft.Extensions.ProjectModel.*/project.json"); + foreach (var proj in projectModel) + { + DotnetPack(proj, BUILD_DIR_LOCAL, E("Configuration"), E("KOREBUILD_DOTNET_PACK_OPTIONS") + " --no-build"); + } + foreach (var nupkg in Files.Include(Path.Combine(BUILD_DIR_LOCAL, "*/" + E("Configuration") + "/*.nupkg"))) { File.Copy(nupkg, Path.Combine(BUILD_DIR_LOCAL, Path.GetFileName(nupkg)), true); diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/IProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/IProjectContext.cs similarity index 100% rename from src/Microsoft.Extensions.ProjectModel.Sources/IProjectContext.cs rename to src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/IProjectContext.cs diff --git a/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Microsoft.Extensions.ProjectModel.Abstractions.Sources.xproj b/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Microsoft.Extensions.ProjectModel.Abstractions.Sources.xproj new file mode 100644 index 0000000000..3a11d66f5f --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Microsoft.Extensions.ProjectModel.Abstractions.Sources.xproj @@ -0,0 +1,19 @@ + + + + 14.0.25420 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 8a97d718-0681-43c5-a70b-535dbbdf4fa1 + Microsoft.Extensions.ProjectModel.Abstractions.Sources + .\obj + .\bin\ + + + + 2.0 + + + \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/Resolution/Dependency.cs b/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/Dependency.cs similarity index 100% rename from src/Microsoft.Extensions.ProjectModel.Sources/Resolution/Dependency.cs rename to src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/Dependency.cs diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/Resolution/DependencyDescription.cs b/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/DependencyDescription.cs similarity index 100% rename from src/Microsoft.Extensions.ProjectModel.Sources/Resolution/DependencyDescription.cs rename to src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/DependencyDescription.cs diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/Resolution/DependencyType.cs b/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/DependencyType.cs similarity index 100% rename from src/Microsoft.Extensions.ProjectModel.Sources/Resolution/DependencyType.cs rename to src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/DependencyType.cs diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/Resolution/ResolvedReference.cs b/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/ResolvedReference.cs similarity index 100% rename from src/Microsoft.Extensions.ProjectModel.Sources/Resolution/ResolvedReference.cs rename to src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/ResolvedReference.cs diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/project.json b/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/project.json similarity index 100% rename from src/Microsoft.Extensions.ProjectModel.Sources/project.json rename to src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/project.json diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetDependencyProvider.cs b/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetDependencyProvider.cs similarity index 100% rename from src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetDependencyProvider.cs rename to src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetDependencyProvider.cs diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetProjectContext.cs similarity index 100% rename from src/Microsoft.Extensions.ProjectModel.Sources/DotNet/DotNetProjectContext.cs rename to src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetProjectContext.cs diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/DotNet/IncludeContextExtensions.cs b/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/IncludeContextExtensions.cs similarity index 100% rename from src/Microsoft.Extensions.ProjectModel.Sources/DotNet/IncludeContextExtensions.cs rename to src/Microsoft.Extensions.ProjectModel.DotNet.Sources/IncludeContextExtensions.cs diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/Microsoft.Extensions.ProjectModel.Sources.xproj b/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/Microsoft.Extensions.ProjectModel.DotNet.Sources.xproj similarity index 85% rename from src/Microsoft.Extensions.ProjectModel.Sources/Microsoft.Extensions.ProjectModel.Sources.xproj rename to src/Microsoft.Extensions.ProjectModel.DotNet.Sources/Microsoft.Extensions.ProjectModel.DotNet.Sources.xproj index 772d9c1c91..25df3ea5e1 100644 --- a/src/Microsoft.Extensions.ProjectModel.Sources/Microsoft.Extensions.ProjectModel.Sources.xproj +++ b/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/Microsoft.Extensions.ProjectModel.DotNet.Sources.xproj @@ -6,11 +6,12 @@ - 99d6ce89-7302-4c3a-83eb-d534c24644d2 - Microsoft.Extensions.ProjectModel + 1f643a36-a1fc-4502-9d03-75837f20e1a4 + Microsoft.Extensions.ProjectModel.DotNet.Sources .\obj .\bin\ + 2.0 diff --git a/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/project.json b/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/project.json new file mode 100644 index 0000000000..23d8c31849 --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/project.json @@ -0,0 +1,7 @@ +{ + "version": "1.0.0-*", + "shared": "**/*.cs", + "frameworks": { + "netstandard1.0": {} + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/Internal/DotNetCoreSdk.cs b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/Internal/DotNetCoreSdk.cs similarity index 100% rename from src/Microsoft.Extensions.ProjectModel.Sources/Internal/DotNetCoreSdk.cs rename to src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/Internal/DotNetCoreSdk.cs diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/Internal/DotNetCoreSdkResolver.cs b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/Internal/DotNetCoreSdkResolver.cs similarity index 100% rename from src/Microsoft.Extensions.ProjectModel.Sources/Internal/DotNetCoreSdkResolver.cs rename to src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/Internal/DotNetCoreSdkResolver.cs diff --git a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/Microsoft.Extensions.ProjectModel.MsBuild.Sources.xproj b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/Microsoft.Extensions.ProjectModel.MsBuild.Sources.xproj new file mode 100644 index 0000000000..d7ece4a980 --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/Microsoft.Extensions.ProjectModel.MsBuild.Sources.xproj @@ -0,0 +1,19 @@ + + + + 14.0.25420 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 7362ae32-7753-4e7c-86d0-dca86af413fa + Microsoft.Extensions.ProjectModel.MsBuild.Sources + .\obj + .\bin\ + + + + 2.0 + + + \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildContext.cs b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildContext.cs similarity index 100% rename from src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildContext.cs rename to src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildContext.cs diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildExtensions.cs b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildExtensions.cs similarity index 100% rename from src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildExtensions.cs rename to src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildExtensions.cs diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectContext.cs similarity index 100% rename from src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContext.cs rename to src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectContext.cs diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContextBuilder.cs b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectContextBuilder.cs similarity index 100% rename from src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectContextBuilder.cs rename to src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectContextBuilder.cs diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectDependencyProvider.cs b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectDependencyProvider.cs similarity index 100% rename from src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectDependencyProvider.cs rename to src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectDependencyProvider.cs diff --git a/src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectFinder.cs b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectFinder.cs similarity index 100% rename from src/Microsoft.Extensions.ProjectModel.Sources/MsBuild/MsBuildProjectFinder.cs rename to src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectFinder.cs diff --git a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/project.json b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/project.json new file mode 100644 index 0000000000..23d8c31849 --- /dev/null +++ b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/project.json @@ -0,0 +1,7 @@ +{ + "version": "1.0.0-*", + "shared": "**/*.cs", + "frameworks": { + "netstandard1.0": {} + } +} \ No newline at end of file diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/project.json b/test/Microsoft.Extensions.ProjectModel.Tests/project.json index 58c314075e..d408f83c23 100644 --- a/test/Microsoft.Extensions.ProjectModel.Tests/project.json +++ b/test/Microsoft.Extensions.ProjectModel.Tests/project.json @@ -12,7 +12,15 @@ "Microsoft.DotNet.ProjectModel": "1.0.0-rc3-003121", "Microsoft.Build.Runtime": "15.1.298-preview5", "Microsoft.Extensions.FileProviders.Physical": "1.1.0-*", - "Microsoft.Extensions.ProjectModel.Sources": { + "Microsoft.Extensions.ProjectModel.Abstractions.Sources": { + "type": "build", + "version": "1.0.0-*" + }, + "Microsoft.Extensions.ProjectModel.DotNet.Sources": { + "type": "build", + "version": "1.0.0-*" + }, + "Microsoft.Extensions.ProjectModel.MsBuild.Sources": { "type": "build", "version": "1.0.0-*" }, From 8be3b16756f1e68cf27cb08850497ed23f7b49c1 Mon Sep 17 00:00:00 2001 From: Prafull Bhosale Date: Mon, 10 Oct 2016 14:06:34 -0700 Subject: [PATCH 0279/1029] Fix DotNetDependencyProviderTest for CI --- .../DotNet/DotNetDependencyProviderTests.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/DotNet/DotNetDependencyProviderTests.cs b/test/Microsoft.Extensions.ProjectModel.Tests/DotNet/DotNetDependencyProviderTests.cs index ccb96e4303..e5fe160a69 100644 --- a/test/Microsoft.Extensions.ProjectModel.Tests/DotNet/DotNetDependencyProviderTests.cs +++ b/test/Microsoft.Extensions.ProjectModel.Tests/DotNet/DotNetDependencyProviderTests.cs @@ -63,25 +63,21 @@ namespace Microsoft.Extensions.ProjectModel.DotNet var context = new DotNetProjectContext(oldContext, "Debug", Path.Combine(fileProvider.Root, "demo", "bin")); - var home = Environment.GetEnvironmentVariable("USERPROFILE") - ?? Environment.GetEnvironmentVariable("HOME"); - var nugetPackageRoot = Path.Combine(home, ".nuget", "packages"); - var expectedPackagePath = Path.Combine(nugetPackageRoot, "Microsoft.AspNetCore.Mvc", "1.0.0"); - var expectedReferencePath = Path.Combine(expectedPackagePath, "lib", "netstandard1.6", "Microsoft.AspNetCore.Mvc.dll"); - var assembly = context .CompilationAssemblies .Where(asm => asm.Name.Equals("Microsoft.AspNetCore.Mvc", StringComparison.OrdinalIgnoreCase)) .First(); - Assert.Equal(expectedReferencePath, assembly.ResolvedPath); + Assert.True(File.Exists(assembly.ResolvedPath)); + Assert.True(assembly.ResolvedPath.EndsWith("Microsoft.AspNetCore.Mvc.dll", StringComparison.OrdinalIgnoreCase)); var mvcPackage = context .PackageDependencies .Where(package => package.Name.Equals("Microsoft.AspNetCore.Mvc", StringComparison.OrdinalIgnoreCase)) .First(); - Assert.Equal(expectedPackagePath, mvcPackage.Path); + Assert.True(Directory.Exists(mvcPackage.Path)); + Assert.True(mvcPackage.Path.EndsWith($"Microsoft.AspNetCore.Mvc{Path.DirectorySeparatorChar}1.0.0", StringComparison.OrdinalIgnoreCase)); } } } From 329b65fc698cc8ae42232f0144f96b38c7be5225 Mon Sep 17 00:00:00 2001 From: Prafull Bhosale Date: Wed, 12 Oct 2016 09:10:35 -0700 Subject: [PATCH 0280/1029] Add AssemblyName to ProjectContext --- .../IProjectContext.cs | 1 + .../DotNetProjectContext.cs | 4 +++- .../MsBuildProjectContext.cs | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/IProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/IProjectContext.cs index ce7731fac6..972f85caff 100644 --- a/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/IProjectContext.cs +++ b/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/IProjectContext.cs @@ -22,6 +22,7 @@ namespace Microsoft.Extensions.ProjectModel string PackageLockFile { get; } string PackagesDirectory { get; } string TargetDirectory { get; } + string AssemblyName { get; } string AssemblyFullPath { get; } IEnumerable CompilationItems { get; } IEnumerable EmbededItems { get; } diff --git a/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetProjectContext.cs index b2b9851ea8..fcacbd75f1 100644 --- a/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetProjectContext.cs +++ b/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetProjectContext.cs @@ -66,7 +66,9 @@ namespace Microsoft.Extensions.ProjectModel public string RuntimeConfigJson => _paths.RuntimeFiles.RuntimeConfigJson; public string PackagesDirectory => _projectContext.PackagesDirectory; public string PackageLockFile => Path.Combine(Path.GetDirectoryName(ProjectFullPath), "project.lock.json"); - + public string AssemblyName => string.IsNullOrEmpty(AssemblyFullPath) + ? ProjectName + : Path.GetFileNameWithoutExtension(AssemblyFullPath); public string AssemblyFullPath => !IsClassLibrary && (_projectContext.IsPortable || TargetFramework.IsDesktop()) ? _paths.RuntimeFiles.Executable diff --git a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectContext.cs index dc2369065e..8e46ac8beb 100644 --- a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectContext.cs +++ b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectContext.cs @@ -73,6 +73,9 @@ namespace Microsoft.Extensions.ProjectModel return Path.Combine(restoreOutputPath, "project.assets.json"); } } + public string AssemblyName => string.IsNullOrEmpty(AssemblyFullPath) + ? ProjectName + : Path.GetFileNameWithoutExtension(AssemblyFullPath); public string AssemblyFullPath => FindProperty("TargetPath"); public string Platform => FindProperty("Platform"); public string ProjectFullPath => Project.FullPath; From 1ae83eff708b5643a4b469b79adce9ede27b2341 Mon Sep 17 00:00:00 2001 From: Prafull Bhosale Date: Wed, 12 Oct 2016 09:49:12 -0700 Subject: [PATCH 0281/1029] Handle compilerOptions in project.json --- .../DotNetProjectContext.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetProjectContext.cs index fcacbd75f1..e038e6b42c 100644 --- a/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetProjectContext.cs +++ b/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetProjectContext.cs @@ -52,7 +52,7 @@ namespace Microsoft.Extensions.ProjectModel _compilerOptions = _projectContext.ProjectFile.GetCompilerOptions(TargetFramework, Configuration); // Workaround https://github.com/dotnet/cli/issues/3164 - IsClassLibrary = !(_compilerOptions.EmitEntryPoint + IsClassLibrary = !(_compilerOptions?.EmitEntryPoint ?? projectContext.ProjectFile.GetCompilerOptions(null, configuration).EmitEntryPoint.GetValueOrDefault()); _dependencyProvider = new Lazy(() => new DotNetDependencyProvider(_projectContext)); @@ -80,13 +80,17 @@ namespace Microsoft.Extensions.ProjectModel // TODO read from xproj if available public string RootNamespace => _projectContext.ProjectFile.Name; public string TargetDirectory => _paths.RuntimeOutputPath; - public string Platform => _compilerOptions.Platform; + public string Platform => _compilerOptions?.Platform; public IEnumerable CompilationItems - => _compilerOptions.CompileInclude.ResolveFiles(); + => (_compilerOptions?.CompileInclude == null) + ? _projectContext.ProjectFile.Files.SourceFiles + : _compilerOptions.CompileInclude.ResolveFiles(); public IEnumerable EmbededItems - => _compilerOptions.EmbedInclude.ResolveFiles(); + => (_compilerOptions?.EmbedInclude == null) + ? _projectContext.ProjectFile.Files.ResourceFiles.Keys + : _compilerOptions.EmbedInclude.ResolveFiles(); public IEnumerable PackageDependencies { From 8fb38d36377c9529f3ee2ed01db0596ee3e87325 Mon Sep 17 00:00:00 2001 From: Prafull Bhosale Date: Wed, 12 Oct 2016 13:17:56 -0700 Subject: [PATCH 0282/1029] Add Project References to ProjectContext --- .../IProjectContext.cs | 1 + .../DotNetDependencyProvider.cs | 52 ++++++++++++------- .../DotNetProjectContext.cs | 14 +++++ .../MsBuildProjectContext.cs | 13 +++++ .../MsBuildProjectDependencyProvider.cs | 12 +++++ .../DotNet/DotNetDependencyProviderTests.cs | 43 +++++++++++++-- .../MsBuildProjectDependencyProviderTests.cs | 21 ++++---- 7 files changed, 123 insertions(+), 33 deletions(-) diff --git a/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/IProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/IProjectContext.cs index 972f85caff..de53669917 100644 --- a/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/IProjectContext.cs +++ b/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/IProjectContext.cs @@ -29,5 +29,6 @@ namespace Microsoft.Extensions.ProjectModel string FindProperty(string propertyName); IEnumerable PackageDependencies { get;} IEnumerable CompilationAssemblies { get; } + IEnumerable ProjectReferences { get; } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetDependencyProvider.cs b/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetDependencyProvider.cs index 429a2a6a68..137acba5b6 100644 --- a/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetDependencyProvider.cs +++ b/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetDependencyProvider.cs @@ -17,6 +17,7 @@ namespace Microsoft.Extensions.ProjectModel private List _packageDependencies; private List _resolvedReferences; private string _configuration; + private List _projectReferences; public DotNetDependencyProvider(ProjectContext context, string configuration = Constants.DefaultConfiguration) { @@ -30,6 +31,11 @@ namespace Microsoft.Extensions.ProjectModel DiscoverDependencies(); } + public IEnumerable GetProjectReferences() + { + return _projectReferences; + } + public IEnumerable GetPackageDependencies() { return _packageDependencies; @@ -55,31 +61,41 @@ namespace Microsoft.Extensions.ProjectModel throw new InvalidOperationException("Couldn't resolve dependencies when target framework is not specified."); } - var exports = exporter.GetAllExports(); - var nugetPackages = new Dictionary(StringComparer.OrdinalIgnoreCase); + var exports = exporter.GetDependencies(); _resolvedReferences = new List(); + _packageDependencies = new List(); + _projectReferences = new List(); foreach (var export in exports) { var library = export.Library; - - var description = new DependencyDescription( - library.Identity.Name, - library.Identity.Version.ToString(), - export.Library.Path, - framework.DotNetFrameworkName, - library.Identity.Type.Value, - library.Resolved); - - foreach (var dependency in export.Library.Dependencies) + var project = library as ProjectDescription; + if (project != null) { - var dep = new Dependency(dependency.Name, version: string.Empty); - description.AddDependency(dep); + _projectReferences.Add(project.Project.ProjectFilePath); + } + else + { + var description = new DependencyDescription( + library.Identity.Name, + library.Identity.Version.ToString(), + export.Library.Path, + framework.DotNetFrameworkName, + library.Identity.Type.Value, + library.Resolved); + + foreach (var dependency in export.Library.Dependencies) + { + var dep = new Dependency(dependency.Name, version: string.Empty); + description.AddDependency(dep); + } + + + var itemSpec = $"{framework.DotNetFrameworkName}/{library.Identity.Name}/{library.Identity.Version.ToString()}"; + _packageDependencies.Add(description); } - var itemSpec = $"{framework.DotNetFrameworkName}/{library.Identity.Name}/{library.Identity.Version.ToString()}"; - nugetPackages[itemSpec] = description; - + // For resolved references we need to include all type of dependencies. if (library.Resolved) { foreach (var asset in export.CompilationAssemblies) @@ -91,8 +107,6 @@ namespace Microsoft.Extensions.ProjectModel } } } - - _packageDependencies = nugetPackages.Values.ToList(); } } } diff --git a/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetProjectContext.cs index e038e6b42c..b8d9bb476f 100644 --- a/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetProjectContext.cs +++ b/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetProjectContext.cs @@ -22,6 +22,7 @@ namespace Microsoft.Extensions.ProjectModel private IEnumerable _packageDependencies; private IEnumerable _compilationAssemblies; + private IEnumerable _projectReferences; public DotNetProjectContext(ProjectContext projectContext, string configuration, string outputPath) { @@ -118,6 +119,19 @@ namespace Microsoft.Extensions.ProjectModel } } + public IEnumerable ProjectReferences + { + get + { + if (_projectReferences == null) + { + _projectReferences = _dependencyProvider.Value.GetProjectReferences(); + } + + return _projectReferences; + } + } + /// /// Returns string values of top-level keys in the project.json file /// diff --git a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectContext.cs index 8e46ac8beb..2c9bc7a732 100644 --- a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectContext.cs +++ b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectContext.cs @@ -20,6 +20,7 @@ namespace Microsoft.Extensions.ProjectModel private readonly MsBuildProjectDependencyProvider _dependencyProvider; private IEnumerable _packageDependencies; private IEnumerable _compilationAssemblies; + private IEnumerable _projectReferences; protected ProjectInstance Project { get; } protected string Name { get; } @@ -114,5 +115,17 @@ namespace Microsoft.Extensions.ProjectModel } } + public IEnumerable ProjectReferences + { + get + { + if (_projectReferences == null) + { + _projectReferences = _dependencyProvider.GetProjectReferences(); + } + + return _projectReferences; + } + } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectDependencyProvider.cs b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectDependencyProvider.cs index 8c4345e158..5afad1590a 100644 --- a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectDependencyProvider.cs +++ b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectDependencyProvider.cs @@ -25,6 +25,18 @@ namespace Microsoft.Extensions.ProjectModel _projectInstance = projectInstance; } + public IEnumerable GetProjectReferences() + { + var projectPaths = _projectInstance + .GetItems("ProjectReference") + .Select(reference => reference.EvaluatedInclude); + + return projectPaths + .Select(path => Path.IsPathRooted(path) + ? path + : Path.Combine(_projectInstance.Directory, path)); + } + public IEnumerable GetPackageDependencies() { var packageItems = _projectInstance.GetItems(PackageDependencyItemType); diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/DotNet/DotNetDependencyProviderTests.cs b/test/Microsoft.Extensions.ProjectModel.Tests/DotNet/DotNetDependencyProviderTests.cs index e5fe160a69..18b6c0b9bc 100644 --- a/test/Microsoft.Extensions.ProjectModel.Tests/DotNet/DotNetDependencyProviderTests.cs +++ b/test/Microsoft.Extensions.ProjectModel.Tests/DotNet/DotNetDependencyProviderTests.cs @@ -13,7 +13,33 @@ namespace Microsoft.Extensions.ProjectModel.DotNet { public class DotNetDependencyProviderTests { + private const string globalJson = @" +{ + ""projects"": [ ""demo"", ""demoLib""] +}"; + private const string projectJson = @" +{ + ""buildOptions"": { + }, + ""dependencies"": { + ""Microsoft.AspNetCore.Mvc"": ""1.0.0-*"", + ""demoLib"": ""1.0.0-*"", + }, + ""frameworks"": { + ""netcoreapp1.0"": { + ""dependencies"": { + ""Microsoft.NETCore.App"": { + ""version"": ""1.0.0"", + ""type"": ""platform"" + } + } + } + }, +} +"; + + private const string libProjectJson = @" { ""buildOptions"": { }, @@ -45,13 +71,20 @@ namespace Microsoft.Extensions.ProjectModel.DotNet using (var fileProvider = new TemporaryFileProvider()) { Directory.CreateDirectory(Path.Combine(fileProvider.Root, "demo")); - fileProvider.Add($"demo{Path.DirectorySeparatorChar}project.json", projectJson); - fileProvider.Add($"demo{Path.DirectorySeparatorChar}First.cs", "namespace demo { class First{} }"); + Directory.CreateDirectory(Path.Combine(fileProvider.Root, "demoLib")); + + fileProvider.Add($"global.json", globalJson); + + fileProvider.Add($"demo/project.json", projectJson); + fileProvider.Add($"demo/First.cs", "namespace demo { class First{} }"); + + fileProvider.Add($"demoLib/project.json", libProjectJson); + fileProvider.Add($"demoLib/Second.cs", "namespace demoLib { class First{} }"); var muxer = new Muxer().MuxerPath; var result = Command - .Create(muxer, new[] { "restore", Path.Combine(fileProvider.Root, "demo") }) + .Create(muxer, new[] { "restore", fileProvider.Root }) .OnErrorLine(l => _output.WriteLine(l)) .OnOutputLine(l => _output.WriteLine(l)) .Execute(); @@ -77,7 +110,9 @@ namespace Microsoft.Extensions.ProjectModel.DotNet .First(); Assert.True(Directory.Exists(mvcPackage.Path)); - Assert.True(mvcPackage.Path.EndsWith($"Microsoft.AspNetCore.Mvc{Path.DirectorySeparatorChar}1.0.0", StringComparison.OrdinalIgnoreCase)); + Assert.True(mvcPackage.Path.EndsWith($"Microsoft.AspNetCore.Mvc/1.0.0", StringComparison.OrdinalIgnoreCase)); + + Assert.True(context.ProjectReferences.First().Equals(Path.Combine(fileProvider.Root, "demoLib", "project.json"))); } } } diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectDependencyProviderTests.cs b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectDependencyProviderTests.cs index 9caea9c562..7b4eedc203 100644 --- a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectDependencyProviderTests.cs +++ b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectDependencyProviderTests.cs @@ -53,7 +53,7 @@ namespace Microsoft.Extensions.ProjectModel.MsBuild - + @@ -109,14 +109,14 @@ namespace Microsoft.Extensions.ProjectModel.MsBuild fileProvider.Add("NuGet.config", NugetConfigTxt); // Add Root Project - fileProvider.Add($"Root{Path.DirectorySeparatorChar}test.csproj", RootProjectTxt); - fileProvider.Add($"Root{Path.DirectorySeparatorChar}One.cs", "public class Abc {}"); - fileProvider.Add($"Root{Path.DirectorySeparatorChar}Two.cs", "public class Abc2 {}"); - fileProvider.Add($"Root{Path.DirectorySeparatorChar}Excluded.cs", "public class Abc {}"); + fileProvider.Add($"Root/test.csproj", RootProjectTxt); + fileProvider.Add($"Root/One.cs", "public class Abc {}"); + fileProvider.Add($"Root/Two.cs", "public class Abc2 {}"); + fileProvider.Add($"Root/Excluded.cs", "public class Abc {}"); // Add Class Library project - fileProvider.Add($"Library1{Path.DirectorySeparatorChar}library.csproj", LibraryProjectTxt); - fileProvider.Add($"Library1{Path.DirectorySeparatorChar}Three.cs", "public class Abc3 {}"); + fileProvider.Add($"Library1/Library1.csproj", LibraryProjectTxt); + fileProvider.Add($"Library1/Three.cs", "public class Abc3 {}"); var testContext = _fixture.GetMsBuildContext(); @@ -152,9 +152,8 @@ namespace Microsoft.Extensions.ProjectModel.MsBuild .FirstOrDefault(); Assert.NotNull(lib1Dll); - var expectedPath = Path.Combine(fileProvider.Root, "Root", "bin", "Debug", "netcoreapp1.0", "lib1.dll"); - Assert.Equal(expectedPath, lib1Dll.ResolvedPath, ignoreCase: true); - + Assert.True(File.Exists(lib1Dll.ResolvedPath)); + // This reference doesn't resolve so should not be available here. Assert.False(compilationAssemblies.Any(assembly => assembly.Name.Equals("xyz", StringComparison.OrdinalIgnoreCase))); @@ -165,6 +164,8 @@ namespace Microsoft.Extensions.ProjectModel.MsBuild Assert.NotNull(mvcPackage); Assert.True(mvcPackage.Dependencies.Any(dependency => dependency.Name.Equals("Microsoft.Extensions.DependencyInjection", StringComparison.OrdinalIgnoreCase))); + + Assert.True(context.ProjectReferences.First().Equals(Path.Combine(fileProvider.Root, "Library1", "Library1.csproj"))); } } } From fd6df3c74dd77a1e167ef1361816323946497719 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 12 Oct 2016 13:45:08 -0700 Subject: [PATCH 0283/1029] Updating to netcoreapp1.1 --- src/Microsoft.DotNet.Watcher.Tools/project.json | 2 +- src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json | 2 +- src/Microsoft.Extensions.SecretManager.Tools/project.json | 2 +- .../Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json | 2 +- test/Microsoft.DotNet.Watcher.Tools.Tests/project.json | 2 +- test/Microsoft.Extensions.ProjectModel.Tests/project.json | 2 +- .../Microsoft.Extensions.SecretManager.Tools.Tests/project.json | 2 +- test/TestApps/AppWithDeps/project.json | 2 +- test/TestApps/GlobbingApp/project.json | 2 +- test/TestApps/NoDepsApp/project.json | 2 +- tools/NuGetPackager/project.json | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index e54d7b3774..c7e805b5af 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -28,6 +28,6 @@ } }, "frameworks": { - "netcoreapp1.0": {} + "netcoreapp1.1": {} } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json index b860143998..3806f870ec 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json @@ -29,6 +29,6 @@ "System.Data.SqlClient": "4.3.0-*" }, "frameworks": { - "netcoreapp1.0": {} + "netcoreapp1.1": {} } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index 77d376be2d..c92dc34172 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -30,6 +30,6 @@ "System.Runtime.Serialization.Primitives": "4.3.0-*" }, "frameworks": { - "netcoreapp1.0": {} + "netcoreapp1.1": {} } } \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index 7242cbab37..c863adcff4 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -16,7 +16,7 @@ "xunit": "2.2.0-*" }, "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json index a084f633f2..ad8145cb1e 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json @@ -9,7 +9,7 @@ "xunit": "2.2.0-*" }, "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { "version": "1.1.0-*", diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/project.json b/test/Microsoft.Extensions.ProjectModel.Tests/project.json index d408f83c23..ad3e782b4b 100644 --- a/test/Microsoft.Extensions.ProjectModel.Tests/project.json +++ b/test/Microsoft.Extensions.ProjectModel.Tests/project.json @@ -28,7 +28,7 @@ "xunit": "2.2.0-*" }, "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { "version": "1.0.0", diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json index 537709e5c8..7eaee45bee 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json @@ -10,7 +10,7 @@ }, "testRunner": "xunit", "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { "version": "1.1.0-*", diff --git a/test/TestApps/AppWithDeps/project.json b/test/TestApps/AppWithDeps/project.json index 8b1c2f6bab..3ddabc7548 100644 --- a/test/TestApps/AppWithDeps/project.json +++ b/test/TestApps/AppWithDeps/project.json @@ -8,7 +8,7 @@ } }, "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", diff --git a/test/TestApps/GlobbingApp/project.json b/test/TestApps/GlobbingApp/project.json index 6418c6d199..108c5bc492 100644 --- a/test/TestApps/GlobbingApp/project.json +++ b/test/TestApps/GlobbingApp/project.json @@ -12,7 +12,7 @@ } }, "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", diff --git a/test/TestApps/NoDepsApp/project.json b/test/TestApps/NoDepsApp/project.json index 4972d51a39..991f800c29 100644 --- a/test/TestApps/NoDepsApp/project.json +++ b/test/TestApps/NoDepsApp/project.json @@ -3,7 +3,7 @@ "emitEntryPoint": true }, "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", diff --git a/tools/NuGetPackager/project.json b/tools/NuGetPackager/project.json index 146561308a..5e70d4c332 100644 --- a/tools/NuGetPackager/project.json +++ b/tools/NuGetPackager/project.json @@ -15,7 +15,7 @@ }, "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "imports": "dnxcore50" } } From 08332a96b718ce5b0a192385a196dbcb62f77e21 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 12 Oct 2016 13:45:26 -0700 Subject: [PATCH 0284/1029] Updating to netcoreapp1.1 --- test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json | 2 +- test/Microsoft.Extensions.WebEncoders.Tests/project.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index 8e5e79eeb2..754cf25670 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -12,7 +12,7 @@ }, "testRunner": "xunit", "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { "version": "1.1.0-*", diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index 4c9ee42471..9171910c7c 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -11,7 +11,7 @@ "keyFile": "../../tools/Key.snk" }, "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { "version": "1.1.0-*", From ddcee4774dc3d316498c8a177d9b765eabe8bc33 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 12 Oct 2016 13:45:39 -0700 Subject: [PATCH 0285/1029] Updating to netcoreapp1.1 --- test/Microsoft.AspNetCore.JsonPatch.Test/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index 9da14bf59e..9e95ee86e0 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -11,7 +11,7 @@ }, "testRunner": "xunit", "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { "version": "1.1.0-*", From 0627d859aff01eca2562893ed1ffb265cf37216a Mon Sep 17 00:00:00 2001 From: Prafull Bhosale Date: Wed, 12 Oct 2016 14:39:12 -0700 Subject: [PATCH 0286/1029] Fix path issue in assertion for DotNetDependencyProviderTests --- .../DotNet/DotNetDependencyProviderTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/DotNet/DotNetDependencyProviderTests.cs b/test/Microsoft.Extensions.ProjectModel.Tests/DotNet/DotNetDependencyProviderTests.cs index 18b6c0b9bc..ccf0d95555 100644 --- a/test/Microsoft.Extensions.ProjectModel.Tests/DotNet/DotNetDependencyProviderTests.cs +++ b/test/Microsoft.Extensions.ProjectModel.Tests/DotNet/DotNetDependencyProviderTests.cs @@ -110,7 +110,7 @@ namespace Microsoft.Extensions.ProjectModel.DotNet .First(); Assert.True(Directory.Exists(mvcPackage.Path)); - Assert.True(mvcPackage.Path.EndsWith($"Microsoft.AspNetCore.Mvc/1.0.0", StringComparison.OrdinalIgnoreCase)); + Assert.True(mvcPackage.Path.EndsWith($"Microsoft.AspNetCore.Mvc{Path.DirectorySeparatorChar}1.0.0", StringComparison.OrdinalIgnoreCase), mvcPackage.Path); Assert.True(context.ProjectReferences.First().Equals(Path.Combine(fileProvider.Root, "demoLib", "project.json"))); } From 2b86005a855d724873ec02b2434b1872c5646b79 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 12 Oct 2016 16:08:44 -0700 Subject: [PATCH 0287/1029] Revert "Updating to netcoreapp1.1" This reverts commit 08332a96b718ce5b0a192385a196dbcb62f77e21. --- test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json | 2 +- test/Microsoft.Extensions.WebEncoders.Tests/project.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index 754cf25670..8e5e79eeb2 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -12,7 +12,7 @@ }, "testRunner": "xunit", "frameworks": { - "netcoreapp1.1": { + "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "version": "1.1.0-*", diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index 9171910c7c..4c9ee42471 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -11,7 +11,7 @@ "keyFile": "../../tools/Key.snk" }, "frameworks": { - "netcoreapp1.1": { + "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "version": "1.1.0-*", From 681812d0f40cb9c4281215413e8b3c0feca30509 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 12 Oct 2016 16:08:53 -0700 Subject: [PATCH 0288/1029] Revert "Updating to netcoreapp1.1" This reverts commit ddcee4774dc3d316498c8a177d9b765eabe8bc33. --- test/Microsoft.AspNetCore.JsonPatch.Test/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index 9e95ee86e0..9da14bf59e 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -11,7 +11,7 @@ }, "testRunner": "xunit", "frameworks": { - "netcoreapp1.1": { + "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "version": "1.1.0-*", From 5d998a16d847fb0c507892943899e91c4d89e20e Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 12 Oct 2016 16:12:52 -0700 Subject: [PATCH 0289/1029] dotnet-watch: simplify the end to end testing to not rely on tool installation via restore (#194) --- DotNetTools.sln | 31 -------- .../AppWithDepsTests.cs | 10 +-- .../GlobbingAppTests.cs | 8 +- .../NoDepsAppTests.cs | 11 ++- .../Scenario/DotNetWatchScenario.cs | 30 +------ .../Scenario/ProjectToolScenario.cs | 79 +++++++++---------- .../TestProjects}/AppWithDeps/Program.cs | 0 .../TestProjects}/AppWithDeps/project.json | 0 .../TestProjects}/Dependency/Foo.cs | 0 .../TestProjects}/Dependency/project.json | 0 .../TestProjects}/GlobbingApp/Program.cs | 0 .../TestProjects}/GlobbingApp/exclude/Baz.cs | 0 .../TestProjects}/GlobbingApp/include/Foo.cs | 0 .../TestProjects}/GlobbingApp/project.json | 0 .../TestProjects}/NoDepsApp/Program.cs | 0 .../TestProjects}/NoDepsApp/project.json | 0 .../clean-assets.cmd | 6 ++ .../clean-assets.sh | 8 ++ .../project.json | 16 +++- test/TestApps/AppWithDeps/AppWithDeps.xproj | 17 ---- test/TestApps/Dependency/Dependency.xproj | 17 ---- test/TestApps/GlobbingApp/GlobbingApp.xproj | 17 ---- test/TestApps/NoDepsApp/NoDepsApp.xproj | 17 ---- 23 files changed, 77 insertions(+), 190 deletions(-) rename test/{TestApps => Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects}/AppWithDeps/Program.cs (100%) rename test/{TestApps => Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects}/AppWithDeps/project.json (100%) rename test/{TestApps => Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects}/Dependency/Foo.cs (100%) rename test/{TestApps => Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects}/Dependency/project.json (100%) rename test/{TestApps => Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects}/GlobbingApp/Program.cs (100%) rename test/{TestApps => Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects}/GlobbingApp/exclude/Baz.cs (100%) rename test/{TestApps => Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects}/GlobbingApp/include/Foo.cs (100%) rename test/{TestApps => Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects}/GlobbingApp/project.json (100%) rename test/{TestApps => Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects}/NoDepsApp/Program.cs (100%) rename test/{TestApps => Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects}/NoDepsApp/project.json (100%) create mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.cmd create mode 100755 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.sh delete mode 100644 test/TestApps/AppWithDeps/AppWithDeps.xproj delete mode 100644 test/TestApps/Dependency/Dependency.xproj delete mode 100644 test/TestApps/GlobbingApp/GlobbingApp.xproj delete mode 100644 test/TestApps/NoDepsApp/NoDepsApp.xproj diff --git a/DotNetTools.sln b/DotNetTools.sln index d1de4da4d0..653bddd136 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -16,16 +16,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F5B382BC-2 EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Watcher.Tools.FunctionalTests", "test\Microsoft.DotNet.Watcher.Tools.FunctionalTests\Microsoft.DotNet.Watcher.Tools.FunctionalTests.xproj", "{16BADE2F-1184-4518-8A70-B68A19D0805B}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestApps", "TestApps", "{2876B12E-5841-4792-85A8-2929AEE11885}" -EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NoDepsApp", "test\TestApps\NoDepsApp\NoDepsApp.xproj", "{4F0D8A80-221F-4BCB-822E-44A0655F537E}" -EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "GlobbingApp", "test\TestApps\GlobbingApp\GlobbingApp.xproj", "{2AB1A28B-2022-49EA-AF77-AC8A875915CC}" -EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AppWithDeps", "test\TestApps\AppWithDeps\AppWithDeps.xproj", "{F7734E61-F510-41E0-AD15-301A64081CD1}" -EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Dependency", "test\TestApps\Dependency\Dependency.xproj", "{2F48041A-F7D1-478F-9C38-D41F0F05E8CA}" -EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.SecretManager.Tools", "src\Microsoft.Extensions.SecretManager.Tools\Microsoft.Extensions.SecretManager.Tools.xproj", "{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}" EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.SecretManager.Tools.Tests", "test\Microsoft.Extensions.SecretManager.Tools.Tests\Microsoft.Extensions.SecretManager.Tools.Tests.xproj", "{7B331122-83B1-4F08-A119-DC846959844C}" @@ -60,22 +50,6 @@ Global {16BADE2F-1184-4518-8A70-B68A19D0805B}.Debug|Any CPU.Build.0 = Debug|Any CPU {16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.ActiveCfg = Release|Any CPU {16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.Build.0 = Release|Any CPU - {4F0D8A80-221F-4BCB-822E-44A0655F537E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4F0D8A80-221F-4BCB-822E-44A0655F537E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4F0D8A80-221F-4BCB-822E-44A0655F537E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4F0D8A80-221F-4BCB-822E-44A0655F537E}.Release|Any CPU.Build.0 = Release|Any CPU - {2AB1A28B-2022-49EA-AF77-AC8A875915CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2AB1A28B-2022-49EA-AF77-AC8A875915CC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2AB1A28B-2022-49EA-AF77-AC8A875915CC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2AB1A28B-2022-49EA-AF77-AC8A875915CC}.Release|Any CPU.Build.0 = Release|Any CPU - {F7734E61-F510-41E0-AD15-301A64081CD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F7734E61-F510-41E0-AD15-301A64081CD1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F7734E61-F510-41E0-AD15-301A64081CD1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F7734E61-F510-41E0-AD15-301A64081CD1}.Release|Any CPU.Build.0 = Release|Any CPU - {2F48041A-F7D1-478F-9C38-D41F0F05E8CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2F48041A-F7D1-478F-9C38-D41F0F05E8CA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2F48041A-F7D1-478F-9C38-D41F0F05E8CA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2F48041A-F7D1-478F-9C38-D41F0F05E8CA}.Release|Any CPU.Build.0 = Release|Any CPU {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Debug|Any CPU.Build.0 = Debug|Any CPU {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -119,11 +93,6 @@ Global GlobalSection(NestedProjects) = preSolution {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46} = {66517987-2A5A-4330-B130-207039378FD4} {16BADE2F-1184-4518-8A70-B68A19D0805B} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} - {2876B12E-5841-4792-85A8-2929AEE11885} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} - {4F0D8A80-221F-4BCB-822E-44A0655F537E} = {2876B12E-5841-4792-85A8-2929AEE11885} - {2AB1A28B-2022-49EA-AF77-AC8A875915CC} = {2876B12E-5841-4792-85A8-2929AEE11885} - {F7734E61-F510-41E0-AD15-301A64081CD1} = {2876B12E-5841-4792-85A8-2929AEE11885} - {2F48041A-F7D1-478F-9C38-D41F0F05E8CA} = {2876B12E-5841-4792-85A8-2929AEE11885} {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E} = {66517987-2A5A-4330-B130-207039378FD4} {7B331122-83B1-4F08-A119-DC846959844C} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {8A2E6961-6B12-4A8E-8215-3E7301D52EAC} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs index cae3959577..d36674a223 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs @@ -36,18 +36,14 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests private const string AppWithDeps = "AppWithDeps"; private const string Dependency = "Dependency"; - private static readonly string _appWithDepsFolder = Path.Combine(_repositoryRoot, "test", "TestApps", AppWithDeps); - private static readonly string _dependencyFolder = Path.Combine(_repositoryRoot, "test", "TestApps", Dependency); - public AppWithDepsScenario() { StatusFile = Path.Combine(_scenario.TempFolder, "status"); StartedFile = StatusFile + ".started"; - _scenario.AddProject(_appWithDepsFolder); - _scenario.AddProject(_dependencyFolder); + _scenario.AddTestProjectFolder(AppWithDeps); + _scenario.AddTestProjectFolder(Dependency); - _scenario.AddToolToProject(AppWithDeps, DotnetWatch); _scenario.Restore(); AppWithDepsFolder = Path.Combine(_scenario.WorkFolder, AppWithDeps); @@ -59,7 +55,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // Wait for the process to start using (var wait = new WaitForFileToChange(StatusFile)) { - RunDotNetWatch($"run {StatusFile}", Path.Combine(_scenario.WorkFolder, AppWithDeps)); + RunDotNetWatch(new[] { "run", StatusFile }, Path.Combine(_scenario.WorkFolder, AppWithDeps)); wait.Wait(_defaultTimeout, expectedToChange: true, diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs index 0512b2fd80..87ae1b6df3 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs @@ -136,7 +136,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // Add a file that's in a included folder but not matching the globbing pattern private void ChangeNonCompiledFile(bool usePollingWatcher) - { + { using (var scenario = new GlobbingAppScenario()) { scenario.UsePollingWatcher = usePollingWatcher; @@ -184,15 +184,13 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests private class GlobbingAppScenario : DotNetWatchScenario { private const string TestAppName = "GlobbingApp"; - private static readonly string _testAppFolder = Path.Combine(_repositoryRoot, "test", "TestApps", TestAppName); public GlobbingAppScenario() { StatusFile = Path.Combine(_scenario.TempFolder, "status"); StartedFile = StatusFile + ".started"; - _scenario.AddProject(_testAppFolder); - _scenario.AddToolToProject(TestAppName, DotnetWatch); + _scenario.AddTestProjectFolder(TestAppName); _scenario.Restore(); TestAppFolder = Path.Combine(_scenario.WorkFolder, TestAppName); @@ -203,7 +201,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // Wait for the process to start using (var wait = new WaitForFileToChange(StartedFile)) { - RunDotNetWatch($"run {StatusFile}", Path.Combine(_scenario.WorkFolder, TestAppName)); + RunDotNetWatch(new[] { "run", StatusFile }, Path.Combine(_scenario.WorkFolder, TestAppName)); wait.Wait(_defaultTimeout, expectedToChange: true, diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs index 1b7109828c..023b57512f 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Threading; @@ -21,7 +22,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // Wait for the process to start using (var wait = new WaitForFileToChange(scenario.StartedFile)) { - scenario.RunDotNetWatch($"run {scenario.StatusFile} --no-exit"); + scenario.RunDotNetWatch(new[] { "run", scenario.StatusFile, "--no-exit" }); wait.Wait(_defaultTimeout, expectedToChange: true, @@ -60,7 +61,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // Wait for the process to start using (var wait = new WaitForFileToChange(scenario.StartedFile)) { - scenario.RunDotNetWatch($"run {scenario.StatusFile}"); + scenario.RunDotNetWatch(new[] { "run", scenario.StatusFile }); wait.Wait(_defaultTimeout, expectedToChange: true, @@ -99,15 +100,13 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests private class NoDepsAppScenario : DotNetWatchScenario { private const string TestAppName = "NoDepsApp"; - private static readonly string _testAppFolder = Path.Combine(_repositoryRoot, "test", "TestApps", TestAppName); public NoDepsAppScenario() { StatusFile = Path.Combine(_scenario.TempFolder, "status"); StartedFile = StatusFile + ".started"; - _scenario.AddProject(_testAppFolder); - _scenario.AddToolToProject(TestAppName, DotnetWatch); + _scenario.AddTestProjectFolder(TestAppName); _scenario.Restore(); TestAppFolder = Path.Combine(_scenario.WorkFolder, TestAppName); @@ -117,7 +116,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public string StartedFile { get; private set; } public string TestAppFolder { get; private set; } - public void RunDotNetWatch(string args) + public void RunDotNetWatch(IEnumerable args) { RunDotNetWatch(args, Path.Combine(_scenario.WorkFolder, TestAppName)); } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs index 4af46b1171..bef42282fe 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs @@ -11,25 +11,18 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { public class DotNetWatchScenario : IDisposable { - protected const string DotnetWatch = "Microsoft.DotNet.Watcher.Tools"; - - protected static readonly string _repositoryRoot = FindRepoRoot(); - protected static readonly string _artifactsFolder = Path.Combine(_repositoryRoot, "artifacts", "build"); - protected ProjectToolScenario _scenario; public DotNetWatchScenario() { _scenario = new ProjectToolScenario(); - Directory.CreateDirectory(_artifactsFolder); - _scenario.AddNugetFeed(DotnetWatch, _artifactsFolder); } public Process WatcherProcess { get; private set; } public bool UsePollingWatcher { get; set; } - protected void RunDotNetWatch(string arguments, string workingFolder) + protected void RunDotNetWatch(IEnumerable arguments, string workingFolder) { IDictionary envVariables = null; if (UsePollingWatcher) @@ -40,7 +33,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests }; } - WatcherProcess = _scenario.ExecuteDotnet("watch " + arguments, workingFolder, envVariables); + WatcherProcess = _scenario.ExecuteDotnetWatch(arguments, workingFolder, envVariables); } public virtual void Dispose() @@ -55,24 +48,5 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } _scenario.Dispose(); } - - private static string FindRepoRoot() - { - var di = new DirectoryInfo(Directory.GetCurrentDirectory()); - - while (di.Parent != null) - { - var globalJsonFile = Path.Combine(di.FullName, "global.json"); - - if (File.Exists(globalJsonFile)) - { - return di.FullName; - } - - di = di.Parent; - } - - return null; - } } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs index 48af21836e..41ac05c762 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -8,12 +8,18 @@ using System.IO; using System.Threading; using System.Xml.Linq; using Newtonsoft.Json.Linq; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.Extensions.DependencyModel; +using Microsoft.DotNet.ProjectModel; +using System.Reflection; +using System.Linq; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { public class ProjectToolScenario : IDisposable { private const string NugetConfigFileName = "NuGet.config"; + private static readonly string TestProjectSourceRoot = Path.Combine(AppContext.BaseDirectory, "TestProjects"); private static readonly object _restoreLock = new object(); @@ -26,57 +32,29 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests CreateTestDirectory(); } - public string TempFolder { get; } = Path.Combine(Path.GetDirectoryName(FindNugetConfig()), "testWorkDir", Guid.NewGuid().ToString()); + public string TempFolder { get; } = Path.Combine(Path.GetDirectoryName(FindNugetConfig()), "testWorkDir", Guid.NewGuid().ToString("N")); public string WorkFolder { get; } - public void AddProject(string projectFolder) + public void AddTestProjectFolder(string projectName) { - var destinationFolder = Path.Combine(WorkFolder, Path.GetFileName(projectFolder)); - Console.WriteLine($"Copying project {projectFolder} to {destinationFolder}"); + var srcFolder = Path.Combine(TestProjectSourceRoot, projectName); + var destinationFolder = Path.Combine(WorkFolder, Path.GetFileName(projectName)); + Console.WriteLine($"Copying project {srcFolder} to {destinationFolder}"); Directory.CreateDirectory(destinationFolder); - foreach (var directory in Directory.GetDirectories(projectFolder, "*", SearchOption.AllDirectories)) + foreach (var directory in Directory.GetDirectories(srcFolder, "*", SearchOption.AllDirectories)) { - Directory.CreateDirectory(directory.Replace(projectFolder, destinationFolder)); + Directory.CreateDirectory(directory.Replace(srcFolder, destinationFolder)); } - foreach (var file in Directory.GetFiles(projectFolder, "*.*", SearchOption.AllDirectories)) + foreach (var file in Directory.GetFiles(srcFolder, "*", SearchOption.AllDirectories)) { - File.Copy(file, file.Replace(projectFolder, destinationFolder), true); + File.Copy(file, file.Replace(srcFolder, destinationFolder), true); } } - public void AddNugetFeed(string feedName, string feed) - { - var tempNugetConfigFile = Path.Combine(WorkFolder, NugetConfigFileName); - - var nugetConfig = XDocument.Load(tempNugetConfigFile); - var packageSource = nugetConfig.Element("configuration").Element("packageSources"); - packageSource.Add(new XElement("add", new XAttribute("key", feedName), new XAttribute("value", feed))); - using (var stream = File.OpenWrite(tempNugetConfigFile)) - { - nugetConfig.Save(stream); - } - } - - public void AddToolToProject(string projectName, string toolName) - { - var projectFile = Path.Combine(WorkFolder, projectName, "project.json"); - Console.WriteLine($"Adding {toolName} to {projectFile}"); - - var projectJson = JObject.Parse(File.ReadAllText(projectFile)); - projectJson.Add("tools", - new JObject( - new JProperty(toolName, - new JObject( - new JProperty("version", "1.0.0-*"), - new JProperty("target", "package"))))); - - File.WriteAllText(projectFile, projectJson.ToString()); - } - public void Restore(string project = null) { if (project == null) @@ -93,8 +71,9 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // multiple threads - which results in either sharing violation or corrupted json. lock (_restoreLock) { - var restore = ExecuteDotnet($"restore -v Minimal", project); - restore.WaitForExit(); + var restore = Command + .CreateDotNet("restore", new[] { project }) + .Execute(); if (restore.ExitCode != 0) { @@ -114,11 +93,27 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests File.Copy(nugetConfigFilePath, tempNugetConfigFile); } - public Process ExecuteDotnet(string arguments, string workDir, IDictionary environmentVariables = null) + public Process ExecuteDotnetWatch(IEnumerable arguments, string workDir, IDictionary environmentVariables = null) { - Console.WriteLine($"Running dotnet {arguments} in {workDir}"); + // this launches a new .NET Core process using the runtime of the current test app + // and the version of dotnet-watch that this test app is compiled against + var thisAssembly = Path.GetFileNameWithoutExtension(GetType().GetTypeInfo().Assembly.Location); + var args = new List(); + args.Add("exec"); - var psi = new ProcessStartInfo("dotnet", arguments) + args.Add("--depsfile"); + args.Add(Path.Combine(AppContext.BaseDirectory, thisAssembly + FileNameSuffixes.DepsJson)); + + args.Add("--runtimeconfig"); + args.Add(Path.Combine(AppContext.BaseDirectory, thisAssembly + FileNameSuffixes.RuntimeConfigJson)); + + args.Add(Path.Combine(AppContext.BaseDirectory, "dotnet-watch.dll")); + + var argsStr = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args.Concat(arguments)); + + Console.WriteLine($"Running dotnet {argsStr} in {workDir}"); + + var psi = new ProcessStartInfo(new Muxer().MuxerPath, argsStr) { UseShellExecute = false, WorkingDirectory = workDir, diff --git a/test/TestApps/AppWithDeps/Program.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/Program.cs similarity index 100% rename from test/TestApps/AppWithDeps/Program.cs rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/Program.cs diff --git a/test/TestApps/AppWithDeps/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/project.json similarity index 100% rename from test/TestApps/AppWithDeps/project.json rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/project.json diff --git a/test/TestApps/Dependency/Foo.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Foo.cs similarity index 100% rename from test/TestApps/Dependency/Foo.cs rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Foo.cs diff --git a/test/TestApps/Dependency/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/project.json similarity index 100% rename from test/TestApps/Dependency/project.json rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/project.json diff --git a/test/TestApps/GlobbingApp/Program.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/Program.cs similarity index 100% rename from test/TestApps/GlobbingApp/Program.cs rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/Program.cs diff --git a/test/TestApps/GlobbingApp/exclude/Baz.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/exclude/Baz.cs similarity index 100% rename from test/TestApps/GlobbingApp/exclude/Baz.cs rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/exclude/Baz.cs diff --git a/test/TestApps/GlobbingApp/include/Foo.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/include/Foo.cs similarity index 100% rename from test/TestApps/GlobbingApp/include/Foo.cs rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/include/Foo.cs diff --git a/test/TestApps/GlobbingApp/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/project.json similarity index 100% rename from test/TestApps/GlobbingApp/project.json rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/project.json diff --git a/test/TestApps/NoDepsApp/Program.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/Program.cs similarity index 100% rename from test/TestApps/NoDepsApp/Program.cs rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/Program.cs diff --git a/test/TestApps/NoDepsApp/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/project.json similarity index 100% rename from test/TestApps/NoDepsApp/project.json rename to test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/project.json diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.cmd b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.cmd new file mode 100644 index 0000000000..63104d55c6 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.cmd @@ -0,0 +1,6 @@ +@ECHO OFF +:again +if not "%1" == "" ( + echo "Deleting %1\TestProjects" + rmdir /s /q %1\TestProjects +) \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.sh b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.sh new file mode 100755 index 0000000000..1a5e80fb71 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +if [ -z $1 ]; then + echo "Deleting $1/TestProjects" + rm -rf $1/TestProjects +fi + +exit 0 \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index c863adcff4..1dcfb951c9 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -1,18 +1,22 @@ { "buildOptions": { "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk" + "keyFile": "../../tools/Key.snk", + "copyToOutput": { + "include": "TestProjects/" + }, + "compile": { + "exclude": "TestProjects/" + } }, "dependencies": { "dotnet-test-xunit": "2.2.0-*", "Microsoft.AspNetCore.Testing": "1.1.0-*", "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", - "Microsoft.Extensions.DependencyInjection": "1.1.0-*", "Microsoft.Extensions.Process.Sources": { "type": "build", "version": "1.1.0-*" }, - "Newtonsoft.Json": "9.0.1", "xunit": "2.2.0-*" }, "frameworks": { @@ -25,5 +29,11 @@ } } }, + "scripts": { + "precompile": "clean-assets %compile:OutputDir%" + }, + "publishOptions": { + "include": "TestProjects/" + }, "testRunner": "xunit" } \ No newline at end of file diff --git a/test/TestApps/AppWithDeps/AppWithDeps.xproj b/test/TestApps/AppWithDeps/AppWithDeps.xproj deleted file mode 100644 index 0359495322..0000000000 --- a/test/TestApps/AppWithDeps/AppWithDeps.xproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - f7734e61-f510-41e0-ad15-301a64081cd1 - .\obj - .\bin\ - - - 2.0 - - - \ No newline at end of file diff --git a/test/TestApps/Dependency/Dependency.xproj b/test/TestApps/Dependency/Dependency.xproj deleted file mode 100644 index bab595dfee..0000000000 --- a/test/TestApps/Dependency/Dependency.xproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 2f48041a-f7d1-478f-9c38-d41f0f05e8ca - .\obj - .\bin\ - - - 2.0 - - - \ No newline at end of file diff --git a/test/TestApps/GlobbingApp/GlobbingApp.xproj b/test/TestApps/GlobbingApp/GlobbingApp.xproj deleted file mode 100644 index 6d89d4053b..0000000000 --- a/test/TestApps/GlobbingApp/GlobbingApp.xproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 2ab1a28b-2022-49ea-af77-ac8a875915cc - .\obj - .\bin\ - - - 2.0 - - - \ No newline at end of file diff --git a/test/TestApps/NoDepsApp/NoDepsApp.xproj b/test/TestApps/NoDepsApp/NoDepsApp.xproj deleted file mode 100644 index a85e3bced4..0000000000 --- a/test/TestApps/NoDepsApp/NoDepsApp.xproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 4f0d8a80-221f-4bcb-822e-44a0655f537e - .\obj - .\bin\ - - - 2.0 - - - \ No newline at end of file From f8a1a66ab7962c2030528d68aabb94a41c5ca3e8 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 12 Oct 2016 16:39:36 -0700 Subject: [PATCH 0290/1029] Revert "Updating to netcoreapp1.1" This reverts commit fd6df3c74dd77a1e167ef1361816323946497719. --- src/Microsoft.DotNet.Watcher.Tools/project.json | 2 +- src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json | 2 +- src/Microsoft.Extensions.SecretManager.Tools/project.json | 2 +- .../TestProjects/AppWithDeps/project.json | 2 +- .../TestProjects/GlobbingApp/project.json | 2 +- .../TestProjects/NoDepsApp/project.json | 2 +- .../Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json | 2 +- test/Microsoft.DotNet.Watcher.Tools.Tests/project.json | 2 +- test/Microsoft.Extensions.ProjectModel.Tests/project.json | 2 +- .../Microsoft.Extensions.SecretManager.Tools.Tests/project.json | 2 +- tools/NuGetPackager/project.json | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index c7e805b5af..e54d7b3774 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -28,6 +28,6 @@ } }, "frameworks": { - "netcoreapp1.1": {} + "netcoreapp1.0": {} } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json index 3806f870ec..b860143998 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json @@ -29,6 +29,6 @@ "System.Data.SqlClient": "4.3.0-*" }, "frameworks": { - "netcoreapp1.1": {} + "netcoreapp1.0": {} } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index c92dc34172..77d376be2d 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -30,6 +30,6 @@ "System.Runtime.Serialization.Primitives": "4.3.0-*" }, "frameworks": { - "netcoreapp1.1": {} + "netcoreapp1.0": {} } } \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/project.json index 3ddabc7548..8b1c2f6bab 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/project.json @@ -8,7 +8,7 @@ } }, "frameworks": { - "netcoreapp1.1": { + "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/project.json index 108c5bc492..6418c6d199 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/project.json @@ -12,7 +12,7 @@ } }, "frameworks": { - "netcoreapp1.1": { + "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/project.json index 991f800c29..4972d51a39 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/project.json @@ -3,7 +3,7 @@ "emitEntryPoint": true }, "frameworks": { - "netcoreapp1.1": { + "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index 1dcfb951c9..ecaa2d4046 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -20,7 +20,7 @@ "xunit": "2.2.0-*" }, "frameworks": { - "netcoreapp1.1": { + "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json index ad8145cb1e..a084f633f2 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json @@ -9,7 +9,7 @@ "xunit": "2.2.0-*" }, "frameworks": { - "netcoreapp1.1": { + "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "version": "1.1.0-*", diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/project.json b/test/Microsoft.Extensions.ProjectModel.Tests/project.json index ad3e782b4b..d408f83c23 100644 --- a/test/Microsoft.Extensions.ProjectModel.Tests/project.json +++ b/test/Microsoft.Extensions.ProjectModel.Tests/project.json @@ -28,7 +28,7 @@ "xunit": "2.2.0-*" }, "frameworks": { - "netcoreapp1.1": { + "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "version": "1.0.0", diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json index 7eaee45bee..537709e5c8 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json @@ -10,7 +10,7 @@ }, "testRunner": "xunit", "frameworks": { - "netcoreapp1.1": { + "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "version": "1.1.0-*", diff --git a/tools/NuGetPackager/project.json b/tools/NuGetPackager/project.json index 5e70d4c332..146561308a 100644 --- a/tools/NuGetPackager/project.json +++ b/tools/NuGetPackager/project.json @@ -15,7 +15,7 @@ }, "frameworks": { - "netcoreapp1.1": { + "netcoreapp1.0": { "imports": "dnxcore50" } } From 58d5c2f7d4420b095faeece77c580acfbc4f78ca Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 13 Oct 2016 11:17:57 -0700 Subject: [PATCH 0291/1029] Updating to netcoreapp1.1 --- test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json | 2 +- test/Microsoft.Extensions.WebEncoders.Tests/project.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index 8e5e79eeb2..754cf25670 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -12,7 +12,7 @@ }, "testRunner": "xunit", "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { "version": "1.1.0-*", diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index 4c9ee42471..9171910c7c 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -11,7 +11,7 @@ "keyFile": "../../tools/Key.snk" }, "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { "version": "1.1.0-*", From 17a4e83babc7e4a6882d1e80b68a5e4fb4a1e5f1 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 13 Oct 2016 11:19:06 -0700 Subject: [PATCH 0292/1029] Updating to netcoreapp1.1 --- test/Microsoft.AspNetCore.JsonPatch.Test/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index 9da14bf59e..9e95ee86e0 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -11,7 +11,7 @@ }, "testRunner": "xunit", "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { "version": "1.1.0-*", From 4cbd904154a06e03f1b2dd772f0caee81048797a Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 13 Oct 2016 09:05:17 -0700 Subject: [PATCH 0293/1029] dotnet-watch: add --verbose and --quiet command line flags --- .../CommandLineOptions.cs | 21 ++- .../CommandOutputLogger.cs | 6 +- .../DotNetWatcher.cs | 2 +- src/Microsoft.DotNet.Watcher.Tools/Program.cs | 56 ++++---- .../Properties/Resources.Designer.cs | 46 +++++++ src/Microsoft.DotNet.Watcher.Tools/README.md | 12 +- .../Resources.resx | 123 ++++++++++++++++++ .../CommandLineOptionsTests.cs | 13 +- 8 files changed, 245 insertions(+), 34 deletions(-) create mode 100644 src/Microsoft.DotNet.Watcher.Tools/Properties/Resources.Designer.cs create mode 100644 src/Microsoft.DotNet.Watcher.Tools/Resources.resx diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs index 4d7c998622..6960ea93b6 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs @@ -4,6 +4,8 @@ using System; using System.Collections.Generic; using System.IO; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.Watcher.Tools; using Microsoft.Extensions.CommandLineUtils; namespace Microsoft.DotNet.Watcher @@ -11,8 +13,10 @@ namespace Microsoft.DotNet.Watcher internal class CommandLineOptions { public bool IsHelp { get; private set; } + public bool IsQuiet { get; private set; } + public bool IsVerbose { get; private set; } public IList RemainingArguments { get; private set; } - public static CommandLineOptions Parse(string[] args, TextWriter consoleOutput) + public static CommandLineOptions Parse(string[] args, TextWriter stdout, TextWriter stderr) { if (args == null) { @@ -23,11 +27,16 @@ namespace Microsoft.DotNet.Watcher { Name = "dotnet watch", FullName = "Microsoft DotNet File Watcher", - Out = consoleOutput, + Out = stdout, + Error = stderr, AllowArgumentSeparator = true }; app.HelpOption("-?|-h|--help"); + var optQuiet = app.Option("-q|--quiet", "Suppresses all output except warnings and errors", + CommandOptionType.NoValue); + var optVerbose = app.Option("-v|--verbose", "Show verbose output", + CommandOptionType.NoValue); app.OnExecute(() => { @@ -44,8 +53,16 @@ namespace Microsoft.DotNet.Watcher return null; } + if (optQuiet.HasValue() && optVerbose.HasValue()) + { + stderr.WriteLine(Resources.Error_QuietAndVerboseSpecified.Bold().Red()); + return null; + } + return new CommandLineOptions { + IsQuiet = optQuiet.HasValue(), + IsVerbose = optVerbose.HasValue(), RemainingArguments = app.RemainingArguments, IsHelp = app.IsShowingInformation }; diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandOutputLogger.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandOutputLogger.cs index aeb90f45c2..43b2da4507 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandOutputLogger.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandOutputLogger.cs @@ -50,12 +50,12 @@ namespace Microsoft.DotNet.Watcher { switch (logLevel) { - case LogLevel.Trace: return "\x1b[35mtrace\x1b[39m"; - case LogLevel.Debug: return "\x1b[35mdebug\x1b[39m"; + case LogLevel.Trace: return "\x1b[35mtrce\x1b[39m"; + case LogLevel.Debug: return "\x1b[35mdbug\x1b[39m"; case LogLevel.Information: return "\x1b[32minfo\x1b[39m"; case LogLevel.Warning: return "\x1b[33mwarn\x1b[39m"; case LogLevel.Error: return "\x1b[31mfail\x1b[39m"; - case LogLevel.Critical: return "\x1b[31mcritical\x1b[39m"; + case LogLevel.Critical: return "\x1b[31mcrit\x1b[39m"; } throw new Exception("Unknown LogLevel"); diff --git a/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs index d159af747f..1d9f2fd0fb 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs @@ -121,7 +121,7 @@ namespace Microsoft.DotNet.Watcher private Task WaitForDotnetToExitAsync(string dotnetArguments, string workingDir, CancellationToken cancellationToken) { - _logger.LogInformation($"Running dotnet with the following arguments: {dotnetArguments}"); + _logger.LogDebug($"Running dotnet with the following arguments: {dotnetArguments}"); var dotnetWatcher = _processWatcherFactory(); int dotnetProcessId = dotnetWatcher.Start("dotnet", dotnetArguments, workingDir); diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index d96726f258..71cdc7f5d6 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -6,16 +6,18 @@ using System.IO; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; +using Microsoft.DotNet.Cli.Utils; namespace Microsoft.DotNet.Watcher { public class Program { - private readonly ILoggerFactory _loggerFactory; + private readonly ILoggerFactory _loggerFactory = new LoggerFactory(); private readonly CancellationToken _cancellationToken; - private readonly TextWriter _out; + private readonly TextWriter _stdout; + private readonly TextWriter _stderr; - public Program(TextWriter consoleOutput, CancellationToken cancellationToken) + public Program(TextWriter consoleOutput, TextWriter consoleError, CancellationToken cancellationToken) { if (consoleOutput == null) { @@ -28,23 +30,8 @@ namespace Microsoft.DotNet.Watcher } _cancellationToken = cancellationToken; - _out = consoleOutput; - - _loggerFactory = new LoggerFactory(); - - var logVar = Environment.GetEnvironmentVariable("DOTNET_WATCH_LOG_LEVEL"); - - LogLevel logLevel; - if (string.IsNullOrEmpty(logVar) || !Enum.TryParse(logVar, out logLevel)) - { - logLevel = LogLevel.Information; - } - - var commandProvider = new CommandOutputProvider() - { - LogLevel = logLevel - }; - _loggerFactory.AddProvider(commandProvider); + _stdout = consoleOutput; + _stderr = consoleError; } public static int Main(string[] args) @@ -60,7 +47,7 @@ namespace Microsoft.DotNet.Watcher int exitCode; try { - exitCode = new Program(Console.Out, ctrlCTokenSource.Token) + exitCode = new Program(Console.Out, Console.Error, ctrlCTokenSource.Token) .MainInternalAsync(args) .GetAwaiter() .GetResult(); @@ -76,7 +63,7 @@ namespace Microsoft.DotNet.Watcher private async Task MainInternalAsync(string[] args) { - var options = CommandLineOptions.Parse(args, _out); + var options = CommandLineOptions.Parse(args, _stdout, _stdout); if (options == null) { // invalid args syntax @@ -88,6 +75,12 @@ namespace Microsoft.DotNet.Watcher return 2; } + var commandProvider = new CommandOutputProvider + { + LogLevel = ResolveLogLevel(options) + }; + _loggerFactory.AddProvider(commandProvider); + var projectToWatch = Path.Combine(Directory.GetCurrentDirectory(), ProjectModel.Project.FileName); await DotNetWatcher @@ -96,5 +89,24 @@ namespace Microsoft.DotNet.Watcher return 0; } + + private LogLevel ResolveLogLevel(CommandLineOptions options) + { + if (options.IsQuiet) + { + return LogLevel.Warning; + } + + bool globalVerbose; + bool.TryParse(Environment.GetEnvironmentVariable(CommandContext.Variables.Verbose), out globalVerbose); + + if (options.IsVerbose // dotnet watch --verbose + || globalVerbose) // dotnet --verbose watch + { + return LogLevel.Debug; + } + + return LogLevel.Information; + } } } diff --git a/src/Microsoft.DotNet.Watcher.Tools/Properties/Resources.Designer.cs b/src/Microsoft.DotNet.Watcher.Tools/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..92987141e4 --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/Properties/Resources.Designer.cs @@ -0,0 +1,46 @@ +// +namespace Microsoft.DotNet.Watcher.Tools +{ + using System.Globalization; + using System.Reflection; + using System.Resources; + + internal static class Resources + { + private static readonly ResourceManager _resourceManager + = new ResourceManager("Microsoft.DotNet.Watcher.Tools.Resources", typeof(Resources).GetTypeInfo().Assembly); + + /// + /// Cannot specify both '--quiet' and '--verbose' options. + /// + internal static string Error_QuietAndVerboseSpecified + { + get { return GetString("Error_QuietAndVerboseSpecified"); } + } + + /// + /// Cannot specify both '--quiet' and '--verbose' options. + /// + internal static string FormatError_QuietAndVerboseSpecified() + { + return GetString("Error_QuietAndVerboseSpecified"); + } + + private static string GetString(string name, params string[] formatterNames) + { + var value = _resourceManager.GetString(name); + + System.Diagnostics.Debug.Assert(value != null); + + if (formatterNames != null) + { + for (var i = 0; i < formatterNames.Length; i++) + { + value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); + } + } + + return value; + } + } +} diff --git a/src/Microsoft.DotNet.Watcher.Tools/README.md b/src/Microsoft.DotNet.Watcher.Tools/README.md index 8c47b9c58c..e97e579e1b 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/README.md +++ b/src/Microsoft.DotNet.Watcher.Tools/README.md @@ -20,7 +20,12 @@ Add `Microsoft.DotNet.Watcher.Tools` to the `tools` section of your `project.jso dotnet watch [-?|-h|--help] - dotnet watch [[--] ...] + dotnet watch [options] [[--] ...] + + Options: + -?|-h|--help Show help information + -q|--quiet Suppresses all output except warnings and errors + -v|--verbose Show verbose output Add `watch` after `dotnet` in the command that you want to run: @@ -31,11 +36,10 @@ Add `watch` after `dotnet` in the command that you want to run: | dotnet run --framework net451 -- --arg1 value1 | dotnet **watch** run --framework net451 -- --arg1 value1 | | dotnet test | dotnet **watch** test | -### Advanced configuration options +### Environment variables -Configuration options can be passed to `dotnet watch` through environment variables. The available variables are: +Some configuration options can be passed to `dotnet watch` through environment variables. The available variables are: | Variable | Effect | | ---------------------------------------------- | -------------------------------------------------------- | | DOTNET_USE_POLLING_FILE_WATCHER | If set to "1" or "true", `dotnet watch` will use a polling file watcher instead of CoreFx's `FileSystemWatcher`. Used when watching files on network shares or Docker mounted volumes. | -| DOTNET_WATCH_LOG_LEVEL | Used to set the logging level for messages coming from `dotnet watch`. Accepted values `None`, `Trace`, `Debug`, `Information`, `Warning`, `Error`, `Critical`. Default: `Information`. | diff --git a/src/Microsoft.DotNet.Watcher.Tools/Resources.resx b/src/Microsoft.DotNet.Watcher.Tools/Resources.resx new file mode 100644 index 0000000000..47ccd0a26c --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/Resources.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Cannot specify both '--quiet' and '--verbose' options. + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs index 306cddaacd..be63a361fc 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs @@ -21,7 +21,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { var stdout = new StringBuilder(); - var options = CommandLineOptions.Parse(args, new StringWriter(stdout)); + var options = CommandLineOptions.Parse(args, new StringWriter(stdout), new StringWriter()); Assert.True(options.IsHelp); Assert.Contains("Usage: dotnet watch ", stdout.ToString()); @@ -36,11 +36,20 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { var stdout = new StringBuilder(); - var options = CommandLineOptions.Parse(args, new StringWriter(stdout)); + var options = CommandLineOptions.Parse(args, new StringWriter(stdout), new StringWriter()); Assert.Equal(expected, options.RemainingArguments.ToArray()); Assert.False(options.IsHelp); Assert.Empty(stdout.ToString()); } + + [Fact] + public void CannotHaveQuietAndVerbose() + { + var sb = new StringBuilder(); + var stderr = new StringWriter(sb); + Assert.Null(CommandLineOptions.Parse(new[] { "--quiet", "--verbose" }, new StringWriter(), stderr)); + Assert.Contains(Resources.Error_QuietAndVerboseSpecified, sb.ToString()); + } } } From 3b4b9a84c11c52ba7e4063cda6ea25eeb7ec9af6 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 17 Oct 2016 09:48:54 -0700 Subject: [PATCH 0294/1029] Branching for 1.1.0-preview1 --- NuGet.config | 4 ++-- build.ps1 | 2 +- build.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/NuGet.config b/NuGet.config index 18b373abe1..b25d126620 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,8 +1,8 @@ - + - + diff --git a/build.ps1 b/build.ps1 index 8f2f99691a..787f63ac02 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.1.0-preview1.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index f4208100eb..355c682856 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.1.0-preview1.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi From f280d5ff434257ca679ab9b135f9a7d4235c047b Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 17 Oct 2016 09:49:10 -0700 Subject: [PATCH 0295/1029] Branching for 1.1.0-preview1 --- NuGet.config | 4 ++-- build.ps1 | 2 +- build.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/NuGet.config b/NuGet.config index 826a1f9035..6197c93176 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + - + \ No newline at end of file diff --git a/build.ps1 b/build.ps1 index 8f2f99691a..787f63ac02 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.1.0-preview1.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index f4208100eb..355c682856 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.1.0-preview1.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi From ad17eb8b562c4e0971bd1faa2bb95c1392ebca8d Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 17 Oct 2016 09:49:16 -0700 Subject: [PATCH 0296/1029] Branching for 1.1.0-preview1 --- NuGet.config | 4 ++-- build.ps1 | 2 +- build.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/NuGet.config b/NuGet.config index 0fd623ffdd..ad973186eb 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + - + diff --git a/build.ps1 b/build.ps1 index 8f2f99691a..787f63ac02 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.1.0-preview1.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index f4208100eb..355c682856 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.1.0-preview1.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi From 62df63ada82ce80e4744f98179c0a90424e2a9da Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 17 Oct 2016 09:55:51 -0700 Subject: [PATCH 0297/1029] Updating to preview4 --- makefile.shade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile.shade b/makefile.shade index d8d56a527e..00f152f8b2 100644 --- a/makefile.shade +++ b/makefile.shade @@ -6,7 +6,7 @@ default BUILD_DIR_LOCAL='${Path.Combine(BASE_DIR_LOCAL, "artifacts", "build")}' var VERSION='0.1' var FULL_VERSION='0.1' var AUTHORS='Microsoft Open Technologies, Inc.' --BuildQuality = "preview3"; +-BuildQuality = "preview4"; use-standard-lifecycle k-standard-goals From 0781b5a87cb9eb8b48044b74cb8e6602650a3b63 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Mon, 10 Oct 2016 21:42:33 -0700 Subject: [PATCH 0298/1029] Add `HtmlContentBuilder.Count` - precursor to PR aspnet/Mvc#5378 for issue aspnet/Mvc#3918 --- .../HtmlContentBuilder.cs | 5 ++ .../HtmlContentBuilderTest.cs | 71 +++++++++++-------- 2 files changed, 45 insertions(+), 31 deletions(-) diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilder.cs b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilder.cs index 864f3c8a65..e61d9f7dc8 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilder.cs +++ b/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilder.cs @@ -30,6 +30,11 @@ namespace Microsoft.AspNetCore.Html { } + /// + /// Gets the number of elements in the . + /// + public int Count => Entries.Count; + /// /// Creates a new with the given list of entries. /// diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderTest.cs b/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderTest.cs index 40219b19f7..c3cb7d1954 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderTest.cs +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderTest.cs @@ -22,6 +22,7 @@ namespace Microsoft.Extensions.Internal content.Append("Hello"); // Assert + Assert.Equal(1, content.Count); var result = Assert.Single(content.Entries); Assert.IsType(result); } @@ -69,6 +70,7 @@ namespace Microsoft.Extensions.Internal content.AppendHtml(new TestHtmlContent("Hello")); // Assert + Assert.Equal(1, content.Count); var result = Assert.Single(content.Entries); var testHtmlContent = Assert.IsType(result); testHtmlContent.WriteTo(writer, new HtmlTestEncoder()); @@ -86,9 +88,11 @@ namespace Microsoft.Extensions.Internal content.Append("Test"); // Assert - Assert.Equal(2, content.Entries.Count); - Assert.Equal("Written from TestHtmlContent: hello", content.Entries[0].ToString()); - Assert.Equal("Test", content.Entries[1]); + Assert.Equal(2, content.Count); + Assert.Collection( + content.Entries, + entry => Assert.Equal("Written from TestHtmlContent: hello", entry.ToString()), + entry => Assert.Equal("Test", entry)); } [Fact] @@ -103,7 +107,8 @@ namespace Microsoft.Extensions.Internal content.Clear(); // Assert - Assert.Equal(0, content.Entries.Count); + Assert.Equal(0, content.Count); + Assert.Empty(content.Entries); } [Fact] @@ -121,12 +126,13 @@ namespace Microsoft.Extensions.Internal source.CopyTo(destination); // Assert - Assert.Equal(2, source.Entries.Count); - Assert.Equal(3, destination.Entries.Count); - - Assert.Equal("some-content", Assert.IsType(destination.Entries[0])); - Assert.Equal(new TestHtmlContent("hello"), Assert.IsType(destination.Entries[1])); - Assert.Equal("Test", Assert.IsType(destination.Entries[2])); + Assert.Equal(2, source.Count); + Assert.Equal(3, destination.Count); + Assert.Collection( + destination.Entries, + entry => Assert.Equal("some-content", Assert.IsType(entry)), + entry => Assert.Equal(new TestHtmlContent("hello"), Assert.IsType(entry)), + entry => Assert.Equal("Test", Assert.IsType(entry))); } [Fact] @@ -147,13 +153,14 @@ namespace Microsoft.Extensions.Internal source.CopyTo(destination); // Assert - Assert.Equal(2, source.Entries.Count); - Assert.Equal(1, nested.Entries.Count); - Assert.Equal(3, destination.Entries.Count); - - Assert.Equal("some-content", Assert.IsType(destination.Entries[0])); - Assert.Equal(new TestHtmlContent("hello"), Assert.IsType(destination.Entries[1])); - Assert.Equal("Test", Assert.IsType(destination.Entries[2])); + Assert.Equal(2, source.Count); + Assert.Equal(1, nested.Count); + Assert.Equal(3, destination.Count); + Assert.Collection( + destination.Entries, + entry => Assert.Equal("some-content", Assert.IsType(entry)), + entry => Assert.Equal(new TestHtmlContent("hello"), Assert.IsType(entry)), + entry => Assert.Equal("Test", Assert.IsType(entry))); } [Fact] @@ -171,12 +178,13 @@ namespace Microsoft.Extensions.Internal source.MoveTo(destination); // Assert - Assert.Equal(0, source.Entries.Count); - Assert.Equal(3, destination.Entries.Count); - - Assert.Equal("some-content", Assert.IsType(destination.Entries[0])); - Assert.Equal(new TestHtmlContent("hello"), Assert.IsType(destination.Entries[1])); - Assert.Equal("Test", Assert.IsType(destination.Entries[2])); + Assert.Equal(0, source.Count); + Assert.Equal(3, destination.Count); + Assert.Collection( + destination.Entries, + entry => Assert.Equal("some-content", Assert.IsType(entry)), + entry => Assert.Equal(new TestHtmlContent("hello"), Assert.IsType(entry)), + entry => Assert.Equal("Test", Assert.IsType(entry))); } [Fact] @@ -197,13 +205,14 @@ namespace Microsoft.Extensions.Internal source.MoveTo(destination); // Assert - Assert.Equal(0, source.Entries.Count); - Assert.Equal(0, nested.Entries.Count); - Assert.Equal(3, destination.Entries.Count); - - Assert.Equal("some-content", Assert.IsType(destination.Entries[0])); - Assert.Equal(new TestHtmlContent("hello"), Assert.IsType(destination.Entries[1])); - Assert.Equal("Test", Assert.IsType(destination.Entries[2])); + Assert.Equal(0, source.Count); + Assert.Equal(0, nested.Count); + Assert.Equal(3, destination.Count); + Assert.Collection( + destination.Entries, + entry => Assert.Equal("some-content", Assert.IsType(entry)), + entry => Assert.Equal(new TestHtmlContent("hello"), Assert.IsType(entry)), + entry => Assert.Equal("Test", Assert.IsType(entry))); } [Fact] @@ -219,7 +228,7 @@ namespace Microsoft.Extensions.Internal content.WriteTo(writer, new HtmlTestEncoder()); // Assert - Assert.Equal(2, content.Entries.Count); + Assert.Equal(2, content.Count); Assert.Equal("Written from TestHtmlContent: HelloHtmlEncode[[Test]]", writer.ToString()); } From 721cbe34353e0e99c10c98f7767090df805e16ea Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 12 Oct 2016 17:34:59 -0700 Subject: [PATCH 0299/1029] Refactor dotnet-watch to isolate project.json dependency --- .../CommandLineOptions.cs | 7 +- .../DotNetWatcher.cs | 165 ++++-------------- .../IProjectProvider.cs => IFileSet.cs} | 8 +- .../IProcessWatcher.cs => IFileSetFactory.cs} | 11 +- .../Internal/Ensure.cs | 30 ++++ .../Internal/FileSet.cs | 24 +++ .../Internal/FileSetWatcher.cs | 52 ++++++ .../{Implementation => }/FileWatcher.cs | 0 .../Internal/FileWatcher/DotnetFileWatcher.cs | 23 +-- .../FileWatcher/PollingFileWatcher.cs | 5 +- .../Internal/IProject.cs | 16 -- .../Internal/Implementation/ProcessWatcher.cs | 59 ------- .../Internal/IncludeContextExtensions.cs | 6 +- .../Internal/ProcessRunner.cs | 126 +++++++++++++ .../Internal/{Implementation => }/Project.cs | 4 +- .../Internal/ProjectJsonFileSet.cs | 95 ++++++++++ .../Internal/ProjectJsonFileSetFactory.cs | 51 ++++++ ...ojectProvider.cs => ProjectReaderUtils.cs} | 13 +- .../Internal/ProjectWatcher.cs | 119 ------------- .../Microsoft.DotNet.Watcher.Tools.xproj | 4 +- .../ProcessSpec.cs | 18 ++ src/Microsoft.DotNet.Watcher.Tools/Program.cs | 65 ++++--- .../Properties/Resources.Designer.cs | 16 ++ .../Resources.resx | 3 + .../Scenario/ProjectToolScenario.cs | 11 +- 25 files changed, 520 insertions(+), 411 deletions(-) rename src/Microsoft.DotNet.Watcher.Tools/{Internal/IProjectProvider.cs => IFileSet.cs} (52%) rename src/Microsoft.DotNet.Watcher.Tools/{Internal/IProcessWatcher.cs => IFileSetFactory.cs} (51%) create mode 100644 src/Microsoft.DotNet.Watcher.Tools/Internal/Ensure.cs create mode 100644 src/Microsoft.DotNet.Watcher.Tools/Internal/FileSet.cs create mode 100644 src/Microsoft.DotNet.Watcher.Tools/Internal/FileSetWatcher.cs rename src/Microsoft.DotNet.Watcher.Tools/Internal/{Implementation => }/FileWatcher.cs (100%) delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/Internal/IProject.cs delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/ProcessWatcher.cs create mode 100644 src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs rename src/Microsoft.DotNet.Watcher.Tools/Internal/{Implementation => }/Project.cs (96%) create mode 100644 src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectJsonFileSet.cs create mode 100644 src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectJsonFileSetFactory.cs rename src/Microsoft.DotNet.Watcher.Tools/Internal/{Implementation/ProjectProvider.cs => ProjectReaderUtils.cs} (81%) delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectWatcher.cs create mode 100644 src/Microsoft.DotNet.Watcher.Tools/ProcessSpec.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs index 6960ea93b6..dfd27756bd 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs @@ -1,11 +1,11 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.Collections.Generic; using System.IO; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Watcher.Tools; +using Microsoft.DotNet.Watcher.Internal; using Microsoft.Extensions.CommandLineUtils; namespace Microsoft.DotNet.Watcher @@ -18,10 +18,7 @@ namespace Microsoft.DotNet.Watcher public IList RemainingArguments { get; private set; } public static CommandLineOptions Parse(string[] args, TextWriter stdout, TextWriter stderr) { - if (args == null) - { - throw new ArgumentNullException(nameof(args)); - } + Ensure.NotNull(args, nameof(args)); var app = new CommandLineApplication(throwOnUnexpectedArg: false) { diff --git a/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs index 1d9f2fd0fb..58756c33cd 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs @@ -1,12 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; -using System.Collections.Generic; -using System.IO; using System.Threading; using System.Threading.Tasks; -using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Watcher.Internal; using Microsoft.Extensions.Logging; @@ -14,163 +10,68 @@ namespace Microsoft.DotNet.Watcher { public class DotNetWatcher { - private readonly Func _fileWatcherFactory; - private readonly Func _processWatcherFactory; - private readonly IProjectProvider _projectProvider; - private readonly ILoggerFactory _loggerFactory; - private readonly ILogger _logger; + private readonly ProcessRunner _processRunner; - public DotNetWatcher( - Func fileWatcherFactory, - Func processWatcherFactory, - IProjectProvider projectProvider, - ILoggerFactory loggerFactory) + public DotNetWatcher(ILogger logger) { - _fileWatcherFactory = fileWatcherFactory; - _processWatcherFactory = processWatcherFactory; - _projectProvider = projectProvider; - _loggerFactory = loggerFactory; + Ensure.NotNull(logger, nameof(logger)); - _logger = _loggerFactory.CreateLogger(nameof(DotNetWatcher)); + _logger = logger; + _processRunner = new ProcessRunner(logger); } - public async Task WatchAsync(string projectFile, IEnumerable dotnetArguments, CancellationToken cancellationToken) + public async Task WatchAsync(ProcessSpec processSpec, IFileSetFactory fileSetFactory, CancellationToken cancellationToken) { - if (string.IsNullOrEmpty(projectFile)) - { - throw new ArgumentNullException(nameof(projectFile)); - } - if (dotnetArguments == null) - { - throw new ArgumentNullException(nameof(dotnetArguments)); - } - if (cancellationToken == null) - { - throw new ArgumentNullException(nameof(cancellationToken)); - } + Ensure.NotNull(processSpec, nameof(processSpec)); - var dotnetArgumentsAsString = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(dotnetArguments); - - var workingDir = Path.GetDirectoryName(projectFile); + var cancelledTaskSource = new TaskCompletionSource(); + cancellationToken.Register(state => ((TaskCompletionSource)state).TrySetResult(null), cancelledTaskSource); while (true) { - await WaitForValidProjectJsonAsync(projectFile, cancellationToken); - cancellationToken.ThrowIfCancellationRequested(); + var fileSet = await fileSetFactory.CreateAsync(cancellationToken); + if (cancellationToken.IsCancellationRequested) + { + return; + } using (var currentRunCancellationSource = new CancellationTokenSource()) using (var combinedCancellationSource = CancellationTokenSource.CreateLinkedTokenSource( cancellationToken, currentRunCancellationSource.Token)) + using (var fileSetWatcher = new FileSetWatcher(fileSet)) { - var fileWatchingTask = WaitForProjectFileToChangeAsync(projectFile, combinedCancellationSource.Token); - var dotnetTask = WaitForDotnetToExitAsync(dotnetArgumentsAsString, workingDir, combinedCancellationSource.Token); + var fileSetTask = fileSetWatcher.GetChangedFileAsync(combinedCancellationSource.Token); + var processTask = _processRunner.RunAsync(processSpec, combinedCancellationSource.Token); - var tasksToWait = new Task[] { dotnetTask, fileWatchingTask }; + var finishedTask = await Task.WhenAny(processTask, fileSetTask, cancelledTaskSource.Task); - int finishedTaskIndex = Task.WaitAny(tasksToWait, cancellationToken); - - // Regardless of the outcome, make sure everything is cancelled + // Regardless of the which task finished first, make sure everything is cancelled // and wait for dotnet to exit. We don't want orphan processes currentRunCancellationSource.Cancel(); - Task.WaitAll(tasksToWait); - cancellationToken.ThrowIfCancellationRequested(); + await Task.WhenAll(processTask, fileSetTask); - string changedFile; - if (finishedTaskIndex == 0) - { - // This is the dotnet task - var dotnetExitCode = dotnetTask.Result; - - if (dotnetExitCode == 0) - { - _logger.LogInformation($"dotnet exit code: {dotnetExitCode}"); - } - else - { - _logger.LogError($"dotnet exit code: {dotnetExitCode}"); - } - - _logger.LogInformation("Waiting for a file to change before restarting dotnet..."); - // Now wait for a file to change before restarting dotnet - changedFile = await WaitForProjectFileToChangeAsync(projectFile, cancellationToken); - } - else - { - // This is a file watcher task - changedFile = fileWatchingTask.Result; - } - - if (!string.IsNullOrEmpty(changedFile)) - { - _logger.LogInformation($"File changed: {changedFile}"); - } - } - } - } - - private async Task WaitForProjectFileToChangeAsync(string projectFile, CancellationToken cancellationToken) - { - using (var projectWatcher = CreateProjectWatcher(projectFile, watchProjectJsonOnly: false)) - { - return await projectWatcher.WaitForChangeAsync(cancellationToken); - } - } - - private Task WaitForDotnetToExitAsync(string dotnetArguments, string workingDir, CancellationToken cancellationToken) - { - _logger.LogDebug($"Running dotnet with the following arguments: {dotnetArguments}"); - - var dotnetWatcher = _processWatcherFactory(); - int dotnetProcessId = dotnetWatcher.Start("dotnet", dotnetArguments, workingDir); - _logger.LogInformation($"dotnet process id: {dotnetProcessId}"); - - return dotnetWatcher.WaitForExitAsync(cancellationToken); - } - - private async Task WaitForValidProjectJsonAsync(string projectFile, CancellationToken cancellationToken) - { - while (true) - { - IProject project; - string errors; - if (_projectProvider.TryReadProject(projectFile, out project, out errors)) - { - return; - } - - _logger.LogError($"Error(s) reading project file '{projectFile}': "); - _logger.LogError(errors); - _logger.LogInformation("Fix the error to continue."); - - using (var projectWatcher = CreateProjectWatcher(projectFile, watchProjectJsonOnly: true)) - { - await projectWatcher.WaitForChangeAsync(cancellationToken); - - if (cancellationToken.IsCancellationRequested) + if (finishedTask == cancelledTaskSource.Task || cancellationToken.IsCancellationRequested) { return; } - _logger.LogInformation($"File changed: {projectFile}"); + if (finishedTask == processTask) + { + _logger.LogInformation("Waiting for a file to change before restarting dotnet..."); + + // Now wait for a file to change before restarting process + await fileSetWatcher.GetChangedFileAsync(cancellationToken); + } + + if (!string.IsNullOrEmpty(fileSetTask.Result)) + { + _logger.LogInformation($"File changed: {fileSetTask.Result}"); + } } } } - - private ProjectWatcher CreateProjectWatcher(string projectFile, bool watchProjectJsonOnly) - { - return new ProjectWatcher(projectFile, watchProjectJsonOnly, _fileWatcherFactory, _projectProvider); - } - - public static DotNetWatcher CreateDefault(ILoggerFactory loggerFactory) - { - return new DotNetWatcher( - fileWatcherFactory: () => new FileWatcher(), - processWatcherFactory: () => new ProcessWatcher(), - projectProvider: new ProjectProvider(), - loggerFactory: loggerFactory); - } } } diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/IProjectProvider.cs b/src/Microsoft.DotNet.Watcher.Tools/IFileSet.cs similarity index 52% rename from src/Microsoft.DotNet.Watcher.Tools/Internal/IProjectProvider.cs rename to src/Microsoft.DotNet.Watcher.Tools/IFileSet.cs index 30b2a94ee9..7554d3f542 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/IProjectProvider.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/IFileSet.cs @@ -1,10 +1,12 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.DotNet.Watcher.Internal +using System.Collections.Generic; + +namespace Microsoft.DotNet.Watcher { - public interface IProjectProvider + public interface IFileSet : IEnumerable { - bool TryReadProject(string projectFile, out IProject project, out string errors); + bool Contains(string filePath); } } diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/IProcessWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/IFileSetFactory.cs similarity index 51% rename from src/Microsoft.DotNet.Watcher.Tools/Internal/IProcessWatcher.cs rename to src/Microsoft.DotNet.Watcher.Tools/IFileSetFactory.cs index e80bd7c0a9..6a70c06a4c 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/IProcessWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/IFileSetFactory.cs @@ -1,16 +1,13 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.Threading; using System.Threading.Tasks; -namespace Microsoft.DotNet.Watcher.Internal +namespace Microsoft.DotNet.Watcher { - public interface IProcessWatcher + public interface IFileSetFactory { - int Start(string executable, string arguments, string workingDir); - - Task WaitForExitAsync(CancellationToken cancellationToken); + Task CreateAsync(CancellationToken cancellationToken); } -} +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/Ensure.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/Ensure.cs new file mode 100644 index 0000000000..12bfe5f05d --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/Ensure.cs @@ -0,0 +1,30 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.DotNet.Watcher.Tools; + +namespace Microsoft.DotNet.Watcher.Internal +{ + internal static class Ensure + { + public static T NotNull(T obj, string paramName) + where T : class + { + if (obj == null) + { + throw new ArgumentNullException(paramName); + } + return obj; + } + + public static string NotNullOrEmpty(string obj, string paramName) + { + if (string.IsNullOrEmpty(obj)) + { + throw new ArgumentException(Resources.Error_StringNullOrEmpty, paramName); + } + return obj; + } + } +} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSet.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSet.cs new file mode 100644 index 0000000000..5cc524e79e --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSet.cs @@ -0,0 +1,24 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.DotNet.Watcher.Internal +{ + public class FileSet : IFileSet + { + private readonly HashSet _files; + + public FileSet(IEnumerable files) + { + _files = new HashSet(files, StringComparer.OrdinalIgnoreCase); + } + + public bool Contains(string filePath) => _files.Contains(filePath); + + public IEnumerator GetEnumerator() => _files.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _files.GetEnumerator(); + } +} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSetWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSetWatcher.cs new file mode 100644 index 0000000000..a1f56d9650 --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSetWatcher.cs @@ -0,0 +1,52 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.DotNet.Watcher.Internal +{ + public class FileSetWatcher : IDisposable + { + private readonly IFileWatcher _fileWatcher; + private readonly IFileSet _fileSet; + + public FileSetWatcher(IFileSet fileSet) + { + _fileSet = fileSet; + _fileWatcher = new FileWatcher(); + } + + public async Task GetChangedFileAsync(CancellationToken cancellationToken) + { + foreach (var file in _fileSet) + { + _fileWatcher.WatchDirectory(Path.GetDirectoryName(file)); + } + + var tcs = new TaskCompletionSource(); + cancellationToken.Register(() => tcs.TrySetResult(null)); + + Action callback = path => + { + if (_fileSet.Contains(path)) + { + tcs.TrySetResult(path); + } + }; + + _fileWatcher.OnFileChange += callback; + var changedFile = await tcs.Task; + _fileWatcher.OnFileChange -= callback; + + return changedFile; + } + + public void Dispose() + { + _fileWatcher.Dispose(); + } + } +} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/FileWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher.cs similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/FileWatcher.cs rename to src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/DotnetFileWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/DotnetFileWatcher.cs index e76fa088f6..4cda4f0cf8 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/DotnetFileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/DotnetFileWatcher.cs @@ -22,10 +22,8 @@ namespace Microsoft.DotNet.Watcher.Internal internal DotnetFileWatcher(string watchedDirectory, Func fileSystemWatcherFactory) { - if (string.IsNullOrEmpty(watchedDirectory)) - { - throw new ArgumentNullException(nameof(watchedDirectory)); - } + Ensure.NotNull(fileSystemWatcherFactory, nameof(fileSystemWatcherFactory)); + Ensure.NotNullOrEmpty(watchedDirectory, nameof(watchedDirectory)); _watchedDirectory = watchedDirectory; _watcherFactory = fileSystemWatcherFactory; @@ -38,10 +36,7 @@ namespace Microsoft.DotNet.Watcher.Internal private static FileSystemWatcher DefaultWatcherFactory(string watchedDirectory) { - if (string.IsNullOrEmpty(watchedDirectory)) - { - throw new ArgumentNullException(nameof(watchedDirectory)); - } + Ensure.NotNullOrEmpty(watchedDirectory, nameof(watchedDirectory)); return new FileSystemWatcher(watchedDirectory); } @@ -51,10 +46,7 @@ namespace Microsoft.DotNet.Watcher.Internal // Recreate the watcher CreateFileSystemWatcher(); - if (OnError != null) - { - OnError(this, null); - } + OnError?.Invoke(this, null); } private void WatcherRenameHandler(object sender, RenamedEventArgs e) @@ -81,11 +73,8 @@ namespace Microsoft.DotNet.Watcher.Internal private void NotifyChange(string fullPath) { - if (OnFileChange != null) - { - // Only report file changes - OnFileChange(this, fullPath); - } + // Only report file changes + OnFileChange?.Invoke(this, fullPath); } private void CreateFileSystemWatcher() diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs index 1920eecb90..9ca5084347 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs @@ -27,10 +27,7 @@ namespace Microsoft.DotNet.Watcher.Internal public PollingFileWatcher(string watchedDirectory) { - if (string.IsNullOrEmpty(watchedDirectory)) - { - throw new ArgumentNullException(nameof(watchedDirectory)); - } + Ensure.NotNullOrEmpty(watchedDirectory, nameof(watchedDirectory)); _watchedDirectory = new DirectoryInfo(watchedDirectory); diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/IProject.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/IProject.cs deleted file mode 100644 index ca1dfb670a..0000000000 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/IProject.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; - -namespace Microsoft.DotNet.Watcher.Internal -{ - public interface IProject - { - string ProjectFile { get; } - - IEnumerable Files { get; } - - IEnumerable ProjectDependencies { get; } - } -} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/ProcessWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/ProcessWatcher.cs deleted file mode 100644 index 466ef9be17..0000000000 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/ProcessWatcher.cs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Diagnostics; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.Internal; - -namespace Microsoft.DotNet.Watcher.Internal -{ - public class ProcessWatcher : IProcessWatcher - { - private Process _runningProcess; - - public int Start(string executable, string arguments, string workingDir) - { - // This is not thread safe but it will not run in a multithreaded environment so don't worry - if (_runningProcess != null) - { - throw new InvalidOperationException("The previous process is still running"); - } - - _runningProcess = new Process(); - _runningProcess.StartInfo = new ProcessStartInfo() - { - FileName = executable, - Arguments = arguments, - UseShellExecute = false, - WorkingDirectory = workingDir - }; - - _runningProcess.Start(); - - return _runningProcess.Id; - } - - public Task WaitForExitAsync(CancellationToken cancellationToken) - { - cancellationToken.Register(() => - { - if (_runningProcess != null) - { - _runningProcess.KillTree(); - } - }); - - return Task.Run(() => - { - _runningProcess.WaitForExit(); - - var exitCode = _runningProcess.ExitCode; - _runningProcess = null; - - return exitCode; - }); - } - } -} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/IncludeContextExtensions.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/IncludeContextExtensions.cs index d01703999d..bd7cf0b8ad 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/IncludeContextExtensions.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/IncludeContextExtensions.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.Collections.Generic; using System.Linq; using Microsoft.DotNet.ProjectModel.Files; @@ -12,10 +11,7 @@ namespace Microsoft.DotNet.Watcher.Internal { public static IEnumerable ResolveFiles(this IncludeContext context) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } + Ensure.NotNull(context, nameof(context)); return IncludeFilesResolver .GetIncludeFiles(context, "/", diagnostics: null) diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs new file mode 100644 index 0000000000..f8d9260039 --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs @@ -0,0 +1,126 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Internal; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.Extensions.Logging; + +namespace Microsoft.DotNet.Watcher.Internal +{ + public class ProcessRunner + { + private readonly ILogger _logger; + + public ProcessRunner(ILogger logger) + { + Ensure.NotNull(logger, nameof(logger)); + + _logger = logger; + } + + // May not be necessary in the future. See https://github.com/dotnet/corefx/issues/12039 + public async Task RunAsync(ProcessSpec processSpec, CancellationToken cancellationToken) + { + Ensure.NotNull(processSpec, nameof(processSpec)); + + int exitCode; + + using (var process = CreateProcess(processSpec)) + using (var processState = new ProcessState(process)) + { + cancellationToken.Register(() => processState.TryKill()); + + process.Start(); + _logger.LogInformation("{execName} process id: {pid}", processSpec.ShortDisplayName(), process.Id); + + await processState.Task; + + exitCode = process.ExitCode; + } + + LogResult(processSpec, exitCode); + + return exitCode; + } + + private Process CreateProcess(ProcessSpec processSpec) + { + var arguments = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(processSpec.Arguments); + + _logger.LogInformation("Running {execName} with the following arguments: {args}", processSpec.ShortDisplayName(), arguments); + + var startInfo = new ProcessStartInfo + { + FileName = processSpec.Executable, + Arguments = arguments, + UseShellExecute = false, + WorkingDirectory = processSpec.WorkingDirectory + }; + var process = new Process + { + StartInfo = startInfo, + EnableRaisingEvents = true + }; + return process; + } + + private void LogResult(ProcessSpec processSpec, int exitCode) + { + var processName = processSpec.ShortDisplayName(); + if (exitCode == 0) + { + _logger.LogInformation("{execName} exit code: {code}", processName, exitCode); + } + else + { + _logger.LogError("{execName} exit code: {code}", processName, exitCode); + } + } + + private class ProcessState : IDisposable + { + private readonly Process _process; + private readonly TaskCompletionSource _tcs = new TaskCompletionSource(); + private volatile bool _disposed; + + public ProcessState(Process process) + { + _process = process; + _process.Exited += OnExited; + } + + public Task Task => _tcs.Task; + + public void TryKill() + { + try + { + if (!_process.HasExited) + { + _process.KillTree(); + } + } + catch + { } + } + + private void OnExited(object sender, EventArgs args) + => _tcs.TrySetResult(null); + + public void Dispose() + { + if (!_disposed) + { + _disposed = true; + TryKill(); + _process.Exited -= OnExited; + _process.Dispose(); + } + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/Project.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/Project.cs similarity index 96% rename from src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/Project.cs rename to src/Microsoft.DotNet.Watcher.Tools/Internal/Project.cs index 10d8624df3..8485cc331b 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/Project.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/Project.cs @@ -1,16 +1,14 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.Collections.Generic; using System.IO; using System.Linq; -using Microsoft.DotNet.ProjectModel.Files; using Microsoft.DotNet.ProjectModel.Graph; namespace Microsoft.DotNet.Watcher.Internal { - internal class Project : IProject + public class Project { public Project(ProjectModel.Project runtimeProject) { diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectJsonFileSet.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectJsonFileSet.cs new file mode 100644 index 0000000000..c9d67daf5c --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectJsonFileSet.cs @@ -0,0 +1,95 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Microsoft.DotNet.Watcher.Internal +{ + public class ProjectJsonFileSet : IFileSet + { + private readonly string _projectFile; + private ISet _currentFiles; + + public ProjectJsonFileSet(string projectFile) + { + _projectFile = projectFile; + } + + public bool Contains(string filePath) + { + // if it was in the original list of files we were watching + if (_currentFiles?.Contains(filePath) == true) + { + return true; + } + + // It's possible the new file was not in the old set but will be in the new set. + // Additions should be considered part of this. + RefreshFileList(); + + return _currentFiles.Contains(filePath); + } + + public IEnumerator GetEnumerator() + { + EnsureInitialized(); + return _currentFiles.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + EnsureInitialized(); + return _currentFiles.GetEnumerator(); + } + + private void EnsureInitialized() + { + if (_currentFiles == null) + { + RefreshFileList(); + } + } + + private void RefreshFileList() + { + _currentFiles = new HashSet(FindFiles(), StringComparer.OrdinalIgnoreCase); + } + + private IEnumerable FindFiles() + { + var projects = new HashSet(); // temporary store to prevent re-parsing a project multiple times + return GetProjectFilesClosure(_projectFile, projects); + } + + private IEnumerable GetProjectFilesClosure(string projectFile, ISet projects) + { + if (projects.Contains(projectFile)) + { + yield break; + } + + projects.Add(projectFile); + + Project project; + string errors; + + if (ProjectReader.TryReadProject(projectFile, out project, out errors)) + { + foreach (var file in project.Files) + { + yield return file; + } + + foreach (var dependency in project.ProjectDependencies) + { + foreach (var file in GetProjectFilesClosure(dependency, projects)) + { + yield return file; + } + } + } + } + } +} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectJsonFileSetFactory.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectJsonFileSetFactory.cs new file mode 100644 index 0000000000..419776d4dc --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectJsonFileSetFactory.cs @@ -0,0 +1,51 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; + +namespace Microsoft.DotNet.Watcher.Internal +{ + public class ProjectJsonFileSetFactory : IFileSetFactory + { + private readonly ILogger _logger; + private readonly string _projectFile; + public ProjectJsonFileSetFactory(ILogger logger, string projectFile) + { + Ensure.NotNull(logger, nameof(logger)); + Ensure.NotNullOrEmpty(projectFile, nameof(projectFile)); + + _logger = logger; + _projectFile = projectFile; + } + + public async Task CreateAsync(CancellationToken cancellationToken) + { + while (true) + { + cancellationToken.ThrowIfCancellationRequested(); + + Project project; + string errors; + if (ProjectReader.TryReadProject(_projectFile, out project, out errors)) + { + return new ProjectJsonFileSet(_projectFile); + } + + _logger.LogError($"Error(s) reading project file '{_projectFile}': "); + _logger.LogError(errors); + _logger.LogInformation("Fix the error to continue."); + + var fileSet = new FileSet(new[] { _projectFile }); + + using (var watcher = new FileSetWatcher(fileSet)) + { + await watcher.GetChangedFileAsync(cancellationToken); + + _logger.LogInformation($"File changed: {_projectFile}"); + } + } + } + } +} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/ProjectProvider.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectReaderUtils.cs similarity index 81% rename from src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/ProjectProvider.cs rename to src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectReaderUtils.cs index 6d1cf3d99e..ffd2e012f4 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/Implementation/ProjectProvider.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectReaderUtils.cs @@ -2,16 +2,14 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.Generic; using System.Linq; using System.Text; -using Microsoft.DotNet.ProjectModel; namespace Microsoft.DotNet.Watcher.Internal { - public class ProjectProvider : IProjectProvider + public class ProjectReader { - public bool TryReadProject(string projectFile, out IProject project, out string errors) + public static bool TryReadProject(string projectFile, out Project project, out string errors) { errors = null; project = null; @@ -35,12 +33,11 @@ namespace Microsoft.DotNet.Watcher.Internal return true; } - // Same as TryGetProject but it doesn't throw - private bool TryGetProject(string projectFile, out ProjectModel.Project project, out string errorMessage) + private static bool TryGetProject(string projectFile, out ProjectModel.Project project, out string errorMessage) { try { - if (!ProjectReader.TryGetProject(projectFile, out project)) + if (!ProjectModel.ProjectReader.TryGetProject(projectFile, out project)) { if (project?.Diagnostics != null && project.Diagnostics.Any()) { @@ -66,7 +63,7 @@ namespace Microsoft.DotNet.Watcher.Internal return false; } - private string CollectMessages(Exception exception) + private static string CollectMessages(Exception exception) { var builder = new StringBuilder(); builder.AppendLine(exception.Message); diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectWatcher.cs deleted file mode 100644 index 6b5fce3ab5..0000000000 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectWatcher.cs +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.DotNet.Watcher.Internal -{ - public class ProjectWatcher : IDisposable - { - private readonly IProjectProvider _projectProvider; - private readonly IFileWatcher _fileWatcher; - - private readonly string _rootProject; - private readonly bool _watchProjectJsonOnly; - - private ISet _watchedFiles; - - public ProjectWatcher( - string projectToWatch, - bool watchProjectJsonOnly, - Func fileWatcherFactory, - IProjectProvider projectProvider) - { - _projectProvider = projectProvider; - _fileWatcher = fileWatcherFactory(); - - _rootProject = projectToWatch; - _watchProjectJsonOnly = watchProjectJsonOnly; - } - - public async Task WaitForChangeAsync(CancellationToken cancellationToken) - { - _watchedFiles = GetProjectFilesClosure(_rootProject); - - foreach (var file in _watchedFiles) - { - _fileWatcher.WatchDirectory(Path.GetDirectoryName(file)); - } - - var tcs = new TaskCompletionSource(); - cancellationToken.Register(() => tcs.TrySetResult(null)); - - Action callback = path => - { - // If perf becomes a problem, this could be a good starting point - // because it reparses the project on every change - // Maybe it could time-buffer the changes in case there are a lot - // of files changed at the same time - if (IsFileInTheWatchedSet(path)) - { - tcs.TrySetResult(path); - } - }; - - _fileWatcher.OnFileChange += callback; - var changedFile = await tcs.Task; - _fileWatcher.OnFileChange -= callback; - - return changedFile; - } - - public void Dispose() - { - _fileWatcher?.Dispose(); - } - - private bool IsFileInTheWatchedSet(string file) - { - // If the file was already watched - // or if the new project file closure determined - // by file globbing patterns contains the new file - // Note, we cannot simply rebuild the closure every time because it wouldn't - // detect renamed files that have the new name outside of the closure - return - _watchedFiles.Contains(file) || - GetProjectFilesClosure(_rootProject).Contains(file); - } - - private ISet GetProjectFilesClosure(string projectFile) - { - var closure = new HashSet(); - - if (_watchProjectJsonOnly) - { - closure.Add(projectFile); - } - else - { - GetProjectFilesClosure(projectFile, closure); - } - return closure; - } - - private void GetProjectFilesClosure(string projectFile, ISet closure) - { - closure.Add(projectFile); - - IProject project; - string errors; - - if (_projectProvider.TryReadProject(projectFile, out project, out errors)) - { - foreach (var file in project.Files) - { - closure.Add(file); - } - - foreach (var dependency in project.ProjectDependencies) - { - GetProjectFilesClosure(dependency, closure); - } - } - } - } -} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.xproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.xproj index f6e8a5813a..6ce5b43fae 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.xproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.xproj @@ -4,7 +4,7 @@ 14.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - + 8a8ceabc-ac47-43ff-a5df-69224f7e1f46 .\obj @@ -16,5 +16,5 @@ 2.0 - + \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/ProcessSpec.cs b/src/Microsoft.DotNet.Watcher.Tools/ProcessSpec.cs new file mode 100644 index 0000000000..2d18b9a0be --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/ProcessSpec.cs @@ -0,0 +1,18 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.IO; + +namespace Microsoft.DotNet.Watcher +{ + public class ProcessSpec + { + public string Executable { get; set; } + public string WorkingDirectory { get; set; } + public IEnumerable Arguments { get; set; } + + public string ShortDisplayName() + => Path.GetFileNameWithoutExtension(Executable); + } +} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index 71cdc7f5d6..14a115c978 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -5,29 +5,23 @@ using System; using System.IO; using System.Threading; using System.Threading.Tasks; -using Microsoft.Extensions.Logging; using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.Watcher.Internal; +using Microsoft.Extensions.Logging; namespace Microsoft.DotNet.Watcher { public class Program { - private readonly ILoggerFactory _loggerFactory = new LoggerFactory(); + private const string LoggerName = "DotNetWatcher"; private readonly CancellationToken _cancellationToken; private readonly TextWriter _stdout; private readonly TextWriter _stderr; public Program(TextWriter consoleOutput, TextWriter consoleError, CancellationToken cancellationToken) { - if (consoleOutput == null) - { - throw new ArgumentNullException(nameof(consoleOutput)); - } - - if (cancellationToken == null) - { - throw new ArgumentNullException(nameof(cancellationToken)); - } + Ensure.NotNull(consoleOutput, nameof(consoleOutput)); + Ensure.NotNull(consoleError, nameof(consoleError)); _cancellationToken = cancellationToken; _stdout = consoleOutput; @@ -36,28 +30,43 @@ namespace Microsoft.DotNet.Watcher public static int Main(string[] args) { + DebugHelper.HandleDebugSwitch(ref args); + using (CancellationTokenSource ctrlCTokenSource = new CancellationTokenSource()) { Console.CancelKeyPress += (sender, ev) => { + if (!ctrlCTokenSource.IsCancellationRequested) + { + Console.WriteLine($"[{LoggerName}] Shutdown requested. Press CTRL+C again to force exit."); + ev.Cancel = true; + } + else + { + ev.Cancel = false; + } ctrlCTokenSource.Cancel(); - ev.Cancel = false; }; - int exitCode; try { - exitCode = new Program(Console.Out, Console.Error, ctrlCTokenSource.Token) + return new Program(Console.Out, Console.Error, ctrlCTokenSource.Token) .MainInternalAsync(args) .GetAwaiter() .GetResult(); } - catch (TaskCanceledException) + catch (Exception ex) { - // swallow when only exception is the CTRL+C exit cancellation task - exitCode = 0; + if (ex is TaskCanceledException || ex is OperationCanceledException) + { + // swallow when only exception is the CTRL+C forced an exit + return 0; + } + + Console.Error.WriteLine(ex.ToString()); + Console.Error.WriteLine($"[{LoggerName}] An unexpected error occurred".Bold().Red()); + return 1; } - return exitCode; } } @@ -75,17 +84,25 @@ namespace Microsoft.DotNet.Watcher return 2; } + var loggerFactory = new LoggerFactory(); var commandProvider = new CommandOutputProvider { LogLevel = ResolveLogLevel(options) }; - _loggerFactory.AddProvider(commandProvider); + loggerFactory.AddProvider(commandProvider); + var logger = loggerFactory.CreateLogger(LoggerName); - var projectToWatch = Path.Combine(Directory.GetCurrentDirectory(), ProjectModel.Project.FileName); + var projectFile = Path.Combine(Directory.GetCurrentDirectory(), ProjectModel.Project.FileName); + var projectFileSetFactory = new ProjectJsonFileSetFactory(logger, projectFile); + var processInfo = new ProcessSpec + { + Executable = new Muxer().MuxerPath, + WorkingDirectory = Path.GetDirectoryName(projectFile), + Arguments = options.RemainingArguments + }; - await DotNetWatcher - .CreateDefault(_loggerFactory) - .WatchAsync(projectToWatch, options.RemainingArguments, _cancellationToken); + await new DotNetWatcher(logger) + .WatchAsync(processInfo, projectFileSetFactory, _cancellationToken); return 0; } @@ -97,7 +114,7 @@ namespace Microsoft.DotNet.Watcher return LogLevel.Warning; } - bool globalVerbose; + bool globalVerbose; bool.TryParse(Environment.GetEnvironmentVariable(CommandContext.Variables.Verbose), out globalVerbose); if (options.IsVerbose // dotnet watch --verbose diff --git a/src/Microsoft.DotNet.Watcher.Tools/Properties/Resources.Designer.cs b/src/Microsoft.DotNet.Watcher.Tools/Properties/Resources.Designer.cs index 92987141e4..5cdf225bb8 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Properties/Resources.Designer.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Properties/Resources.Designer.cs @@ -26,6 +26,22 @@ namespace Microsoft.DotNet.Watcher.Tools return GetString("Error_QuietAndVerboseSpecified"); } + /// + /// Value cannot be null or an empty string. + /// + internal static string Error_StringNullOrEmpty + { + get { return GetString("Error_StringNullOrEmpty"); } + } + + /// + /// Value cannot be null or an empty string. + /// + internal static string FormatError_StringNullOrEmpty() + { + return GetString("Error_StringNullOrEmpty"); + } + private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); diff --git a/src/Microsoft.DotNet.Watcher.Tools/Resources.resx b/src/Microsoft.DotNet.Watcher.Tools/Resources.resx index 47ccd0a26c..34336a97ba 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Resources.resx +++ b/src/Microsoft.DotNet.Watcher.Tools/Resources.resx @@ -120,4 +120,7 @@ Cannot specify both '--quiet' and '--verbose' options. + + Value cannot be null or an empty string. + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs index 41ac05c762..c0c2ce0016 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -5,14 +5,11 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Threading; -using System.Xml.Linq; -using Newtonsoft.Json.Linq; -using Microsoft.DotNet.Cli.Utils; -using Microsoft.Extensions.DependencyModel; -using Microsoft.DotNet.ProjectModel; -using System.Reflection; using System.Linq; +using System.Reflection; +using System.Threading; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.ProjectModel; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { From 640ee4e8838ee6827d2c522fc14e8ce23134eb28 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 17 Oct 2016 12:25:11 -0700 Subject: [PATCH 0300/1029] React to upgrade to preview2.1 CLI --- tools/NuGetPackager/project.json | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tools/NuGetPackager/project.json b/tools/NuGetPackager/project.json index 146561308a..f42b3d92d0 100644 --- a/tools/NuGetPackager/project.json +++ b/tools/NuGetPackager/project.json @@ -1,5 +1,4 @@ { - "version": "1.0.0-*", "buildOptions": { "emitEntryPoint": true }, @@ -7,7 +6,7 @@ "dependencies": { "Microsoft.NETCore.App": { "type": "platform", - "version": "1.0.0" + "version": "1.1.0-*" }, "Microsoft.DotNet.ProjectModel": "1.0.0-*", "Microsoft.DotNet.Cli.Utils": "1.0.0-*", @@ -15,8 +14,6 @@ }, "frameworks": { - "netcoreapp1.0": { - "imports": "dnxcore50" - } + "netcoreapp1.1": { } } } \ No newline at end of file From 68533f32f742bc17a2447ad7379a9ab3761a3fa8 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 17 Oct 2016 13:38:40 -0700 Subject: [PATCH 0301/1029] Upgrade test project to netcoreapp1.1 --- test/Microsoft.Extensions.ProjectModel.Tests/project.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/project.json b/test/Microsoft.Extensions.ProjectModel.Tests/project.json index d408f83c23..09eaf72e6f 100644 --- a/test/Microsoft.Extensions.ProjectModel.Tests/project.json +++ b/test/Microsoft.Extensions.ProjectModel.Tests/project.json @@ -28,10 +28,10 @@ "xunit": "2.2.0-*" }, "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { - "version": "1.0.0", + "version": "1.1.0-*", "type": "platform" } } From 70bafa9753f97311eb470d09e48a44893169bb5b Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 17 Oct 2016 15:09:24 -0700 Subject: [PATCH 0302/1029] Upgrade to MSBuild 15.1.319-preview5 and fix broken tests. (#201) --- NuGet.config | 1 + .../MsBuildProjectContextBuilderTest.cs | 2 +- .../MsBuildProjectDependencyProviderTests.cs | 36 ++++++++----------- .../project.json | 5 +-- 4 files changed, 19 insertions(+), 25 deletions(-) diff --git a/NuGet.config b/NuGet.config index 18b373abe1..68a0afe0e4 100644 --- a/NuGet.config +++ b/NuGet.config @@ -2,6 +2,7 @@ + diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs index 4dfeab0d99..debac6638e 100644 --- a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs +++ b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs @@ -130,7 +130,7 @@ namespace Microsoft.Extensions.ProjectModel Assert.False(_files.GetFileInfo("obj").Exists); Assert.Equal(expectedCompileItems, context.CompilationItems.OrderBy(i => i).ToArray()); Assert.Equal(Path.Combine(_files.Root, "bin", "Debug", "netcoreapp1.0", "test.dll"), context.AssemblyFullPath); - Assert.True(context.IsClassLibrary); + Assert.True(context.IsClassLibrary, "Expecting IsClassLibrary == true"); Assert.Equal("TestProject", context.ProjectName); Assert.Equal(FrameworkConstants.CommonFrameworks.NetCoreApp10, context.TargetFramework); Assert.Equal("Microsoft.TestProject", context.RootNamespace); diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectDependencyProviderTests.cs b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectDependencyProviderTests.cs index 7b4eedc203..ce6985ff1b 100644 --- a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectDependencyProviderTests.cs +++ b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectDependencyProviderTests.cs @@ -3,17 +3,19 @@ using System; using System.Linq; -using Microsoft.Extensions.ProjectModel.Tests; -using Xunit; -using Xunit.Abstractions; using System.IO; using Microsoft.DotNet.Cli.Utils; +using Microsoft.Extensions.ProjectModel.Tests; using NuGet.Frameworks; +using Xunit; +using Xunit.Abstractions; namespace Microsoft.Extensions.ProjectModel.MsBuild { - public class MsBuildProjectDependencyProviderTests: IClassFixture + public class MsBuildProjectDependencyProviderTests : IClassFixture { + private const string SkipReason = "CI doesn't yet have a new enough version of .NET Core SDK"; + private const string NugetConfigTxt = @" @@ -98,7 +100,7 @@ namespace Microsoft.Extensions.ProjectModel.MsBuild _output = output; } - [Fact(Skip = "CI doesn't yet have a new enough version of .NET Core SDK")] + [Fact(Skip = SkipReason)] public void BuildDependenciesForProject() { using (var fileProvider = new TemporaryFileProvider()) @@ -122,7 +124,7 @@ namespace Microsoft.Extensions.ProjectModel.MsBuild var muxer = Path.Combine(testContext.ExtensionsPath, "../..", "dotnet.exe"); var result = Command - .Create(muxer, new[] { "restore3", Path.Combine(fileProvider.Root, "Library1","Library1.csproj") }) + .Create(muxer, new[] { "restore3", Path.Combine(fileProvider.Root, "Library1", "Library1.csproj") }) .OnErrorLine(l => _output.WriteLine(l)) .OnOutputLine(l => _output.WriteLine(l)) .Execute(); @@ -146,26 +148,16 @@ namespace Microsoft.Extensions.ProjectModel.MsBuild var context = builder.Build(); - var compilationAssemblies = context.CompilationAssemblies; - var lib1Dll = compilationAssemblies - .Where(assembly => assembly.Name.Equals("Library1", StringComparison.OrdinalIgnoreCase)) - .FirstOrDefault(); - - Assert.NotNull(lib1Dll); - Assert.True(File.Exists(lib1Dll.ResolvedPath)); + var lib1Dll = Assert.Single(context.CompilationAssemblies, a => a.Name.Equals("Library1", StringComparison.OrdinalIgnoreCase)); + Assert.False(File.Exists(lib1Dll.ResolvedPath), $"Design time build. Shouldn't produce a file to {lib1Dll.ResolvedPath}"); // This reference doesn't resolve so should not be available here. - Assert.False(compilationAssemblies.Any(assembly => assembly.Name.Equals("xyz", StringComparison.OrdinalIgnoreCase))); + Assert.DoesNotContain("xyz", context.CompilationAssemblies.Select(a => a.Name), StringComparer.OrdinalIgnoreCase); var packageDependencies = context.PackageDependencies; - var mvcPackage = packageDependencies - .Where(p => p.Name.Equals("Microsoft.AspNetCore.Mvc", StringComparison.OrdinalIgnoreCase)) - .FirstOrDefault(); - Assert.NotNull(mvcPackage); - - Assert.True(mvcPackage.Dependencies.Any(dependency => dependency.Name.Equals("Microsoft.Extensions.DependencyInjection", StringComparison.OrdinalIgnoreCase))); - - Assert.True(context.ProjectReferences.First().Equals(Path.Combine(fileProvider.Root, "Library1", "Library1.csproj"))); + var mvcPackage = Assert.Single(context.PackageDependencies, p => p.Name.Equals("Microsoft.AspNetCore.Mvc", StringComparison.OrdinalIgnoreCase)); + Assert.Contains("Microsoft.Extensions.DependencyInjection", mvcPackage.Dependencies.Select(d => d.Name), StringComparer.OrdinalIgnoreCase); + Assert.Equal(Path.Combine(fileProvider.Root, "Root", "..", "Library1", "Library1.csproj"), context.ProjectReferences.First()); } } } diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/project.json b/test/Microsoft.Extensions.ProjectModel.Tests/project.json index 09eaf72e6f..dbb538c472 100644 --- a/test/Microsoft.Extensions.ProjectModel.Tests/project.json +++ b/test/Microsoft.Extensions.ProjectModel.Tests/project.json @@ -7,10 +7,11 @@ } }, "dependencies": { - "NuGet.Frameworks": "3.5.0-rc1-final", + "NuGet.ProjectModel": "3.6.0-*", + "NuGet.Frameworks": "3.6.0-*", "Microsoft.DotNet.Cli.Utils": "1.0.0-preview2-003121", "Microsoft.DotNet.ProjectModel": "1.0.0-rc3-003121", - "Microsoft.Build.Runtime": "15.1.298-preview5", + "Microsoft.Build.Runtime": "15.1.319-preview5", "Microsoft.Extensions.FileProviders.Physical": "1.1.0-*", "Microsoft.Extensions.ProjectModel.Abstractions.Sources": { "type": "build", From c7ff19c28534c68875d041a73c36de07faa3566f Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 18 Oct 2016 09:45:09 -0700 Subject: [PATCH 0303/1029] Remove Microsoft.Extensions.ProjectModel Resolves #182 --- NuGet.config | 2 - NuGetPackageVerifier.json | 8 - makefile.shade | 6 - .../IProjectContext.cs | 34 --- ...ns.ProjectModel.Abstractions.Sources.xproj | 19 -- .../Resolution/Dependency.cs | 26 -- .../Resolution/DependencyDescription.cs | 51 ---- .../Resolution/DependencyType.cs | 20 -- .../Resolution/ResolvedReference.cs | 21 -- .../project.json | 7 - .../DotNetDependencyProvider.cs | 112 ------- .../DotNetProjectContext.cs | 155 ---------- .../IncludeContextExtensions.cs | 25 -- ...tensions.ProjectModel.DotNet.Sources.xproj | 19 -- .../project.json | 7 - .../Internal/DotNetCoreSdk.cs | 11 - .../Internal/DotNetCoreSdkResolver.cs | 129 -------- ...ensions.ProjectModel.MsBuild.Sources.xproj | 19 -- .../MsBuildContext.cs | 39 --- .../MsBuildExtensions.cs | 14 - .../MsBuildProjectContext.cs | 131 -------- .../MsBuildProjectContextBuilder.cs | 285 ------------------ .../MsBuildProjectDependencyProvider.cs | 138 --------- .../MsBuildProjectFinder.cs | 72 ----- .../project.json | 7 - .../DotNet/DotNetDependencyProviderTests.cs | 119 -------- ...rosoft.Extensions.ProjectModel.Tests.xproj | 21 -- .../MsBuild/DotNetCoreSdkResolverTest.cs | 57 ---- .../MsBuildProjectContextBuilderTest.cs | 139 --------- .../MsBuildProjectDependencyProviderTests.cs | 164 ---------- .../MsBuild/MsBuildProjectFinderTest.cs | 73 ----- .../Utilities/TemporaryFileProvider.cs | 29 -- .../project.json | 42 --- test/Shared/MsBuildFixture.cs | 40 --- 34 files changed, 2041 deletions(-) delete mode 100644 src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/IProjectContext.cs delete mode 100644 src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Microsoft.Extensions.ProjectModel.Abstractions.Sources.xproj delete mode 100644 src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/Dependency.cs delete mode 100644 src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/DependencyDescription.cs delete mode 100644 src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/DependencyType.cs delete mode 100644 src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/ResolvedReference.cs delete mode 100644 src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/project.json delete mode 100644 src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetDependencyProvider.cs delete mode 100644 src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetProjectContext.cs delete mode 100644 src/Microsoft.Extensions.ProjectModel.DotNet.Sources/IncludeContextExtensions.cs delete mode 100644 src/Microsoft.Extensions.ProjectModel.DotNet.Sources/Microsoft.Extensions.ProjectModel.DotNet.Sources.xproj delete mode 100644 src/Microsoft.Extensions.ProjectModel.DotNet.Sources/project.json delete mode 100644 src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/Internal/DotNetCoreSdk.cs delete mode 100644 src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/Internal/DotNetCoreSdkResolver.cs delete mode 100644 src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/Microsoft.Extensions.ProjectModel.MsBuild.Sources.xproj delete mode 100644 src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildContext.cs delete mode 100644 src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildExtensions.cs delete mode 100644 src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectContext.cs delete mode 100644 src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectContextBuilder.cs delete mode 100644 src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectDependencyProvider.cs delete mode 100644 src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectFinder.cs delete mode 100644 src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/project.json delete mode 100644 test/Microsoft.Extensions.ProjectModel.Tests/DotNet/DotNetDependencyProviderTests.cs delete mode 100644 test/Microsoft.Extensions.ProjectModel.Tests/Microsoft.Extensions.ProjectModel.Tests.xproj delete mode 100644 test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/DotNetCoreSdkResolverTest.cs delete mode 100644 test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs delete mode 100644 test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectDependencyProviderTests.cs delete mode 100644 test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectFinderTest.cs delete mode 100644 test/Microsoft.Extensions.ProjectModel.Tests/Utilities/TemporaryFileProvider.cs delete mode 100644 test/Microsoft.Extensions.ProjectModel.Tests/project.json delete mode 100644 test/Shared/MsBuildFixture.cs diff --git a/NuGet.config b/NuGet.config index 68a0afe0e4..0fd623ffdd 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,8 +1,6 @@  - - diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index 7a340ecaad..aa4710b372 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -30,14 +30,6 @@ } } }, - "adx-nonshipping": { - "rules": [], - "packages": { - "Microsoft.Extensions.ProjectModel.Abstractions.Sources": {}, - "Microsoft.Extensions.ProjectModel.DotNet.Sources": {}, - "Microsoft.Extensions.ProjectModel.MsBuild.Sources": {} - } - }, "Default": { "rules": [ "DefaultCompositeRule" diff --git a/makefile.shade b/makefile.shade index 00f152f8b2..7ac55d8aa4 100644 --- a/makefile.shade +++ b/makefile.shade @@ -22,12 +22,6 @@ k-standard-goals "-n src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec " + "-n src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec "); - var projectModel = Files.Include("src/Microsoft.Extensions.ProjectModel.*/project.json"); - foreach (var proj in projectModel) - { - DotnetPack(proj, BUILD_DIR_LOCAL, E("Configuration"), E("KOREBUILD_DOTNET_PACK_OPTIONS") + " --no-build"); - } - foreach (var nupkg in Files.Include(Path.Combine(BUILD_DIR_LOCAL, "*/" + E("Configuration") + "/*.nupkg"))) { File.Copy(nupkg, Path.Combine(BUILD_DIR_LOCAL, Path.GetFileName(nupkg)), true); diff --git a/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/IProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/IProjectContext.cs deleted file mode 100644 index de53669917..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/IProjectContext.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using Microsoft.Extensions.ProjectModel.Resolution; -using NuGet.Frameworks; - -namespace Microsoft.Extensions.ProjectModel -{ - public interface IProjectContext - { - string ProjectName { get; } - string Configuration { get; } - string Platform { get; } - string ProjectFullPath { get; } - string RootNamespace { get; } - bool IsClassLibrary { get; } - NuGetFramework TargetFramework { get; } - string Config { get; } - string DepsJson { get; } - string RuntimeConfigJson { get; } - string PackageLockFile { get; } - string PackagesDirectory { get; } - string TargetDirectory { get; } - string AssemblyName { get; } - string AssemblyFullPath { get; } - IEnumerable CompilationItems { get; } - IEnumerable EmbededItems { get; } - string FindProperty(string propertyName); - IEnumerable PackageDependencies { get;} - IEnumerable CompilationAssemblies { get; } - IEnumerable ProjectReferences { get; } - } -} \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Microsoft.Extensions.ProjectModel.Abstractions.Sources.xproj b/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Microsoft.Extensions.ProjectModel.Abstractions.Sources.xproj deleted file mode 100644 index 3a11d66f5f..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Microsoft.Extensions.ProjectModel.Abstractions.Sources.xproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - 14.0.25420 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 8a97d718-0681-43c5-a70b-535dbbdf4fa1 - Microsoft.Extensions.ProjectModel.Abstractions.Sources - .\obj - .\bin\ - - - - 2.0 - - - \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/Dependency.cs b/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/Dependency.cs deleted file mode 100644 index 7722da1762..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/Dependency.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Microsoft.Extensions.ProjectModel.Resolution -{ - public class Dependency - { - public Dependency(string name, string version) - { - if (string.IsNullOrEmpty(name)) - { - throw new ArgumentNullException(nameof(name)); - } - - Name = name; - Version = version; - } - public string Name { get; } - public string Version { get; } - } -} diff --git a/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/DependencyDescription.cs b/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/DependencyDescription.cs deleted file mode 100644 index 25dc5249f7..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/DependencyDescription.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Microsoft.Extensions.ProjectModel.Resolution -{ - public class DependencyDescription - { - private readonly List _dependencies; - - public DependencyDescription(string name, string version, string path, string framework, string type, bool isResolved) - { - if (string.IsNullOrEmpty(name)) - { - throw new ArgumentNullException(nameof(name)); - } - - if (string.IsNullOrEmpty(framework)) - { - throw new ArgumentNullException(nameof(framework)); - } - - Name = name; - Version = version; - TargetFramework = framework; - Resolved = isResolved; - Path = path; - DependencyType dt; - Type = Enum.TryParse(type, ignoreCase: true , result: out dt) ? dt : DependencyType.Unknown; - - _dependencies = new List(); - } - - public string TargetFramework { get; } - public string Name { get; } - public string Path { get; } - public string Version { get; } - public DependencyType Type { get; } - public bool Resolved { get; } - public IEnumerable Dependencies => _dependencies; - - public void AddDependency(Dependency dependency) - { - _dependencies.Add(dependency); - } - } -} diff --git a/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/DependencyType.cs b/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/DependencyType.cs deleted file mode 100644 index 4f49efa9b1..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/DependencyType.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Microsoft.Extensions.ProjectModel.Resolution -{ - public enum DependencyType - { - Target, - Package, - Assembly, - Project, - AnalyzerAssembly, - Unknown - } -} diff --git a/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/ResolvedReference.cs b/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/ResolvedReference.cs deleted file mode 100644 index 4833d86071..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/Resolution/ResolvedReference.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Microsoft.Extensions.ProjectModel.Resolution -{ - public class ResolvedReference - { - public ResolvedReference(string name,string resolvedPath) - { - Name = name; - ResolvedPath = resolvedPath; - } - public string ResolvedPath { get; } - public string Name { get; } - } -} diff --git a/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/project.json b/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/project.json deleted file mode 100644 index 23d8c31849..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.Abstractions.Sources/project.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "version": "1.0.0-*", - "shared": "**/*.cs", - "frameworks": { - "netstandard1.0": {} - } -} \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetDependencyProvider.cs b/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetDependencyProvider.cs deleted file mode 100644 index 137acba5b6..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetDependencyProvider.cs +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.IO; -using Microsoft.DotNet.ProjectModel; -using Microsoft.Extensions.ProjectModel.Resolution; -using Microsoft.DotNet.Cli.Utils; - -namespace Microsoft.Extensions.ProjectModel -{ - internal class DotNetDependencyProvider - { - private ProjectContext _context; - private List _packageDependencies; - private List _resolvedReferences; - private string _configuration; - private List _projectReferences; - - public DotNetDependencyProvider(ProjectContext context, string configuration = Constants.DefaultConfiguration) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - _configuration = configuration; - _context = context; - DiscoverDependencies(); - } - - public IEnumerable GetProjectReferences() - { - return _projectReferences; - } - - public IEnumerable GetPackageDependencies() - { - return _packageDependencies; - } - - public IEnumerable GetResolvedReferences() - { - return _resolvedReferences; - } - - private void DiscoverDependencies() - { - var exporter = _context.CreateExporter(_configuration); - - if (exporter == null) - { - throw new InvalidOperationException($"Couldn't create a library exporter for configuration {_configuration}"); - } - - var framework = _context.TargetFramework; - if (framework == null) - { - throw new InvalidOperationException("Couldn't resolve dependencies when target framework is not specified."); - } - - var exports = exporter.GetDependencies(); - _resolvedReferences = new List(); - _packageDependencies = new List(); - _projectReferences = new List(); - - foreach (var export in exports) - { - var library = export.Library; - var project = library as ProjectDescription; - if (project != null) - { - _projectReferences.Add(project.Project.ProjectFilePath); - } - else - { - var description = new DependencyDescription( - library.Identity.Name, - library.Identity.Version.ToString(), - export.Library.Path, - framework.DotNetFrameworkName, - library.Identity.Type.Value, - library.Resolved); - - foreach (var dependency in export.Library.Dependencies) - { - var dep = new Dependency(dependency.Name, version: string.Empty); - description.AddDependency(dep); - } - - - var itemSpec = $"{framework.DotNetFrameworkName}/{library.Identity.Name}/{library.Identity.Version.ToString()}"; - _packageDependencies.Add(description); - } - - // For resolved references we need to include all type of dependencies. - if (library.Resolved) - { - foreach (var asset in export.CompilationAssemblies) - { - var resolvedRef = new ResolvedReference( - name: Path.GetFileNameWithoutExtension(asset.FileName), - resolvedPath: asset.ResolvedPath); - _resolvedReferences.Add(resolvedRef); - } - } - } - } - } -} diff --git a/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetProjectContext.cs deleted file mode 100644 index b8d9bb476f..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/DotNetProjectContext.cs +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using Microsoft.DotNet.ProjectModel; -using Microsoft.Extensions.ProjectModel.Resolution; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using NuGet.Frameworks; - -namespace Microsoft.Extensions.ProjectModel -{ - internal class DotNetProjectContext : IProjectContext - { - private readonly ProjectContext _projectContext; - private readonly OutputPaths _paths; - private readonly Lazy _rawProject; - private readonly CommonCompilerOptions _compilerOptions; - private readonly Lazy _dependencyProvider; - - private IEnumerable _packageDependencies; - private IEnumerable _compilationAssemblies; - private IEnumerable _projectReferences; - - public DotNetProjectContext(ProjectContext projectContext, string configuration, string outputPath) - { - if (projectContext == null) - { - throw new ArgumentNullException(nameof(projectContext)); - } - - if (string.IsNullOrEmpty(configuration)) - { - throw new ArgumentNullException(nameof(configuration)); - } - - _rawProject = new Lazy(() => - { - using (var stream = new FileStream(projectContext.ProjectFile.ProjectFilePath, FileMode.Open, FileAccess.Read)) - using (var streamReader = new StreamReader(stream)) - using (var jsonReader = new JsonTextReader(streamReader)) - { - return JObject.Load(jsonReader); - } - }); - - Configuration = configuration; - _projectContext = projectContext; - - _paths = projectContext.GetOutputPaths(configuration, buidBasePath: null, outputPath: outputPath); - _compilerOptions = _projectContext.ProjectFile.GetCompilerOptions(TargetFramework, Configuration); - - // Workaround https://github.com/dotnet/cli/issues/3164 - IsClassLibrary = !(_compilerOptions?.EmitEntryPoint - ?? projectContext.ProjectFile.GetCompilerOptions(null, configuration).EmitEntryPoint.GetValueOrDefault()); - - _dependencyProvider = new Lazy(() => new DotNetDependencyProvider(_projectContext)); - } - - public bool IsClassLibrary { get; } - - public NuGetFramework TargetFramework => _projectContext.TargetFramework; - public string Config => _paths.RuntimeFiles.Config; - public string DepsJson => _paths.RuntimeFiles.DepsJson; - public string RuntimeConfigJson => _paths.RuntimeFiles.RuntimeConfigJson; - public string PackagesDirectory => _projectContext.PackagesDirectory; - public string PackageLockFile => Path.Combine(Path.GetDirectoryName(ProjectFullPath), "project.lock.json"); - public string AssemblyName => string.IsNullOrEmpty(AssemblyFullPath) - ? ProjectName - : Path.GetFileNameWithoutExtension(AssemblyFullPath); - public string AssemblyFullPath => - !IsClassLibrary && (_projectContext.IsPortable || TargetFramework.IsDesktop()) - ? _paths.RuntimeFiles.Executable - : _paths.RuntimeFiles.Assembly; - - public string Configuration { get; } - public string ProjectFullPath => _projectContext.ProjectFile.ProjectFilePath; - public string ProjectName => _projectContext.ProjectFile.Name; - // TODO read from xproj if available - public string RootNamespace => _projectContext.ProjectFile.Name; - public string TargetDirectory => _paths.RuntimeOutputPath; - public string Platform => _compilerOptions?.Platform; - - public IEnumerable CompilationItems - => (_compilerOptions?.CompileInclude == null) - ? _projectContext.ProjectFile.Files.SourceFiles - : _compilerOptions.CompileInclude.ResolveFiles(); - - public IEnumerable EmbededItems - => (_compilerOptions?.EmbedInclude == null) - ? _projectContext.ProjectFile.Files.ResourceFiles.Keys - : _compilerOptions.EmbedInclude.ResolveFiles(); - - public IEnumerable PackageDependencies - { - get - { - if (_packageDependencies == null) - { - _packageDependencies = _dependencyProvider.Value.GetPackageDependencies(); - } - - return _packageDependencies; - } - } - - public IEnumerable CompilationAssemblies - { - get - { - if (_compilationAssemblies == null) - { - _compilationAssemblies = _dependencyProvider.Value.GetResolvedReferences(); - } - - return _compilationAssemblies; - } - } - - public IEnumerable ProjectReferences - { - get - { - if (_projectReferences == null) - { - _projectReferences = _dependencyProvider.Value.GetProjectReferences(); - } - - return _projectReferences; - } - } - - /// - /// Returns string values of top-level keys in the project.json file - /// - /// - /// - public string FindProperty(string propertyName) => FindProperty(propertyName); - - public TProperty FindProperty(string propertyName) - { - foreach (var item in _rawProject.Value) - { - if (item.Key.Equals(propertyName, StringComparison.OrdinalIgnoreCase)) - { - return item.Value.Value(); - } - } - - return default(TProperty); - } - } -} \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/IncludeContextExtensions.cs b/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/IncludeContextExtensions.cs deleted file mode 100644 index 938d84ed5c..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/IncludeContextExtensions.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.DotNet.ProjectModel.Files; - -namespace Microsoft.Extensions.ProjectModel -{ - internal static class IncludeContextExtensions - { - public static IEnumerable ResolveFiles(this IncludeContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - return IncludeFilesResolver - .GetIncludeFiles(context, "/", diagnostics: null) - .Select(f => f.SourcePath); - } - } -} diff --git a/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/Microsoft.Extensions.ProjectModel.DotNet.Sources.xproj b/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/Microsoft.Extensions.ProjectModel.DotNet.Sources.xproj deleted file mode 100644 index 25df3ea5e1..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/Microsoft.Extensions.ProjectModel.DotNet.Sources.xproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - 14.0.25420 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 1f643a36-a1fc-4502-9d03-75837f20e1a4 - Microsoft.Extensions.ProjectModel.DotNet.Sources - .\obj - .\bin\ - - - - 2.0 - - - \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/project.json b/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/project.json deleted file mode 100644 index 23d8c31849..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.DotNet.Sources/project.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "version": "1.0.0-*", - "shared": "**/*.cs", - "frameworks": { - "netstandard1.0": {} - } -} \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/Internal/DotNetCoreSdk.cs b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/Internal/DotNetCoreSdk.cs deleted file mode 100644 index 40dd59d6d9..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/Internal/DotNetCoreSdk.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.Extensions.ProjectModel.Internal -{ - internal class DotNetCoreSdk - { - public string BasePath { get; set; } - public string Version { get; set; } - } -} \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/Internal/DotNetCoreSdkResolver.cs b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/Internal/DotNetCoreSdkResolver.cs deleted file mode 100644 index 684654674f..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/Internal/DotNetCoreSdkResolver.cs +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Microsoft.DotNet.Cli.Utils; -using Newtonsoft.Json; -using NuGet.Versioning; - -namespace Microsoft.Extensions.ProjectModel.Internal -{ - internal class DotNetCoreSdkResolver - { - private readonly string _installationDir; - - /// - /// Represents a resolver that uses the currently executing to find the .NET Core SDK installation - /// - public static readonly DotNetCoreSdkResolver DefaultResolver = new DotNetCoreSdkResolver(Path.GetDirectoryName(new Muxer().MuxerPath)); - - /// - /// Instantiates a resolver that locates the SDK - /// - /// The directory containing dotnet muxer, aka DOTNET_HOME - public DotNetCoreSdkResolver(string installationDir) - { - _installationDir = installationDir; - } - - /// - /// Find the latest SDK installation (uses SemVer 1.0 to determine what is "latest") - /// - /// Path to SDK root directory - public DotNetCoreSdk ResolveLatest() - { - var latest = FindInstalled() - .Select(d => new { path = d, version = SemanticVersion.Parse(Path.GetFileName(d)) }) - .OrderByDescending(sdk => sdk.version) - .FirstOrDefault(); - - if (latest == null) - { - throw CreateSdkNotInstalledException(); - } - - return new DotNetCoreSdk - { - BasePath = latest.path, - Version = latest.version.ToFullString() - }; - } - - public DotNetCoreSdk ResolveProjectSdk(string projectDir) - { - var sdkVersion = ResolveGlobalJsonSdkVersion(projectDir); - if (string.IsNullOrEmpty(sdkVersion)) - { - return ResolveLatest(); - } - - var sdk = FindInstalled() - .Where(p => Path.GetFileName(p).Equals(sdkVersion, StringComparison.OrdinalIgnoreCase)) - .Select(d => new { path = d, version = SemanticVersion.Parse(Path.GetFileName(d)) }) - .FirstOrDefault(); - - if (sdk == null) - { - throw CreateSdkNotInstalledException(); - } - - return new DotNetCoreSdk - { - BasePath = sdk.path, - Version = sdk.version.ToFullString() - }; - } - - private Exception CreateSdkNotInstalledException() - { - return new DirectoryNotFoundException($"Could not find an installation of the .NET Core SDK in '{_installationDir}'"); - } - - private IEnumerable FindInstalled() - => Directory.EnumerateDirectories(Path.Combine(_installationDir, "sdk")); - - private string ResolveGlobalJsonSdkVersion(string start) - { - var dir = new DirectoryInfo(start); - FileInfo fileInfo = null; - while (dir != null) - { - var candidate = Path.Combine(dir.FullName, "global.json"); - if (File.Exists(candidate)) - { - fileInfo = new FileInfo(candidate); - break; - } - dir = dir.Parent; - } - if (fileInfo == null) - { - return null; - } - try - { - var contents = File.ReadAllText(fileInfo.FullName); - var globalJson = JsonConvert.DeserializeObject(contents); - return globalJson?.sdk?.version; - } - catch (JsonException) - { - // TODO log - return null; - } - } - - private class GlobalJsonStub - { - public GlobalJsonSdkStub sdk { get; set; } - - public class GlobalJsonSdkStub - { - public string version { get; set; } - } - } - } -} \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/Microsoft.Extensions.ProjectModel.MsBuild.Sources.xproj b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/Microsoft.Extensions.ProjectModel.MsBuild.Sources.xproj deleted file mode 100644 index d7ece4a980..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/Microsoft.Extensions.ProjectModel.MsBuild.Sources.xproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - 14.0.25420 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 7362ae32-7753-4e7c-86d0-dca86af413fa - Microsoft.Extensions.ProjectModel.MsBuild.Sources - .\obj - .\bin\ - - - - 2.0 - - - \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildContext.cs b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildContext.cs deleted file mode 100644 index 4b50ca089e..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildContext.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using Microsoft.Extensions.ProjectModel.Internal; - -namespace Microsoft.Extensions.ProjectModel -{ - /// - /// Represents the msbuild context used to parse a project model - /// - internal class MsBuildContext - { - public string MsBuildExecutableFullPath { get; private set; } - public string ExtensionsPath { get; private set; } - - public static MsBuildContext FromCurrentDotNetSdk() - { - var sdk = DotNetCoreSdkResolver.DefaultResolver.ResolveLatest(); - return FromDotNetSdk(sdk); - } - - public static MsBuildContext FromDotNetSdk(DotNetCoreSdk sdk) - { - if (sdk == null) - { - throw new ArgumentNullException(nameof(sdk)); - } - - return new MsBuildContext - { - // might change... See https://github.com/Microsoft/msbuild/issues/1136 - MsBuildExecutableFullPath = Path.Combine(sdk.BasePath, "MSBuild.exe"), - ExtensionsPath = sdk.BasePath - }; - } - } -} \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildExtensions.cs b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildExtensions.cs deleted file mode 100644 index eef3bef01c..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildExtensions.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Linq; - -namespace Microsoft.Build.Execution -{ - internal static class MsBuildExtensions - { - public static string FindProperty(this ProjectInstance projectInstance, string propertyName, StringComparison comparer) - => projectInstance.Properties.FirstOrDefault(p => p.Name.Equals(propertyName, comparer))?.EvaluatedValue; - } -} diff --git a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectContext.cs b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectContext.cs deleted file mode 100644 index 2c9bc7a732..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectContext.cs +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using Microsoft.Build.Execution; -using NuGet.Frameworks; -using System.Linq; -using Microsoft.Extensions.ProjectModel.Resolution; - -namespace Microsoft.Extensions.ProjectModel -{ - internal class MsBuildProjectContext : IProjectContext - { - private const string CompileItemName = "Compile"; - private const string EmbedItemName = "EmbeddedResource"; - private const string FullPathMetadataName = "FullPath"; - - private readonly MsBuildProjectDependencyProvider _dependencyProvider; - private IEnumerable _packageDependencies; - private IEnumerable _compilationAssemblies; - private IEnumerable _projectReferences; - - protected ProjectInstance Project { get; } - protected string Name { get; } - - public MsBuildProjectContext(string name, string configuration, ProjectInstance project) - { - Project = project; - - Configuration = configuration; - Name = name; - _dependencyProvider = new MsBuildProjectDependencyProvider(Project); - } - - public string FindProperty(string propertyName) - { - return Project.GetProperty(propertyName)?.EvaluatedValue; - } - - public string ProjectName => FindProperty("ProjectName") ?? Name; - public string Configuration { get; } - - public NuGetFramework TargetFramework - { - get - { - var tfm = FindProperty("NuGetTargetMoniker") ?? FindProperty("TargetFramework"); - if (tfm == null) - { - return null; - } - return NuGetFramework.Parse(tfm); - } - } - - public bool IsClassLibrary => FindProperty("OutputType").Equals("Library", StringComparison.OrdinalIgnoreCase); - - // TODO get from actual properties according to TFM - public string Config => AssemblyFullPath + ".config"; - public string DepsJson => Path.Combine(TargetDirectory, Path.GetFileNameWithoutExtension(AssemblyFullPath) + ".deps.json"); - public string RuntimeConfigJson => Path.Combine(TargetDirectory, Path.GetFileNameWithoutExtension(AssemblyFullPath) + ".runtimeconfig.json"); - public string PackagesDirectory => FindProperty("NuGetPackageRoot"); - public string PackageLockFile - { - get - { - var restoreOutputPath = FindProperty("RestoreOutputPath"); - if (string.IsNullOrEmpty(restoreOutputPath)) - { - restoreOutputPath = Path.Combine(Path.GetDirectoryName(ProjectFullPath), "obj"); - } - return Path.Combine(restoreOutputPath, "project.assets.json"); - } - } - public string AssemblyName => string.IsNullOrEmpty(AssemblyFullPath) - ? ProjectName - : Path.GetFileNameWithoutExtension(AssemblyFullPath); - public string AssemblyFullPath => FindProperty("TargetPath"); - public string Platform => FindProperty("Platform"); - public string ProjectFullPath => Project.FullPath; - public string RootNamespace => FindProperty("RootNamespace") ?? ProjectName; - public string TargetDirectory => FindProperty("TargetDir"); - - public IEnumerable CompilationItems - => Project.GetItems(CompileItemName).Select(i => i.GetMetadataValue(FullPathMetadataName)); - - public IEnumerable EmbededItems - => Project.GetItems(EmbedItemName).Select(i => i.GetMetadataValue(FullPathMetadataName)); - - public IEnumerable PackageDependencies - { - get - { - if (_packageDependencies == null) - { - _packageDependencies = _dependencyProvider.GetPackageDependencies(); - } - - return _packageDependencies; - } - } - - public IEnumerable CompilationAssemblies - { - get - { - if (_compilationAssemblies == null) - { - _compilationAssemblies = _dependencyProvider.GetResolvedReferences(); - } - - return _compilationAssemblies; - } - } - - public IEnumerable ProjectReferences - { - get - { - if (_projectReferences == null) - { - _projectReferences = _dependencyProvider.GetProjectReferences(); - } - - return _projectReferences; - } - } - } -} \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectContextBuilder.cs b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectContextBuilder.cs deleted file mode 100644 index 8033dd0012..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectContextBuilder.cs +++ /dev/null @@ -1,285 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Xml; -using Microsoft.Build.Construction; -using Microsoft.Build.Evaluation; -using Microsoft.Build.Execution; -using Microsoft.Build.Framework; -using Microsoft.Extensions.FileProviders; -using Microsoft.Extensions.FileProviders.Physical; -using Microsoft.Extensions.ProjectModel.Internal; -using NuGet.Frameworks; -using System.Linq; - -namespace Microsoft.Extensions.ProjectModel -{ - internal class MsBuildProjectContextBuilder - { - protected string _configuration; - protected IFileInfo _fileInfo; - protected string[] _buildTargets; - protected Dictionary _globalProperties = new Dictionary(); - private MsBuildContext _msbuildContext; - - public MsBuildProjectContextBuilder() - { - Initialize(); - } - - public virtual MsBuildProjectContextBuilder Clone() - { - var builder = new MsBuildProjectContextBuilder() - .WithProperties(_globalProperties) - .WithBuildTargets(_buildTargets); - - if (_msbuildContext != null) - { - builder.UseMsBuild(_msbuildContext); - } - - if (_fileInfo != null) - { - builder.WithProjectFile(_fileInfo); - } - - if (_configuration != null) - { - builder.WithConfiguration(_configuration); - } - - return builder; - } - - public MsBuildProjectContextBuilder WithBuildTargets(string[] targets) - { - if (targets == null) - { - throw new ArgumentNullException(nameof(targets)); - } - - _buildTargets = targets; - return this; - } - - public MsBuildProjectContextBuilder WithConfiguration(string configuration) - { - _configuration = configuration; - WithProperty("Configuration", configuration); - return this; - } - - public MsBuildProjectContextBuilder AsDesignTimeBuild() - { - // don't to expensive things - WithProperty("DesignTimeBuild", "true"); - WithProperty("_ResolveReferenceDependencies", "true"); - WithProperty("BuildProjectReferences", "false"); - return this; - } - - // should be needed in most cases, but can be used to override - public MsBuildProjectContextBuilder UseMsBuild(MsBuildContext context) - { - _msbuildContext = context; - - /* - Workaround https://github.com/Microsoft/msbuild/issues/999 - Error: System.TypeInitializationException : The type initializer for 'BuildEnvironmentHelperSingleton' threw an exception. - Could not determine a valid location to MSBuild. Try running this process from the Developer Command Prompt for Visual Studio. - */ - - Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", context.MsBuildExecutableFullPath); - WithProperty("MSBuildExtensionsPath", context.ExtensionsPath); - - return this; - } - - public MsBuildProjectContextBuilder WithProperties(IDictionary properties) - { - foreach (var prop in properties) - { - _globalProperties[prop.Key] = prop.Value; - } - - return this; - } - - public MsBuildProjectContextBuilder WithProperty(string property, string value) - { - _globalProperties[property] = value; - return this; - } - - public MsBuildProjectContextBuilder WithProjectFile(string filePath) - { - if (string.IsNullOrEmpty(filePath)) - { - throw new ArgumentNullException(nameof(filePath)); - } - - var fileInfo = new PhysicalFileInfo(new FileInfo(filePath)); - return WithProjectFile(fileInfo); - } - - public MsBuildProjectContextBuilder WithProjectFile(IFileInfo fileInfo) - { - if (_msbuildContext == null) - { - var projectDir = Path.GetDirectoryName(fileInfo.PhysicalPath); - var sdk = DotNetCoreSdkResolver.DefaultResolver.ResolveProjectSdk(projectDir); - UseMsBuild(MsBuildContext.FromDotNetSdk(sdk)); - } - - _fileInfo = fileInfo; - return this; - } - - public MsBuildProjectContextBuilder WithTargetFramework(NuGetFramework framework) - => WithTargetFramework(framework.GetShortFolderName()); - - public MsBuildProjectContextBuilder WithTargetFramework(string framework) - => WithProperty("TargetFramework", framework); - - public virtual MsBuildProjectContext Build(bool ignoreBuildErrors = false) - { - var projectCollection = CreateProjectCollection(); - var project = CreateProject(_fileInfo, _configuration, _globalProperties, projectCollection); - if (project.GetProperty("TargetFramework") == null) - { - var frameworks = GetAvailableTargetFrameworks(project).ToList(); - if (frameworks.Count > 1) - { - throw new InvalidOperationException($"Multiple frameworks are available. Either use {nameof(WithTargetFramework)} or {nameof(BuildAllTargetFrameworks)}"); - } - - if (frameworks.Count == 0) - { - throw new InvalidOperationException($"No frameworks are available. Either use {nameof(WithTargetFramework)} or {nameof(BuildAllTargetFrameworks)}"); - } - - project.SetGlobalProperty("TargetFramework", frameworks.Single()); - } - - var projectInstance = CreateProjectInstance(project, _buildTargets, ignoreBuildErrors); - - var name = Path.GetFileNameWithoutExtension(_fileInfo.Name); - return new MsBuildProjectContext(name, _configuration, projectInstance); - } - - public IEnumerable BuildAllTargetFrameworks() - { - var projectCollection = CreateProjectCollection(); - var project = CreateProject(_fileInfo, _configuration, _globalProperties, projectCollection); - - foreach (var framework in GetAvailableTargetFrameworks(project)) - { - var builder = Clone(); - builder.WithTargetFramework(framework); - yield return builder.Build(); - } - } - - protected virtual void Initialize() - { - WithBuildTargets(new[] { "ResolveReferences", "ResolvePackageDependenciesDesignTime" }); - WithProperty("_ResolveReferenceDependencies", "true"); - } - - protected virtual ProjectCollection CreateProjectCollection() => new ProjectCollection(); - - protected virtual Project CreateProject(IFileInfo fileInfo, - string configuration, - IDictionary globalProps, - ProjectCollection projectCollection) - { - using (var stream = fileInfo.CreateReadStream()) - { - var xmlReader = XmlReader.Create(stream); - - var xml = ProjectRootElement.Create(xmlReader, projectCollection, preserveFormatting: true); - xml.FullPath = fileInfo.PhysicalPath; - - return new Project(xml, globalProps, toolsVersion: null, projectCollection: projectCollection); - } - } - - protected virtual ProjectInstance CreateProjectInstance(Project project, string[] targets, bool ignoreErrors) - { - var projectInstance = project.CreateProjectInstance(); - if (targets.Length == 0) - { - return projectInstance; - } - - var logger = new InMemoryLogger(); - projectInstance.Build(targets, new[] { logger }); - - if (!ignoreErrors && logger.Errors.Count > 0) - { - throw CreateBuildFailedException(project.FullPath, logger.Errors); - } - - return projectInstance; - } - - private Exception CreateBuildFailedException(string filePath, IList errors) - { - var sb = new StringBuilder(); - sb.AppendLine($"Building '{filePath}' failed."); - - for (var i = 0; i < errors.Count; i++) - { - sb.Append(i).Append(" :").AppendLine(errors[i].Message); - } - - throw new InvalidOperationException(sb.ToString()); - } - - private IEnumerable GetAvailableTargetFrameworks(Project project) - { - var frameworks = project.GetProperty("TargetFrameworks")?.EvaluatedValue; - if (string.IsNullOrEmpty(frameworks)) - { - return Enumerable.Empty(); - } - return frameworks.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); - } - - private class InMemoryLogger : ILogger - { - private readonly Stack _onShutdown = new Stack(); - - internal IList Errors = new List(); - - public string Parameters { get; set; } - public LoggerVerbosity Verbosity { get; set; } - - public void Initialize(IEventSource eventSource) - { - eventSource.ErrorRaised += OnError; - _onShutdown.Push(() => - { - eventSource.ErrorRaised -= OnError; - }); - } - - private void OnError(object sender, BuildErrorEventArgs e) - { - Errors.Add(e); - } - - public void Shutdown() - { - while (_onShutdown.Count > 0) - { - _onShutdown.Pop()?.Invoke(); - } - } - } - } -} \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectDependencyProvider.cs b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectDependencyProvider.cs deleted file mode 100644 index 5afad1590a..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectDependencyProvider.cs +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Microsoft.Build.Execution; -using Microsoft.Extensions.ProjectModel.Resolution; - -namespace Microsoft.Extensions.ProjectModel -{ - internal class MsBuildProjectDependencyProvider - { - private const string PackageDependencyItemType = "_DependenciesDesignTime"; - private const string ResolvedReferenceItemType = "ReferencePath"; - - private readonly ProjectInstance _projectInstance; - public MsBuildProjectDependencyProvider(ProjectInstance projectInstance) - { - if (projectInstance == null) - { - throw new ArgumentNullException(nameof(projectInstance)); - } - _projectInstance = projectInstance; - } - - public IEnumerable GetProjectReferences() - { - var projectPaths = _projectInstance - .GetItems("ProjectReference") - .Select(reference => reference.EvaluatedInclude); - - return projectPaths - .Select(path => Path.IsPathRooted(path) - ? path - : Path.Combine(_projectInstance.Directory, path)); - } - - public IEnumerable GetPackageDependencies() - { - var packageItems = _projectInstance.GetItems(PackageDependencyItemType); - var packageInfo = new Dictionary(StringComparer.OrdinalIgnoreCase); - if (packageItems != null) - { - foreach (var packageItem in packageItems) - { - var packageDependency = CreateDependencyDescriptionFromItem(packageItem); - if (packageDependency != null) - { - packageInfo[packageItem.EvaluatedInclude] = packageDependency; - } - } - - // 2nd pass to populate dependencies; - - PopulateDependencies(packageInfo, packageItems); - } - - return packageInfo.Values; - } - - - public IEnumerable GetResolvedReferences() - { - var refItems = _projectInstance.GetItems(ResolvedReferenceItemType); - - var resolvedReferences = refItems - ?.Select(refItem => CreateResolvedReferenceFromProjectItem(refItem)) - .Where(resolvedReference => resolvedReference != null); - - return resolvedReferences; - } - - private static ResolvedReference CreateResolvedReferenceFromProjectItem(ProjectItemInstance item) - { - var resolvedPath = item.EvaluatedInclude; - - if (string.IsNullOrEmpty(resolvedPath)) - { - return null; - } - - var name = Path.GetFileNameWithoutExtension(resolvedPath); - return new ResolvedReference(name, resolvedPath); - } - - private static DependencyDescription CreateDependencyDescriptionFromItem(ProjectItemInstance item) - { - // For type == Target, we do not get Name in the metadata. This is a special node where the dependencies are - // the direct dependencies of the project. - var itemSpec = item.EvaluatedInclude; - var name = item.HasMetadata("Name") ? item.GetMetadataValue("Name") : itemSpec; - - if (string.IsNullOrEmpty(name)) - { - return null; - } - - var version = item.GetMetadataValue("Version"); - var path = item.GetMetadataValue("Path"); - var type = item.GetMetadataValue("Type"); - var resolved = item.GetMetadataValue("Resolved"); - - bool isResolved; - isResolved = bool.TryParse(resolved, out isResolved) ? isResolved : false; - var framework = itemSpec.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries).First(); - - return new DependencyDescription(name, version, path, framework, type, isResolved); - } - - private static void PopulateDependencies(Dictionary dependencies, ICollection items) - { - foreach (var item in items) - { - var depSpecs = item.GetMetadataValue("Dependencies") - ?.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); - DependencyDescription currentDescription = null; - if (depSpecs == null || !dependencies.TryGetValue(item.EvaluatedInclude, out currentDescription)) - { - return; - } - - var prefix = item.EvaluatedInclude.Split('/').FirstOrDefault(); - foreach (var depSpec in depSpecs) - { - var spec = $"{prefix}/{depSpec}"; - DependencyDescription dependency = null; - if (dependencies.TryGetValue(spec, out dependency)) - { - var dep = new Dependency(dependency.Name, dependency.Version); - currentDescription.AddDependency(dep); - } - } - } - } - } -} diff --git a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectFinder.cs b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectFinder.cs deleted file mode 100644 index 3b43918631..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/MsBuildProjectFinder.cs +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -// TODO if this becomes a true API instead of .Sources package, put strings into resource file - -namespace Microsoft.Extensions.ProjectModel -{ - internal class MsBuildProjectFinder - { - private readonly string _directory; - - public MsBuildProjectFinder(string directory) - { - if (string.IsNullOrEmpty(directory)) - { - throw new ArgumentException("Value cannot be null or empty", nameof(directory)); - } - - _directory = directory; - } - - public string FindMsBuildProject(string project = null) - { - var projectPath = project ?? _directory; - - if (!Path.IsPathRooted(projectPath)) - { - projectPath = Path.Combine(_directory, projectPath); - } - - if (Directory.Exists(projectPath)) - { - var projects = FindProjectFiles(projectPath).ToList(); - if (projects.Count > 1) - { - throw MultipleProjectsFound(projectPath); - } - - if (projects.Count == 0) - { - throw NoProjectsFound(projectPath); - } - - return projects[0]; - } - - if (!File.Exists(projectPath)) - { - throw FileDoesNotExist(projectPath); - } - - return projectPath; - } - - protected virtual Exception FileDoesNotExist(string filePath) - => new InvalidOperationException($"No file was found at '{filePath}'."); - - protected virtual Exception MultipleProjectsFound(string directory) - => new InvalidOperationException($"Multiple MSBuild project files found in '{directory}'."); - - protected virtual Exception NoProjectsFound(string directory) - => new InvalidOperationException($"Could not find a MSBuild project file in '{directory}'."); - - protected virtual IEnumerable FindProjectFiles(string directory) - => Directory.EnumerateFileSystemEntries(directory, "*.*proj", SearchOption.TopDirectoryOnly); - } -} \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/project.json b/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/project.json deleted file mode 100644 index 23d8c31849..0000000000 --- a/src/Microsoft.Extensions.ProjectModel.MsBuild.Sources/project.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "version": "1.0.0-*", - "shared": "**/*.cs", - "frameworks": { - "netstandard1.0": {} - } -} \ No newline at end of file diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/DotNet/DotNetDependencyProviderTests.cs b/test/Microsoft.Extensions.ProjectModel.Tests/DotNet/DotNetDependencyProviderTests.cs deleted file mode 100644 index ccf0d95555..0000000000 --- a/test/Microsoft.Extensions.ProjectModel.Tests/DotNet/DotNetDependencyProviderTests.cs +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Linq; -using Microsoft.DotNet.Cli.Utils; -using Microsoft.DotNet.ProjectModel; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Extensions.ProjectModel.DotNet -{ - public class DotNetDependencyProviderTests - { - private const string globalJson = @" -{ - ""projects"": [ ""demo"", ""demoLib""] -}"; - - private const string projectJson = @" -{ - ""buildOptions"": { - }, - ""dependencies"": { - ""Microsoft.AspNetCore.Mvc"": ""1.0.0-*"", - ""demoLib"": ""1.0.0-*"", - }, - ""frameworks"": { - ""netcoreapp1.0"": { - ""dependencies"": { - ""Microsoft.NETCore.App"": { - ""version"": ""1.0.0"", - ""type"": ""platform"" - } - } - } - }, -} -"; - - private const string libProjectJson = @" -{ - ""buildOptions"": { - }, - ""dependencies"": { - ""Microsoft.AspNetCore.Mvc"": ""1.0.0-*"", - }, - ""frameworks"": { - ""netcoreapp1.0"": { - ""dependencies"": { - ""Microsoft.NETCore.App"": { - ""version"": ""1.0.0"", - ""type"": ""platform"" - } - } - } - }, -} -"; - private readonly ITestOutputHelper _output; - - public DotNetDependencyProviderTests(ITestOutputHelper output) - { - _output = output; - } - - [Fact] - public void BuildProjectDependencies() - { - using (var fileProvider = new TemporaryFileProvider()) - { - Directory.CreateDirectory(Path.Combine(fileProvider.Root, "demo")); - Directory.CreateDirectory(Path.Combine(fileProvider.Root, "demoLib")); - - fileProvider.Add($"global.json", globalJson); - - fileProvider.Add($"demo/project.json", projectJson); - fileProvider.Add($"demo/First.cs", "namespace demo { class First{} }"); - - fileProvider.Add($"demoLib/project.json", libProjectJson); - fileProvider.Add($"demoLib/Second.cs", "namespace demoLib { class First{} }"); - - var muxer = new Muxer().MuxerPath; - - var result = Command - .Create(muxer, new[] { "restore", fileProvider.Root }) - .OnErrorLine(l => _output.WriteLine(l)) - .OnOutputLine(l => _output.WriteLine(l)) - .Execute(); - - Assert.Equal(0, result.ExitCode); - var oldContext = ProjectContext - .CreateContextForEachFramework(Path.Combine(fileProvider.Root, "demo", "project.json")) - .First(); - - var context = new DotNetProjectContext(oldContext, "Debug", Path.Combine(fileProvider.Root, "demo", "bin")); - - var assembly = context - .CompilationAssemblies - .Where(asm => asm.Name.Equals("Microsoft.AspNetCore.Mvc", StringComparison.OrdinalIgnoreCase)) - .First(); - - Assert.True(File.Exists(assembly.ResolvedPath)); - Assert.True(assembly.ResolvedPath.EndsWith("Microsoft.AspNetCore.Mvc.dll", StringComparison.OrdinalIgnoreCase)); - - var mvcPackage = context - .PackageDependencies - .Where(package => package.Name.Equals("Microsoft.AspNetCore.Mvc", StringComparison.OrdinalIgnoreCase)) - .First(); - - Assert.True(Directory.Exists(mvcPackage.Path)); - Assert.True(mvcPackage.Path.EndsWith($"Microsoft.AspNetCore.Mvc{Path.DirectorySeparatorChar}1.0.0", StringComparison.OrdinalIgnoreCase), mvcPackage.Path); - - Assert.True(context.ProjectReferences.First().Equals(Path.Combine(fileProvider.Root, "demoLib", "project.json"))); - } - } - } -} diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/Microsoft.Extensions.ProjectModel.Tests.xproj b/test/Microsoft.Extensions.ProjectModel.Tests/Microsoft.Extensions.ProjectModel.Tests.xproj deleted file mode 100644 index a056486759..0000000000 --- a/test/Microsoft.Extensions.ProjectModel.Tests/Microsoft.Extensions.ProjectModel.Tests.xproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - 14.0.25420 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 1a66a831-4f06-46d9-b483-70a4e75a2f7f - Microsoft.Extensions.ProjectModel - .\obj - .\bin\ - - - 2.0 - - - - - - \ No newline at end of file diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/DotNetCoreSdkResolverTest.cs b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/DotNetCoreSdkResolverTest.cs deleted file mode 100644 index 344cb20777..0000000000 --- a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/DotNetCoreSdkResolverTest.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using Microsoft.Extensions.ProjectModel.Internal; -using Xunit; - -namespace Microsoft.Extensions.ProjectModel -{ - public class DotNetCoreSdkResolverTest : IDisposable - { - private readonly string _fakeInstallDir; - public DotNetCoreSdkResolverTest() - { - _fakeInstallDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(_fakeInstallDir); - Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk")); - } - - [Fact] - public void ResolveLatest() - { - var project = Path.Combine(_fakeInstallDir, "project"); - Directory.CreateDirectory(project); - Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk", "1.0.1")); - Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk", "1.0.0")); - Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk", "1.0.0-beta1")); - var sdk = new DotNetCoreSdkResolver(_fakeInstallDir).ResolveLatest(); - Assert.Equal("1.0.1", sdk.Version); - Assert.Equal(Path.Combine(_fakeInstallDir, "sdk", "1.0.1"), sdk.BasePath); - } - - [Fact] - public void ResolveProjectSdk() - { - var project = Path.Combine(_fakeInstallDir, "project"); - Directory.CreateDirectory(project); - Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk", "1.0.0")); - Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk", "1.0.0-abc-123")); - Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk", "1.0.0-xyz-123")); - File.WriteAllText(Path.Combine(_fakeInstallDir, "global.json"), @"{ - ""sdk"": { - ""version"": ""1.0.0-abc-123"" - } - }"); - var sdk = new DotNetCoreSdkResolver(_fakeInstallDir).ResolveProjectSdk(project); - Assert.Equal("1.0.0-abc-123", sdk.Version); - Assert.Equal(Path.Combine(_fakeInstallDir, "sdk", "1.0.0-abc-123"), sdk.BasePath); - } - - public void Dispose() - { - Directory.Delete(_fakeInstallDir, recursive: true); - } - } -} \ No newline at end of file diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs deleted file mode 100644 index debac6638e..0000000000 --- a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectContextBuilderTest.cs +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Linq; -using Microsoft.DotNet.Cli.Utils; -using Microsoft.Extensions.ProjectModel.Tests; -using NuGet.Frameworks; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Extensions.ProjectModel -{ - public class MsBuildProjectContextBuilderTest : IClassFixture, IDisposable - { - private const string SkipReason = "CI doesn't yet have a new enough version of .NET Core SDK"; - - private readonly MsBuildFixture _fixture; - private readonly ITestOutputHelper _output; - private readonly TemporaryFileProvider _files; - - public MsBuildProjectContextBuilderTest(MsBuildFixture fixture, ITestOutputHelper output) - { - _fixture = fixture; - _output = output; - _files = new TemporaryFileProvider(); - } - - public void Dispose() - { - _files.Dispose(); - } - - [Fact(Skip = SkipReason)] - public void BuildsAllTargetFrameworks() - { - - _files.Add("test.proj", @" - - - net451;netstandard1.3 - - -"); - var contexts = new MsBuildProjectContextBuilder() - .WithBuildTargets(Array.Empty()) - .WithProjectFile(_files.GetFileInfo("test.proj")) - .BuildAllTargetFrameworks() - .ToList(); - - Assert.Collection(contexts, - context => - { - Assert.Equal(FrameworkConstants.CommonFrameworks.Net451, context.TargetFramework); - }, - context => - { - Assert.Equal(FrameworkConstants.CommonFrameworks.NetStandard13, context.TargetFramework); - }); - } - - [Fact(Skip = SkipReason)] - public void ExecutesDesignTimeBuild() - { - // TODO remove when SDK becomes available on other feeds - _files.Add("NuGet.config", @" - - - - - - - -"); - - _files.Add("test.csproj", @" - - - - - Microsoft.TestProject - TestProject - Library - netcoreapp1.0 - bin\$(Configuration) - - - - - - - - - 1.0.0-* - - - 1.0.1 - - - - - -"); - - _files.Add("One.cs", "public class Abc {}"); - _files.Add("Two.cs", "public class Abc2 {}"); - _files.Add("Excluded.cs", "public class Abc {}"); - - var testContext = _fixture.GetMsBuildContext(); - - var muxer = Path.Combine(testContext.ExtensionsPath, "../..", "dotnet.exe"); - var result = Command - .Create(muxer, new[] { "restore3", Path.Combine(_files.Root, "test.csproj") }) - .OnErrorLine(l => _output.WriteLine(l)) - .OnOutputLine(l => _output.WriteLine(l)) - .Execute(); - Assert.Equal(0, result.ExitCode); - - var expectedCompileItems = new[] { "One.cs", "Two.cs" }.Select(p => Path.Combine(_files.Root, p)).ToArray(); - - var context = new MsBuildProjectContextBuilder() - .AsDesignTimeBuild() - .UseMsBuild(testContext) - .WithConfiguration("Debug") - .WithProjectFile(_files.GetFileInfo("test.csproj")) - .Build(); - - Assert.False(_files.GetFileInfo("bin").Exists); - Assert.False(_files.GetFileInfo("obj").Exists); - Assert.Equal(expectedCompileItems, context.CompilationItems.OrderBy(i => i).ToArray()); - Assert.Equal(Path.Combine(_files.Root, "bin", "Debug", "netcoreapp1.0", "test.dll"), context.AssemblyFullPath); - Assert.True(context.IsClassLibrary, "Expecting IsClassLibrary == true"); - Assert.Equal("TestProject", context.ProjectName); - Assert.Equal(FrameworkConstants.CommonFrameworks.NetCoreApp10, context.TargetFramework); - Assert.Equal("Microsoft.TestProject", context.RootNamespace); - } - } -} diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectDependencyProviderTests.cs b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectDependencyProviderTests.cs deleted file mode 100644 index ce6985ff1b..0000000000 --- a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectDependencyProviderTests.cs +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Linq; -using System.IO; -using Microsoft.DotNet.Cli.Utils; -using Microsoft.Extensions.ProjectModel.Tests; -using NuGet.Frameworks; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Extensions.ProjectModel.MsBuild -{ - public class MsBuildProjectDependencyProviderTests : IClassFixture - { - private const string SkipReason = "CI doesn't yet have a new enough version of .NET Core SDK"; - - private const string NugetConfigTxt = @" - - - - - - - - -"; - - private const string RootProjectTxt = @" - - - - - Microsoft.TestProject - TestProject - Library - netcoreapp1.0 - bin\$(Configuration) - - - - - - - - - 1.0.0-* - - - 1.0.0-* - - - 1.0.1 - - - - - - - - - - -"; - - private const string LibraryProjectTxt = @" - - - - - Microsoft.Library - Library1 - Library - netcoreapp1.0 - bin\$(Configuration) - - - - - - - - - 1.0.0-* - - - 1.0.1 - - - - -"; - private readonly MsBuildFixture _fixture; - private readonly ITestOutputHelper _output; - - public MsBuildProjectDependencyProviderTests(MsBuildFixture fixture, ITestOutputHelper output) - { - _fixture = fixture; - _output = output; - } - - [Fact(Skip = SkipReason)] - public void BuildDependenciesForProject() - { - using (var fileProvider = new TemporaryFileProvider()) - { - Directory.CreateDirectory(Path.Combine(fileProvider.Root, "Root")); - Directory.CreateDirectory(Path.Combine(fileProvider.Root, "Library1")); - // TODO remove when SDK becomes available on other feeds - fileProvider.Add("NuGet.config", NugetConfigTxt); - - // Add Root Project - fileProvider.Add($"Root/test.csproj", RootProjectTxt); - fileProvider.Add($"Root/One.cs", "public class Abc {}"); - fileProvider.Add($"Root/Two.cs", "public class Abc2 {}"); - fileProvider.Add($"Root/Excluded.cs", "public class Abc {}"); - - // Add Class Library project - fileProvider.Add($"Library1/Library1.csproj", LibraryProjectTxt); - fileProvider.Add($"Library1/Three.cs", "public class Abc3 {}"); - - var testContext = _fixture.GetMsBuildContext(); - - var muxer = Path.Combine(testContext.ExtensionsPath, "../..", "dotnet.exe"); - var result = Command - .Create(muxer, new[] { "restore3", Path.Combine(fileProvider.Root, "Library1", "Library1.csproj") }) - .OnErrorLine(l => _output.WriteLine(l)) - .OnOutputLine(l => _output.WriteLine(l)) - .Execute(); - - Assert.Equal(0, result.ExitCode); - - result = Command - .Create(muxer, new[] { "restore3", Path.Combine(fileProvider.Root, "Root", "test.csproj") }) - .OnErrorLine(l => _output.WriteLine(l)) - .OnOutputLine(l => _output.WriteLine(l)) - .Execute(); - - Assert.Equal(0, result.ExitCode); - - var builder = new MsBuildProjectContextBuilder() - .AsDesignTimeBuild() - .UseMsBuild(testContext) - .WithTargetFramework(FrameworkConstants.CommonFrameworks.NetCoreApp10) - .WithConfiguration("Debug") - .WithProjectFile(fileProvider.GetFileInfo(Path.Combine("Root", "test.csproj"))); - - var context = builder.Build(); - - var lib1Dll = Assert.Single(context.CompilationAssemblies, a => a.Name.Equals("Library1", StringComparison.OrdinalIgnoreCase)); - Assert.False(File.Exists(lib1Dll.ResolvedPath), $"Design time build. Shouldn't produce a file to {lib1Dll.ResolvedPath}"); - - // This reference doesn't resolve so should not be available here. - Assert.DoesNotContain("xyz", context.CompilationAssemblies.Select(a => a.Name), StringComparer.OrdinalIgnoreCase); - - var packageDependencies = context.PackageDependencies; - var mvcPackage = Assert.Single(context.PackageDependencies, p => p.Name.Equals("Microsoft.AspNetCore.Mvc", StringComparison.OrdinalIgnoreCase)); - Assert.Contains("Microsoft.Extensions.DependencyInjection", mvcPackage.Dependencies.Select(d => d.Name), StringComparer.OrdinalIgnoreCase); - Assert.Equal(Path.Combine(fileProvider.Root, "Root", "..", "Library1", "Library1.csproj"), context.ProjectReferences.First()); - } - } - } -} diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectFinderTest.cs b/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectFinderTest.cs deleted file mode 100644 index 3d4155cfc5..0000000000 --- a/test/Microsoft.Extensions.ProjectModel.Tests/MsBuild/MsBuildProjectFinderTest.cs +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using Xunit; - -namespace Microsoft.Extensions.ProjectModel.MsBuild -{ - public class MsBuildProjectFinderTest - { - [Theory] - [InlineData(".csproj")] - [InlineData(".vbproj")] - [InlineData(".fsproj")] - public void FindsSingleProject(string extension) - { - using (var files = new TemporaryFileProvider()) - { - var filename = "TestProject" + extension; - files.Add(filename, ""); - - var finder = new MsBuildProjectFinder(files.Root); - - Assert.Equal(Path.Combine(files.Root, filename), finder.FindMsBuildProject()); - } - } - - [Fact] - public void ThrowsWhenNoFile() - { - using (var files = new TemporaryFileProvider()) - { - var finder = new MsBuildProjectFinder(files.Root); - - Assert.Throws(() => finder.FindMsBuildProject()); - } - } - - [Fact] - public void ThrowsWhenMultipleFile() - { - using (var files = new TemporaryFileProvider()) - { - files.Add("Test1.csproj", ""); - files.Add("Test2.csproj", ""); - var finder = new MsBuildProjectFinder(files.Root); - - Assert.Throws(() => finder.FindMsBuildProject()); - } - } - - [Fact] - public void ThrowsWhenFileDoesNotExist() - { - using (var files = new TemporaryFileProvider()) - { - var finder = new MsBuildProjectFinder(files.Root); - - Assert.Throws(() => finder.FindMsBuildProject("test.csproj")); - } - } - - [Fact] - public void ThrowsWhenRootDoesNotExist() - { - var files = new TemporaryFileProvider(); - var finder = new MsBuildProjectFinder(files.Root); - files.Dispose(); - Assert.Throws(() => finder.FindMsBuildProject()); - } - } -} diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/Utilities/TemporaryFileProvider.cs b/test/Microsoft.Extensions.ProjectModel.Tests/Utilities/TemporaryFileProvider.cs deleted file mode 100644 index 9e21d6a371..0000000000 --- a/test/Microsoft.Extensions.ProjectModel.Tests/Utilities/TemporaryFileProvider.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Text; -using Microsoft.Extensions.FileProviders; - -namespace Microsoft.Extensions.ProjectModel -{ - internal class TemporaryFileProvider : PhysicalFileProvider - { - public TemporaryFileProvider() - :base(Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "tmpfiles", Guid.NewGuid().ToString())).FullName) - { - } - - public void Add(string filename, string contents) - { - File.WriteAllText(Path.Combine(this.Root, filename), contents, Encoding.UTF8); - } - - public new void Dispose() - { - base.Dispose(); - Directory.Delete(Root, recursive: true); - } - } -} \ No newline at end of file diff --git a/test/Microsoft.Extensions.ProjectModel.Tests/project.json b/test/Microsoft.Extensions.ProjectModel.Tests/project.json deleted file mode 100644 index dbb538c472..0000000000 --- a/test/Microsoft.Extensions.ProjectModel.Tests/project.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "buildOptions": { - "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk", - "compile": { - "include": "../Shared/*.cs" - } - }, - "dependencies": { - "NuGet.ProjectModel": "3.6.0-*", - "NuGet.Frameworks": "3.6.0-*", - "Microsoft.DotNet.Cli.Utils": "1.0.0-preview2-003121", - "Microsoft.DotNet.ProjectModel": "1.0.0-rc3-003121", - "Microsoft.Build.Runtime": "15.1.319-preview5", - "Microsoft.Extensions.FileProviders.Physical": "1.1.0-*", - "Microsoft.Extensions.ProjectModel.Abstractions.Sources": { - "type": "build", - "version": "1.0.0-*" - }, - "Microsoft.Extensions.ProjectModel.DotNet.Sources": { - "type": "build", - "version": "1.0.0-*" - }, - "Microsoft.Extensions.ProjectModel.MsBuild.Sources": { - "type": "build", - "version": "1.0.0-*" - }, - "dotnet-test-xunit": "2.2.0-*", - "xunit": "2.2.0-*" - }, - "frameworks": { - "netcoreapp1.1": { - "dependencies": { - "Microsoft.NETCore.App": { - "version": "1.1.0-*", - "type": "platform" - } - } - } - }, - "testRunner": "xunit" -} diff --git a/test/Shared/MsBuildFixture.cs b/test/Shared/MsBuildFixture.cs deleted file mode 100644 index b8d1b8c237..0000000000 --- a/test/Shared/MsBuildFixture.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using Microsoft.Extensions.ProjectModel.Internal; -using NuGet.Versioning; - -namespace Microsoft.Extensions.ProjectModel.Tests -{ - public class MsBuildFixture - { - // TODO remove this when preview3 stabilizies - private readonly SemanticVersion _minMsBuildVersion = SemanticVersion.Parse("1.0.0-preview3-003748"); - - // TODO remove when our CI updates to using MSBuild or when Microsoft/msbuild#4213 is resolved - internal MsBuildContext GetMsBuildContext() - { - // for CI - var sdk = DotNetCoreSdkResolver.DefaultResolver.ResolveLatest(); - - // for dev work in VS - if (SemanticVersion.Parse(sdk.Version) < _minMsBuildVersion) - { - var home = Environment.GetEnvironmentVariable("USERPROFILE") - ?? Environment.GetEnvironmentVariable("HOME"); - var dotnetHome = Path.Combine(home, ".dotnet"); - var resovler = new DotNetCoreSdkResolver(dotnetHome); - sdk = resovler.ResolveLatest(); - } - - if (SemanticVersion.Parse(sdk.Version) < _minMsBuildVersion) - { - throw new InvalidOperationException($"Version of .NET Core SDK found in '{sdk.BasePath}' is not new enough for these tests."); - } - - return MsBuildContext.FromDotNetSdk(sdk); - } - } -} \ No newline at end of file From 01d35b06244c2bb6eceb275dd55e9a893dd81402 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 21 Oct 2016 12:09:20 -0700 Subject: [PATCH 0304/1029] Update .sln to remove project files that don't exist anymore [ci skip] --- DotNetTools.sln | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/DotNetTools.sln b/DotNetTools.sln index 653bddd136..77ef49227e 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -28,14 +28,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{59E02BDF EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NuGetPackager", "tools\NuGetPackager\NuGetPackager.xproj", "{8B781D87-1FC3-4A34-9089-2BDF6B562B85}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.ProjectModel.Tests", "test\Microsoft.Extensions.ProjectModel.Tests\Microsoft.Extensions.ProjectModel.Tests.xproj", "{1A66A831-4F06-46D9-B483-70A4E75A2F7F}" -EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.ProjectModel.Abstractions.Sources", "src\Microsoft.Extensions.ProjectModel.Abstractions.Sources\Microsoft.Extensions.ProjectModel.Abstractions.Sources.xproj", "{8A97D718-0681-43C5-A70B-535DBBDF4FA1}" -EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.ProjectModel.DotNet.Sources", "src\Microsoft.Extensions.ProjectModel.DotNet.Sources\Microsoft.Extensions.ProjectModel.DotNet.Sources.xproj", "{1F643A36-A1FC-4502-9D03-75837F20E1A4}" -EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.ProjectModel.MsBuild.Sources", "src\Microsoft.Extensions.ProjectModel.MsBuild.Sources\Microsoft.Extensions.ProjectModel.MsBuild.Sources.xproj", "{7362AE32-7753-4E7C-86D0-DCA86AF413FA}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -70,22 +62,6 @@ Global {8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Debug|Any CPU.Build.0 = Debug|Any CPU {8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Release|Any CPU.ActiveCfg = Release|Any CPU {8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Release|Any CPU.Build.0 = Release|Any CPU - {1A66A831-4F06-46D9-B483-70A4E75A2F7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1A66A831-4F06-46D9-B483-70A4E75A2F7F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1A66A831-4F06-46D9-B483-70A4E75A2F7F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1A66A831-4F06-46D9-B483-70A4E75A2F7F}.Release|Any CPU.Build.0 = Release|Any CPU - {8A97D718-0681-43C5-A70B-535DBBDF4FA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8A97D718-0681-43C5-A70B-535DBBDF4FA1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8A97D718-0681-43C5-A70B-535DBBDF4FA1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8A97D718-0681-43C5-A70B-535DBBDF4FA1}.Release|Any CPU.Build.0 = Release|Any CPU - {1F643A36-A1FC-4502-9D03-75837F20E1A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1F643A36-A1FC-4502-9D03-75837F20E1A4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1F643A36-A1FC-4502-9D03-75837F20E1A4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1F643A36-A1FC-4502-9D03-75837F20E1A4}.Release|Any CPU.Build.0 = Release|Any CPU - {7362AE32-7753-4E7C-86D0-DCA86AF413FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7362AE32-7753-4E7C-86D0-DCA86AF413FA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7362AE32-7753-4E7C-86D0-DCA86AF413FA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7362AE32-7753-4E7C-86D0-DCA86AF413FA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -98,9 +74,5 @@ Global {8A2E6961-6B12-4A8E-8215-3E7301D52EAC} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {53F3B53D-303A-4DAA-9C38-4F55195FA5B9} = {66517987-2A5A-4330-B130-207039378FD4} {8B781D87-1FC3-4A34-9089-2BDF6B562B85} = {59E02BDF-98DE-4D64-B576-2D0299D5E052} - {1A66A831-4F06-46D9-B483-70A4E75A2F7F} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} - {8A97D718-0681-43C5-A70B-535DBBDF4FA1} = {66517987-2A5A-4330-B130-207039378FD4} - {1F643A36-A1FC-4502-9D03-75837F20E1A4} = {66517987-2A5A-4330-B130-207039378FD4} - {7362AE32-7753-4E7C-86D0-DCA86AF413FA} = {66517987-2A5A-4330-B130-207039378FD4} EndGlobalSection EndGlobal From a0e164f379c73010e41aea9a511ef66cc961be7e Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 14 Oct 2016 17:43:17 -0700 Subject: [PATCH 0305/1029] dotnet-user-secrets: add support for json output and piping json input --- .../Internal/ClearCommand.cs | 9 +- .../Internal/CommandContext.cs | 24 +++++ .../Internal/CommandLineOptions.cs | 16 ++- .../Internal/ICommand.cs | 6 +- .../Internal/IConsole.cs | 15 +++ .../Internal/ListCommand.cs | 46 ++++++-- .../Internal/PhysicalConsole.cs | 19 ++++ .../ReadableJsonConfigurationSource.cs | 18 ++++ .../Internal/RemoveCommand.cs | 12 +-- .../Internal/SecretsStore.cs | 28 +++-- .../Internal/SetCommand.cs | 89 +++++++++++---- .../Program.cs | 18 ++-- .../Properties/Resources.Designer.cs | 34 ++++++ .../README.md | 22 ++++ .../Resources.resx | 7 ++ .../SecretManagerTests.cs | 31 +++++- .../SetCommandTest.cs | 101 ++++++++++++++++++ .../TestConsole.cs | 17 +++ .../UserSecretHelper.cs | 2 +- 19 files changed, 450 insertions(+), 64 deletions(-) create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandContext.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Internal/IConsole.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Internal/PhysicalConsole.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Internal/ReadableJsonConfigurationSource.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/README.md create mode 100644 test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs create mode 100644 test/Microsoft.Extensions.SecretManager.Tools.Tests/TestConsole.cs diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ClearCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ClearCommand.cs index 41c6634364..2569b6eaf4 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ClearCommand.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ClearCommand.cs @@ -2,11 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.Extensions.CommandLineUtils; -using Microsoft.Extensions.Logging; namespace Microsoft.Extensions.SecretManager.Tools.Internal { - internal class ClearCommand : ICommand + public class ClearCommand : ICommand { public static void Configure(CommandLineApplication command, CommandLineOptions options) { @@ -19,10 +18,10 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal }); } - public void Execute(SecretsStore store, ILogger logger) + public void Execute(CommandContext context) { - store.Clear(); - store.Save(); + context.SecretStore.Clear(); + context.SecretStore.Save(); } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandContext.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandContext.cs new file mode 100644 index 0000000000..9503178930 --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandContext.cs @@ -0,0 +1,24 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Extensions.Logging; + +namespace Microsoft.Extensions.SecretManager.Tools.Internal +{ + public class CommandContext + { + public CommandContext( + SecretsStore store, + ILogger logger, + IConsole console) + { + SecretStore = store; + Logger = logger; + Console = console; + } + + public IConsole Console { get; } + public ILogger Logger { get; } + public SecretsStore SecretStore { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs index 1b93392b4d..37705429a5 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System.IO; using System.Reflection; using Microsoft.Extensions.CommandLineUtils; @@ -9,16 +8,18 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal { public class CommandLineOptions { + public string Id { get; set; } public bool IsVerbose { get; set; } public bool IsHelp { get; set; } public string Project { get; set; } - internal ICommand Command { get; set; } + public ICommand Command { get; set; } - public static CommandLineOptions Parse(string[] args, TextWriter output) + public static CommandLineOptions Parse(string[] args, IConsole console) { var app = new CommandLineApplication() { - Out = output, + Out = console.Out, + Error = console.Error, Name = "dotnet user-secrets", FullName = "User Secrets Manager", Description = "Manages user secrets" @@ -33,7 +34,13 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal var optionProject = app.Option("-p|--project ", "Path to project, default is current directory", CommandOptionType.SingleValue, inherited: true); + // the escape hatch if project evaluation fails, or if users want to alter a secret store other than the one + // in the current project + var optionId = app.Option("--id", "The user secret id to use.", + CommandOptionType.SingleValue, inherited: true); + var options = new CommandLineOptions(); + app.Command("set", c => SetCommand.Configure(c, options)); app.Command("remove", c => RemoveCommand.Configure(c, options)); app.Command("list", c => ListCommand.Configure(c, options)); @@ -48,6 +55,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal return null; } + options.Id = optionId.Value(); options.IsHelp = app.IsShowingInformation; options.IsVerbose = optionVerbose.HasValue(); options.Project = optionProject.Value(); diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ICommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ICommand.cs index 3d6035d083..636c08a07c 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ICommand.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ICommand.cs @@ -1,12 +1,10 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Microsoft.Extensions.Logging; - namespace Microsoft.Extensions.SecretManager.Tools.Internal { - internal interface ICommand + public interface ICommand { - void Execute(SecretsStore store, ILogger logger); + void Execute(CommandContext context); } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/IConsole.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/IConsole.cs new file mode 100644 index 0000000000..819d477106 --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/IConsole.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; + +namespace Microsoft.Extensions.SecretManager.Tools.Internal +{ + public interface IConsole + { + TextWriter Out { get; } + TextWriter Error { get; } + TextReader In { get; } + bool IsInputRedirected { get; } + } +} diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ListCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ListCommand.cs index efc012cd5a..16ee59a882 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ListCommand.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ListCommand.cs @@ -3,35 +3,67 @@ using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; namespace Microsoft.Extensions.SecretManager.Tools.Internal { - internal class ListCommand : ICommand + public class ListCommand : ICommand { + private readonly bool _jsonOutput; + public static void Configure(CommandLineApplication command, CommandLineOptions options) { command.Description = "Lists all the application secrets"; command.HelpOption(); + var optJson = command.Option("--json", "Use json output. JSON is wrapped by '//BEGIN' and '//END'", + CommandOptionType.NoValue); + command.OnExecute(() => { - options.Command = new ListCommand(); + options.Command = new ListCommand(optJson.HasValue()); }); } - public void Execute(SecretsStore store, ILogger logger) + public ListCommand(bool jsonOutput) { - if (store.Count == 0) + _jsonOutput = jsonOutput; + } + + public void Execute(CommandContext context) + { + if (_jsonOutput) { - logger.LogInformation(Resources.Error_No_Secrets_Found); + ReportJson(context); + return; + } + + if (context.SecretStore.Count == 0) + { + context.Logger.LogInformation(Resources.Error_No_Secrets_Found); } else { - foreach (var secret in store.AsEnumerable()) + foreach (var secret in context.SecretStore.AsEnumerable()) { - logger.LogInformation(Resources.FormatMessage_Secret_Value_Format(secret.Key, secret.Value)); + context.Logger.LogInformation(Resources.FormatMessage_Secret_Value_Format(secret.Key, secret.Value)); } } } + + private void ReportJson(CommandContext context) + { + var jObject = new JObject(); + foreach(var item in context.SecretStore.AsEnumerable()) + { + jObject[item.Key] = item.Value; + } + + // TODO logger would prefix each line. + context.Console.Out.WriteLine("//BEGIN"); + context.Console.Out.WriteLine(jObject.ToString(Formatting.Indented)); + context.Console.Out.WriteLine("//END"); + } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/PhysicalConsole.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/PhysicalConsole.cs new file mode 100644 index 0000000000..6be8ff495f --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/PhysicalConsole.cs @@ -0,0 +1,19 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; + +namespace Microsoft.Extensions.SecretManager.Tools.Internal +{ + public class PhysicalConsole : IConsole + { + private PhysicalConsole() { } + + public static IConsole Singleton { get; } = new PhysicalConsole(); + public TextWriter Error => Console.Error; + public TextReader In => Console.In; + public TextWriter Out => Console.Out; + public bool IsInputRedirected => Console.IsInputRedirected; + } +} diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ReadableJsonConfigurationSource.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ReadableJsonConfigurationSource.cs new file mode 100644 index 0000000000..96d0554aeb --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ReadableJsonConfigurationSource.cs @@ -0,0 +1,18 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using Microsoft.Extensions.Configuration.Json; + +namespace Microsoft.Extensions.SecretManager.Tools.Internal +{ + public class ReadableJsonConfigurationProvider : JsonConfigurationProvider + { + public ReadableJsonConfigurationProvider() + : base(new JsonConfigurationSource()) + { + } + + public IDictionary CurrentData => Data; + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs index ff48c253cc..84910b9a99 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs @@ -6,7 +6,7 @@ using Microsoft.Extensions.Logging; namespace Microsoft.Extensions.SecretManager.Tools.Internal { - internal class RemoveCommand : ICommand + public class RemoveCommand : ICommand { private readonly string _keyName; @@ -33,16 +33,16 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal _keyName = keyName; } - public void Execute(SecretsStore store, ILogger logger) + public void Execute(CommandContext context) { - if (!store.ContainsKey(_keyName)) + if (!context.SecretStore.ContainsKey(_keyName)) { - logger.LogWarning(Resources.Error_Missing_Secret, _keyName); + context.Logger.LogWarning(Resources.Error_Missing_Secret, _keyName); } else { - store.Remove(_keyName); - store.Save(); + context.SecretStore.Remove(_keyName); + context.SecretStore.Save(); } } } diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs index b25a757500..67461d732d 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs @@ -13,7 +13,7 @@ using Newtonsoft.Json.Linq; namespace Microsoft.Extensions.SecretManager.Tools.Internal { - internal class SecretsStore + public class SecretsStore { private readonly string _secretsFilePath; private IDictionary _secrets; @@ -27,13 +27,15 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal _secretsFilePath = PathHelper.GetSecretsPathFromSecretsId(userSecretsId); logger.LogDebug(Resources.Message_Secret_File_Path, _secretsFilePath); + _secrets = Load(userSecretsId); + } - _secrets = new ConfigurationBuilder() - .AddJsonFile(_secretsFilePath, optional: true) - .Build() - .AsEnumerable() - .Where(i => i.Value != null) - .ToDictionary(i => i.Key, i => i.Value, StringComparer.OrdinalIgnoreCase); + public string this[string key] + { + get + { + return _secrets[key]; + } } public int Count => _secrets.Count; @@ -54,7 +56,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal } } - public void Save() + public virtual void Save() { Directory.CreateDirectory(Path.GetDirectoryName(_secretsFilePath)); @@ -69,5 +71,15 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal File.WriteAllText(_secretsFilePath, contents.ToString(), Encoding.UTF8); } + + protected virtual IDictionary Load(string userSecretsId) + { + return new ConfigurationBuilder() + .AddJsonFile(_secretsFilePath, optional: true) + .Build() + .AsEnumerable() + .Where(i => i.Value != null) + .ToDictionary(i => i.Key, i => i.Value, StringComparer.OrdinalIgnoreCase); + } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs index 15852cef64..4799d9ff88 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs @@ -1,12 +1,15 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Diagnostics; +using System.IO; +using System.Text; using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Logging; namespace Microsoft.Extensions.SecretManager.Tools.Internal { - internal class SetCommand : ICommand + public class SetCommand : ICommand { private readonly string _keyName; private readonly string _keyValue; @@ -14,38 +17,88 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal public static void Configure(CommandLineApplication command, CommandLineOptions options) { command.Description = "Sets the user secret to the specified value"; + command.ExtendedHelpText = @" +Additional Info: + This command will also handle piped input. Piped input is expected to be a valid JSON format. + +Examples: + dotnet user-secrets set ConnStr ""User ID=bob;Password=***"" + cat secrets.json | dotnet user-secrets set +"; + command.HelpOption(); - var keyArg = command.Argument("[name]", "Name of the secret"); + var nameArg = command.Argument("[name]", "Name of the secret"); var valueArg = command.Argument("[value]", "Value of the secret"); command.OnExecute(() => { - if (keyArg.Value == null) - { - throw new GracefulException("Missing parameter value for 'name'.\nUse the '--help' flag to see info."); - } - - if (valueArg.Value == null) - { - throw new GracefulException("Missing parameter value for 'value'.\nUse the '--help' flag to see info."); - } - - options.Command = new SetCommand(keyArg.Value, valueArg.Value); + options.Command = new SetCommand(nameArg.Value, valueArg.Value); }); } - public SetCommand(string keyName, string keyValue) + internal SetCommand(string keyName, string keyValue) { + Debug.Assert(keyName != null || keyValue == null, "Inconsistent state. keyValue must not be null if keyName is null."); _keyName = keyName; _keyValue = keyValue; } - public void Execute(SecretsStore store, ILogger logger) + internal SetCommand() + { } + + public void Execute(CommandContext context) { - store.Set(_keyName, _keyValue); - store.Save(); - logger.LogInformation(Resources.Message_Saved_Secret, _keyName, _keyValue); + if (context.Console.IsInputRedirected && _keyName == null) + { + ReadFromInput(context); + } + else + { + SetFromArguments(context); + } + } + + private void ReadFromInput(CommandContext context) + { + // parses stdin with the same parser that Microsoft.Extensions.Configuration.Json would use + var provider = new ReadableJsonConfigurationProvider(); + using (var stream = new MemoryStream()) + { + using (var writer = new StreamWriter(stream, Encoding.Unicode, 1024, true)) + { + writer.Write(context.Console.In.ReadToEnd()); // TODO buffer? + } + + stream.Seek(0, SeekOrigin.Begin); + provider.Load(stream); + } + + foreach (var k in provider.CurrentData) + { + context.SecretStore.Set(k.Key, k.Value); + } + + context.Logger.LogInformation(Resources.Message_Saved_Secrets, provider.CurrentData.Count); + + context.SecretStore.Save(); + } + + private void SetFromArguments(CommandContext context) + { + if (_keyName == null) + { + throw new GracefulException(Resources.FormatError_MissingArgument("name")); + } + + if (_keyValue == null) + { + throw new GracefulException((Resources.FormatError_MissingArgument("value"))); + } + + context.SecretStore.Set(_keyName, _keyValue); + context.SecretStore.Save(); + context.Logger.LogInformation(Resources.Message_Saved_Secret, _keyName, _keyValue); } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs index 82422bd189..cef3cad322 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs @@ -18,17 +18,17 @@ namespace Microsoft.Extensions.SecretManager.Tools { private ILogger _logger; private CommandOutputProvider _loggerProvider; - private readonly TextWriter _consoleOutput; + private readonly IConsole _console; private readonly string _workingDirectory; public Program() - : this(Console.Out, Directory.GetCurrentDirectory()) + : this(PhysicalConsole.Singleton, Directory.GetCurrentDirectory()) { } - internal Program(TextWriter consoleOutput, string workingDirectory) + internal Program(IConsole console, string workingDirectory) { - _consoleOutput = consoleOutput; + _console = console; _workingDirectory = workingDirectory; var loggerFactory = new LoggerFactory(); @@ -117,7 +117,7 @@ namespace Microsoft.Extensions.SecretManager.Tools internal int RunInternal(params string[] args) { - var options = CommandLineOptions.Parse(args, _consoleOutput); + var options = CommandLineOptions.Parse(args, _console); if (options == null) { @@ -136,12 +136,18 @@ namespace Microsoft.Extensions.SecretManager.Tools var userSecretsId = ResolveUserSecretsId(options); var store = new SecretsStore(userSecretsId, Logger); - options.Command.Execute(store, Logger); + var context = new CommandContext(store, Logger, _console); + options.Command.Execute(context); return 0; } private string ResolveUserSecretsId(CommandLineOptions options) { + if (!string.IsNullOrEmpty(options.Id)) + { + return options.Id; + } + var projectPath = options.Project ?? _workingDirectory; if (!Path.IsPathRooted(projectPath)) diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs b/src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs index d9ae9fe2c6..f8af024110 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs @@ -26,6 +26,24 @@ namespace Microsoft.Extensions.SecretManager.Tools return string.Format(CultureInfo.CurrentCulture, GetString("Error_Command_Failed", "message"), message); } + /// + /// Missing parameter value for '{name}'. + /// Use the '--help' flag to see info. + /// + internal static string Error_MissingArgument + { + get { return GetString("Error_MissingArgument"); } + } + + /// + /// Missing parameter value for '{name}'. + /// Use the '--help' flag to see info. + /// + internal static string FormatError_MissingArgument(object name) + { + return string.Format(CultureInfo.CurrentCulture, GetString("Error_MissingArgument", "name"), name); + } + /// /// Cannot find '{key}' in the secret store. /// @@ -106,6 +124,22 @@ namespace Microsoft.Extensions.SecretManager.Tools return string.Format(CultureInfo.CurrentCulture, GetString("Message_Saved_Secret", "key", "value"), key, value); } + /// + /// Successfully saved {number} secrets to the secret store. + /// + internal static string Message_Saved_Secrets + { + get { return GetString("Message_Saved_Secrets"); } + } + + /// + /// Successfully saved {number} secrets to the secret store. + /// + internal static string FormatMessage_Saved_Secrets(object number) + { + return string.Format(CultureInfo.CurrentCulture, GetString("Message_Saved_Secrets", "number"), number); + } + /// /// Secrets file path {secretsFilePath}. /// diff --git a/src/Microsoft.Extensions.SecretManager.Tools/README.md b/src/Microsoft.Extensions.SecretManager.Tools/README.md new file mode 100644 index 0000000000..088485fd7a --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/README.md @@ -0,0 +1,22 @@ +dotnet-user-secrets +=================== + +`dotnet-user-secrets` is a command line tool for managing the secrets in a user secret store. + +### How To Install + +Add `Microsoft.Extensions.SecretManager.Tools` to the `tools` section of your `project.json` file: + +```js +{ + .. + "tools": { + "Microsoft.Extensions.SecretManager.Tools": "1.0.0-*" + } + ... +} +``` + +### How To Use + +Run `dotnet user-secrets --help` for more information about usage. \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Resources.resx b/src/Microsoft.Extensions.SecretManager.Tools/Resources.resx index 76631dea0d..63d65502dc 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Resources.resx +++ b/src/Microsoft.Extensions.SecretManager.Tools/Resources.resx @@ -120,6 +120,10 @@ Command failed : {message} + + Missing parameter value for '{name}'. +Use the '--help' flag to see info. + Cannot find '{key}' in the secret store. @@ -135,6 +139,9 @@ Successfully saved {key} = {value} to the secret store. + + Successfully saved {number} secrets to the secret store. + Secrets file path {secretsFilePath}. diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs index f9b8f62961..082b53c3dd 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs @@ -8,9 +8,9 @@ using System.Text; using Microsoft.Extensions.Configuration.UserSecrets; using Microsoft.Extensions.Configuration.UserSecrets.Tests; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.SecretManager.Tools.Internal; using Xunit; using Xunit.Abstractions; -using Microsoft.Extensions.SecretManager.Tools.Internal; namespace Microsoft.Extensions.SecretManager.Tools.Tests { @@ -48,7 +48,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests public void Error_Project_DoesNotExist() { var projectPath = Path.Combine(GetTempSecretProject(), "does_not_exist", "project.json"); - var secretManager = new Program(Console.Out, Directory.GetCurrentDirectory()) { Logger = _logger }; + var secretManager = new Program(new TestConsole(), Directory.GetCurrentDirectory()) { Logger = _logger }; var ex = Assert.Throws(() => secretManager.RunInternal("list", "--project", projectPath)); @@ -61,7 +61,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests var projectPath = GetTempSecretProject(); var cwd = Path.Combine(projectPath, "nested1"); Directory.CreateDirectory(cwd); - var secretManager = new Program(Console.Out, cwd) { Logger = _logger, CommandOutputProvider = _logger.CommandOutputProvider }; + var secretManager = new Program(new TestConsole(), cwd) { Logger = _logger, CommandOutputProvider = _logger.CommandOutputProvider }; secretManager.CommandOutputProvider.LogLevel = LogLevel.Debug; secretManager.RunInternal("list", "-p", "../", "--verbose"); @@ -86,7 +86,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests var dir = fromCurrentDirectory ? projectPath : Path.GetTempPath(); - var secretManager = new Program(Console.Out, dir) { Logger = _logger }; + var secretManager = new Program(new TestConsole(), dir) { Logger = _logger }; foreach (var secret in secrets) { @@ -222,6 +222,27 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests Assert.Contains("AzureAd:ClientSecret = abcd郩˙î", _logger.Messages); } + [Fact] + public void List_Json() + { + var output = new StringBuilder(); + var testConsole = new TestConsole + { + Out = new StringWriter(output) + }; + string id; + var projectPath = GetTempSecretProject(out id); + var secretsFile = PathHelper.GetSecretsPathFromSecretsId(id); + Directory.CreateDirectory(Path.GetDirectoryName(secretsFile)); + File.WriteAllText(secretsFile, @"{ ""AzureAd"": { ""ClientSecret"": ""abcd郩˙î""} }", Encoding.UTF8); + var secretManager = new Program(testConsole, Path.GetDirectoryName(projectPath)) { Logger = _logger }; + secretManager.RunInternal("list", "--id", id, "--json"); + var stdout = output.ToString(); + Assert.Contains("//BEGIN", stdout); + Assert.Contains(@"""AzureAd:ClientSecret"": ""abcd郩˙î""", stdout); + Assert.Contains("//END", stdout); + } + [Fact] public void Set_Flattens_Nested_Objects() { @@ -265,7 +286,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests ? projectPath : Path.GetTempPath(); - var secretManager = new Program(Console.Out, dir) { Logger = _logger }; + var secretManager = new Program(new TestConsole(), dir) { Logger = _logger }; var secrets = new KeyValuePair[] { diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs new file mode 100644 index 0000000000..7fdd43b009 --- /dev/null +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs @@ -0,0 +1,101 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; +using System.Collections.Generic; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.SecretManager.Tools.Internal; +using Xunit; + +namespace Microsoft.Extensions.SecretManager.Tools.Tests +{ + public class SetCommandTest + { + [Fact] + public void SetsFromPipedInput() + { + var input = @" +{ + ""Key1"": ""str value"", +""Key2"": 1234, +""Key3"": false +}"; + var testConsole = new TestConsole + { + IsInputRedirected = true, + In = new StringReader(input) + }; + var secretStore = new TestSecretsStore(); + var command = new SetCommand(); + + command.Execute(new CommandContext(secretStore, NullLogger.Instance, testConsole)); + + Assert.Equal(3, secretStore.Count); + Assert.Equal("str value", secretStore["Key1"]); + Assert.Equal("1234", secretStore["Key2"]); + Assert.Equal("False", secretStore["Key3"]); + } + + [Fact] + public void ParsesNestedObjects() + { + var input = @" + { + ""Key1"": { + ""nested"" : ""value"" + }, + ""array"": [ 1, 2 ] + }"; + + var testConsole = new TestConsole + { + IsInputRedirected = true, + In = new StringReader(input) + }; + var secretStore = new TestSecretsStore(); + var command = new SetCommand(); + + command.Execute(new CommandContext(secretStore, NullLogger.Instance, testConsole)); + + Assert.Equal(3, secretStore.Count); + Assert.True(secretStore.ContainsKey("Key1:nested")); + Assert.Equal("value", secretStore["Key1:nested"]); + Assert.Equal("1", secretStore["array:0"]); + Assert.Equal("2", secretStore["array:1"]); + } + + [Fact] + public void OnlyPipesInIfNoArgs() + { + var testConsole = new TestConsole + { + IsInputRedirected = true, + In = new StringReader("") + }; + var secretStore = new TestSecretsStore(); + var command = new SetCommand("key", null); + + var ex = Assert.Throws( + () => command.Execute(new CommandContext(secretStore, NullLogger.Instance, testConsole))); + Assert.Equal(Resources.FormatError_MissingArgument("value"), ex.Message); + } + + private class TestSecretsStore : SecretsStore + { + public TestSecretsStore() + : base("xyz", NullLogger.Instance) + { + } + + protected override IDictionary Load(string userSecretsId) + { + return new Dictionary(); + } + + public override void Save() + { + // noop + } + } + } +} diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/TestConsole.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/TestConsole.cs new file mode 100644 index 0000000000..8370ecf065 --- /dev/null +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/TestConsole.cs @@ -0,0 +1,17 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using Microsoft.Extensions.SecretManager.Tools.Internal; + +namespace Microsoft.Extensions.SecretManager.Tools.Tests +{ + public class TestConsole : IConsole + { + public TextWriter Error { get; set; } = Console.Error; + public TextReader In { get; set; } = Console.In; + public TextWriter Out { get; set; } = Console.Out; + public bool IsInputRedirected { get; set; } = false; + } +} diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretHelper.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretHelper.cs index 87dbddc3e4..00932db0f3 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretHelper.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretHelper.cs @@ -7,7 +7,7 @@ using Newtonsoft.Json; namespace Microsoft.Extensions.Configuration.UserSecrets.Tests { - internal class UserSecretHelper + public class UserSecretHelper { internal static string GetTempSecretProject() { From 9744f94b39c65c228be87b35f97c1f28d3fd54a6 Mon Sep 17 00:00:00 2001 From: Scott Hanselman Date: Tue, 1 Nov 2016 18:39:14 -0700 Subject: [PATCH 0306/1029] Update README for dotnet-watch to specify which version to install (#210) --- src/Microsoft.DotNet.Watcher.Tools/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/README.md b/src/Microsoft.DotNet.Watcher.Tools/README.md index e97e579e1b..7a21544e70 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/README.md +++ b/src/Microsoft.DotNet.Watcher.Tools/README.md @@ -4,13 +4,15 @@ dotnet-watch ### How To Install -Add `Microsoft.DotNet.Watcher.Tools` to the `tools` section of your `project.json` file: +Add `Microsoft.DotNet.Watcher.Tools` to the `tools` section of your `project.json` file. + +Use the version "1.0.0-preview2-final" if you are using .NET Core 1.0.0 and use "1.0.0-preview3-final" if you are using .NET Core 1.1.0. ``` { ... "tools": { - "Microsoft.DotNet.Watcher.Tools": "1.0.0-*" + "Microsoft.DotNet.Watcher.Tools": "1.0.0-preview2-final" //"1.0.0-preview3-final" for .NET Core 1.1.0 } ... } From 29df59b89cbe4021bf8b1f19f3e5f447c232ede4 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 7 Oct 2016 09:56:08 -0700 Subject: [PATCH 0307/1029] Create initial prototype of dotnet-user-secrets with MSBuild support --- .gitignore | 1 + .../FindUserSecretsProperty.targets | 6 + .../Internal/CommandLineOptions.cs | 6 + .../Internal/GracefulException.cs | 25 ---- .../Internal/MsBuildProjectFinder.cs | 61 ++++++++ .../Internal/ProjectIdResolver.cs | 130 ++++++++++++++++++ .../Internal/RemoveCommand.cs | 1 + .../Internal/SecretsStore.cs | 1 + .../Internal/SetCommand.cs | 1 + ...soft.Extensions.SecretManager.Tools.nuspec | 10 +- .../Program.cs | 101 +++----------- .../Properties/Resources.Designer.cs | 80 +++++++++++ .../Resources.resx | 69 ++++++---- .../project.json | 20 ++- .../MsBuildProjectFinderTest.cs | 86 ++++++++++++ .../SecretManagerTests.cs | 115 +++++++++------- .../SetCommandTest.cs | 2 +- .../TemporaryFileProvider.cs | 29 ++++ .../UserSecretHelper.cs | 47 ------- .../UserSecretsTestFixture.cs | 103 ++++++++++++++ 20 files changed, 649 insertions(+), 245 deletions(-) create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/FindUserSecretsProperty.targets delete mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Internal/GracefulException.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Internal/MsBuildProjectFinder.cs create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs create mode 100644 test/Microsoft.Extensions.SecretManager.Tools.Tests/MsBuildProjectFinderTest.cs create mode 100644 test/Microsoft.Extensions.SecretManager.Tools.Tests/TemporaryFileProvider.cs delete mode 100644 test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretHelper.cs create mode 100644 test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs diff --git a/.gitignore b/.gitignore index 33889157be..29b5f79c9b 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,7 @@ project.lock.json .testPublish/ .build/ /.vs/ +.vscode/ testWorkDir/ *.nuget.props *.nuget.targets \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/FindUserSecretsProperty.targets b/src/Microsoft.Extensions.SecretManager.Tools/FindUserSecretsProperty.targets new file mode 100644 index 0000000000..694dc25008 --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/FindUserSecretsProperty.targets @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs index 37705429a5..42d826e1e0 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Reflection; +using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.CommandLineUtils; namespace Microsoft.Extensions.SecretManager.Tools.Internal @@ -13,6 +14,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal public bool IsHelp { get; set; } public string Project { get; set; } public ICommand Command { get; set; } + public string Configuration { get; set; } public static CommandLineOptions Parse(string[] args, IConsole console) { @@ -34,6 +36,9 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal var optionProject = app.Option("-p|--project ", "Path to project, default is current directory", CommandOptionType.SingleValue, inherited: true); + var optionConfig = app.Option("-c|--configuration ", $"The project configuration to use. Defaults to {Constants.DefaultConfiguration}", + CommandOptionType.SingleValue, inherited: true); + // the escape hatch if project evaluation fails, or if users want to alter a secret store other than the one // in the current project var optionId = app.Option("--id", "The user secret id to use.", @@ -55,6 +60,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal return null; } + options.Configuration = optionConfig.Value(); options.Id = optionId.Value(); options.IsHelp = app.IsShowingInformation; options.IsVerbose = optionVerbose.HasValue(); diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/GracefulException.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/GracefulException.cs deleted file mode 100644 index 7e54c8ba2f..0000000000 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/GracefulException.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; - -namespace Microsoft.Extensions.SecretManager.Tools.Internal -{ - /// - /// An exception whose stack trace should be suppressed in console output - /// - public class GracefulException : Exception - { - public GracefulException() - { - } - - public GracefulException(string message) : base(message) - { - } - - public GracefulException(string message, Exception innerException) : base(message, innerException) - { - } - } -} diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/MsBuildProjectFinder.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/MsBuildProjectFinder.cs new file mode 100644 index 0000000000..e080b4cb83 --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/MsBuildProjectFinder.cs @@ -0,0 +1,61 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Linq; +using Microsoft.DotNet.Cli.Utils; + +namespace Microsoft.Extensions.SecretManager.Tools.Internal +{ + internal class MsBuildProjectFinder + { + private readonly string _directory; + + public MsBuildProjectFinder(string directory) + { + if (string.IsNullOrEmpty(directory)) + { + throw new ArgumentException(Resources.Common_StringNullOrEmpty, nameof(directory)); + } + + _directory = directory; + } + + public string FindMsBuildProject(string project) + { + var projectPath = project ?? _directory; + + if (!Path.IsPathRooted(projectPath)) + { + projectPath = Path.Combine(_directory, projectPath); + } + + if (Directory.Exists(projectPath)) + { + var projects = Directory.EnumerateFileSystemEntries(projectPath, "*.*proj", SearchOption.TopDirectoryOnly) + .Where(f => !".xproj".Equals(Path.GetExtension(f), StringComparison.OrdinalIgnoreCase)) + .ToList(); + + if (projects.Count > 1) + { + throw new GracefulException(Resources.FormatError_MultipleProjectsFound(projectPath)); + } + + if (projects.Count == 0) + { + throw new GracefulException(Resources.FormatError_NoProjectsFound(projectPath)); + } + + return projects[0]; + } + + if (!File.Exists(projectPath)) + { + throw new GracefulException(Resources.FormatError_ProjectPath_NotFound(projectPath)); + } + + return projectPath; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs new file mode 100644 index 0000000000..683f412c83 --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs @@ -0,0 +1,130 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Extensions.SecretManager.Tools.Internal +{ + public class ProjectIdResolver : IDisposable + { + private const string TargetsFileName = "FindUserSecretsProperty.targets"; + private readonly ILogger _logger; + private readonly string _workingDirectory; + private readonly List _tempFiles = new List(); + + public ProjectIdResolver(ILogger logger, string workingDirectory) + { + _workingDirectory = workingDirectory; + _logger = logger; + } + + public string Resolve(string project, string configuration = Constants.DefaultConfiguration) + { + var finder = new MsBuildProjectFinder(_workingDirectory); + var projectFile = finder.FindMsBuildProject(project); + + _logger.LogDebug(Resources.Message_Project_File_Path, projectFile); + + var targetFile = GetTargetFile(); + var outputFile = Path.GetTempFileName(); + _tempFiles.Add(outputFile); + + var commandOutput = new List(); + var commandResult = Command.CreateDotNet("msbuild", + new[] { + targetFile, + "/nologo", + "/t:_FindUserSecretsProperty", + $"/p:Project={projectFile}", + $"/p:OutputFile={outputFile}", + $"/p:Configuration={configuration}" + }) + .CaptureStdErr() + .CaptureStdOut() + .OnErrorLine(l => commandOutput.Add(l)) + .OnOutputLine(l => commandOutput.Add(l)) + .Execute(); + + if (commandResult.ExitCode != 0) + { + _logger.LogDebug(string.Join(Environment.NewLine, commandOutput)); + throw new GracefulException(Resources.FormatError_ProjectFailedToLoad(projectFile)); + } + + var id = File.ReadAllText(outputFile)?.Trim(); + if (string.IsNullOrEmpty(id)) + { + throw new GracefulException(Resources.FormatError_ProjectMissingId(projectFile)); + } + + return id; + } + + public void Dispose() + { + foreach (var file in _tempFiles) + { + TryDelete(file); + } + } + + private string GetTargetFile() + { + var assemblyDir = Path.GetDirectoryName(GetType().GetTypeInfo().Assembly.Location); + + // targets should be in one of these locations, depending on test setup and tools installation + var searchPaths = new[] + { + AppContext.BaseDirectory, + assemblyDir, // next to assembly + Path.Combine(assemblyDir, "../../tools"), // inside the nupkg + }; + + var foundFile = searchPaths + .Select(dir => Path.Combine(dir, TargetsFileName)) + .Where(File.Exists) + .FirstOrDefault(); + + if (foundFile != null) + { + return foundFile; + } + + // This should only really happen during testing. Current build system doesn't give us a good way to ensure the + // test project has an always-up to date version of the targets file. + // TODO cleanup after we switch to an MSBuild system in which can specify "CopyToOutputDirectory: Always" to resolve this issue + var outputPath = Path.GetTempFileName(); + using (var resource = GetType().GetTypeInfo().Assembly.GetManifestResourceStream(TargetsFileName)) + using (var stream = new FileStream(outputPath, FileMode.Create)) + { + resource.CopyTo(stream); + } + + // cleanup + _tempFiles.Add(outputPath); + + return outputPath; + } + + private static void TryDelete(string file) + { + try + { + if (File.Exists(file)) + { + File.Delete(file); + } + } + catch + { + // whatever + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs index 84910b9a99..6e6e5af027 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Logging; diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs index 67461d732d..588e66dcba 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs @@ -26,6 +26,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal } _secretsFilePath = PathHelper.GetSecretsPathFromSecretsId(userSecretsId); + logger.LogDebug(Resources.Message_Secret_File_Path, _secretsFilePath); _secrets = Load(userSecretsId); } diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs index 4799d9ff88..e8c3855961 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.IO; using System.Text; +using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Logging; diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec index 2ddab547bf..db6cb0bf93 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec @@ -16,16 +16,16 @@ - + - - - - + + + + diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs index cef3cad322..3ef60eb563 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs @@ -2,15 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Diagnostics; using System.IO; -using System.Linq; +using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.FileProviders; -using Microsoft.Extensions.FileProviders.Physical; using Microsoft.Extensions.SecretManager.Tools.Internal; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; namespace Microsoft.Extensions.SecretManager.Tools { @@ -21,12 +16,16 @@ namespace Microsoft.Extensions.SecretManager.Tools private readonly IConsole _console; private readonly string _workingDirectory; - public Program() - : this(PhysicalConsole.Singleton, Directory.GetCurrentDirectory()) + public static int Main(string[] args) { + DebugHelper.HandleDebugSwitch(ref args); + + int rc; + new Program(PhysicalConsole.Singleton, Directory.GetCurrentDirectory()).TryRun(args, out rc); + return rc; } - internal Program(IConsole console, string workingDirectory) + public Program(IConsole console, string workingDirectory) { _console = console; _workingDirectory = workingDirectory; @@ -65,33 +64,6 @@ namespace Microsoft.Extensions.SecretManager.Tools } } - public static int Main(string[] args) - { - HandleDebugFlag(ref args); - - int rc; - new Program().TryRun(args, out rc); - return rc; - } - - [Conditional("DEBUG")] - private static void HandleDebugFlag(ref string[] args) - { - for (var i = 0; i < args.Length; ++i) - { - if (args[i] == "--debug") - { - Console.WriteLine("Process ID " + Process.GetCurrentProcess().Id); - Console.WriteLine("Paused for debugger. Press ENTER to continue"); - Console.ReadLine(); - - args = args.Take(i).Concat(args.Skip(i + 1)).ToArray(); - - return; - } - } - } - public bool TryRun(string[] args, out int returnCode) { try @@ -103,6 +75,11 @@ namespace Microsoft.Extensions.SecretManager.Tools { if (exception is GracefulException) { + if (exception.InnerException != null) + { + Logger.LogInformation(exception.InnerException.Message); + } + Logger.LogError(exception.Message); } else @@ -134,65 +111,23 @@ namespace Microsoft.Extensions.SecretManager.Tools CommandOutputProvider.LogLevel = LogLevel.Debug; } - var userSecretsId = ResolveUserSecretsId(options); + var userSecretsId = ResolveId(options); var store = new SecretsStore(userSecretsId, Logger); - var context = new CommandContext(store, Logger, _console); + var context = new Internal.CommandContext(store, Logger, _console); options.Command.Execute(context); return 0; } - private string ResolveUserSecretsId(CommandLineOptions options) + internal string ResolveId(CommandLineOptions options) { if (!string.IsNullOrEmpty(options.Id)) { return options.Id; } - var projectPath = options.Project ?? _workingDirectory; - - if (!Path.IsPathRooted(projectPath)) + using (var resolver = new ProjectIdResolver(Logger, _workingDirectory)) { - projectPath = Path.Combine(_workingDirectory, projectPath); - } - - if (!projectPath.EndsWith("project.json", StringComparison.OrdinalIgnoreCase)) - { - projectPath = Path.Combine(projectPath, "project.json"); - } - - var fileInfo = new PhysicalFileInfo(new FileInfo(projectPath)); - - if (!fileInfo.Exists) - { - throw new GracefulException(Resources.FormatError_ProjectPath_NotFound(projectPath)); - } - - Logger.LogDebug(Resources.Message_Project_File_Path, fileInfo.PhysicalPath); - return ReadUserSecretsId(fileInfo); - } - - // TODO can use runtime API when upgrading to 1.1 - private string ReadUserSecretsId(IFileInfo fileInfo) - { - if (fileInfo == null || !fileInfo.Exists) - { - throw new GracefulException($"Could not find file '{fileInfo.PhysicalPath}'"); - } - - using (var stream = fileInfo.CreateReadStream()) - using (var streamReader = new StreamReader(stream)) - using (var jsonReader = new JsonTextReader(streamReader)) - { - var obj = JObject.Load(jsonReader); - - var userSecretsId = obj.Value("userSecretsId"); - - if (string.IsNullOrEmpty(userSecretsId)) - { - throw new GracefulException($"Could not find 'userSecretsId' in json file '{fileInfo.PhysicalPath}'"); - } - - return userSecretsId; + return resolver.Resolve(options.Project, options.Configuration); } } } diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs b/src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs index f8af024110..a74bdc6798 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs @@ -10,6 +10,22 @@ namespace Microsoft.Extensions.SecretManager.Tools private static readonly ResourceManager _resourceManager = new ResourceManager("Microsoft.Extensions.SecretManager.Tools.Resources", typeof(Resources).GetTypeInfo().Assembly); + /// + /// Value cannot be null or an empty string. + /// + internal static string Common_StringNullOrEmpty + { + get { return GetString("Common_StringNullOrEmpty"); } + } + + /// + /// Value cannot be null or an empty string. + /// + internal static string FormatCommon_StringNullOrEmpty() + { + return GetString("Common_StringNullOrEmpty"); + } + /// /// Command failed : {message} /// @@ -60,6 +76,22 @@ namespace Microsoft.Extensions.SecretManager.Tools return string.Format(CultureInfo.CurrentCulture, GetString("Error_Missing_Secret", "key"), key); } + /// + /// Multiple MSBuild project files found in '{projectPath}'. Specify which to use with the --project option. + /// + internal static string Error_MultipleProjectsFound + { + get { return GetString("Error_MultipleProjectsFound"); } + } + + /// + /// Multiple MSBuild project files found in '{projectPath}'. Specify which to use with the --project option. + /// + internal static string FormatError_MultipleProjectsFound(object projectPath) + { + return string.Format(CultureInfo.CurrentCulture, GetString("Error_MultipleProjectsFound", "projectPath"), projectPath); + } + /// /// No secrets configured for this application. /// @@ -76,6 +108,38 @@ namespace Microsoft.Extensions.SecretManager.Tools return GetString("Error_No_Secrets_Found"); } + /// + /// Could not find a MSBuild project file in '{projectPath}'. Specify which project to use with the --project option. + /// + internal static string Error_NoProjectsFound + { + get { return GetString("Error_NoProjectsFound"); } + } + + /// + /// Could not find a MSBuild project file in '{projectPath}'. Specify which project to use with the --project option. + /// + internal static string FormatError_NoProjectsFound(object projectPath) + { + return string.Format(CultureInfo.CurrentCulture, GetString("Error_NoProjectsFound", "projectPath"), projectPath); + } + + /// + /// Could not find the global property 'UserSecretsId' in MSBuild project '{project}'. Ensure this property is set in the project or use the '--id' command line option. + /// + internal static string Error_ProjectMissingId + { + get { return GetString("Error_ProjectMissingId"); } + } + + /// + /// Could not find the global property 'UserSecretsId' in MSBuild project '{project}'. Ensure this property is set in the project or use the '--id' command line option. + /// + internal static string FormatError_ProjectMissingId(object project) + { + return string.Format(CultureInfo.CurrentCulture, GetString("Error_ProjectMissingId", "project"), project); + } + /// /// The project file '{path}' does not exist. /// @@ -92,6 +156,22 @@ namespace Microsoft.Extensions.SecretManager.Tools return string.Format(CultureInfo.CurrentCulture, GetString("Error_ProjectPath_NotFound", "path"), path); } + /// + /// Could not load the MSBuild project '{project}'. + /// + internal static string Error_ProjectFailedToLoad + { + get { return GetString("Error_ProjectFailedToLoad"); } + } + + /// + /// Could not load the MSBuild project '{project}'. + /// + internal static string FormatError_ProjectFailedToLoad(object project) + { + return string.Format(CultureInfo.CurrentCulture, GetString("Error_ProjectFailedToLoad", "project"), project); + } + /// /// Project file path {project}. /// diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Resources.resx b/src/Microsoft.Extensions.SecretManager.Tools/Resources.resx index 63d65502dc..3ee74a41e9 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Resources.resx +++ b/src/Microsoft.Extensions.SecretManager.Tools/Resources.resx @@ -1,17 +1,17 @@  - @@ -117,6 +117,9 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Value cannot be null or an empty string. + Command failed : {message} @@ -127,12 +130,24 @@ Use the '--help' flag to see info. Cannot find '{key}' in the secret store. + + Multiple MSBuild project files found in '{projectPath}'. Specify which to use with the --project option. + No secrets configured for this application. + + Could not find a MSBuild project file in '{projectPath}'. Specify which project to use with the --project option. + + + Could not find the global property 'UserSecretsId' in MSBuild project '{project}'. Ensure this property is set in the project or use the '--id' command line option. + The project file '{path}' does not exist. + + Could not load the MSBuild project '{project}'. + Project file path {project}. diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index 77d376be2d..1f2aaa7e15 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -4,7 +4,13 @@ "outputName": "dotnet-user-secrets", "emitEntryPoint": true, "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk" + "keyFile": "../../tools/Key.snk", + "copyToOutput": "*.targets", + "embed": { + "mappings": { + "FindUserSecretsProperty.targets": "./FindUserSecretsProperty.targets" + } + } }, "description": "Command line tool to manage user secrets for Microsoft.Extensions.Configuration.", "packOptions": { @@ -16,18 +22,22 @@ "configuration", "secrets", "usersecrets" - ] + ], + "files": { + "mappings": { + "tools/FindUserSecretsProperty.targets": "FindUserSecretsProperty.targets" + } + } }, "dependencies": { + "Microsoft.DotNet.Cli.Utils": "1.0.0-*", "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", "Microsoft.Extensions.Configuration.UserSecrets": "1.1.0-*", "Microsoft.Extensions.Logging": "1.1.0-*", "Microsoft.NETCore.App": { "version": "1.1.0-*", "type": "platform" - }, - "Newtonsoft.Json": "9.0.1", - "System.Runtime.Serialization.Primitives": "4.3.0-*" + } }, "frameworks": { "netcoreapp1.0": {} diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/MsBuildProjectFinderTest.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/MsBuildProjectFinderTest.cs new file mode 100644 index 0000000000..fad1808677 --- /dev/null +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/MsBuildProjectFinderTest.cs @@ -0,0 +1,86 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.Extensions.SecretManager.Tools.Internal; +using Xunit; + +namespace Microsoft.Extensions.SecretsManager.Tools.Tests +{ + public class MsBuildProjectFinderTest + { + [Theory] + [InlineData(".csproj")] + [InlineData(".vbproj")] + [InlineData(".fsproj")] + public void FindsSingleProject(string extension) + { + using (var files = new TemporaryFileProvider()) + { + var filename = "TestProject" + extension; + files.Add(filename, ""); + + var finder = new MsBuildProjectFinder(files.Root); + + Assert.Equal(Path.Combine(files.Root, filename), finder.FindMsBuildProject(null)); + } + } + + [Fact] + public void ThrowsWhenNoFile() + { + using (var files = new TemporaryFileProvider()) + { + var finder = new MsBuildProjectFinder(files.Root); + + Assert.Throws(() => finder.FindMsBuildProject(null)); + } + } + + [Fact] + public void DoesNotMatchXproj() + { + using (var files = new TemporaryFileProvider()) + { + var finder = new MsBuildProjectFinder(files.Root); + files.Add("test.xproj", ""); + + Assert.Throws(() => finder.FindMsBuildProject(null)); + } + } + + [Fact] + public void ThrowsWhenMultipleFile() + { + using (var files = new TemporaryFileProvider()) + { + files.Add("Test1.csproj", ""); + files.Add("Test2.csproj", ""); + var finder = new MsBuildProjectFinder(files.Root); + + Assert.Throws(() => finder.FindMsBuildProject(null)); + } + } + + [Fact] + public void ThrowsWhenFileDoesNotExist() + { + using (var files = new TemporaryFileProvider()) + { + var finder = new MsBuildProjectFinder(files.Root); + + Assert.Throws(() => finder.FindMsBuildProject("test.csproj")); + } + } + + [Fact] + public void ThrowsWhenRootDoesNotExist() + { + var files = new TemporaryFileProvider(); + var finder = new MsBuildProjectFinder(files.Root); + files.Dispose(); + Assert.Throws(() => finder.FindMsBuildProject(null)); + } + } +} diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs index 082b53c3dd..9420fc2110 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs @@ -5,68 +5,79 @@ using System; using System.Collections.Generic; using System.IO; using System.Text; +using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.Configuration.UserSecrets; using Microsoft.Extensions.Configuration.UserSecrets.Tests; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.SecretManager.Tools.Internal; using Xunit; using Xunit.Abstractions; namespace Microsoft.Extensions.SecretManager.Tools.Tests { - public class SecretManagerTests : IDisposable + public class SecretManagerTests : IClassFixture { private TestLogger _logger; - private Stack _disposables = new Stack(); + private readonly UserSecretsTestFixture _fixture; - public SecretManagerTests(ITestOutputHelper output) + public SecretManagerTests(UserSecretsTestFixture fixture, ITestOutputHelper output) { + _fixture = fixture; _logger = new TestLogger(output); + } - private string GetTempSecretProject() + private Program CreateProgram() { - string id; - return GetTempSecretProject(out id); - } - - private string GetTempSecretProject(out string userSecretsId) - { - var projectPath = UserSecretHelper.GetTempSecretProject(out userSecretsId); - _disposables.Push(() => UserSecretHelper.DeleteTempSecretProject(projectPath)); - return projectPath; - } - public void Dispose() - { - while (_disposables.Count > 0) + return new Program(new TestConsole(), Directory.GetCurrentDirectory()) { - _disposables.Pop().Invoke(); - } + Logger = _logger + }; + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void Error_MissingId(string id) + { + var project = Path.Combine(_fixture.CreateProject(id), "TestProject.csproj"); + var secretManager = CreateProgram(); + + var ex = Assert.Throws(() => secretManager.RunInternal("list", "-p", project)); + Assert.Equal(Resources.FormatError_ProjectMissingId(project), ex.Message); + } + + [Fact] + public void Error_InvalidProjectFormat() + { + var project = Path.Combine(_fixture.CreateProject("<"), "TestProject.csproj"); + var secretManager = CreateProgram(); + + var ex = Assert.Throws(() => secretManager.RunInternal("list", "-p", project)); + Assert.Equal(Resources.FormatError_ProjectFailedToLoad(project), ex.Message); } [Fact] public void Error_Project_DoesNotExist() { - var projectPath = Path.Combine(GetTempSecretProject(), "does_not_exist", "project.json"); - var secretManager = new Program(new TestConsole(), Directory.GetCurrentDirectory()) { Logger = _logger }; + var projectPath = Path.Combine(_fixture.GetTempSecretProject(), "does_not_exist", "TestProject.csproj"); + var secretManager = CreateProgram(); var ex = Assert.Throws(() => secretManager.RunInternal("list", "--project", projectPath)); - Assert.Equal(Resources.FormatError_ProjectPath_NotFound(projectPath), ex.Message); } [Fact] public void SupportsRelativePaths() { - var projectPath = GetTempSecretProject(); + var projectPath = _fixture.GetTempSecretProject(); var cwd = Path.Combine(projectPath, "nested1"); Directory.CreateDirectory(cwd); var secretManager = new Program(new TestConsole(), cwd) { Logger = _logger, CommandOutputProvider = _logger.CommandOutputProvider }; secretManager.CommandOutputProvider.LogLevel = LogLevel.Debug; - secretManager.RunInternal("list", "-p", "../", "--verbose"); + secretManager.RunInternal("list", "-p", ".." + Path.DirectorySeparatorChar, "--verbose"); - Assert.Contains(Resources.FormatMessage_Project_File_Path(Path.Combine(projectPath, "project.json")), _logger.Messages); + Assert.Contains(Resources.FormatMessage_Project_File_Path(Path.Combine(cwd, "..", "TestProject.csproj")), _logger.Messages); } [Theory] @@ -82,7 +93,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests new KeyValuePair("key2", string.Empty) }; - var projectPath = GetTempSecretProject(); + var projectPath = _fixture.GetTempSecretProject(); var dir = fromCurrentDirectory ? projectPath : Path.GetTempPath(); @@ -141,8 +152,8 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests [Fact] public void SetSecret_Update_Existing_Secret() { - var projectPath = GetTempSecretProject(); - var secretManager = new Program() { Logger = _logger }; + var projectPath = _fixture.GetTempSecretProject(); + var secretManager = CreateProgram(); secretManager.RunInternal("set", "secret1", "value1", "-p", projectPath); Assert.Equal(1, _logger.Messages.Count); @@ -161,31 +172,31 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests [Fact] public void SetSecret_With_Verbose_Flag() { - string id; - var projectPath = GetTempSecretProject(out id); + string secretId; + var projectPath = _fixture.GetTempSecretProject(out secretId); _logger.SetLevel(LogLevel.Debug); - var secretManager = new Program() { Logger = _logger }; + var secretManager = CreateProgram(); secretManager.RunInternal("-v", "set", "secret1", "value1", "-p", projectPath); Assert.Equal(3, _logger.Messages.Count); - Assert.Contains(string.Format("Project file path {0}.", Path.Combine(projectPath, "project.json")), _logger.Messages); - Assert.Contains(string.Format("Secrets file path {0}.", PathHelper.GetSecretsPathFromSecretsId(id)), _logger.Messages); + Assert.Contains(string.Format("Project file path {0}.", Path.Combine(projectPath, "TestProject.csproj")), _logger.Messages); + Assert.Contains(string.Format("Secrets file path {0}.", PathHelper.GetSecretsPathFromSecretsId(secretId)), _logger.Messages); Assert.Contains("Successfully saved secret1 = value1 to the secret store.", _logger.Messages); _logger.Messages.Clear(); secretManager.RunInternal("-v", "list", "-p", projectPath); Assert.Equal(3, _logger.Messages.Count); - Assert.Contains(string.Format("Project file path {0}.", Path.Combine(projectPath, "project.json")), _logger.Messages); - Assert.Contains(string.Format("Secrets file path {0}.", PathHelper.GetSecretsPathFromSecretsId(id)), _logger.Messages); + Assert.Contains(string.Format("Project file path {0}.", Path.Combine(projectPath, "TestProject.csproj")), _logger.Messages); + Assert.Contains(string.Format("Secrets file path {0}.", PathHelper.GetSecretsPathFromSecretsId(secretId)), _logger.Messages); Assert.Contains("secret1 = value1", _logger.Messages); } [Fact] public void Remove_Non_Existing_Secret() { - var projectPath = GetTempSecretProject(); - var secretManager = new Program() { Logger = _logger }; + var projectPath = _fixture.GetTempSecretProject(); + var secretManager = CreateProgram(); secretManager.RunInternal("remove", "secret1", "-p", projectPath); Assert.Equal(1, _logger.Messages.Count); Assert.Contains("Cannot find 'secret1' in the secret store.", _logger.Messages); @@ -194,8 +205,8 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests [Fact] public void Remove_Is_Case_Insensitive() { - var projectPath = GetTempSecretProject(); - var secretManager = new Program() { Logger = _logger }; + var projectPath = _fixture.GetTempSecretProject(); + var secretManager = CreateProgram(); secretManager.RunInternal("set", "SeCreT1", "value", "-p", projectPath); secretManager.RunInternal("list", "-p", projectPath); Assert.Contains("SeCreT1 = value", _logger.Messages); @@ -211,12 +222,12 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests [Fact] public void List_Flattens_Nested_Objects() { - string id; - var projectPath = GetTempSecretProject(out id); - var secretsFile = PathHelper.GetSecretsPathFromSecretsId(id); + string secretId; + var projectPath = _fixture.GetTempSecretProject(out secretId); + var secretsFile = PathHelper.GetSecretsPathFromSecretsId(secretId); Directory.CreateDirectory(Path.GetDirectoryName(secretsFile)); File.WriteAllText(secretsFile, @"{ ""AzureAd"": { ""ClientSecret"": ""abcd郩˙î""} }", Encoding.UTF8); - var secretManager = new Program() { Logger = _logger }; + var secretManager = CreateProgram(); secretManager.RunInternal("list", "-p", projectPath); Assert.Equal(1, _logger.Messages.Count); Assert.Contains("AzureAd:ClientSecret = abcd郩˙î", _logger.Messages); @@ -231,7 +242,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests Out = new StringWriter(output) }; string id; - var projectPath = GetTempSecretProject(out id); + var projectPath = _fixture.GetTempSecretProject(out id); var secretsFile = PathHelper.GetSecretsPathFromSecretsId(id); Directory.CreateDirectory(Path.GetDirectoryName(secretsFile)); File.WriteAllText(secretsFile, @"{ ""AzureAd"": { ""ClientSecret"": ""abcd郩˙î""} }", Encoding.UTF8); @@ -246,12 +257,12 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests [Fact] public void Set_Flattens_Nested_Objects() { - string id; - var projectPath = GetTempSecretProject(out id); - var secretsFile = PathHelper.GetSecretsPathFromSecretsId(id); + string secretId; + var projectPath = _fixture.GetTempSecretProject(out secretId); + var secretsFile = PathHelper.GetSecretsPathFromSecretsId(secretId); Directory.CreateDirectory(Path.GetDirectoryName(secretsFile)); File.WriteAllText(secretsFile, @"{ ""AzureAd"": { ""ClientSecret"": ""abcd郩˙î""} }", Encoding.UTF8); - var secretManager = new Program() { Logger = _logger }; + var secretManager = CreateProgram(); secretManager.RunInternal("set", "AzureAd:ClientSecret", "¡™£¢∞", "-p", projectPath); Assert.Equal(1, _logger.Messages.Count); secretManager.RunInternal("list", "-p", projectPath); @@ -268,8 +279,8 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests [Fact] public void List_Empty_Secrets_File() { - var projectPath = GetTempSecretProject(); - var secretManager = new Program() { Logger = _logger }; + var projectPath = _fixture.GetTempSecretProject(); + var secretManager = CreateProgram(); secretManager.RunInternal("list", "-p", projectPath); Assert.Equal(1, _logger.Messages.Count); Assert.Contains(Resources.Error_No_Secrets_Found, _logger.Messages); @@ -280,7 +291,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests [InlineData(false)] public void Clear_Secrets(bool fromCurrentDirectory) { - var projectPath = GetTempSecretProject(); + var projectPath = _fixture.GetTempSecretProject(); var dir = fromCurrentDirectory ? projectPath diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs index 7fdd43b009..b704a87c36 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs @@ -75,7 +75,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests var secretStore = new TestSecretsStore(); var command = new SetCommand("key", null); - var ex = Assert.Throws( + var ex = Assert.Throws< Microsoft.DotNet.Cli.Utils.GracefulException>( () => command.Execute(new CommandContext(secretStore, NullLogger.Instance, testConsole))); Assert.Equal(Resources.FormatError_MissingArgument("value"), ex.Message); } diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/TemporaryFileProvider.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/TemporaryFileProvider.cs new file mode 100644 index 0000000000..08e4449d0c --- /dev/null +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/TemporaryFileProvider.cs @@ -0,0 +1,29 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Text; + +namespace Microsoft.Extensions.SecretsManager.Tools.Tests +{ + internal class TemporaryFileProvider : IDisposable + { + public TemporaryFileProvider() + { + Root = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "tmpfiles", Guid.NewGuid().ToString())).FullName; + } + + public string Root { get; } + + public void Add(string filename, string contents) + { + File.WriteAllText(Path.Combine(Root, filename), contents, Encoding.UTF8); + } + + public void Dispose() + { + Directory.Delete(Root, recursive: true); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretHelper.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretHelper.cs deleted file mode 100644 index 00932db0f3..0000000000 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretHelper.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using Newtonsoft.Json; - -namespace Microsoft.Extensions.Configuration.UserSecrets.Tests -{ - public class UserSecretHelper - { - internal static string GetTempSecretProject() - { - string userSecretsId; - return GetTempSecretProject(out userSecretsId); - } - - internal static string GetTempSecretProject(out string userSecretsId) - { - var projectPath = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "usersecretstest", Guid.NewGuid().ToString())); - userSecretsId = Guid.NewGuid().ToString(); - File.WriteAllText( - Path.Combine(projectPath.FullName, "project.json"), - JsonConvert.SerializeObject(new { userSecretsId })); - return projectPath.FullName; - } - - internal static void SetTempSecretInProject(string projectPath, string userSecretsId) - { - File.WriteAllText( - Path.Combine(projectPath, "project.json"), - JsonConvert.SerializeObject(new { userSecretsId })); - } - - internal static void DeleteTempSecretProject(string projectPath) - { - try - { - Directory.Delete(projectPath, true); - } - catch (Exception) - { - // Ignore failures. - } - } - } -} \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs new file mode 100644 index 0000000000..cf92e9b040 --- /dev/null +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs @@ -0,0 +1,103 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; + +namespace Microsoft.Extensions.Configuration.UserSecrets.Tests +{ + public class UserSecretsTestFixture : IDisposable + { + private Stack _disposables = new Stack(); + + public const string TestSecretsId = "b918174fa80346bbb7f4a386729c0eff"; + + public UserSecretsTestFixture() + { + _disposables.Push(() => TryDelete(Path.GetDirectoryName(PathHelper.GetSecretsPathFromSecretsId(TestSecretsId)))); + } + + public void Dispose() + { + while (_disposables.Count > 0) + { + _disposables.Pop()?.Invoke(); + } + } + + public string GetTempSecretProject() + { + string userSecretsId; + return GetTempSecretProject(out userSecretsId); + } + + private const string ProjectTemplate = @" + + + + Exe + netcoreapp1.0 + {0} + + + + + + + + + + +"; + + public string GetTempSecretProject(out string userSecretsId) + { + userSecretsId = Guid.NewGuid().ToString(); + return CreateProject(userSecretsId); + } + + public string CreateProject(string userSecretsId) + { + var projectPath = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "usersecretstest", Guid.NewGuid().ToString())); + var prop = string.IsNullOrEmpty(userSecretsId) + ? string.Empty + : $"{userSecretsId}"; + + File.WriteAllText( + Path.Combine(projectPath.FullName, "TestProject.csproj"), + string.Format(ProjectTemplate, prop)); + + var id = userSecretsId; + _disposables.Push(() => + { + try + { + // may throw if id is bad + var secretsDir = Path.GetDirectoryName(PathHelper.GetSecretsPathFromSecretsId(id)); + TryDelete(secretsDir); + } + catch { } + }); + _disposables.Push(() => TryDelete(projectPath.FullName)); + + return projectPath.FullName; + } + + private static void TryDelete(string directory) + { + try + { + if (Directory.Exists(directory)) + { + Directory.Delete(directory, true); + } + } + catch (Exception) + { + // Ignore failures. + Console.WriteLine("Failed to delete " + directory); + } + } + } +} \ No newline at end of file From 8fd91043d32c4992f7e8d3a326c317d977240ad3 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 17 Oct 2016 16:50:35 -0700 Subject: [PATCH 0308/1029] Switch korebuild version to feature/msbuild --- build.ps1 | 14 +++++++------- build.sh | 20 ++++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/build.ps1 b/build.ps1 index 8f2f99691a..f780c43a82 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,6 +1,6 @@ $ErrorActionPreference = "Stop" -function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $retries) +function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $retries) { while($true) { @@ -19,7 +19,7 @@ function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $ret Start-Sleep -Seconds 10 } - else + else { $exception = $_.Exception throw $exception @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP @@ -43,18 +43,18 @@ $buildFolder = ".build" $buildFile="$buildFolder\KoreBuild.ps1" if (!(Test-Path $buildFolder)) { - Write-Host "Downloading KoreBuild from $koreBuildZip" - + Write-Host "Downloading KoreBuild from $koreBuildZip" + $tempFolder=$env:TEMP + "\KoreBuild-" + [guid]::NewGuid() New-Item -Path "$tempFolder" -Type directory | Out-Null $localZipFile="$tempFolder\korebuild.zip" - + DownloadWithRetry -url $koreBuildZip -downloadLocation $localZipFile -retries 6 Add-Type -AssemblyName System.IO.Compression.FileSystem [System.IO.Compression.ZipFile]::ExtractToDirectory($localZipFile, $tempFolder) - + New-Item -Path "$buildFolder" -Type directory | Out-Null copy-item "$tempFolder\**\build\*" $buildFolder -Recurse diff --git a/build.sh b/build.sh index f4208100eb..0a1463b9e4 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi @@ -12,12 +12,12 @@ buildFile="$buildFolder/KoreBuild.sh" if test ! -d $buildFolder; then echo "Downloading KoreBuild from $koreBuildZip" - - tempFolder="/tmp/KoreBuild-$(uuidgen)" + + tempFolder="/tmp/KoreBuild-$(uuidgen)" mkdir $tempFolder - + localZipFile="$tempFolder/korebuild.zip" - + retries=6 until (wget -O $localZipFile $koreBuildZip 2>/dev/null || curl -o $localZipFile --location $koreBuildZip 2>/dev/null) do @@ -29,17 +29,17 @@ if test ! -d $buildFolder; then echo "Waiting 10 seconds before retrying. Retries left: $retries" sleep 10s done - + unzip -q -d $tempFolder $localZipFile - + mkdir $buildFolder cp -r $tempFolder/**/build/** $buildFolder - + chmod +x $buildFile - + # Cleanup if test ! -d $tempFolder; then - rm -rf $tempFolder + rm -rf $tempFolder fi fi From 46989858463c7ceb38be58dd8f3b3ae6e57f4f3b Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 28 Oct 2016 18:56:03 -0700 Subject: [PATCH 0309/1029] Port dotnet-watch to support MSBuild --- NuGet.config | 2 + .../CommandLineOptions.cs | 4 + .../Internal/FileSetWatcher.cs | 5 +- .../Internal/FileWatcher.cs | 2 +- .../FileWatcher/PollingFileWatcher.cs | 5 + .../Internal/IFileWatcher.cs | 14 - .../Internal/IncludeContextExtensions.cs | 21 -- .../Internal/MsBuildFileSetFactory.cs | 164 +++++++++ .../Internal/MsBuildProjectFinder.cs | 57 ++++ .../Internal/OutputSink.cs | 27 ++ .../Internal/Project.cs | 74 ---- .../Internal/ProjectJsonFileSet.cs | 95 ------ .../Internal/ProjectJsonFileSetFactory.cs | 51 --- .../Internal/ProjectReaderUtils.cs | 88 ----- .../Microsoft.DotNet.Watcher.Tools.nuspec | 3 +- src/Microsoft.DotNet.Watcher.Tools/Program.cs | 15 +- .../Properties/Resources.Designer.cs | 48 +++ src/Microsoft.DotNet.Watcher.Tools/README.md | 58 ++++ .../Resources.resx | 63 ++-- .../dotnetwatch.targets | 18 + .../project.json | 18 +- .../tools/DotNetWatchCommon.targets | 28 ++ .../tools/DotNetWatchInner.targets | 70 ++++ .../tools/DotNetWatchOuter.targets | 69 ++++ .../AppWithDepsTests.cs | 29 +- .../GlobbingAppTests.cs | 37 +- .../NoDepsAppTests.cs | 28 +- .../Scenario/DotNetWatchScenario.cs | 15 +- .../Scenario/ProjectToolScenario.cs | 64 ++-- .../AppWithDeps/AppWithDeps.csproj | 16 + .../TestProjects/AppWithDeps/project.json | 20 -- .../TestProjects/Dependency/Dependency.csproj | 15 + .../TestProjects/Dependency/project.json | 8 - .../GlobbingApp/GlobbingApp.csproj | 15 + .../TestProjects/GlobbingApp/project.json | 24 -- .../TestProjects/NoDepsApp/NoDepsApp.csproj | 15 + .../TestProjects/NoDepsApp/project.json | 15 - .../clean-assets.cmd | 7 +- .../clean-assets.sh | 6 + .../AssertEx.cs | 27 ++ .../MsBuildFileSetFactoryTest.cs | 315 ++++++++++++++++++ .../Utilities/TemporaryCSharpProject.cs | 106 ++++++ .../Utilities/TemporaryDirectory.cs | 107 ++++++ .../Utilities/TestProjectGraph.cs | 41 +++ .../Utilities/XunitLogger.cs | 35 ++ .../copyfiles.cmd | 9 + .../copyfiles.sh | 12 + .../project.json | 6 +- 48 files changed, 1463 insertions(+), 508 deletions(-) delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/Internal/IFileWatcher.cs delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/Internal/IncludeContextExtensions.cs create mode 100644 src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs create mode 100644 src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildProjectFinder.cs create mode 100644 src/Microsoft.DotNet.Watcher.Tools/Internal/OutputSink.cs delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/Internal/Project.cs delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectJsonFileSet.cs delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectJsonFileSetFactory.cs delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectReaderUtils.cs create mode 100644 src/Microsoft.DotNet.Watcher.Tools/dotnetwatch.targets create mode 100644 src/Microsoft.DotNet.Watcher.Tools/tools/DotNetWatchCommon.targets create mode 100644 src/Microsoft.DotNet.Watcher.Tools/tools/DotNetWatchInner.targets create mode 100644 src/Microsoft.DotNet.Watcher.Tools/tools/DotNetWatchOuter.targets create mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/project.json create mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/project.json create mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/project.json create mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/project.json create mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs create mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs create mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryCSharpProject.cs create mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryDirectory.cs create mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TestProjectGraph.cs create mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/XunitLogger.cs create mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.cmd create mode 100755 test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.sh diff --git a/NuGet.config b/NuGet.config index 0fd623ffdd..3957d769d2 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,6 +1,8 @@  + + diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs index dfd27756bd..08c9b473f5 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs @@ -12,6 +12,7 @@ namespace Microsoft.DotNet.Watcher { internal class CommandLineOptions { + public string Project { get; private set; } public bool IsHelp { get; private set; } public bool IsQuiet { get; private set; } public bool IsVerbose { get; private set; } @@ -30,6 +31,8 @@ namespace Microsoft.DotNet.Watcher }; app.HelpOption("-?|-h|--help"); + var optProjects = app.Option("-p|--project", "The project to watch", + CommandOptionType.SingleValue); // TODO multiple shouldn't be too hard to support var optQuiet = app.Option("-q|--quiet", "Suppresses all output except warnings and errors", CommandOptionType.NoValue); var optVerbose = app.Option("-v|--verbose", "Show verbose output", @@ -58,6 +61,7 @@ namespace Microsoft.DotNet.Watcher return new CommandLineOptions { + Project = optProjects.Value(), IsQuiet = optQuiet.HasValue(), IsVerbose = optVerbose.HasValue(), RemainingArguments = app.RemainingArguments, diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSetWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSetWatcher.cs index a1f56d9650..b97b547a52 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSetWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSetWatcher.cs @@ -10,13 +10,14 @@ namespace Microsoft.DotNet.Watcher.Internal { public class FileSetWatcher : IDisposable { - private readonly IFileWatcher _fileWatcher; + private readonly FileWatcher _fileWatcher = new FileWatcher(); private readonly IFileSet _fileSet; public FileSetWatcher(IFileSet fileSet) { + Ensure.NotNull(fileSet, nameof(fileSet)); + _fileSet = fileSet; - _fileWatcher = new FileWatcher(); } public async Task GetChangedFileAsync(CancellationToken cancellationToken) diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher.cs index 79036c28de..20840f40b9 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher.cs @@ -8,7 +8,7 @@ using System.Linq; namespace Microsoft.DotNet.Watcher.Internal { - public class FileWatcher : IFileWatcher + public class FileWatcher { private bool _disposed; diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs index 9ca5084347..d26dcc54f2 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs @@ -182,6 +182,11 @@ namespace Microsoft.DotNet.Watcher.Internal private void ForeachEntityInDirectory(DirectoryInfo dirInfo, Action fileAction) { + if (!dirInfo.Exists) + { + return; + } + var entities = dirInfo.EnumerateFileSystemInfos("*.*"); foreach (var entity in entities) { diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/IFileWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/IFileWatcher.cs deleted file mode 100644 index 1e43363789..0000000000 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/IFileWatcher.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; - -namespace Microsoft.DotNet.Watcher.Internal -{ - public interface IFileWatcher : IDisposable - { - event Action OnFileChange; - - void WatchDirectory(string directory); - } -} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/IncludeContextExtensions.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/IncludeContextExtensions.cs deleted file mode 100644 index bd7cf0b8ad..0000000000 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/IncludeContextExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using System.Linq; -using Microsoft.DotNet.ProjectModel.Files; - -namespace Microsoft.DotNet.Watcher.Internal -{ - internal static class IncludeContextExtensions - { - public static IEnumerable ResolveFiles(this IncludeContext context) - { - Ensure.NotNull(context, nameof(context)); - - return IncludeFilesResolver - .GetIncludeFiles(context, "/", diagnostics: null) - .Select(f => f.SourcePath); - } - } -} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs new file mode 100644 index 0000000000..f40a43732a --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs @@ -0,0 +1,164 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.Watcher.Tools; +using Microsoft.Extensions.Logging; + +namespace Microsoft.DotNet.Watcher.Internal +{ + public class MsBuildFileSetFactory : IFileSetFactory + { + private const string ProjectExtensionFileExtension = ".dotnetwatch.targets"; + private const string WatchTargetsFileName = "DotNetWatchCommon.targets"; + private readonly ILogger _logger; + private readonly string _projectFile; + private readonly string _watchTargetsDir; + private readonly OutputSink _outputSink; + + public MsBuildFileSetFactory(ILogger logger, string projectFile) + : this(logger, projectFile, new OutputSink()) + { + } + + // output sink is for testing + internal MsBuildFileSetFactory(ILogger logger, string projectFile, OutputSink outputSink) + { + Ensure.NotNull(logger, nameof(logger)); + Ensure.NotNullOrEmpty(projectFile, nameof(projectFile)); + Ensure.NotNull(outputSink, nameof(outputSink)); + + _logger = logger; + _projectFile = projectFile; + _watchTargetsDir = FindWatchTargetsDir(); + _outputSink = outputSink; + } + + internal List BuildFlags { get; } = new List + { + "/nologo", + "/v:n", + "/t:GenerateWatchList", + "/p:DotNetWatchBuild=true", // extensibility point for users + "/p:DesignTimeBuild=true", // don't do expensive things + }; + + public async Task CreateAsync(CancellationToken cancellationToken) + { + EnsureInitialized(); + + var watchList = Path.GetTempFileName(); + try + { + var projectDir = Path.GetDirectoryName(_projectFile); + + while (true) + { + cancellationToken.ThrowIfCancellationRequested(); + +#if DEBUG + var stopwatch = new Stopwatch(); + stopwatch.Start(); +#endif + var capture = _outputSink.StartCapture(); + // TODO adding files doesn't currently work. Need to provide a way to detect new files + // find files + var exitCode = Command.CreateDotNet("msbuild", + new[] + { + _projectFile, + $"/p:_DotNetWatchTargetsLocation={_watchTargetsDir}", // add our dotnet-watch targets + $"/p:_DotNetWatchListFile={watchList}", + }.Concat(BuildFlags)) + .CaptureStdErr() + .CaptureStdOut() + .OnErrorLine(l => capture.WriteErrorLine(l)) + .OnOutputLine(l => capture.WriteOutputLine(l)) + .WorkingDirectory(projectDir) + .Execute() + .ExitCode; + + if (exitCode == 0) + { + var files = File.ReadAllLines(watchList) + .Select(l => l?.Trim()) + .Where(l => !string.IsNullOrEmpty(l)); + + var fileset = new FileSet(files); + +#if DEBUG + _logger.LogDebug(string.Join(Environment.NewLine, fileset)); + Debug.Assert(files.All(Path.IsPathRooted), "All files should be rooted paths"); + stopwatch.Stop(); + _logger.LogDebug("Gathered project information in {time}ms", stopwatch.ElapsedMilliseconds); +#endif + + return fileset; + } + + _logger.LogError($"Error(s) finding watch items project file '{Path.GetFileName(_projectFile)}': "); + _logger.LogError(capture.GetAllLines("[MSBUILD] : ")); + _logger.LogInformation("Fix the error to continue."); + + var fileSet = new FileSet(new[] { _projectFile }); + + using (var watcher = new FileSetWatcher(fileSet)) + { + await watcher.GetChangedFileAsync(cancellationToken); + + _logger.LogInformation($"File changed: {_projectFile}"); + } + } + } + finally + { + File.Delete(watchList); + } + } + + // Ensures file exists in $(MSBuildProjectExtensionsPath)/$(MSBuildProjectFile).dotnetwatch.targets + private void EnsureInitialized() + { + // default value for MSBuildProjectExtensionsPath. + var projectExtensionsPath = Path.Combine(Path.GetDirectoryName(_projectFile), "obj"); + + // see https://github.com/Microsoft/msbuild/blob/bf9b21cc7869b96ea2289ff31f6aaa5e1d525a26/src/XMakeTasks/Microsoft.Common.targets#L127 + var projectExtensionFile = Path.Combine(projectExtensionsPath, Path.GetFileName(_projectFile) + ProjectExtensionFileExtension); + + if (!File.Exists(projectExtensionFile)) + { + // ensure obj folder is available + Directory.CreateDirectory(Path.GetDirectoryName(projectExtensionFile)); + + using (var fileStream = new FileStream(projectExtensionFile, FileMode.Create)) + using (var assemblyStream = GetType().GetTypeInfo().Assembly.GetManifestResourceStream("dotnetwatch.targets")) + { + assemblyStream.CopyTo(fileStream); + } + } + } + + private string FindWatchTargetsDir() + { + var assemblyDir = Path.GetDirectoryName(GetType().GetTypeInfo().Assembly.Location); + var searchPaths = new[] + { + AppContext.BaseDirectory, + assemblyDir, + Path.Combine(assemblyDir, "../../tools"), // from nuget cache + Path.Combine(assemblyDir, "tools") // from local build + }; + + var targetPath = searchPaths.Select(p => Path.Combine(p, WatchTargetsFileName)).First(File.Exists); + return Path.GetDirectoryName(targetPath); + } + } +} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildProjectFinder.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildProjectFinder.cs new file mode 100644 index 0000000000..ff3f45b66b --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildProjectFinder.cs @@ -0,0 +1,57 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Linq; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.Watcher.Tools; + +namespace Microsoft.DotNet.Watcher.Internal +{ + internal class MsBuildProjectFinder + { + /// + /// Finds a compatible MSBuild project. + /// The base directory to search + /// The filename of the project. Can be null. + /// + public static string FindMsBuildProject(string searchBase, string project) + { + Ensure.NotNullOrEmpty(searchBase, nameof(searchBase)); + + var projectPath = project ?? searchBase; + + if (!Path.IsPathRooted(projectPath)) + { + projectPath = Path.Combine(searchBase, projectPath); + } + + if (Directory.Exists(projectPath)) + { + var projects = Directory.EnumerateFileSystemEntries(projectPath, "*.*proj", SearchOption.TopDirectoryOnly) + .Where(f => !".xproj".Equals(Path.GetExtension(f), StringComparison.OrdinalIgnoreCase)) + .ToList(); + + if (projects.Count > 1) + { + throw new GracefulException(Resources.FormatError_MultipleProjectsFound(projectPath)); + } + + if (projects.Count == 0) + { + throw new GracefulException(Resources.FormatError_NoProjectsFound(projectPath)); + } + + return projects[0]; + } + + if (!File.Exists(projectPath)) + { + throw new GracefulException(Resources.FormatError_ProjectPath_NotFound(projectPath)); + } + + return projectPath; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/OutputSink.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/OutputSink.cs new file mode 100644 index 0000000000..aa764437ad --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/OutputSink.cs @@ -0,0 +1,27 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.DotNet.Watcher.Internal +{ + internal class OutputSink + { + public OutputCapture Current { get; private set; } + public OutputCapture StartCapture() + { + return (Current = new OutputCapture()); + } + + public class OutputCapture + { + private readonly List _lines = new List(); + public IEnumerable Lines => _lines; + public void WriteOutputLine(string line) => _lines.Add(line); + public void WriteErrorLine(string line) => _lines.Add(line); + public string GetAllLines(string prefix) => string.Join(Environment.NewLine, _lines.Select(l => prefix + l)); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/Project.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/Project.cs deleted file mode 100644 index 8485cc331b..0000000000 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/Project.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Microsoft.DotNet.ProjectModel.Graph; - -namespace Microsoft.DotNet.Watcher.Internal -{ - public class Project - { - public Project(ProjectModel.Project runtimeProject) - { - ProjectFile = runtimeProject.ProjectFilePath; - ProjectDirectory = runtimeProject.ProjectDirectory; - - var compilerOptions = runtimeProject.GetCompilerOptions(targetFramework: null, configurationName: null); - - var filesToWatch = new List() { runtimeProject.ProjectFilePath }; - if (compilerOptions?.CompileInclude != null) - { - filesToWatch.AddRange(compilerOptions.CompileInclude.ResolveFiles()); - } - else - { - filesToWatch.AddRange(runtimeProject.Files.SourceFiles); - } - - if (compilerOptions?.EmbedInclude != null) - { - filesToWatch.AddRange(compilerOptions.EmbedInclude.ResolveFiles()); - } - else - { - // For resource files the key is the name of the file, not the value - filesToWatch.AddRange(runtimeProject.Files.ResourceFiles.Keys); - } - - filesToWatch.AddRange(runtimeProject.Files.SharedFiles); - filesToWatch.AddRange(runtimeProject.Files.PreprocessSourceFiles); - - Files = filesToWatch; - - var projectLockJsonPath = Path.Combine(runtimeProject.ProjectDirectory, "project.lock.json"); - - if (File.Exists(projectLockJsonPath)) - { - var lockFile = LockFileReader.Read(projectLockJsonPath, designTime: false); - ProjectDependencies = lockFile.ProjectLibraries - .Where(dep => !string.IsNullOrEmpty(dep.Path)) // The dependency path is null for xproj -> csproj reference - .Select(dep => GetProjectRelativeFullPath(dep.Path)) - .ToList(); - } - else - { - ProjectDependencies = new string[0]; - } - } - - public IEnumerable ProjectDependencies { get; private set; } - - public IEnumerable Files { get; private set; } - - public string ProjectFile { get; private set; } - - public string ProjectDirectory { get; private set; } - - private string GetProjectRelativeFullPath(string path) - { - return Path.GetFullPath(Path.Combine(ProjectDirectory, path)); - } - } -} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectJsonFileSet.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectJsonFileSet.cs deleted file mode 100644 index c9d67daf5c..0000000000 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectJsonFileSet.cs +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections; -using System.Collections.Generic; - -namespace Microsoft.DotNet.Watcher.Internal -{ - public class ProjectJsonFileSet : IFileSet - { - private readonly string _projectFile; - private ISet _currentFiles; - - public ProjectJsonFileSet(string projectFile) - { - _projectFile = projectFile; - } - - public bool Contains(string filePath) - { - // if it was in the original list of files we were watching - if (_currentFiles?.Contains(filePath) == true) - { - return true; - } - - // It's possible the new file was not in the old set but will be in the new set. - // Additions should be considered part of this. - RefreshFileList(); - - return _currentFiles.Contains(filePath); - } - - public IEnumerator GetEnumerator() - { - EnsureInitialized(); - return _currentFiles.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - EnsureInitialized(); - return _currentFiles.GetEnumerator(); - } - - private void EnsureInitialized() - { - if (_currentFiles == null) - { - RefreshFileList(); - } - } - - private void RefreshFileList() - { - _currentFiles = new HashSet(FindFiles(), StringComparer.OrdinalIgnoreCase); - } - - private IEnumerable FindFiles() - { - var projects = new HashSet(); // temporary store to prevent re-parsing a project multiple times - return GetProjectFilesClosure(_projectFile, projects); - } - - private IEnumerable GetProjectFilesClosure(string projectFile, ISet projects) - { - if (projects.Contains(projectFile)) - { - yield break; - } - - projects.Add(projectFile); - - Project project; - string errors; - - if (ProjectReader.TryReadProject(projectFile, out project, out errors)) - { - foreach (var file in project.Files) - { - yield return file; - } - - foreach (var dependency in project.ProjectDependencies) - { - foreach (var file in GetProjectFilesClosure(dependency, projects)) - { - yield return file; - } - } - } - } - } -} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectJsonFileSetFactory.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectJsonFileSetFactory.cs deleted file mode 100644 index 419776d4dc..0000000000 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectJsonFileSetFactory.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; - -namespace Microsoft.DotNet.Watcher.Internal -{ - public class ProjectJsonFileSetFactory : IFileSetFactory - { - private readonly ILogger _logger; - private readonly string _projectFile; - public ProjectJsonFileSetFactory(ILogger logger, string projectFile) - { - Ensure.NotNull(logger, nameof(logger)); - Ensure.NotNullOrEmpty(projectFile, nameof(projectFile)); - - _logger = logger; - _projectFile = projectFile; - } - - public async Task CreateAsync(CancellationToken cancellationToken) - { - while (true) - { - cancellationToken.ThrowIfCancellationRequested(); - - Project project; - string errors; - if (ProjectReader.TryReadProject(_projectFile, out project, out errors)) - { - return new ProjectJsonFileSet(_projectFile); - } - - _logger.LogError($"Error(s) reading project file '{_projectFile}': "); - _logger.LogError(errors); - _logger.LogInformation("Fix the error to continue."); - - var fileSet = new FileSet(new[] { _projectFile }); - - using (var watcher = new FileSetWatcher(fileSet)) - { - await watcher.GetChangedFileAsync(cancellationToken); - - _logger.LogInformation($"File changed: {_projectFile}"); - } - } - } - } -} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectReaderUtils.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectReaderUtils.cs deleted file mode 100644 index ffd2e012f4..0000000000 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProjectReaderUtils.cs +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Linq; -using System.Text; - -namespace Microsoft.DotNet.Watcher.Internal -{ - public class ProjectReader - { - public static bool TryReadProject(string projectFile, out Project project, out string errors) - { - errors = null; - project = null; - - ProjectModel.Project runtimeProject; - if (!TryGetProject(projectFile, out runtimeProject, out errors)) - { - return false; - } - - try - { - project = new Project(runtimeProject); - } - catch (Exception ex) - { - errors = CollectMessages(ex); - return false; - } - - return true; - } - - private static bool TryGetProject(string projectFile, out ProjectModel.Project project, out string errorMessage) - { - try - { - if (!ProjectModel.ProjectReader.TryGetProject(projectFile, out project)) - { - if (project?.Diagnostics != null && project.Diagnostics.Any()) - { - errorMessage = string.Join(Environment.NewLine, project.Diagnostics.Select(e => e.ToString())); - } - else - { - errorMessage = "Failed to read project.json"; - } - } - else - { - errorMessage = null; - return true; - } - } - catch (Exception ex) - { - errorMessage = CollectMessages(ex); - } - - project = null; - return false; - } - - private static string CollectMessages(Exception exception) - { - var builder = new StringBuilder(); - builder.AppendLine(exception.Message); - - var aggregateException = exception as AggregateException; - if (aggregateException != null) - { - foreach (var message in aggregateException.Flatten().InnerExceptions.Select(CollectMessages)) - { - builder.AppendLine(message); - } - } - - while (exception.InnerException != null) - { - builder.AppendLine(CollectMessages(exception.InnerException)); - exception = exception.InnerException; - } - return builder.ToString(); - } - } -} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec index 53b80837cd..259eaa5cfb 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec @@ -24,6 +24,7 @@ - + + \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index 14a115c978..06cedfa8cf 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -17,15 +17,18 @@ namespace Microsoft.DotNet.Watcher private readonly CancellationToken _cancellationToken; private readonly TextWriter _stdout; private readonly TextWriter _stderr; + private readonly string _workingDir; - public Program(TextWriter consoleOutput, TextWriter consoleError, CancellationToken cancellationToken) + public Program(TextWriter consoleOutput, TextWriter consoleError, string workingDir, CancellationToken cancellationToken) { Ensure.NotNull(consoleOutput, nameof(consoleOutput)); Ensure.NotNull(consoleError, nameof(consoleError)); + Ensure.NotNullOrEmpty(workingDir, nameof(workingDir)); _cancellationToken = cancellationToken; _stdout = consoleOutput; _stderr = consoleError; + _workingDir = workingDir; } public static int Main(string[] args) @@ -50,7 +53,7 @@ namespace Microsoft.DotNet.Watcher try { - return new Program(Console.Out, Console.Error, ctrlCTokenSource.Token) + return new Program(Console.Out, Console.Error, Directory.GetCurrentDirectory(), ctrlCTokenSource.Token) .MainInternalAsync(args) .GetAwaiter() .GetResult(); @@ -92,8 +95,10 @@ namespace Microsoft.DotNet.Watcher loggerFactory.AddProvider(commandProvider); var logger = loggerFactory.CreateLogger(LoggerName); - var projectFile = Path.Combine(Directory.GetCurrentDirectory(), ProjectModel.Project.FileName); - var projectFileSetFactory = new ProjectJsonFileSetFactory(logger, projectFile); + // TODO multiple projects should be easy enough to add here + var projectFile = MsBuildProjectFinder.FindMsBuildProject(_workingDir, options.Project); + var fileSetFactory = new MsBuildFileSetFactory(logger, projectFile); + var processInfo = new ProcessSpec { Executable = new Muxer().MuxerPath, @@ -102,7 +107,7 @@ namespace Microsoft.DotNet.Watcher }; await new DotNetWatcher(logger) - .WatchAsync(processInfo, projectFileSetFactory, _cancellationToken); + .WatchAsync(processInfo, fileSetFactory, _cancellationToken); return 0; } diff --git a/src/Microsoft.DotNet.Watcher.Tools/Properties/Resources.Designer.cs b/src/Microsoft.DotNet.Watcher.Tools/Properties/Resources.Designer.cs index 5cdf225bb8..30c1d18cb7 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Properties/Resources.Designer.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Properties/Resources.Designer.cs @@ -10,6 +10,54 @@ namespace Microsoft.DotNet.Watcher.Tools private static readonly ResourceManager _resourceManager = new ResourceManager("Microsoft.DotNet.Watcher.Tools.Resources", typeof(Resources).GetTypeInfo().Assembly); + /// + /// The project file '{path}' does not exist. + /// + internal static string Error_ProjectPath_NotFound + { + get { return GetString("Error_ProjectPath_NotFound"); } + } + + /// + /// The project file '{path}' does not exist. + /// + internal static string FormatError_ProjectPath_NotFound(object path) + { + return string.Format(CultureInfo.CurrentCulture, GetString("Error_ProjectPath_NotFound", "path"), path); + } + + /// + /// Multiple MSBuild project files found in '{projectPath}'. Specify which to use with the --project option. + /// + internal static string Error_MultipleProjectsFound + { + get { return GetString("Error_MultipleProjectsFound"); } + } + + /// + /// Multiple MSBuild project files found in '{projectPath}'. Specify which to use with the --project option. + /// + internal static string FormatError_MultipleProjectsFound(object projectPath) + { + return string.Format(CultureInfo.CurrentCulture, GetString("Error_MultipleProjectsFound", "projectPath"), projectPath); + } + + /// + /// Could not find a MSBuild project file in '{projectPath}'. Specify which project to use with the --project option. + /// + internal static string Error_NoProjectsFound + { + get { return GetString("Error_NoProjectsFound"); } + } + + /// + /// Could not find a MSBuild project file in '{projectPath}'. Specify which project to use with the --project option. + /// + internal static string FormatError_NoProjectsFound(object projectPath) + { + return string.Format(CultureInfo.CurrentCulture, GetString("Error_NoProjectsFound", "projectPath"), projectPath); + } + /// /// Cannot specify both '--quiet' and '--verbose' options. /// diff --git a/src/Microsoft.DotNet.Watcher.Tools/README.md b/src/Microsoft.DotNet.Watcher.Tools/README.md index 7a21544e70..ec769af3e6 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/README.md +++ b/src/Microsoft.DotNet.Watcher.Tools/README.md @@ -45,3 +45,61 @@ Some configuration options can be passed to `dotnet watch` through environment v | Variable | Effect | | ---------------------------------------------- | -------------------------------------------------------- | | DOTNET_USE_POLLING_FILE_WATCHER | If set to "1" or "true", `dotnet watch` will use a polling file watcher instead of CoreFx's `FileSystemWatcher`. Used when watching files on network shares or Docker mounted volumes. | + +### MSBuild + +dotnet-watch can be configured from the MSBuild project file being watched. + +**Project References** + +By default, dotnet-watch will scan the entire graph of project references and watch all files within those projects. + +dotnet-watch will ignore project references with the `Watch="false"` attribute. + +```xml + + + +``` + +**Watch items** + +dotnet-watch will watch all items in the "Watch" item group. +By default, this group inclues all items in "Compile" and "EmbeddedResource". + +More items can be added to watch in a project file by adding items to 'Watch'. + +Example: + +```xml + + + + +``` + +dotnet-watch will ignore Compile and EmbeddedResource items with the `Watch="false"` attribute. + +Example: + +```xml + + + + + +``` + + +**Advanced configuration** + +dotnet-watch performs a design-time build to find items to watch. +When this build is run, dotnet-watch will set the property `DotNetWatchBuild=true`. + +Example: + +```xml + + + +``` \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Resources.resx b/src/Microsoft.DotNet.Watcher.Tools/Resources.resx index 34336a97ba..125a4cfea3 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Resources.resx +++ b/src/Microsoft.DotNet.Watcher.Tools/Resources.resx @@ -1,17 +1,17 @@  - @@ -117,6 +117,15 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + The project file '{path}' does not exist. + + + Multiple MSBuild project files found in '{projectPath}'. Specify which to use with the --project option. + + + Could not find a MSBuild project file in '{projectPath}'. Specify which project to use with the --project option. + Cannot specify both '--quiet' and '--verbose' options. diff --git a/src/Microsoft.DotNet.Watcher.Tools/dotnetwatch.targets b/src/Microsoft.DotNet.Watcher.Tools/dotnetwatch.targets new file mode 100644 index 0000000000..d3e73557be --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/dotnetwatch.targets @@ -0,0 +1,18 @@ + + + + <_DotNetWatchTargetsFile Condition="'$(_DotNetWatchTargetsFile)' == ''">$(MSBuildThisFileFullPath) + + + + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index e54d7b3774..21d7ce1d69 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -5,15 +5,29 @@ "tags": [ "dotnet", "watch" - ] + ], + "files": { + "include": "tools/*.targets" + } }, "buildOptions": { "outputName": "dotnet-watch", "warningsAsErrors": true, "emitEntryPoint": true, - "keyFile": "../../tools/Key.snk" + "debugType": "portable", + "keyFile": "../../tools/Key.snk", + "copyToOutput": "tools/*.targets", + "embed": { + "mappings": { + "dotnetwatch.targets": "dotnetwatch.targets" + } + } }, "dependencies": { + "Microsoft.DotNet.ProjectModel": { + "version": "1.0.0-*", + "exclude": "all" + }, "Microsoft.DotNet.Cli.Utils": "1.0.0-*", "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", "Microsoft.Extensions.Logging": "1.1.0-*", diff --git a/src/Microsoft.DotNet.Watcher.Tools/tools/DotNetWatchCommon.targets b/src/Microsoft.DotNet.Watcher.Tools/tools/DotNetWatchCommon.targets new file mode 100644 index 0000000000..c3477393fc --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/tools/DotNetWatchCommon.targets @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/tools/DotNetWatchInner.targets b/src/Microsoft.DotNet.Watcher.Tools/tools/DotNetWatchInner.targets new file mode 100644 index 0000000000..9bdd83dd6d --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/tools/DotNetWatchInner.targets @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + <_DotNetWatchProjects Include="@(ProjectReference->'%(FullPath)')" Condition="'%(ProjectReference.Watch)' != 'false'" /> + <_DotNetWatchImportsTargets Include="@(_DotNetWatchProjects->'%(RelativeDir)obj\%(FileName)%(Extension).dotnetwatch.targets')"> + $(_DotNetWatchTargetsFile) + + + + + + + + + + + <_DotNetWatchProjects Include="$(MSBuildProjectFullPath)"/> + + + \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/tools/DotNetWatchOuter.targets b/src/Microsoft.DotNet.Watcher.Tools/tools/DotNetWatchOuter.targets new file mode 100644 index 0000000000..f2dfb9e104 --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/tools/DotNetWatchOuter.targets @@ -0,0 +1,69 @@ + + + + + + + + + <_TargetFramework Include="$(TargetFrameworks)" /> + + + + + + + + + + <_TargetFramework Include="$(TargetFrameworks)" /> + + + + + + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs index d36674a223..6428f7f6fe 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs @@ -4,6 +4,7 @@ using System; using System.IO; using Xunit; +using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { @@ -11,11 +12,18 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30); + private readonly ITestOutputHelper _logger; + + public AppWithDepsTests(ITestOutputHelper logger) + { + _logger = logger; + } + // Change a file included in compilation [Fact] public void ChangeFileInDependency() { - using (var scenario = new AppWithDepsScenario()) + using (var scenario = new AppWithDepsScenario(_logger)) { scenario.Start(); using (var wait = new WaitForFileToChange(scenario.StartedFile)) @@ -36,18 +44,19 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests private const string AppWithDeps = "AppWithDeps"; private const string Dependency = "Dependency"; - public AppWithDepsScenario() + public AppWithDepsScenario(ITestOutputHelper logger) + : base(logger) { - StatusFile = Path.Combine(_scenario.TempFolder, "status"); + StatusFile = Path.Combine(Scenario.TempFolder, "status"); StartedFile = StatusFile + ".started"; - - _scenario.AddTestProjectFolder(AppWithDeps); - _scenario.AddTestProjectFolder(Dependency); - _scenario.Restore(); + Scenario.AddTestProjectFolder(AppWithDeps); + Scenario.AddTestProjectFolder(Dependency); - AppWithDepsFolder = Path.Combine(_scenario.WorkFolder, AppWithDeps); - DependencyFolder = Path.Combine(_scenario.WorkFolder, Dependency); + Scenario.Restore3(AppWithDeps); // restore3 should be transitive + + AppWithDepsFolder = Path.Combine(Scenario.WorkFolder, AppWithDeps); + DependencyFolder = Path.Combine(Scenario.WorkFolder, Dependency); } public void Start() @@ -55,7 +64,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // Wait for the process to start using (var wait = new WaitForFileToChange(StatusFile)) { - RunDotNetWatch(new[] { "run", StatusFile }, Path.Combine(_scenario.WorkFolder, AppWithDeps)); + RunDotNetWatch(new[] { "run3", StatusFile }, Path.Combine(Scenario.WorkFolder, AppWithDeps)); wait.Wait(_defaultTimeout, expectedToChange: true, diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs index 87ae1b6df3..31b0cb9167 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.IO; using System.Threading; using Xunit; +using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { @@ -15,6 +16,13 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests private static readonly TimeSpan _negativeTestWaitTime = TimeSpan.FromSeconds(10); + private readonly ITestOutputHelper _logger; + + public GlobbingAppTests(ITestOutputHelper logger) + { + _logger = logger; + } + [Fact] public void ChangeCompiledFile_PollingWatcher() { @@ -30,7 +38,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // Change a file included in compilation private void ChangeCompiledFile(bool usePollingWatcher) { - using (var scenario = new GlobbingAppScenario()) + using (var scenario = new GlobbingAppScenario(_logger)) using (var wait = new WaitForFileToChange(scenario.StartedFile)) { scenario.UsePollingWatcher = usePollingWatcher; @@ -53,7 +61,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public void AddCompiledFile() { // Add a file in a folder that's included in compilation - using (var scenario = new GlobbingAppScenario()) + using (var scenario = new GlobbingAppScenario(_logger)) using (var wait = new WaitForFileToChange(scenario.StartedFile)) { scenario.Start(); @@ -71,7 +79,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [Fact] public void DeleteCompiledFile() { - using (var scenario = new GlobbingAppScenario()) + using (var scenario = new GlobbingAppScenario(_logger)) using (var wait = new WaitForFileToChange(scenario.StartedFile)) { scenario.Start(); @@ -86,10 +94,10 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } // Delete an entire folder - [Fact(Skip = "Blocking build")] + [Fact] public void DeleteSourceFolder() { - using (var scenario = new GlobbingAppScenario()) + using (var scenario = new GlobbingAppScenario(_logger)) using (var wait = new WaitForFileToChange(scenario.StartedFile)) { scenario.Start(); @@ -107,7 +115,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [Fact] public void RenameCompiledFile() { - using (var scenario = new GlobbingAppScenario()) + using (var scenario = new GlobbingAppScenario(_logger)) using (var wait = new WaitForFileToChange(scenario.StatusFile)) { scenario.Start(); @@ -137,7 +145,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // Add a file that's in a included folder but not matching the globbing pattern private void ChangeNonCompiledFile(bool usePollingWatcher) { - using (var scenario = new GlobbingAppScenario()) + using (var scenario = new GlobbingAppScenario(_logger)) { scenario.UsePollingWatcher = usePollingWatcher; @@ -162,7 +170,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [Fact] public void ChangeExcludedFile() { - using (var scenario = new GlobbingAppScenario()) + using (var scenario = new GlobbingAppScenario(_logger)) { scenario.Start(); @@ -185,15 +193,16 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { private const string TestAppName = "GlobbingApp"; - public GlobbingAppScenario() + public GlobbingAppScenario(ITestOutputHelper logger) + : base(logger) { - StatusFile = Path.Combine(_scenario.TempFolder, "status"); + StatusFile = Path.Combine(Scenario.TempFolder, "status"); StartedFile = StatusFile + ".started"; - _scenario.AddTestProjectFolder(TestAppName); - _scenario.Restore(); + Scenario.AddTestProjectFolder(TestAppName); + Scenario.Restore3(TestAppName); - TestAppFolder = Path.Combine(_scenario.WorkFolder, TestAppName); + TestAppFolder = Path.Combine(Scenario.WorkFolder, TestAppName); } public void Start() @@ -201,7 +210,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // Wait for the process to start using (var wait = new WaitForFileToChange(StartedFile)) { - RunDotNetWatch(new[] { "run", StatusFile }, Path.Combine(_scenario.WorkFolder, TestAppName)); + RunDotNetWatch(new[] { "run3", StatusFile }, Path.Combine(Scenario.WorkFolder, TestAppName)); wait.Wait(_defaultTimeout, expectedToChange: true, diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs index 023b57512f..7c385a6ed1 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs @@ -7,22 +7,29 @@ using System.Diagnostics; using System.IO; using System.Threading; using Xunit; +using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { public class NoDepsAppTests { private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30); + private readonly ITestOutputHelper _logger; + + public NoDepsAppTests(ITestOutputHelper logger) + { + _logger = logger; + } [Fact] public void RestartProcessOnFileChange() { - using (var scenario = new NoDepsAppScenario()) + using (var scenario = new NoDepsAppScenario(_logger)) { // Wait for the process to start using (var wait = new WaitForFileToChange(scenario.StartedFile)) { - scenario.RunDotNetWatch(new[] { "run", scenario.StatusFile, "--no-exit" }); + scenario.RunDotNetWatch(new[] { "run3", "-f", "netcoreapp1.0", scenario.StatusFile, "--no-exit" }); wait.Wait(_defaultTimeout, expectedToChange: true, @@ -56,12 +63,12 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [Fact] public void RestartProcessThatTerminatesAfterFileChange() { - using (var scenario = new NoDepsAppScenario()) + using (var scenario = new NoDepsAppScenario(_logger)) { // Wait for the process to start using (var wait = new WaitForFileToChange(scenario.StartedFile)) { - scenario.RunDotNetWatch(new[] { "run", scenario.StatusFile }); + scenario.RunDotNetWatch(new[] { "run3", "-f", "netcoreapp1.0", scenario.StatusFile }); wait.Wait(_defaultTimeout, expectedToChange: true, @@ -101,15 +108,16 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { private const string TestAppName = "NoDepsApp"; - public NoDepsAppScenario() + public NoDepsAppScenario(ITestOutputHelper logger) + : base(logger) { - StatusFile = Path.Combine(_scenario.TempFolder, "status"); + StatusFile = Path.Combine(Scenario.TempFolder, "status"); StartedFile = StatusFile + ".started"; - _scenario.AddTestProjectFolder(TestAppName); - _scenario.Restore(); + Scenario.AddTestProjectFolder(TestAppName); + Scenario.Restore3(TestAppName); - TestAppFolder = Path.Combine(_scenario.WorkFolder, TestAppName); + TestAppFolder = Path.Combine(Scenario.WorkFolder, TestAppName); } public string StatusFile { get; private set; } @@ -118,7 +126,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public void RunDotNetWatch(IEnumerable args) { - RunDotNetWatch(args, Path.Combine(_scenario.WorkFolder, TestAppName)); + RunDotNetWatch(args, Path.Combine(Scenario.WorkFolder, TestAppName)); } } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs index bef42282fe..a49a0ed616 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs @@ -6,16 +6,21 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using Microsoft.Extensions.Internal; +using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { public class DotNetWatchScenario : IDisposable { - protected ProjectToolScenario _scenario; - + protected ProjectToolScenario Scenario { get; } public DotNetWatchScenario() + : this(null) { - _scenario = new ProjectToolScenario(); + } + + public DotNetWatchScenario(ITestOutputHelper logger) + { + Scenario = new ProjectToolScenario(logger); } public Process WatcherProcess { get; private set; } @@ -33,7 +38,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests }; } - WatcherProcess = _scenario.ExecuteDotnetWatch(arguments, workingFolder, envVariables); + WatcherProcess = Scenario.ExecuteDotnetWatch(arguments, workingFolder, envVariables); } public virtual void Dispose() @@ -46,7 +51,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } WatcherProcess.Dispose(); } - _scenario.Dispose(); + Scenario.Dispose(); } } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs index c0c2ce0016..73eff54e4a 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -10,6 +10,7 @@ using System.Reflection; using System.Threading; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.ProjectModel; +using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { @@ -17,13 +18,17 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { private const string NugetConfigFileName = "NuGet.config"; private static readonly string TestProjectSourceRoot = Path.Combine(AppContext.BaseDirectory, "TestProjects"); - - private static readonly object _restoreLock = new object(); + private readonly ITestOutputHelper _logger; public ProjectToolScenario() + : this(null) { - Console.WriteLine($"The temporary test folder is {TempFolder}"); + } + public ProjectToolScenario(ITestOutputHelper logger) + { + _logger = logger; + _logger?.WriteLine($"The temporary test folder is {TempFolder}"); WorkFolder = Path.Combine(TempFolder, "work"); CreateTestDirectory(); @@ -37,7 +42,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { var srcFolder = Path.Combine(TestProjectSourceRoot, projectName); var destinationFolder = Path.Combine(WorkFolder, Path.GetFileName(projectName)); - Console.WriteLine($"Copying project {srcFolder} to {destinationFolder}"); + _logger?.WriteLine($"Copying project {srcFolder} to {destinationFolder}"); Directory.CreateDirectory(destinationFolder); @@ -63,19 +68,40 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests project = Path.Combine(WorkFolder, project); } - // Tests are run in parallel and they try to restore tools concurrently. - // This causes issues because the deps json file for a tool is being written from - // multiple threads - which results in either sharing violation or corrupted json. - lock (_restoreLock) - { - var restore = Command - .CreateDotNet("restore", new[] { project }) - .Execute(); + _logger?.WriteLine($"Restoring project in {project}"); - if (restore.ExitCode != 0) - { - throw new Exception($"Exit code {restore.ExitCode}"); - } + var restore = Command + .CreateDotNet("restore", new[] { project }) + .CaptureStdErr() + .CaptureStdOut() + .OnErrorLine(l => _logger?.WriteLine(l)) + .OnOutputLine(l => _logger?.WriteLine(l)) + .Execute(); + + if (restore.ExitCode != 0) + { + throw new Exception($"Exit code {restore.ExitCode}"); + } + } + + public void Restore3(string project) + { + project = Path.Combine(WorkFolder, project); + + _logger?.WriteLine($"Restoring msbuild project in {project}"); + + var restore = Command + .CreateDotNet("restore3", new [] { "/v:m" }) + .WorkingDirectory(project) + .CaptureStdErr() + .CaptureStdOut() + .OnErrorLine(l => _logger?.WriteLine(l)) + .OnOutputLine(l => _logger?.WriteLine(l)) + .Execute(); + + if (restore.ExitCode != 0) + { + throw new Exception($"Exit code {restore.ExitCode}"); } } @@ -92,7 +118,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public Process ExecuteDotnetWatch(IEnumerable arguments, string workDir, IDictionary environmentVariables = null) { - // this launches a new .NET Core process using the runtime of the current test app + // this launches a new .NET Core process using the runtime of the current test app // and the version of dotnet-watch that this test app is compiled against var thisAssembly = Path.GetFileNameWithoutExtension(GetType().GetTypeInfo().Assembly.Location); var args = new List(); @@ -108,12 +134,12 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests var argsStr = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args.Concat(arguments)); - Console.WriteLine($"Running dotnet {argsStr} in {workDir}"); + _logger?.WriteLine($"Running dotnet {argsStr} in {workDir}"); var psi = new ProcessStartInfo(new Muxer().MuxerPath, argsStr) { UseShellExecute = false, - WorkingDirectory = workDir, + WorkingDirectory = workDir }; if (environmentVariables != null) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj new file mode 100644 index 0000000000..f06027243d --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj @@ -0,0 +1,16 @@ + + + + + netcoreapp1.0 + Exe + + + + + + + + + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/project.json deleted file mode 100644 index 8b1c2f6bab..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/project.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "buildOptions": { - "emitEntryPoint": true - }, - "dependencies": { - "Dependency": { - "target": "project" - } - }, - "frameworks": { - "netcoreapp1.0": { - "dependencies": { - "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.1.0-*" - } - } - } - } -} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj new file mode 100644 index 0000000000..243360cf92 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj @@ -0,0 +1,15 @@ + + + + + netstandard1.5 + Library + + + + + + + + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/project.json deleted file mode 100644 index f697b65d49..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/project.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "dependencies": { - "NETStandard.Library": "1.6.1-*" - }, - "frameworks": { - "netstandard1.5": {} - } -} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj new file mode 100644 index 0000000000..cb088af5e3 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj @@ -0,0 +1,15 @@ + + + + + netcoreapp1.0 + Exe + + + + + + + + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/project.json deleted file mode 100644 index 6418c6d199..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/project.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "buildOptions": { - "emitEntryPoint": true, - "compile": { - "include": [ - "Program.cs", - "include/*.cs" - ], - "exclude": [ - "exclude/*" - ] - } - }, - "frameworks": { - "netcoreapp1.0": { - "dependencies": { - "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.1.0-*" - } - } - } - } -} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj new file mode 100644 index 0000000000..67edbf1349 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj @@ -0,0 +1,15 @@ + + + + + netcoreapp1.0 + Exe + + + + + + + + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/project.json deleted file mode 100644 index 4972d51a39..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/project.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "buildOptions": { - "emitEntryPoint": true - }, - "frameworks": { - "netcoreapp1.0": { - "dependencies": { - "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.1.0-*" - } - } - } - } -} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.cmd b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.cmd index 63104d55c6..2d1d41f1a8 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.cmd +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.cmd @@ -3,4 +3,9 @@ if not "%1" == "" ( echo "Deleting %1\TestProjects" rmdir /s /q %1\TestProjects -) \ No newline at end of file + echo "Deleting %1\tools" + rmdir /s /q %1\tools +) + +mkdir %1\tools +copy ..\..\src\Microsoft.DotNet.Watcher.Tools\tools\*.targets %1\tools \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.sh b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.sh index 1a5e80fb71..5b096cd399 100755 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.sh +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.sh @@ -3,6 +3,12 @@ if [ -z $1 ]; then echo "Deleting $1/TestProjects" rm -rf $1/TestProjects + + echo "Deleting $1/tools" + rm -rf $1/tools fi +mkdir -p $1/tools +cp ../../src/Microsoft.DotNet.Watcher.Tools/tools/*.targets $1/tools + exit 0 \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs new file mode 100644 index 0000000000..48975a9175 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs @@ -0,0 +1,27 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Xunit; + +namespace Microsoft.DotNetWatcher.Tools.Tests +{ + public static class AssertEx + { + public static void EqualFileList(string root, IEnumerable expectedFiles, IEnumerable actualFiles) + { + var expected = expectedFiles.Select(p => Path.Combine(root, p)); + EqualFileList(expected, actualFiles); + } + + public static void EqualFileList(IEnumerable expectedFiles, IEnumerable actualFiles) + { + Func normalize = p => p.Replace('\\', '/'); + var expected = new HashSet(expectedFiles.Select(normalize)); + Assert.True(expected.SetEquals(actualFiles.Select(normalize)), "File sets should be equal"); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs new file mode 100644 index 0000000000..555be13c70 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs @@ -0,0 +1,315 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.DotNet.Watcher; +using Microsoft.DotNet.Watcher.Internal; +using Microsoft.Extensions.Logging; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.DotNetWatcher.Tools.Tests +{ + using ItemSpec = TemporaryCSharpProject.ItemSpec; + + public class MsBuildFileSetFactoryTest : IDisposable + { + private ILogger _logger; + private readonly TemporaryDirectory _tempDir; + public MsBuildFileSetFactoryTest(ITestOutputHelper output) + { + _logger = new XunitLogger(output); + _tempDir = new TemporaryDirectory(); + } + + [Fact] + public async Task FindsCustomWatchItems() + { + TemporaryCSharpProject target; + _tempDir + .WithCSharpProject("Project1", out target) + .WithTargetFrameworks("netcoreapp1.0") + .WithDefaultGlobs() + .WithItem(new ItemSpec { Name = "Watch", Include = "*.js", Exclude = "gulpfile.js" }) + .Dir() + .WithFile("Program.cs") + .WithFile("app.js") + .WithFile("gulpfile.js"); + + var fileset = await GetFileSet(target); + + AssertEx.EqualFileList( + _tempDir.Root, + new[] + { + "Project1.csproj", + "Program.cs", + "app.js" + }, + fileset + ); + } + + [Fact] + public async Task ExcludesDefaultItemsWithWatchFalseMetadata() + { + TemporaryCSharpProject target; + _tempDir + .WithCSharpProject("Project1", out target) + .WithTargetFrameworks("net40") + .WithItem(new ItemSpec { Name = "Compile", Include = "*.cs" }) + .WithItem(new ItemSpec { Name = "EmbeddedResource", Include = "*.resx", Watch = false }) + .Dir() + .WithFile("Program.cs") + .WithFile("Strings.resx"); + + var fileset = await GetFileSet(target); + + AssertEx.EqualFileList( + _tempDir.Root, + new[] + { + "Project1.csproj", + "Program.cs", + }, + fileset + ); + } + + [Fact] + public async Task SingleTfm() + { + TemporaryCSharpProject target; + + _tempDir + .SubDir("src") + .SubDir("Project1") + .WithCSharpProject("Project1", out target) + .WithTargetFrameworks("netcoreapp1.0") + .WithDefaultGlobs() + .Dir() + .WithFile("Program.cs") + .WithFile("Class1.cs") + .SubDir("obj").WithFile("ignored.cs").Up() + .SubDir("Properties").WithFile("Strings.resx").Up() + .Up() + .Up() + .Create(); + + var fileset = await GetFileSet(target); + + AssertEx.EqualFileList( + _tempDir.Root, + new[] + { + "src/Project1/Project1.csproj", + "src/Project1/Program.cs", + "src/Project1/Class1.cs", + "src/Project1/Properties/Strings.resx", + }, + fileset + ); + } + + [Fact] + public async Task MultiTfm() + { + TemporaryCSharpProject target; + _tempDir + .SubDir("src") + .SubDir("Project1") + .WithCSharpProject("Project1", out target) + .WithTargetFrameworks("netcoreapp1.0", "net451") + .WithItem("Compile", "Class1.netcore.cs", "'$(TargetFramework)'=='netcoreapp1.0'") + .WithItem("Compile", "Class1.desktop.cs", "'$(TargetFramework)'=='net451'") + .Dir() + .WithFile("Class1.netcore.cs") + .WithFile("Class1.desktop.cs") + .WithFile("Class1.notincluded.cs"); + + var fileset = await GetFileSet(target); + + AssertEx.EqualFileList( + _tempDir.Root, + new[] + { + "src/Project1/Project1.csproj", + "src/Project1/Class1.netcore.cs", + "src/Project1/Class1.desktop.cs", + }, + fileset + ); + } + + [Fact] + public async Task ProjectReferences_OneLevel() + { + TemporaryCSharpProject target; + TemporaryCSharpProject proj2; + _tempDir + .SubDir("src") + .SubDir("Project2") + .WithCSharpProject("Project2", out proj2) + .WithTargetFrameworks("netstandard1.1") + .WithDefaultGlobs() + .Dir() + .WithFile("Class2.cs") + .Up() + .SubDir("Project1") + .WithCSharpProject("Project1", out target) + .WithTargetFrameworks("netcoreapp1.0", "net451") + .WithProjectReference(proj2) + .WithDefaultGlobs() + .Dir() + .WithFile("Class1.cs"); + + var fileset = await GetFileSet(target); + + AssertEx.EqualFileList( + _tempDir.Root, + new[] + { + "src/Project2/Project2.csproj", + "src/Project2/Class2.cs", + "src/Project1/Project1.csproj", + "src/Project1/Class1.cs", + }, + fileset + ); + } + + [Fact] + public async Task TransitiveProjectReferences_TwoLevels() + { + TemporaryCSharpProject target; + TemporaryCSharpProject proj2; + TemporaryCSharpProject proj3; + _tempDir + .SubDir("src") + .SubDir("Project3") + .WithCSharpProject("Project3", out proj3) + .WithTargetFrameworks("netstandard1.0") + .WithDefaultGlobs() + .Dir() + .WithFile("Class3.cs") + .Up() + .SubDir("Project2") + .WithCSharpProject("Project2", out proj2) + .WithTargetFrameworks("netstandard1.1") + .WithProjectReference(proj3) + .WithDefaultGlobs() + .Dir() + .WithFile("Class2.cs") + .Up() + .SubDir("Project1") + .WithCSharpProject("Project1", out target) + .WithTargetFrameworks("netcoreapp1.0", "net451") + .WithProjectReference(proj2) + .WithDefaultGlobs() + .Dir() + .WithFile("Class1.cs"); + + var fileset = await GetFileSet(target); + + AssertEx.EqualFileList( + _tempDir.Root, + new[] + { + "src/Project3/Project3.csproj", + "src/Project3/Class3.cs", + "src/Project2/Project2.csproj", + "src/Project2/Class2.cs", + "src/Project1/Project1.csproj", + "src/Project1/Class1.cs", + }, + fileset + ); + } + + [Fact] + public async Task ProjectReferences_Graph() + { + var graph = new TestProjectGraph(_tempDir); + graph.OnCreate(p => p.WithTargetFrameworks("net45").WithDefaultGlobs()); + var matches = Regex.Matches(@" + A->B B->C C->D D->E + B->E + A->F F->G G->E + F->E + W->U + Y->Z + Y->B + Y->F", + @"(\w)->(\w)"); + + Assert.Equal(13, matches.Count); + foreach (Match m in matches) + { + var target = graph.GetOrCreate(m.Groups[2].Value); + graph.GetOrCreate(m.Groups[1].Value).WithProjectReference(target); + } + + graph.Find("A").WithProjectReference(graph.Find("W"), watch: false); + + var output = new OutputSink(); + var filesetFactory = new MsBuildFileSetFactory(_logger, graph.GetOrCreate("A").Path, output) + { + // enables capturing markers to know which projects have been visited + BuildFlags = { "/p:_DotNetWatchTraceOutput=true" } + }; + + var fileset = await GetFileSet(filesetFactory); + + _logger.LogInformation(output.Current.GetAllLines("Sink output: ")); + + var includedProjects = new[] { "A", "B", "C", "D", "E", "F", "G" }; + AssertEx.EqualFileList( + _tempDir.Root, + includedProjects + .Select(p => $"{p}/{p}.csproj"), + fileset + ); + + // ensure unreachable projects exist but where not included + Assert.NotNull(graph.Find("W")); + Assert.NotNull(graph.Find("U")); + Assert.NotNull(graph.Find("Y")); + Assert.NotNull(graph.Find("Z")); + + // ensure each project is only visited once for collecting watch items + Assert.All(includedProjects, + projectName => + Assert.Single(output.Current.Lines, + line => line.Contains($"Collecting watch items from '{projectName}'")) + ); + + // ensure each project is only visited once to collect project references + Assert.All(includedProjects, + projectName => + Assert.Single(output.Current.Lines, + line => line.Contains($"Collecting referenced projects from '{projectName}'")) + ); + } + + private Task GetFileSet(TemporaryCSharpProject target) + => GetFileSet(new MsBuildFileSetFactory(_logger, target.Path)); + private async Task GetFileSet(MsBuildFileSetFactory filesetFactory) + { + _tempDir.Create(); + var createTask = filesetFactory.CreateAsync(CancellationToken.None); + var finished = await Task.WhenAny(createTask, Task.Delay(TimeSpan.FromSeconds(10))); + + Assert.Same(createTask, finished); + return createTask.Result; + } + + public void Dispose() + { + _tempDir.Dispose(); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryCSharpProject.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryCSharpProject.cs new file mode 100644 index 0000000000..bad0e0a949 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryCSharpProject.cs @@ -0,0 +1,106 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.DotNetWatcher.Tools.Tests +{ + public class TemporaryCSharpProject + { + private const string Template = + @" + + + {0} + Exe + + + {1} + + +"; + + private const string DefaultGlobs = +@" +"; + + private readonly string _filename; + private readonly TemporaryDirectory _directory; + private string[] _tfms; + private List _items = new List(); + + public TemporaryCSharpProject(string name, TemporaryDirectory directory) + { + Name = name; + _filename = name + ".csproj"; + _directory = directory; + } + + public string Name { get; } + public string Path => System.IO.Path.Combine(_directory.Root, _filename); + + public TemporaryCSharpProject WithTargetFrameworks(params string[] tfms) + { + _tfms = tfms; + return this; + } + + public TemporaryCSharpProject WithItem(string itemName, string include, string condition = null) + => WithItem(new ItemSpec { Name = itemName, Include = include, Condition = condition }); + + public TemporaryCSharpProject WithItem(ItemSpec item) + { + var sb = new StringBuilder("<"); + sb.Append(item.Name).Append(" "); + if (item.Include != null) sb.Append(" Include=\"").Append(item.Include).Append('"'); + if (item.Remove != null) sb.Append(" Remove=\"").Append(item.Remove).Append('"'); + if (item.Exclude != null) sb.Append(" Exclude=\"").Append(item.Exclude).Append('"'); + if (item.Condition != null) sb.Append(" Exclude=\"").Append(item.Condition).Append('"'); + if (!item.Watch) sb.Append(" Watch=\"false\" "); + sb.Append(" />"); + _items.Add(sb.ToString()); + return this; + } + + public TemporaryCSharpProject WithProjectReference(TemporaryCSharpProject reference, bool watch = true) + { + if (ReferenceEquals(this, reference)) + { + throw new InvalidOperationException("Can add project reference to self"); + } + + return WithItem(new ItemSpec { Name = "ProjectReference", Include = reference.Path, Watch = watch }); + } + + public TemporaryCSharpProject WithDefaultGlobs() + { + _items.Add(DefaultGlobs); + return this; + } + + public TemporaryDirectory Dir() => _directory; + + public void Create() + { + var tfm = _tfms == null || _tfms.Length == 0 + ? string.Empty + : _tfms.Length == 1 + ? $"{_tfms[0]}" + : $"{string.Join(";", _tfms)}"; + + _directory.CreateFile(_filename, string.Format(Template, tfm, string.Join("\r\n", _items))); + } + + public class ItemSpec + { + public string Name { get; set; } + public string Include { get; set; } + public string Exclude { get; set; } + public string Remove { get; set; } + public bool Watch { get; set; } = true; + public string Condition { get; set; } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryDirectory.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryDirectory.cs new file mode 100644 index 0000000000..ee90092e22 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryDirectory.cs @@ -0,0 +1,107 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; + +namespace Microsoft.DotNetWatcher.Tools.Tests +{ + public class TemporaryDirectory : IDisposable + { + private List _projects = new List(); + private List _subdirs = new List(); + private List _files = new List(); + private TemporaryDirectory _parent; + + public TemporaryDirectory() + { + Root = Path.Combine(Path.GetTempPath(), "dotnet-watch-tests", Guid.NewGuid().ToString("N")); + } + + private TemporaryDirectory(string path, TemporaryDirectory parent) + { + _parent = parent; + Root = path; + } + + public TemporaryDirectory SubDir(string name) + { + var subdir = new TemporaryDirectory(Path.Combine(Root, name), this); + _subdirs.Add(subdir); + return subdir; + } + + public string Root { get; } + + public TemporaryCSharpProject WithCSharpProject(string name) + { + var project = new TemporaryCSharpProject(name, this); + _projects.Add(project); + return project; + } + + public TemporaryCSharpProject WithCSharpProject(string name, out TemporaryCSharpProject project) + { + project = WithCSharpProject(name); + return project; + } + + public TemporaryDirectory WithFile(string name) + { + _files.Add(name); + return this; + } + + public TemporaryDirectory Up() + { + if (_parent == null) + { + throw new InvalidOperationException("This is the root directory"); + } + return _parent; + } + + public void Create() + { + Directory.CreateDirectory(Root); + + foreach (var dir in _subdirs) + { + dir.Create(); + } + + foreach (var project in _projects) + { + project.Create(); + } + + foreach (var file in _files) + { + CreateFile(file, string.Empty); + } + } + + public void CreateFile(string filename, string contents) + { + File.WriteAllText(Path.Combine(Root, filename), contents); + } + + public void Dispose() + { + if (Root == null || !Directory.Exists(Root) || _parent != null) + { + return; + } + + try + { + Directory.Delete(Root, recursive: true); + } + catch + { + Console.Error.WriteLine($"Test cleanup failed to delete '{Root}'"); + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TestProjectGraph.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TestProjectGraph.cs new file mode 100644 index 0000000000..730f82f0db --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TestProjectGraph.cs @@ -0,0 +1,41 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; + +namespace Microsoft.DotNetWatcher.Tools.Tests +{ + public class TestProjectGraph + { + private readonly TemporaryDirectory _directory; + private Action _onCreate; + private Dictionary _projects = new Dictionary(); + public TestProjectGraph(TemporaryDirectory directory) + { + _directory = directory; + } + + public void OnCreate(Action onCreate) + { + _onCreate = onCreate; + } + + public TemporaryCSharpProject Find(string projectName) + => _projects.ContainsKey(projectName) + ? _projects[projectName] + : null; + + public TemporaryCSharpProject GetOrCreate(string projectName) + { + TemporaryCSharpProject sourceProj; + if (!_projects.TryGetValue(projectName, out sourceProj)) + { + sourceProj = _directory.SubDir(projectName).WithCSharpProject(projectName); + _onCreate?.Invoke(sourceProj); + _projects.Add(projectName, sourceProj); + } + return sourceProj; + } + } +} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/XunitLogger.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/XunitLogger.cs new file mode 100644 index 0000000000..640a4a0664 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/XunitLogger.cs @@ -0,0 +1,35 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.Extensions.Logging; +using Xunit.Abstractions; + +namespace Microsoft.DotNetWatcher.Tools.Tests +{ + internal class XunitLogger : ILogger + { + private readonly ITestOutputHelper _output; + public XunitLogger(ITestOutputHelper output) + { + _output = output; + } + + public IDisposable BeginScope(TState state) + => NullScope.Instance; + + public bool IsEnabled(LogLevel logLevel) => true; + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + _output.WriteLine($"{logLevel}: {formatter(state, exception)}"); + } + + private class NullScope : IDisposable + { + private NullScope() { } + public static NullScope Instance = new NullScope(); + public void Dispose() { } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.cmd b/test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.cmd new file mode 100644 index 0000000000..812690859e --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.cmd @@ -0,0 +1,9 @@ +@ECHO OFF +:again +if not "%1" == "" ( + echo "Deleting %1\tools" + rmdir /s /q %1\tools +) + +mkdir %1\tools +copy ..\..\src\Microsoft.DotNet.Watcher.Tools\tools\*.targets %1\tools \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.sh b/test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.sh new file mode 100755 index 0000000000..8c12918ae7 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +if [ -z $1 ]; then + echo "Deleting $1/tools" + rm -rf $1/tools +fi + +mkdir -p $1/tools +echo "Copying ./../src/Microsoft.DotNet.Watcher.Tools/tools/*.targets" +cp ../../src/Microsoft.DotNet.Watcher.Tools/tools/*.targets $1/tools + +exit 0 \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json index a084f633f2..f938c008bf 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json @@ -1,7 +1,8 @@ { "buildOptions": { "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk" + "keyFile": "../../tools/Key.snk", + "debugType": "portable" }, "dependencies": { "dotnet-test-xunit": "2.2.0-*", @@ -18,5 +19,8 @@ } } }, + "scripts": { + "precompile": "copyfiles %compile:OutputDir%" + }, "testRunner": "xunit" } \ No newline at end of file From 7afad9102f54ac978f1bb05f3b685bbeba7ec9e4 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 31 Oct 2016 14:28:14 -0700 Subject: [PATCH 0310/1029] Update dotnet-watch README.md --- src/Microsoft.DotNet.Watcher.Tools/README.md | 51 ++++++++++++-------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/README.md b/src/Microsoft.DotNet.Watcher.Tools/README.md index ec769af3e6..1ad4f241c9 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/README.md +++ b/src/Microsoft.DotNet.Watcher.Tools/README.md @@ -4,6 +4,8 @@ dotnet-watch ### How To Install +**project.json** + Add `Microsoft.DotNet.Watcher.Tools` to the `tools` section of your `project.json` file. Use the version "1.0.0-preview2-final" if you are using .NET Core 1.0.0 and use "1.0.0-preview3-final" if you are using .NET Core 1.1.0. @@ -18,18 +20,28 @@ Use the version "1.0.0-preview2-final" if you are using .NET Core 1.0.0 and use } ``` +**MSBuild** +Install `Microsoft.DotNet.Watcher.Tools` as a `DotNetCliReference` to your project. + +```xml + + + +``` + + ### How To Use dotnet watch [-?|-h|--help] - dotnet watch [options] [[--] ...] + dotnet watch [options] [[--] ...] Options: -?|-h|--help Show help information -q|--quiet Suppresses all output except warnings and errors -v|--verbose Show verbose output -Add `watch` after `dotnet` in the command that you want to run: +Add `watch` after `dotnet` and before the command arguments that you want to run: | What you want to run | Dotnet watch command | | ---------------------------------------------- | -------------------------------------------------------- | @@ -50,27 +62,13 @@ Some configuration options can be passed to `dotnet watch` through environment v dotnet-watch can be configured from the MSBuild project file being watched. -**Project References** - -By default, dotnet-watch will scan the entire graph of project references and watch all files within those projects. - -dotnet-watch will ignore project references with the `Watch="false"` attribute. - -```xml - - - -``` - **Watch items** -dotnet-watch will watch all items in the "Watch" item group. -By default, this group inclues all items in "Compile" and "EmbeddedResource". +dotnet-watch will watch all items in the **Watch** item group. +By default, this group inclues all items in **Compile** and **EmbeddedResource**. More items can be added to watch in a project file by adding items to 'Watch'. -Example: - ```xml @@ -86,7 +84,20 @@ Example: - + + + +``` + +**Project References** + +By default, dotnet-watch will scan the entire graph of project references and watch all files within those projects. + +dotnet-watch will ignore project references with the `Watch="false"` attribute. + +```xml + + ``` @@ -100,6 +111,6 @@ Example: ```xml - + ``` \ No newline at end of file From 6fd5e2ab52417ff0d05190b601a84928b003445b Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 1 Nov 2016 17:34:05 -0700 Subject: [PATCH 0311/1029] Install cli preview3 side-by-side for msbuild testing --- CliToolVersion.txt | 1 + build.ps1 | 8 +- build.sh | 8 +- dotnet-install.ps1 | 427 +++++++++++ dotnet-install.sh | 688 ++++++++++++++++++ makefile.shade | 19 + .../AppWithDepsTests.cs | 4 +- .../GlobbingAppTests.cs | 4 +- .../NoDepsAppTests.cs | 6 +- .../Scenario/ProjectToolScenario.cs | 31 +- .../AppWithDeps/AppWithDeps.csproj | 4 +- .../TestProjects/Dependency/Dependency.csproj | 4 +- .../GlobbingApp/GlobbingApp.csproj | 4 +- .../TestProjects/NoDepsApp/NoDepsApp.csproj | 4 +- .../project.json | 2 +- .../Utilities/TemporaryCSharpProject.cs | 43 +- .../project.json | 2 +- .../project.json | 2 +- 18 files changed, 1203 insertions(+), 58 deletions(-) create mode 100644 CliToolVersion.txt create mode 100644 dotnet-install.ps1 create mode 100755 dotnet-install.sh diff --git a/CliToolVersion.txt b/CliToolVersion.txt new file mode 100644 index 0000000000..6b51205059 --- /dev/null +++ b/CliToolVersion.txt @@ -0,0 +1 @@ +1.0.0-preview3-003981 \ No newline at end of file diff --git a/build.ps1 b/build.ps1 index f780c43a82..441eef967c 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP @@ -64,4 +64,10 @@ if (!(Test-Path $buildFolder)) { } } +$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 +$dotnetHome = "$buildFolder\.dotnet" +mkdir $dotnetHome -ErrorAction Ignore | Out-Null +& .\dotnet-install.ps1 -Version $(Get-Content .\CliToolVersion.txt) -InstallDir $dotnetHome +& .\dotnet-install.ps1 -Version 1.1.0 -Channel release/1.1.0 -SharedRuntime -InstallDir $dotnetHome + &"$buildFile" $args \ No newline at end of file diff --git a/build.sh b/build.sh index 0a1463b9e4..cdfdace2ba 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi @@ -43,4 +43,10 @@ if test ! -d $buildFolder; then fi fi +export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 +dotnetHome="$buildFolder/.dotnet" +mkdir -p $dotnetHome +./dotnet-install.sh --install-dir $dotnetHome --version $(cat CliToolVersion.txt) +./dotnet-install.sh --install-dir $dotnetHome --version 1.1.0 --channel release/1.1.0 --shared-runtime + $buildFile -r $repoFolder "$@" \ No newline at end of file diff --git a/dotnet-install.ps1 b/dotnet-install.ps1 new file mode 100644 index 0000000000..d656007d5f --- /dev/null +++ b/dotnet-install.ps1 @@ -0,0 +1,427 @@ +# +# Copyright (c) .NET Foundation and contributors. All rights reserved. +# Licensed under the MIT license. See LICENSE file in the project root for full license information. +# + +<# +.SYNOPSIS + Installs dotnet cli +.DESCRIPTION + Installs dotnet cli. If dotnet installation already exists in the given directory + it will update it only if the requested version differs from the one already installed. +.PARAMETER Channel + Default: preview + Channel is the way of reasoning about stability and quality of dotnet. This parameter takes one of the values: + - future - Possibly unstable, frequently changing, may contain new finished and unfinished features + - preview - Pre-release stable with known issues and feature gaps + - production - Most stable releases +.PARAMETER Version + Default: latest + Represents a build version on specific channel. Possible values: + - 4-part version in a format A.B.C.D - represents specific version of build + - latest - most latest build on specific channel + - lkg - last known good version on specific channel + Note: LKG work is in progress. Once the work is finished, this will become new default +.PARAMETER InstallDir + Default: %LocalAppData%\Microsoft\dotnet + Path to where to install dotnet. Note that binaries will be placed directly in a given directory. +.PARAMETER Architecture + Default: - this value represents currently running OS architecture + Architecture of dotnet binaries to be installed. + Possible values are: , x64 and x86 +.PARAMETER SharedRuntime + Default: false + Installs just the shared runtime bits, not the entire SDK +.PARAMETER DebugSymbols + If set the installer will include symbols in the installation. +.PARAMETER DryRun + If set it will not perform installation but instead display what command line to use to consistently install + currently requested version of dotnet cli. In example if you specify version 'latest' it will display a link + with specific version so that this command can be used deterministicly in a build script. + It also displays binaries location if you prefer to install or download it yourself. +.PARAMETER NoPath + By default this script will set environment variable PATH for the current process to the binaries folder inside installation folder. + If set it will display binaries location but not set any environment variable. +.PARAMETER Verbose + Displays diagnostics information. +.PARAMETER AzureFeed + Default: https://dotnetcli.azureedge.net/dotnet + This parameter should not be usually changed by user. It allows to change URL for the Azure feed used by this installer. +.PARAMETER ProxyAddress + If set, the installer will use the proxy when making web requests +#> +[cmdletbinding()] +param( + [string]$Channel="rel-1.0.0", + [string]$Version="Latest", + [string]$InstallDir="", + [string]$Architecture="", + [switch]$SharedRuntime, + [switch]$DebugSymbols, # TODO: Switch does not work yet. Symbols zip is not being uploaded yet. + [switch]$DryRun, + [switch]$NoPath, + [string]$AzureFeed="https://dotnetcli.azureedge.net/dotnet", + [string]$UncachedFeed="https://dotnetcli.blob.core.windows.net/dotnet", + [string]$ProxyAddress +) + +Set-StrictMode -Version Latest +$ErrorActionPreference="Stop" +$ProgressPreference="SilentlyContinue" + +$BinFolderRelativePath="" + +# example path with regex: shared/1.0.0-beta-12345/somepath +$VersionRegEx="/\d+\.\d+[^/]+/" +$OverrideNonVersionedFiles=$true + +function Say($str) { + Write-Host "dotnet-install: $str" +} + +function Say-Verbose($str) { + Write-Verbose "dotnet-install: $str" +} + +function Say-Invocation($Invocation) { + $command = $Invocation.MyCommand; + $args = (($Invocation.BoundParameters.Keys | foreach { "-$_ `"$($Invocation.BoundParameters[$_])`"" }) -join " ") + Say-Verbose "$command $args" +} + +function Get-Machine-Architecture() { + Say-Invocation $MyInvocation + + # possible values: AMD64, IA64, x86 + return $ENV:PROCESSOR_ARCHITECTURE +} + +# TODO: Architecture and CLIArchitecture should be unified +function Get-CLIArchitecture-From-Architecture([string]$Architecture) { + Say-Invocation $MyInvocation + + switch ($Architecture.ToLower()) { + { $_ -eq "" } { return Get-CLIArchitecture-From-Architecture $(Get-Machine-Architecture) } + { ($_ -eq "amd64") -or ($_ -eq "x64") } { return "x64" } + { $_ -eq "x86" } { return "x86" } + default { throw "Architecture not supported. If you think this is a bug, please report it at https://github.com/dotnet/cli/issues" } + } +} + +function Get-Version-Info-From-Version-Text([string]$VersionText) { + Say-Invocation $MyInvocation + + $Data = @($VersionText.Split([char[]]@(), [StringSplitOptions]::RemoveEmptyEntries)); + + $VersionInfo = @{} + $VersionInfo.CommitHash = $Data[0].Trim() + $VersionInfo.Version = $Data[1].Trim() + return $VersionInfo +} + +function Load-Assembly([string] $Assembly) { + try { + Add-Type -Assembly $Assembly | Out-Null + } + catch { + # On Nano Server, Powershell Core Edition is used. Add-Type is unable to resolve base class assemblies because they are not GAC'd. + # Loading the base class assemblies is not unnecessary as the types will automatically get resolved. + } +} + +function GetHTTPResponse([Uri] $Uri) +{ + $HttpClient = $null + + try { + # HttpClient is used vs Invoke-WebRequest in order to support Nano Server which doesn't support the Invoke-WebRequest cmdlet. + Load-Assembly -Assembly System.Net.Http + if($ProxyAddress){ + $HttpClientHandler = New-Object System.Net.Http.HttpClientHandler + $HttpClientHandler.Proxy = New-Object System.Net.WebProxy -Property @{Address=$ProxyAddress} + $HttpClient = New-Object System.Net.Http.HttpClient -ArgumentList $HttpClientHandler + } + else { + $HttpClient = New-Object System.Net.Http.HttpClient + } + + $Response = $HttpClient.GetAsync($Uri).Result + if (($Response -eq $null) -or (-not ($Response.IsSuccessStatusCode))) + { + $ErrorMsg = "Failed to download $Uri." + if ($Response -ne $null) + { + $ErrorMsg += " $Response" + } + + throw $ErrorMsg + } + + return $Response + } + finally { + if ($HttpClient -ne $null) { + $HttpClient.Dispose() + } + } +} + + +function Get-Latest-Version-Info([string]$AzureFeed, [string]$AzureChannel, [string]$CLIArchitecture) { + Say-Invocation $MyInvocation + + $VersionFileUrl = $null + if ($SharedRuntime) { + $VersionFileUrl = "$UncachedFeed/$AzureChannel/dnvm/latest.sharedfx.win.$CLIArchitecture.version" + } + else { + $VersionFileUrl = "$UncachedFeed/Sdk/$AzureChannel/latest.version" + } + + $Response = GetHTTPResponse -Uri $VersionFileUrl + $StringContent = $Response.Content.ReadAsStringAsync().Result + + switch ($Response.Content.Headers.ContentType) { + { ($_ -eq "application/octet-stream") } { $VersionText = [Text.Encoding]::UTF8.GetString($StringContent) } + { ($_ -eq "text/plain") } { $VersionText = $StringContent } + default { throw "``$Response.Content.Headers.ContentType`` is an unknown .version file content type." } + } + + $VersionInfo = Get-Version-Info-From-Version-Text $VersionText + + return $VersionInfo +} + +# TODO: AzureChannel and Channel should be unified +function Get-Azure-Channel-From-Channel([string]$Channel) { + Say-Invocation $MyInvocation + + # For compatibility with build scripts accept also directly Azure channels names + switch ($Channel.ToLower()) { + { ($_ -eq "future") -or ($_ -eq "dev") } { return "dev" } + { $_ -eq "production" } { throw "Production channel does not exist yet" } + default { return $_ } + } +} + +function Get-Specific-Version-From-Version([string]$AzureFeed, [string]$AzureChannel, [string]$CLIArchitecture, [string]$Version) { + Say-Invocation $MyInvocation + + switch ($Version.ToLower()) { + { $_ -eq "latest" } { + $LatestVersionInfo = Get-Latest-Version-Info -AzureFeed $AzureFeed -AzureChannel $AzureChannel -CLIArchitecture $CLIArchitecture + return $LatestVersionInfo.Version + } + { $_ -eq "lkg" } { throw "``-Version LKG`` not supported yet." } + default { return $Version } + } +} + +function Get-Download-Links([string]$AzureFeed, [string]$AzureChannel, [string]$SpecificVersion, [string]$CLIArchitecture) { + Say-Invocation $MyInvocation + + $ret = @() + + if ($SharedRuntime) { + $PayloadURL = "$AzureFeed/$AzureChannel/Binaries/$SpecificVersion/dotnet-win-$CLIArchitecture.$SpecificVersion.zip" + } + else { + $PayloadURL = "$AzureFeed/Sdk/$SpecificVersion/dotnet-dev-win-$CLIArchitecture.$SpecificVersion.zip" + } + + Say-Verbose "Constructed payload URL: $PayloadURL" + $ret += $PayloadURL + + return $ret +} + +function Get-User-Share-Path() { + Say-Invocation $MyInvocation + + $InstallRoot = $env:DOTNET_INSTALL_DIR + if (!$InstallRoot) { + $InstallRoot = "$env:LocalAppData\Microsoft\dotnet" + } + return $InstallRoot +} + +function Resolve-Installation-Path([string]$InstallDir) { + Say-Invocation $MyInvocation + + if ($InstallDir -eq "") { + return Get-User-Share-Path + } + return $InstallDir +} + +function Get-Version-Info-From-Version-File([string]$InstallRoot, [string]$RelativePathToVersionFile) { + Say-Invocation $MyInvocation + + $VersionFile = Join-Path -Path $InstallRoot -ChildPath $RelativePathToVersionFile + Say-Verbose "Local version file: $VersionFile" + + if (Test-Path $VersionFile) { + $VersionText = cat $VersionFile + Say-Verbose "Local version file text: $VersionText" + return Get-Version-Info-From-Version-Text $VersionText + } + + Say-Verbose "Local version file not found." + + return $null +} + +function Is-Dotnet-Package-Installed([string]$InstallRoot, [string]$RelativePathToPackage, [string]$SpecificVersion) { + Say-Invocation $MyInvocation + + $DotnetPackagePath = Join-Path -Path $InstallRoot -ChildPath $RelativePathToPackage | Join-Path -ChildPath $SpecificVersion + Say-Verbose "Is-Dotnet-Package-Installed: Path to a package: $DotnetPackagePath" + return Test-Path $DotnetPackagePath -PathType Container +} + +function Get-Absolute-Path([string]$RelativeOrAbsolutePath) { + # Too much spam + # Say-Invocation $MyInvocation + + return $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($RelativeOrAbsolutePath) +} + +function Get-Path-Prefix-With-Version($path) { + $match = [regex]::match($path, $VersionRegEx) + if ($match.Success) { + return $entry.FullName.Substring(0, $match.Index + $match.Length) + } + + return $null +} + +function Get-List-Of-Directories-And-Versions-To-Unpack-From-Dotnet-Package([System.IO.Compression.ZipArchive]$Zip, [string]$OutPath) { + Say-Invocation $MyInvocation + + $ret = @() + foreach ($entry in $Zip.Entries) { + $dir = Get-Path-Prefix-With-Version $entry.FullName + if ($dir -ne $null) { + $path = Get-Absolute-Path $(Join-Path -Path $OutPath -ChildPath $dir) + if (-Not (Test-Path $path -PathType Container)) { + $ret += $dir + } + } + } + + $ret = $ret | Sort-Object | Get-Unique + + $values = ($ret | foreach { "$_" }) -join ";" + Say-Verbose "Directories to unpack: $values" + + return $ret +} + +# Example zip content and extraction algorithm: +# Rule: files if extracted are always being extracted to the same relative path locally +# .\ +# a.exe # file does not exist locally, extract +# b.dll # file exists locally, override only if $OverrideFiles set +# aaa\ # same rules as for files +# ... +# abc\1.0.0\ # directory contains version and exists locally +# ... # do not extract content under versioned part +# abc\asd\ # same rules as for files +# ... +# def\ghi\1.0.1\ # directory contains version and does not exist locally +# ... # extract content +function Extract-Dotnet-Package([string]$ZipPath, [string]$OutPath) { + Say-Invocation $MyInvocation + + Load-Assembly -Assembly System.IO.Compression.FileSystem + Set-Variable -Name Zip + try { + $Zip = [System.IO.Compression.ZipFile]::OpenRead($ZipPath) + + $DirectoriesToUnpack = Get-List-Of-Directories-And-Versions-To-Unpack-From-Dotnet-Package -Zip $Zip -OutPath $OutPath + + foreach ($entry in $Zip.Entries) { + $PathWithVersion = Get-Path-Prefix-With-Version $entry.FullName + if (($PathWithVersion -eq $null) -Or ($DirectoriesToUnpack -contains $PathWithVersion)) { + $DestinationPath = Get-Absolute-Path $(Join-Path -Path $OutPath -ChildPath $entry.FullName) + $DestinationDir = Split-Path -Parent $DestinationPath + $OverrideFiles=$OverrideNonVersionedFiles -Or (-Not (Test-Path $DestinationPath)) + if ((-Not $DestinationPath.EndsWith("\")) -And $OverrideFiles) { + New-Item -ItemType Directory -Force -Path $DestinationDir | Out-Null + [System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $DestinationPath, $OverrideNonVersionedFiles) + } + } + } + } + finally { + if ($Zip -ne $null) { + $Zip.Dispose() + } + } +} + +function DownloadFile([Uri]$Uri, [string]$OutPath) { + $Stream = $null + + try { + $Response = GetHTTPResponse -Uri $Uri + $Stream = $Response.Content.ReadAsStreamAsync().Result + $File = [System.IO.File]::Create($OutPath) + $Stream.CopyTo($File) + $File.Close() + } + finally { + if ($Stream -ne $null) { + $Stream.Dispose() + } + } +} + +$AzureChannel = Get-Azure-Channel-From-Channel -Channel $Channel +$CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture +$SpecificVersion = Get-Specific-Version-From-Version -AzureFeed $AzureFeed -AzureChannel $AzureChannel -CLIArchitecture $CLIArchitecture -Version $Version +$DownloadLinks = Get-Download-Links -AzureFeed $AzureFeed -AzureChannel $AzureChannel -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture + +if ($DryRun) { + Say "Payload URLs:" + foreach ($DownloadLink in $DownloadLinks) { + Say "- $DownloadLink" + } + Say "Repeatable invocation: .\$($MyInvocation.MyCommand) -Version $SpecificVersion -Channel $Channel -Architecture $CLIArchitecture -InstallDir $InstallDir" + exit 0 +} + +$InstallRoot = Resolve-Installation-Path $InstallDir +Say-Verbose "InstallRoot: $InstallRoot" + +$IsSdkInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage "sdk" -SpecificVersion $SpecificVersion +Say-Verbose ".NET SDK installed? $IsSdkInstalled" +if ($IsSdkInstalled) { + Say ".NET SDK version $SpecificVersion is already installed." + exit 0 +} + +New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null + +foreach ($DownloadLink in $DownloadLinks) { + $ZipPath = [System.IO.Path]::GetTempFileName() + Say "Downloading $DownloadLink" + DownloadFile -Uri $DownloadLink -OutPath $ZipPath + + Say "Extracting zip from $DownloadLink" + Extract-Dotnet-Package -ZipPath $ZipPath -OutPath $InstallRoot + + Remove-Item $ZipPath +} + +$BinPath = Get-Absolute-Path $(Join-Path -Path $InstallRoot -ChildPath $BinFolderRelativePath) +if (-Not $NoPath) { + Say "Adding to current process PATH: `"$BinPath`". Note: This change will not be visible if PowerShell was run as a child process." + $env:path = "$BinPath;" + $env:path +} +else { + Say "Binaries of dotnet can be found in $BinPath" +} + +Say "Installation finished" +exit 0 diff --git a/dotnet-install.sh b/dotnet-install.sh new file mode 100755 index 0000000000..7f6f869564 --- /dev/null +++ b/dotnet-install.sh @@ -0,0 +1,688 @@ +# Copyright (c) .NET Foundation and contributors. All rights reserved. +# Licensed under the MIT license. See LICENSE file in the project root for full license information. +# + +# Note: This script should be compatible with the dash shell used in Ubuntu. So avoid bashisms! See https://wiki.ubuntu.com/DashAsBinSh for more info + +# Stop script on NZEC +set -e +# Stop script if unbound variable found (use ${var:-} if intentional) +set -u +# By default cmd1 | cmd2 returns exit code of cmd2 regardless of cmd1 success +# This is causing it to fail +set -o pipefail + +# Use in the the functions: eval $invocation +invocation='say_verbose "Calling: ${yellow:-}${FUNCNAME[0]} ${green:-}$*${normal:-}"' + +# standard output may be used as a return value in the functions +# we need a way to write text on the screen in the functions so that +# it won't interfere with the return value. +# Exposing stream 3 as a pipe to standard output of the script itself +exec 3>&1 + +# Setup some colors to use. These need to work in fairly limited shells, like the Ubuntu Docker container where there are only 8 colors. +# See if stdout is a terminal +if [ -t 1 ]; then + # see if it supports colors + ncolors=$(tput colors) + if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then + bold="$(tput bold || echo)" + normal="$(tput sgr0 || echo)" + black="$(tput setaf 0 || echo)" + red="$(tput setaf 1 || echo)" + green="$(tput setaf 2 || echo)" + yellow="$(tput setaf 3 || echo)" + blue="$(tput setaf 4 || echo)" + magenta="$(tput setaf 5 || echo)" + cyan="$(tput setaf 6 || echo)" + white="$(tput setaf 7 || echo)" + fi +fi + +say_err() { + printf "%b\n" "${red:-}dotnet_install: Error: $1${normal:-}" >&2 +} + +say() { + # using stream 3 (defined in the beginning) to not interfere with stdout of functions + # which may be used as return value + printf "%b\n" "${cyan:-}dotnet-install:${normal:-} $1" >&3 +} + +say_verbose() { + if [ "$verbose" = true ]; then + say "$1" + fi +} + +get_current_os_name() { + eval $invocation + + local uname=$(uname) + if [ "$uname" = "Darwin" ]; then + echo "osx" + return 0 + else + if [ -e /etc/os-release ]; then + . /etc/os-release + + case "$ID.$VERSION_ID" in + "centos.7") + echo "centos" + return 0 + ;; + "debian.8") + echo "debian" + return 0 + ;; + "fedora.23") + echo "fedora.23" + return 0 + ;; + "fedora.24") + echo "fedora.24" + return 0 + ;; + "opensuse.13.2") + echo "opensuse.13.2" + return 0 + ;; + "opensuse.42.1") + echo "opensuse.42.1" + return 0 + ;; + "rhel.7.0" | "rhel.7.1" | "rhel.7.2") + echo "rhel" + return 0 + ;; + "ubuntu.14.04") + echo "ubuntu" + return 0 + ;; + "ubuntu.16.04") + echo "ubuntu.16.04" + return 0 + ;; + "ubuntu.16.10") + echo "ubuntu.16.10" + return 0 + ;; + "alpine.3.4.3") + echo "alpine" + return 0 + ;; + esac + fi + fi + + say_err "OS name could not be detected: $ID.$VERSION_ID" + return 1 +} + +machine_has() { + eval $invocation + + which "$1" > /dev/null 2>&1 + return $? +} + +check_min_reqs() { + if ! machine_has "curl"; then + say_err "curl is required to download dotnet. Install curl to proceed." + return 1 + fi + + return 0 +} + +check_pre_reqs() { + eval $invocation + + local failing=false; + + if [ "${DOTNET_INSTALL_SKIP_PREREQS:-}" = "1" ]; then + return 0 + fi + + if [ "$(uname)" = "Linux" ]; then + if ! [ -x "$(command -v ldconfig)" ]; then + echo "ldconfig is not in PATH, trying /sbin/ldconfig." + LDCONFIG_COMMAND="/sbin/ldconfig" + else + LDCONFIG_COMMAND="ldconfig" + fi + + [ -z "$($LDCONFIG_COMMAND -p | grep libunwind)" ] && say_err "Unable to locate libunwind. Install libunwind to continue" && failing=true + [ -z "$($LDCONFIG_COMMAND -p | grep libssl)" ] && say_err "Unable to locate libssl. Install libssl to continue" && failing=true + [ -z "$($LDCONFIG_COMMAND -p | grep libcurl)" ] && say_err "Unable to locate libcurl. Install libcurl to continue" && failing=true + [ -z "$($LDCONFIG_COMMAND -p | grep libicu)" ] && say_err "Unable to locate libicu. Install libicu to continue" && failing=true + fi + + if [ "$failing" = true ]; then + return 1 + fi + + return 0 +} + +# args: +# input - $1 +to_lowercase() { + #eval $invocation + + echo "$1" | tr '[:upper:]' '[:lower:]' + return 0 +} + +# args: +# input - $1 +remove_trailing_slash() { + #eval $invocation + + local input=${1:-} + echo "${input%/}" + return 0 +} + +# args: +# input - $1 +remove_beginning_slash() { + #eval $invocation + + local input=${1:-} + echo "${input#/}" + return 0 +} + +# args: +# root_path - $1 +# child_path - $2 - this parameter can be empty +combine_paths() { + eval $invocation + + # TODO: Consider making it work with any number of paths. For now: + if [ ! -z "${3:-}" ]; then + say_err "combine_paths: Function takes two parameters." + return 1 + fi + + local root_path=$(remove_trailing_slash $1) + local child_path=$(remove_beginning_slash ${2:-}) + say_verbose "combine_paths: root_path=$root_path" + say_verbose "combine_paths: child_path=$child_path" + echo "$root_path/$child_path" + return 0 +} + +get_machine_architecture() { + eval $invocation + + # Currently the only one supported + echo "x64" + return 0 +} + +# args: +# architecture - $1 +get_normalized_architecture_from_architecture() { + eval $invocation + + local architecture=$(to_lowercase $1) + case $architecture in + \) + echo "$(get_normalized_architecture_from_architecture $(get_machine_architecture))" + return 0 + ;; + amd64|x64) + echo "x64" + return 0 + ;; + x86) + say_err "Architecture ``x86`` currently not supported" + return 1 + ;; + esac + + say_err "Architecture ``$architecture`` not supported. If you think this is a bug, please report it at https://github.com/dotnet/cli/issues" + return 1 +} + +# version_info is a conceptual two line string representing commit hash and 4-part version +# format: +# Line 1: # commit_hash +# Line 2: # 4-part version + +# args: +# version_text - stdin +get_version_from_version_info() { + eval $invocation + + cat | tail -n 1 + return 0 +} + +# args: +# version_text - stdin +get_commit_hash_from_version_info() { + eval $invocation + + cat | head -n 1 + return 0 +} + +# args: +# install_root - $1 +# relative_path_to_package - $2 +# specific_version - $3 +is_dotnet_package_installed() { + eval $invocation + + local install_root=$1 + local relative_path_to_package=$2 + local specific_version=${3//[$'\t\r\n']} + + local dotnet_package_path=$(combine_paths $(combine_paths $install_root $relative_path_to_package) $specific_version) + say_verbose "is_dotnet_package_installed: dotnet_package_path=$dotnet_package_path" + + if [ -d "$dotnet_package_path" ]; then + return 0 + else + return 1 + fi +} + +# args: +# azure_feed - $1 +# azure_channel - $2 +# normalized_architecture - $3 +get_latest_version_info() { + eval $invocation + + local azure_feed=$1 + local azure_channel=$2 + local normalized_architecture=$3 + + local osname + osname=$(get_current_os_name) || return 1 + + local version_file_url=null + if [ "$shared_runtime" = true ]; then + version_file_url="$uncached_feed/$azure_channel/dnvm/latest.sharedfx.$osname.$normalized_architecture.version" + else + version_file_url="$uncached_feed/Sdk/$azure_channel/latest.version" + fi + say_verbose "get_latest_version_info: latest url: $version_file_url" + + download $version_file_url + return $? +} + +# args: +# channel - $1 +get_azure_channel_from_channel() { + eval $invocation + + local channel=$(to_lowercase $1) + case $channel in + future|dev) + echo "dev" + return 0 + ;; + production) + say_err "Production channel does not exist yet" + return 1 + esac + + echo $channel + return 0 +} + +# args: +# azure_feed - $1 +# azure_channel - $2 +# normalized_architecture - $3 +# version - $4 +get_specific_version_from_version() { + eval $invocation + + local azure_feed=$1 + local azure_channel=$2 + local normalized_architecture=$3 + local version=$(to_lowercase $4) + + case $version in + latest) + local version_info + version_info="$(get_latest_version_info $azure_feed $azure_channel $normalized_architecture)" || return 1 + say_verbose "get_specific_version_from_version: version_info=$version_info" + echo "$version_info" | get_version_from_version_info + return 0 + ;; + lkg) + say_err "``--version LKG`` not supported yet." + return 1 + ;; + *) + echo $version + return 0 + ;; + esac +} + +# args: +# azure_feed - $1 +# azure_channel - $2 +# normalized_architecture - $3 +# specific_version - $4 +construct_download_link() { + eval $invocation + + local azure_feed=$1 + local azure_channel=$2 + local normalized_architecture=$3 + local specific_version=${4//[$'\t\r\n']} + + local osname + osname=$(get_current_os_name) || return 1 + + local download_link=null + if [ "$shared_runtime" = true ]; then + download_link="$azure_feed/$azure_channel/Binaries/$specific_version/dotnet-$osname-$normalized_architecture.$specific_version.tar.gz" + else + download_link="$azure_feed/Sdk/$specific_version/dotnet-dev-$osname-$normalized_architecture.$specific_version.tar.gz" + fi + + echo "$download_link" + return 0 +} + +get_user_share_path() { + eval $invocation + + if [ ! -z "${DOTNET_INSTALL_DIR:-}" ]; then + echo $DOTNET_INSTALL_DIR + else + echo "$HOME/.dotnet" + fi + return 0 +} + +# args: +# install_dir - $1 +resolve_installation_path() { + eval $invocation + + local install_dir=$1 + if [ "$install_dir" = "" ]; then + local user_share_path=$(get_user_share_path) + say_verbose "resolve_installation_path: share_path=$user_share_path" + echo "$user_share_path" + return 0 + fi + + echo "$install_dir" + return 0 +} + +# args: +# install_root - $1 +get_installed_version_info() { + eval $invocation + + local install_root=$1 + local version_file=$(combine_paths "$install_root" "$local_version_file_relative_path") + say_verbose "Local version file: $version_file" + if [ ! -z "$version_file" ] | [ -r "$version_file" ]; then + local version_info="$(cat $version_file)" + echo "$version_info" + return 0 + fi + + say_verbose "Local version file not found." + return 0 +} + +# args: +# relative_or_absolute_path - $1 +get_absolute_path() { + eval $invocation + + local relative_or_absolute_path=$1 + echo $(cd $(dirname "$1") && pwd -P)/$(basename "$1") + return 0 +} + +# args: +# input_files - stdin +# root_path - $1 +# out_path - $2 +# override - $3 +copy_files_or_dirs_from_list() { + eval $invocation + + local root_path=$(remove_trailing_slash $1) + local out_path=$(remove_trailing_slash $2) + local override=$3 + local override_switch=$(if [ "$override" = false ]; then printf -- "-n"; fi) + + cat | uniq | while read -r file_path; do + local path=$(remove_beginning_slash ${file_path#$root_path}) + local target=$out_path/$path + if [ "$override" = true ] || (! ([ -d "$target" ] || [ -e "$target" ])); then + mkdir -p $out_path/$(dirname $path) + cp -R $override_switch $root_path/$path $target + fi + done +} + +# args: +# zip_path - $1 +# out_path - $2 +extract_dotnet_package() { + eval $invocation + + local zip_path=$1 + local out_path=$2 + + local temp_out_path=$(mktemp -d $temporary_file_template) + + local failed=false + tar -xzf "$zip_path" -C "$temp_out_path" > /dev/null || failed=true + + local folders_with_version_regex='^.*/[0-9]+\.[0-9]+[^/]+/' + find $temp_out_path -type f | grep -Eo $folders_with_version_regex | copy_files_or_dirs_from_list $temp_out_path $out_path false + find $temp_out_path -type f | grep -Ev $folders_with_version_regex | copy_files_or_dirs_from_list $temp_out_path $out_path true + + rm -rf $temp_out_path + + if [ "$failed" = true ]; then + say_err "Extraction failed" + return 1 + fi +} + +# args: +# remote_path - $1 +# [out_path] - $2 - stdout if not provided +download() { + eval $invocation + + local remote_path=$1 + local out_path=${2:-} + + local failed=false + if [ -z "$out_path" ]; then + curl --fail -s $remote_path || failed=true + else + curl --fail -s -o $out_path $remote_path || failed=true + fi + + if [ "$failed" = true ]; then + say_err "Download failed" + return 1 + fi +} + +calculate_vars() { + eval $invocation + + azure_channel=$(get_azure_channel_from_channel "$channel") + say_verbose "azure_channel=$azure_channel" + + normalized_architecture=$(get_normalized_architecture_from_architecture "$architecture") + say_verbose "normalized_architecture=$normalized_architecture" + + specific_version=$(get_specific_version_from_version $azure_feed $azure_channel $normalized_architecture $version) + say_verbose "specific_version=$specific_version" + if [ -z "$specific_version" ]; then + say_err "Could not get version information." + return 1 + fi + + download_link=$(construct_download_link $azure_feed $azure_channel $normalized_architecture $specific_version) + say_verbose "download_link=$download_link" + + install_root=$(resolve_installation_path $install_dir) + say_verbose "install_root=$install_root" +} + +install_dotnet() { + eval $invocation + + if is_dotnet_package_installed $install_root "sdk" $specific_version; then + say ".NET SDK version $specific_version is already installed." + return 0 + fi + + mkdir -p $install_root + zip_path=$(mktemp $temporary_file_template) + say_verbose "Zip path: $zip_path" + + say "Downloading $download_link" + download "$download_link" $zip_path + say_verbose "Downloaded file exists and readable? $(if [ -r $zip_path ]; then echo "yes"; else echo "no"; fi)" + + say "Extracting zip" + extract_dotnet_package $zip_path $install_root + + return 0 +} + +local_version_file_relative_path="/.version" +bin_folder_relative_path="" +temporary_file_template="${TMPDIR:-/tmp}/dotnet.XXXXXXXXX" + +channel="rel-1.0.0" +version="Latest" +install_dir="" +architecture="" +debug_symbols=false +dry_run=false +no_path=false +azure_feed="https://dotnetcli.azureedge.net/dotnet" +uncached_feed="https://dotnetcli.blob.core.windows.net/dotnet" +verbose=false +shared_runtime=false + +while [ $# -ne 0 ] +do + name=$1 + case $name in + -c|--channel|-[Cc]hannel) + shift + channel=$1 + ;; + -v|--version|-[Vv]ersion) + shift + version="$1" + ;; + -i|--install-dir|-[Ii]nstall[Dd]ir) + shift + install_dir="$1" + ;; + --arch|--architecture|-[Aa]rch|-[Aa]rchitecture) + shift + architecture="$1" + ;; + --shared-runtime|-[Ss]hared[Rr]untime) + shared_runtime=true + ;; + --debug-symbols|-[Dd]ebug[Ss]ymbols) + debug_symbols=true + ;; + --dry-run|-[Dd]ry[Rr]un) + dry_run=true + ;; + --no-path|-[Nn]o[Pp]ath) + no_path=true + ;; + --verbose|-[Vv]erbose) + verbose=true + ;; + --azure-feed|-[Aa]zure[Ff]eed) + shift + azure_feed="$1" + ;; + -?|--?|-h|--help|-[Hh]elp) + script_name="$(basename $0)" + echo ".NET Tools Installer" + echo "Usage: $script_name [-c|--channel ] [-v|--version ] [-p|--prefix ]" + echo " $script_name -h|-?|--help" + echo "" + echo "$script_name is a simple command line interface for obtaining dotnet cli." + echo "" + echo "Options:" + echo " -c,--channel Download from the CHANNEL specified (default: $channel)." + echo " -Channel" + echo " -v,--version Use specific version, ``latest`` or ``lkg``. Defaults to ``latest``." + echo " -Version" + echo " -i,--install-dir Install under specified location (see Install Location below)" + echo " -InstallDir" + echo " --architecture Architecture of .NET Tools. Currently only x64 is supported." + echo " --arch,-Architecture,-Arch" + echo " --shared-runtime Installs just the shared runtime bits, not the entire SDK." + echo " -SharedRuntime" + echo " --debug-symbols,-DebugSymbols Specifies if symbols should be included in the installation." + echo " --dry-run,-DryRun Do not perform installation. Display download link." + echo " --no-path, -NoPath Do not set PATH for the current process." + echo " --verbose,-Verbose Display diagnostics information." + echo " --azure-feed,-AzureFeed Azure feed location. Defaults to $azure_feed" + echo " -?,--?,-h,--help,-Help Shows this help message" + echo "" + echo "Install Location:" + echo " Location is chosen in following order:" + echo " - --install-dir option" + echo " - Environmental variable DOTNET_INSTALL_DIR" + echo " - /usr/local/share/dotnet" + exit 0 + ;; + *) + say_err "Unknown argument \`$name\`" + exit 1 + ;; + esac + + shift +done + +check_min_reqs +calculate_vars +if [ "$dry_run" = true ]; then + say "Payload URL: $download_link" + say "Repeatable invocation: ./$(basename $0) --version $specific_version --channel $channel --install-dir $install_dir" + exit 0 +fi + +check_pre_reqs +install_dotnet + +bin_path=$(get_absolute_path $(combine_paths $install_root $bin_folder_relative_path)) +if [ "$no_path" = false ]; then + say "Adding to current process PATH: ``$bin_path``. Note: This change will be visible only when sourcing script." + export PATH=$bin_path:$PATH +else + say "Binaries of dotnet can be found in $bin_path" +fi + +say "Installation finished successfully." diff --git a/makefile.shade b/makefile.shade index 7ac55d8aa4..a20eb95f77 100644 --- a/makefile.shade +++ b/makefile.shade @@ -11,6 +11,25 @@ var AUTHORS='Microsoft Open Technologies, Inc.' use-standard-lifecycle k-standard-goals +#xunit-test + @{ + foreach (var project in Files.Include("test/*/project.json")) + { + var projectDir = Path.GetDirectoryName(project); + var projectName = Path.GetFileName(projectDir); + var targetDir = Path.Combine(projectDir, "bin", E("Configuration"), "netcoreapp1.0"); + var depsFile = Path.Combine(targetDir, projectName + ".deps.json"); + var configFile = Path.Combine(targetDir, projectName + ".runtimeconfig.json"); + var assembly = Path.Combine(targetDir, projectName + ".dll"); + var home = Environment.GetEnvironmentVariable("USERPROFILE") ?? Environment.GetEnvironmentVariable("HOME"); + var packageCache = Environment.GetEnvironmentVariable("NUGET_PACKAGES") ?? Path.Combine(home, ".nuget/packages"); + Exec(".build/.dotnet/dotnet", "exec --depsfile \"" + depsFile + "\"" + + " --runtimeconfig \"" + configFile + "\" " + + "\"" + Path.Combine(packageCache, "dotnet-test-xunit/2.2.0-preview2-build1029/lib/netcoreapp1.0/dotnet-test-xunit.dll") + "\" " + + "\"" + assembly+ "\" "); + } + } + #build-pack .build-compile target='compile' @{ if (Directory.Exists("src") && !IsLinux) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs index 6428f7f6fe..9e17328c69 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs @@ -53,7 +53,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests Scenario.AddTestProjectFolder(AppWithDeps); Scenario.AddTestProjectFolder(Dependency); - Scenario.Restore3(AppWithDeps); // restore3 should be transitive + Scenario.Restore(AppWithDeps); // restore3 should be transitive AppWithDepsFolder = Path.Combine(Scenario.WorkFolder, AppWithDeps); DependencyFolder = Path.Combine(Scenario.WorkFolder, Dependency); @@ -64,7 +64,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // Wait for the process to start using (var wait = new WaitForFileToChange(StatusFile)) { - RunDotNetWatch(new[] { "run3", StatusFile }, Path.Combine(Scenario.WorkFolder, AppWithDeps)); + RunDotNetWatch(new[] { "run", StatusFile }, Path.Combine(Scenario.WorkFolder, AppWithDeps)); wait.Wait(_defaultTimeout, expectedToChange: true, diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs index 31b0cb9167..912b243115 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs @@ -200,7 +200,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests StartedFile = StatusFile + ".started"; Scenario.AddTestProjectFolder(TestAppName); - Scenario.Restore3(TestAppName); + Scenario.Restore(TestAppName); TestAppFolder = Path.Combine(Scenario.WorkFolder, TestAppName); } @@ -210,7 +210,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // Wait for the process to start using (var wait = new WaitForFileToChange(StartedFile)) { - RunDotNetWatch(new[] { "run3", StatusFile }, Path.Combine(Scenario.WorkFolder, TestAppName)); + RunDotNetWatch(new[] { "run", StatusFile }, Path.Combine(Scenario.WorkFolder, TestAppName)); wait.Wait(_defaultTimeout, expectedToChange: true, diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs index 7c385a6ed1..81f5f962dc 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs @@ -29,7 +29,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // Wait for the process to start using (var wait = new WaitForFileToChange(scenario.StartedFile)) { - scenario.RunDotNetWatch(new[] { "run3", "-f", "netcoreapp1.0", scenario.StatusFile, "--no-exit" }); + scenario.RunDotNetWatch(new[] { "run", scenario.StatusFile, "--no-exit" }); wait.Wait(_defaultTimeout, expectedToChange: true, @@ -68,7 +68,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // Wait for the process to start using (var wait = new WaitForFileToChange(scenario.StartedFile)) { - scenario.RunDotNetWatch(new[] { "run3", "-f", "netcoreapp1.0", scenario.StatusFile }); + scenario.RunDotNetWatch(new[] { "run", scenario.StatusFile }); wait.Wait(_defaultTimeout, expectedToChange: true, @@ -115,7 +115,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests StartedFile = StatusFile + ".started"; Scenario.AddTestProjectFolder(TestAppName); - Scenario.Restore3(TestAppName); + Scenario.Restore(TestAppName); TestAppFolder = Path.Combine(Scenario.WorkFolder, TestAppName); } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs index 73eff54e4a..a8ce555257 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -57,41 +57,14 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } } - public void Restore(string project = null) - { - if (project == null) - { - project = WorkFolder; - } - else - { - project = Path.Combine(WorkFolder, project); - } - - _logger?.WriteLine($"Restoring project in {project}"); - - var restore = Command - .CreateDotNet("restore", new[] { project }) - .CaptureStdErr() - .CaptureStdOut() - .OnErrorLine(l => _logger?.WriteLine(l)) - .OnOutputLine(l => _logger?.WriteLine(l)) - .Execute(); - - if (restore.ExitCode != 0) - { - throw new Exception($"Exit code {restore.ExitCode}"); - } - } - - public void Restore3(string project) + public void Restore(string project) { project = Path.Combine(WorkFolder, project); _logger?.WriteLine($"Restoring msbuild project in {project}"); var restore = Command - .CreateDotNet("restore3", new [] { "/v:m" }) + .Create(new Muxer().MuxerPath, new[] { "restore", "/p:SkipInvalidConfigurations=true" }) .WorkingDirectory(project) .CaptureStdErr() .CaptureStdOut() diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj index f06027243d..9b081c4e68 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj @@ -9,8 +9,8 @@ - - + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj index 243360cf92..93df17cb59 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj @@ -8,8 +8,8 @@ - - + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj index cb088af5e3..74c2998f65 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj @@ -8,8 +8,8 @@ - - + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj index 67edbf1349..71c6a8d4ab 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj @@ -8,8 +8,8 @@ - - + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index ecaa2d4046..16ffa26808 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -10,7 +10,7 @@ } }, "dependencies": { - "dotnet-test-xunit": "2.2.0-*", + "dotnet-test-xunit": "2.2.0-preview2-build1029", "Microsoft.AspNetCore.Testing": "1.1.0-*", "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", "Microsoft.Extensions.Process.Sources": { diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryCSharpProject.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryCSharpProject.cs index bad0e0a949..f73ba47f5b 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryCSharpProject.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryCSharpProject.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Text; namespace Microsoft.DotNetWatcher.Tools.Tests @@ -28,14 +29,17 @@ namespace Microsoft.DotNetWatcher.Tools.Tests private readonly string _filename; private readonly TemporaryDirectory _directory; - private string[] _tfms; private List _items = new List(); + private List _properties = new List(); public TemporaryCSharpProject(string name, TemporaryDirectory directory) { Name = name; _filename = name + ".csproj"; _directory = directory; + + // workaround CLI issue + WithProperty("SkipInvalidConfigurations", "true"); } public string Name { get; } @@ -43,7 +47,28 @@ namespace Microsoft.DotNetWatcher.Tools.Tests public TemporaryCSharpProject WithTargetFrameworks(params string[] tfms) { - _tfms = tfms; + Debug.Assert(tfms.Length > 0); + var propertySpec = new PropertySpec + { + Value = string.Join(";", tfms) + }; + propertySpec.Name = tfms.Length == 1 + ? "TargetFramework" + : "TargetFrameworks"; + + return WithProperty(propertySpec); + } + + public TemporaryCSharpProject WithProperty(string name, string value) + => WithProperty(new PropertySpec { Name = name, Value = value }); + + public TemporaryCSharpProject WithProperty(PropertySpec property) + { + var sb = new StringBuilder(); + sb.Append('<').Append(property.Name).Append('>') + .Append(property.Value) + .Append("'); + _properties.Add(sb.ToString()); return this; } @@ -84,13 +109,7 @@ namespace Microsoft.DotNetWatcher.Tools.Tests public void Create() { - var tfm = _tfms == null || _tfms.Length == 0 - ? string.Empty - : _tfms.Length == 1 - ? $"{_tfms[0]}" - : $"{string.Join(";", _tfms)}"; - - _directory.CreateFile(_filename, string.Format(Template, tfm, string.Join("\r\n", _items))); + _directory.CreateFile(_filename, string.Format(Template, string.Join("\r\n", _properties), string.Join("\r\n", _items))); } public class ItemSpec @@ -102,5 +121,11 @@ namespace Microsoft.DotNetWatcher.Tools.Tests public bool Watch { get; set; } = true; public string Condition { get; set; } } + + public class PropertySpec + { + public string Name { get; set; } + public string Value { get; set; } + } } } \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json index f938c008bf..8aac1452b9 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json @@ -5,7 +5,7 @@ "debugType": "portable" }, "dependencies": { - "dotnet-test-xunit": "2.2.0-*", + "dotnet-test-xunit": "2.2.0-preview2-build1029", "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", "xunit": "2.2.0-*" }, diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json index 537709e5c8..7c6a5831f9 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json @@ -4,7 +4,7 @@ "keyFile": "../../tools/Key.snk" }, "dependencies": { - "dotnet-test-xunit": "2.2.0-*", + "dotnet-test-xunit": "2.2.0-preview2-build1029", "Microsoft.Extensions.SecretManager.Tools": "1.0.0-*", "xunit": "2.2.0-*" }, From d5c0c29a0c56affca88fd4a8d63ca54420bd4ad2 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 1 Nov 2016 18:20:21 -0700 Subject: [PATCH 0312/1029] Remove custom nuget feeds from main project feed config --- NuGet.config | 2 -- build.ps1 | 2 +- build.sh | 2 +- .../TestProjects/AppWithDeps/NuGet.config | 8 ++++++++ .../TestProjects/Dependency/NuGet.config | 8 ++++++++ .../TestProjects/GlobbingApp/NuGet.config | 8 ++++++++ .../TestProjects/NoDepsApp/NuGet.config | 8 ++++++++ .../Utilities/TemporaryDirectory.cs | 8 ++++---- 8 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/NuGet.config create mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/NuGet.config create mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/NuGet.config create mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NuGet.config diff --git a/NuGet.config b/NuGet.config index 3957d769d2..0fd623ffdd 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,8 +1,6 @@  - - diff --git a/build.ps1 b/build.ps1 index 441eef967c..2ca2a1b31c 100644 --- a/build.ps1 +++ b/build.ps1 @@ -68,6 +68,6 @@ $env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 $dotnetHome = "$buildFolder\.dotnet" mkdir $dotnetHome -ErrorAction Ignore | Out-Null & .\dotnet-install.ps1 -Version $(Get-Content .\CliToolVersion.txt) -InstallDir $dotnetHome -& .\dotnet-install.ps1 -Version 1.1.0 -Channel release/1.1.0 -SharedRuntime -InstallDir $dotnetHome +& .\dotnet-install.ps1 -Version 1.1.0-preview1-001100-00 -Channel release/1.1.0 -SharedRuntime -InstallDir $dotnetHome &"$buildFile" $args \ No newline at end of file diff --git a/build.sh b/build.sh index cdfdace2ba..32e70da1a4 100755 --- a/build.sh +++ b/build.sh @@ -47,6 +47,6 @@ export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 dotnetHome="$buildFolder/.dotnet" mkdir -p $dotnetHome ./dotnet-install.sh --install-dir $dotnetHome --version $(cat CliToolVersion.txt) -./dotnet-install.sh --install-dir $dotnetHome --version 1.1.0 --channel release/1.1.0 --shared-runtime +./dotnet-install.sh --install-dir $dotnetHome --version 1.1.0-preview1-001100-00 --channel release/1.1.0 --shared-runtime $buildFile -r $repoFolder "$@" \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/NuGet.config b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/NuGet.config new file mode 100644 index 0000000000..d8093c7fa9 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/NuGet.config @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/NuGet.config b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/NuGet.config new file mode 100644 index 0000000000..d8093c7fa9 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/NuGet.config @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/NuGet.config b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/NuGet.config new file mode 100644 index 0000000000..d8093c7fa9 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/NuGet.config @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NuGet.config b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NuGet.config new file mode 100644 index 0000000000..d8093c7fa9 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NuGet.config @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryDirectory.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryDirectory.cs index ee90092e22..3ec8d6bbee 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryDirectory.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryDirectory.cs @@ -11,7 +11,7 @@ namespace Microsoft.DotNetWatcher.Tools.Tests { private List _projects = new List(); private List _subdirs = new List(); - private List _files = new List(); + private Dictionary _files = new Dictionary(); private TemporaryDirectory _parent; public TemporaryDirectory() @@ -47,9 +47,9 @@ namespace Microsoft.DotNetWatcher.Tools.Tests return project; } - public TemporaryDirectory WithFile(string name) + public TemporaryDirectory WithFile(string name, string contents = "") { - _files.Add(name); + _files[name] = contents; return this; } @@ -78,7 +78,7 @@ namespace Microsoft.DotNetWatcher.Tools.Tests foreach (var file in _files) { - CreateFile(file, string.Empty); + CreateFile(file.Key, file.Value); } } From 975e22ad06e92a3f963a044f6010fcdee0642844 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 2 Nov 2016 09:27:21 -0700 Subject: [PATCH 0313/1029] Drop tools back to Microsoft.NETCore.App 1.0.1 --- CliToolVersion.txt | 2 +- build.ps1 | 1 - build.sh | 1 - src/Microsoft.DotNet.Watcher.Tools/project.json | 6 +----- .../project.json | 4 ++-- src/Microsoft.Extensions.SecretManager.Tools/project.json | 2 +- .../project.json | 2 +- test/Microsoft.DotNet.Watcher.Tools.Tests/project.json | 2 +- .../UserSecretsTestFixture.cs | 2 +- .../project.json | 2 +- 10 files changed, 9 insertions(+), 15 deletions(-) diff --git a/CliToolVersion.txt b/CliToolVersion.txt index 6b51205059..08d0462469 100644 --- a/CliToolVersion.txt +++ b/CliToolVersion.txt @@ -1 +1 @@ -1.0.0-preview3-003981 \ No newline at end of file +1.0.0-preview3-004007 \ No newline at end of file diff --git a/build.ps1 b/build.ps1 index 2ca2a1b31c..6650bad342 100644 --- a/build.ps1 +++ b/build.ps1 @@ -68,6 +68,5 @@ $env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 $dotnetHome = "$buildFolder\.dotnet" mkdir $dotnetHome -ErrorAction Ignore | Out-Null & .\dotnet-install.ps1 -Version $(Get-Content .\CliToolVersion.txt) -InstallDir $dotnetHome -& .\dotnet-install.ps1 -Version 1.1.0-preview1-001100-00 -Channel release/1.1.0 -SharedRuntime -InstallDir $dotnetHome &"$buildFile" $args \ No newline at end of file diff --git a/build.sh b/build.sh index 32e70da1a4..6fde860cce 100755 --- a/build.sh +++ b/build.sh @@ -47,6 +47,5 @@ export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 dotnetHome="$buildFolder/.dotnet" mkdir -p $dotnetHome ./dotnet-install.sh --install-dir $dotnetHome --version $(cat CliToolVersion.txt) -./dotnet-install.sh --install-dir $dotnetHome --version 1.1.0-preview1-001100-00 --channel release/1.1.0 --shared-runtime $buildFile -r $repoFolder "$@" \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index 21d7ce1d69..804dcd5b4e 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -24,10 +24,6 @@ } }, "dependencies": { - "Microsoft.DotNet.ProjectModel": { - "version": "1.0.0-*", - "exclude": "all" - }, "Microsoft.DotNet.Cli.Utils": "1.0.0-*", "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", "Microsoft.Extensions.Logging": "1.1.0-*", @@ -38,7 +34,7 @@ }, "Microsoft.NETCore.App": { "type": "platform", - "version": "1.1.0-*" + "version": "1.0.1" } }, "frameworks": { diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json index b860143998..5b16064ac7 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json @@ -23,10 +23,10 @@ "Microsoft.Extensions.Logging": "1.1.0-*", "Microsoft.Extensions.Logging.Console": "1.1.0-*", "Microsoft.NETCore.App": { - "version": "1.1.0-*", + "version": "1.0.1", "type": "platform" }, - "System.Data.SqlClient": "4.3.0-*" + "System.Data.SqlClient": "4.1.0" }, "frameworks": { "netcoreapp1.0": {} diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index 1f2aaa7e15..7fa5af3662 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -35,7 +35,7 @@ "Microsoft.Extensions.Configuration.UserSecrets": "1.1.0-*", "Microsoft.Extensions.Logging": "1.1.0-*", "Microsoft.NETCore.App": { - "version": "1.1.0-*", + "version": "1.0.1", "type": "platform" } }, diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index 16ffa26808..a1a2015d4a 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -24,7 +24,7 @@ "dependencies": { "Microsoft.NETCore.App": { "type": "platform", - "version": "1.1.0-*" + "version": "1.0.1" } } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json index 8aac1452b9..49c0a70124 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json @@ -13,7 +13,7 @@ "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { - "version": "1.1.0-*", + "version": "1.0.1", "type": "platform" } } diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs index cf92e9b040..a3ff3dfbb1 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs @@ -45,7 +45,7 @@ namespace Microsoft.Extensions.Configuration.UserSecrets.Tests - + diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json index 7c6a5831f9..3512358403 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json @@ -13,7 +13,7 @@ "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { - "version": "1.1.0-*", + "version": "1.0.1", "type": "platform" } } From b4027529a7f954f4fee6d72922edf952cb51aa0a Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 2 Nov 2016 10:38:39 -0700 Subject: [PATCH 0314/1029] Bundle deps.json files in tools packages --- .../Microsoft.DotNet.Watcher.Tools.nuspec | 5 +-- .../project.json | 5 +++ ....Extensions.Caching.SqlConfig.Tools.nuspec | 5 +-- ...soft.Extensions.SecretManager.Tools.nuspec | 5 +-- .../project.json | 5 +++ tools/NuGetPackager/PackCommand.cs | 31 ++++++++++++++----- 6 files changed, 43 insertions(+), 13 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec index 259eaa5cfb..74300b89ea 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec @@ -23,8 +23,9 @@ - - + + + \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index 804dcd5b4e..502c402f2e 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -23,6 +23,11 @@ } } }, + "publishOptions": { + "include": [ + "tools/*.targets" + ] + }, "dependencies": { "Microsoft.DotNet.Cli.Utils": "1.0.0-*", "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec index 82ab8374f4..4b56ae8719 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec @@ -23,7 +23,8 @@ - - + + + \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec index db6cb0bf93..ac4bfbfe7b 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec @@ -26,7 +26,8 @@ - - + + + \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index 7fa5af3662..79b230a15f 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -29,6 +29,11 @@ } } }, + "publishOptions": { + "include": [ + "*.targets" + ] + }, "dependencies": { "Microsoft.DotNet.Cli.Utils": "1.0.0-*", "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", diff --git a/tools/NuGetPackager/PackCommand.cs b/tools/NuGetPackager/PackCommand.cs index 687d0e0d64..fd76e86692 100644 --- a/tools/NuGetPackager/PackCommand.cs +++ b/tools/NuGetPackager/PackCommand.cs @@ -29,15 +29,31 @@ namespace NuGetPackager public async Task PackAsync(string nuspec, string config, string outputDir) { var project = ProjectContext.Create(Path.GetDirectoryName(nuspec), FrameworkConstants.CommonFrameworks.NetCoreApp10); - var props = "configuration=" + config; var idx = 0; + var props = ""; + var first = false; foreach (var depVersion in GetDependencies(project).OrderBy(p => p.Item1).Select(p => p.Item2)) { - props += $";dep_{++idx}={depVersion}"; - } + if (first) + { + first = false; + } + else + { + props += ";"; + } - var buildCommand = Command.CreateDotNet("build", - new[] { project.ProjectFile.ProjectFilePath, "--configuration", config }, + props += $"dep_{++idx}={depVersion}"; + } + var publishDir = Path.Combine(Directory.GetCurrentDirectory(), "artifacts/build", project.ProjectFile.Name); + if (Directory.Exists(publishDir)) + { + Directory.Delete(publishDir, recursive: true); + } + Directory.CreateDirectory(publishDir); + + var buildCommand = Command.CreateDotNet("publish", + new[] { project.ProjectFile.ProjectFilePath, "--configuration", config, "--output", publishDir }, configuration: config); if (buildCommand.Execute().ExitCode != 0) @@ -53,7 +69,8 @@ namespace NuGetPackager "-Verbosity", "detailed", "-OutputDirectory", outputDir, "-Version", version, - "-Properties", props); + "-Properties", props, + "-BasePath", publishDir); } private IEnumerable> GetDependencies(ProjectContext context) @@ -136,7 +153,7 @@ namespace NuGetPackager } Console.WriteLine("log : Downloading nuget.exe 3.5.0-rc1".Bold().Black()); - + var response = await new HttpClient().GetAsync("https://dist.nuget.org/win-x86-commandline/v3.5.0-rc1/NuGet.exe"); using (var file = new FileStream(nugetPath, FileMode.CreateNew)) { From 54031fb3991cad24a58be93bffcc02959660ec2b Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 2 Nov 2016 13:41:59 -0700 Subject: [PATCH 0315/1029] Downgrade to 1.0.1 --- NuGet.config | 2 +- .../Microsoft.DotNet.Watcher.Tools.nuspec | 7 +- .../project.json | 12 +- .../project.json | 6 +- ...soft.Extensions.SecretManager.Tools.nuspec | 9 +- .../project.json | 10 +- src/Shared/CommandLine/AnsiConsole.cs | 143 +++++ src/Shared/CommandLine/CommandArgument.cs | 29 + .../CommandLine/CommandLineApplication.cs | 555 ++++++++++++++++++ src/Shared/CommandLine/CommandOption.cs | 108 ++++ src/Shared/CommandLine/CommandOptionType.cs | 13 + .../CommandLine/CommandParsingException.cs | 18 + .../project.json | 6 +- .../project.json | 2 +- .../SetCommandTest.cs | 26 +- .../project.json | 2 +- tools/NuGetPackager/project.json | 10 +- 17 files changed, 924 insertions(+), 34 deletions(-) create mode 100644 src/Shared/CommandLine/AnsiConsole.cs create mode 100644 src/Shared/CommandLine/CommandArgument.cs create mode 100644 src/Shared/CommandLine/CommandLineApplication.cs create mode 100644 src/Shared/CommandLine/CommandOption.cs create mode 100644 src/Shared/CommandLine/CommandOptionType.cs create mode 100644 src/Shared/CommandLine/CommandParsingException.cs diff --git a/NuGet.config b/NuGet.config index 0fd623ffdd..4017b7ad58 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@  - + diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec index 74300b89ea..0be0f55cbb 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec @@ -15,10 +15,9 @@ - - - - + + + diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index 502c402f2e..742e7e484c 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -21,6 +21,9 @@ "mappings": { "dotnetwatch.targets": "dotnetwatch.targets" } + }, + "compile": { + "include": "../Shared/**/*.cs" } }, "publishOptions": { @@ -29,13 +32,12 @@ ] }, "dependencies": { - "Microsoft.DotNet.Cli.Utils": "1.0.0-*", - "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", - "Microsoft.Extensions.Logging": "1.1.0-*", - "Microsoft.Extensions.Logging.Console": "1.1.0-*", + "Microsoft.DotNet.Cli.Utils": "1.0.0-preview2-003121", + "Microsoft.Extensions.Logging": "1.0.0", + "Microsoft.Extensions.Logging.Console": "1.0.0", "Microsoft.Extensions.Process.Sources": { "type": "build", - "version": "1.1.0-*" + "version": "1.0.0" }, "Microsoft.NETCore.App": { "type": "platform", diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json index 5b16064ac7..3ff33ed3bd 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json @@ -19,9 +19,9 @@ ] }, "dependencies": { - "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", - "Microsoft.Extensions.Logging": "1.1.0-*", - "Microsoft.Extensions.Logging.Console": "1.1.0-*", + "Microsoft.Extensions.CommandLineUtils": "1.0.0", + "Microsoft.Extensions.Logging": "1.0.0", + "Microsoft.Extensions.Logging.Console": "1.0.0", "Microsoft.NETCore.App": { "version": "1.0.1", "type": "platform" diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec index ac4bfbfe7b..f8c596e5e9 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec @@ -17,10 +17,9 @@ - - - - + + + @@ -28,6 +27,6 @@ - + \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index 79b230a15f..d7a2e799bf 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -10,6 +10,9 @@ "mappings": { "FindUserSecretsProperty.targets": "./FindUserSecretsProperty.targets" } + }, + "compile": { + "include": "../Shared/**/*.cs" } }, "description": "Command line tool to manage user secrets for Microsoft.Extensions.Configuration.", @@ -35,10 +38,9 @@ ] }, "dependencies": { - "Microsoft.DotNet.Cli.Utils": "1.0.0-*", - "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", - "Microsoft.Extensions.Configuration.UserSecrets": "1.1.0-*", - "Microsoft.Extensions.Logging": "1.1.0-*", + "Microsoft.DotNet.Cli.Utils": "1.0.0-preview2-003121", + "Microsoft.Extensions.Configuration.UserSecrets": "1.0.0", + "Microsoft.Extensions.Logging": "1.0.0", "Microsoft.NETCore.App": { "version": "1.0.1", "type": "platform" diff --git a/src/Shared/CommandLine/AnsiConsole.cs b/src/Shared/CommandLine/AnsiConsole.cs new file mode 100644 index 0000000000..79d705f25e --- /dev/null +++ b/src/Shared/CommandLine/AnsiConsole.cs @@ -0,0 +1,143 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; + +namespace Microsoft.Extensions.CommandLineUtils +{ + public class AnsiConsole + { + private AnsiConsole(TextWriter writer, bool useConsoleColor) + { + Writer = writer; + + _useConsoleColor = useConsoleColor; + if (_useConsoleColor) + { + OriginalForegroundColor = Console.ForegroundColor; + } + } + + private int _boldRecursion; + private bool _useConsoleColor; + + public static AnsiConsole GetOutput(bool useConsoleColor) + { + return new AnsiConsole(Console.Out, useConsoleColor); + } + + public static AnsiConsole GetError(bool useConsoleColor) + { + return new AnsiConsole(Console.Error, useConsoleColor); + } + + public TextWriter Writer { get; } + + public ConsoleColor OriginalForegroundColor { get; } + + private void SetColor(ConsoleColor color) + { + Console.ForegroundColor = (ConsoleColor)(((int)Console.ForegroundColor & 0x08) | ((int)color & 0x07)); + } + + private void SetBold(bool bold) + { + _boldRecursion += bold ? 1 : -1; + if (_boldRecursion > 1 || (_boldRecursion == 1 && !bold)) + { + return; + } + + Console.ForegroundColor = (ConsoleColor)((int)Console.ForegroundColor ^ 0x08); + } + + public void WriteLine(string message) + { + if (!_useConsoleColor) + { + Writer.WriteLine(message); + return; + } + + var escapeScan = 0; + for (; ;) + { + var escapeIndex = message.IndexOf("\x1b[", escapeScan); + if (escapeIndex == -1) + { + var text = message.Substring(escapeScan); + Writer.Write(text); + break; + } + else + { + var startIndex = escapeIndex + 2; + var endIndex = startIndex; + while (endIndex != message.Length && + message[endIndex] >= 0x20 && + message[endIndex] <= 0x3f) + { + endIndex += 1; + } + + var text = message.Substring(escapeScan, escapeIndex - escapeScan); + Writer.Write(text); + if (endIndex == message.Length) + { + break; + } + + switch (message[endIndex]) + { + case 'm': + int value; + if (int.TryParse(message.Substring(startIndex, endIndex - startIndex), out value)) + { + switch (value) + { + case 1: + SetBold(true); + break; + case 22: + SetBold(false); + break; + case 30: + SetColor(ConsoleColor.Black); + break; + case 31: + SetColor(ConsoleColor.Red); + break; + case 32: + SetColor(ConsoleColor.Green); + break; + case 33: + SetColor(ConsoleColor.Yellow); + break; + case 34: + SetColor(ConsoleColor.Blue); + break; + case 35: + SetColor(ConsoleColor.Magenta); + break; + case 36: + SetColor(ConsoleColor.Cyan); + break; + case 37: + SetColor(ConsoleColor.Gray); + break; + case 39: + SetColor(OriginalForegroundColor); + break; + } + } + break; + } + + escapeScan = endIndex + 1; + } + } + Writer.WriteLine(); + } + } +} diff --git a/src/Shared/CommandLine/CommandArgument.cs b/src/Shared/CommandLine/CommandArgument.cs new file mode 100644 index 0000000000..c687485e33 --- /dev/null +++ b/src/Shared/CommandLine/CommandArgument.cs @@ -0,0 +1,29 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.Extensions.CommandLineUtils +{ + public class CommandArgument + { + public CommandArgument() + { + Values = new List(); + } + + public string Name { get; set; } + public bool ShowInHelpText { get; set; } = true; + public string Description { get; set; } + public List Values { get; private set; } + public bool MultipleValues { get; set; } + public string Value + { + get + { + return Values.FirstOrDefault(); + } + } + } +} diff --git a/src/Shared/CommandLine/CommandLineApplication.cs b/src/Shared/CommandLine/CommandLineApplication.cs new file mode 100644 index 0000000000..0623e5104e --- /dev/null +++ b/src/Shared/CommandLine/CommandLineApplication.cs @@ -0,0 +1,555 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.Extensions.CommandLineUtils +{ + public class CommandLineApplication + { + // Indicates whether the parser should throw an exception when it runs into an unexpected argument. + // If this field is set to false, the parser will stop parsing when it sees an unexpected argument, and all + // remaining arguments, including the first unexpected argument, will be stored in RemainingArguments property. + private readonly bool _throwOnUnexpectedArg; + + public CommandLineApplication(bool throwOnUnexpectedArg = true) + { + _throwOnUnexpectedArg = throwOnUnexpectedArg; + Options = new List(); + Arguments = new List(); + Commands = new List(); + RemainingArguments = new List(); + Invoke = () => 0; + } + + public CommandLineApplication Parent { get; set; } + public string Name { get; set; } + public string FullName { get; set; } + public string Syntax { get; set; } + public string Description { get; set; } + public bool ShowInHelpText { get; set; } = true; + public string ExtendedHelpText { get; set; } + public readonly List Options; + public CommandOption OptionHelp { get; private set; } + public CommandOption OptionVersion { get; private set; } + public readonly List Arguments; + public readonly List RemainingArguments; + public bool IsShowingInformation { get; protected set; } // Is showing help or version? + public Func Invoke { get; set; } + public Func LongVersionGetter { get; set; } + public Func ShortVersionGetter { get; set; } + public readonly List Commands; + public bool AllowArgumentSeparator { get; set; } + public TextWriter Out { get; set; } = Console.Out; + public TextWriter Error { get; set; } = Console.Error; + + public IEnumerable GetOptions() + { + var expr = Options.AsEnumerable(); + var rootNode = this; + while (rootNode.Parent != null) + { + rootNode = rootNode.Parent; + expr = expr.Concat(rootNode.Options.Where(o => o.Inherited)); + } + + return expr; + } + + public CommandLineApplication Command(string name, Action configuration, + bool throwOnUnexpectedArg = true) + { + var command = new CommandLineApplication(throwOnUnexpectedArg) { Name = name, Parent = this }; + Commands.Add(command); + configuration(command); + return command; + } + + public CommandOption Option(string template, string description, CommandOptionType optionType) + => Option(template, description, optionType, _ => { }, inherited: false); + + public CommandOption Option(string template, string description, CommandOptionType optionType, bool inherited) + => Option(template, description, optionType, _ => { }, inherited); + + public CommandOption Option(string template, string description, CommandOptionType optionType, Action configuration) + => Option(template, description, optionType, configuration, inherited: false); + + public CommandOption Option(string template, string description, CommandOptionType optionType, Action configuration, bool inherited) + { + var option = new CommandOption(template, optionType) + { + Description = description, + Inherited = inherited + }; + Options.Add(option); + configuration(option); + return option; + } + + public CommandArgument Argument(string name, string description, bool multipleValues = false) + { + return Argument(name, description, _ => { }, multipleValues); + } + + public CommandArgument Argument(string name, string description, Action configuration, bool multipleValues = false) + { + var lastArg = Arguments.LastOrDefault(); + if (lastArg != null && lastArg.MultipleValues) + { + var message = string.Format("The last argument '{0}' accepts multiple values. No more argument can be added.", + lastArg.Name); + throw new InvalidOperationException(message); + } + + var argument = new CommandArgument { Name = name, Description = description, MultipleValues = multipleValues }; + Arguments.Add(argument); + configuration(argument); + return argument; + } + + public void OnExecute(Func invoke) + { + Invoke = invoke; + } + + public void OnExecute(Func> invoke) + { + Invoke = () => invoke().Result; + } + public int Execute(params string[] args) + { + CommandLineApplication command = this; + CommandOption option = null; + IEnumerator arguments = null; + + for (var index = 0; index < args.Length; index++) + { + var arg = args[index]; + var processed = false; + if (!processed && option == null) + { + string[] longOption = null; + string[] shortOption = null; + + if (arg.StartsWith("--")) + { + longOption = arg.Substring(2).Split(new[] { ':', '=' }, 2); + } + else if (arg.StartsWith("-")) + { + shortOption = arg.Substring(1).Split(new[] { ':', '=' }, 2); + } + if (longOption != null) + { + processed = true; + var longOptionName = longOption[0]; + option = command.GetOptions().SingleOrDefault(opt => string.Equals(opt.LongName, longOptionName, StringComparison.Ordinal)); + + if (option == null) + { + if (string.IsNullOrEmpty(longOptionName) && !command._throwOnUnexpectedArg && AllowArgumentSeparator) + { + // skip over the '--' argument separator + index++; + } + + HandleUnexpectedArg(command, args, index, argTypeName: "option"); + break; + } + + // If we find a help/version option, show information and stop parsing + if (command.OptionHelp == option) + { + command.ShowHelp(); + return 0; + } + else if (command.OptionVersion == option) + { + command.ShowVersion(); + return 0; + } + + if (longOption.Length == 2) + { + if (!option.TryParse(longOption[1])) + { + command.ShowHint(); + throw new CommandParsingException(command, $"Unexpected value '{longOption[1]}' for option '{option.LongName}'"); + } + option = null; + } + else if (option.OptionType == CommandOptionType.NoValue) + { + // No value is needed for this option + option.TryParse(null); + option = null; + } + } + if (shortOption != null) + { + processed = true; + option = command.GetOptions().SingleOrDefault(opt => string.Equals(opt.ShortName, shortOption[0], StringComparison.Ordinal)); + + // If not a short option, try symbol option + if (option == null) + { + option = command.GetOptions().SingleOrDefault(opt => string.Equals(opt.SymbolName, shortOption[0], StringComparison.Ordinal)); + } + + if (option == null) + { + HandleUnexpectedArg(command, args, index, argTypeName: "option"); + break; + } + + // If we find a help/version option, show information and stop parsing + if (command.OptionHelp == option) + { + command.ShowHelp(); + return 0; + } + else if (command.OptionVersion == option) + { + command.ShowVersion(); + return 0; + } + + if (shortOption.Length == 2) + { + if (!option.TryParse(shortOption[1])) + { + command.ShowHint(); + throw new CommandParsingException(command, $"Unexpected value '{shortOption[1]}' for option '{option.LongName}'"); + } + option = null; + } + else if (option.OptionType == CommandOptionType.NoValue) + { + // No value is needed for this option + option.TryParse(null); + option = null; + } + } + } + + if (!processed && option != null) + { + processed = true; + if (!option.TryParse(arg)) + { + command.ShowHint(); + throw new CommandParsingException(command, $"Unexpected value '{arg}' for option '{option.LongName}'"); + } + option = null; + } + + if (!processed && arguments == null) + { + var currentCommand = command; + foreach (var subcommand in command.Commands) + { + if (string.Equals(subcommand.Name, arg, StringComparison.OrdinalIgnoreCase)) + { + processed = true; + command = subcommand; + break; + } + } + + // If we detect a subcommand + if (command != currentCommand) + { + processed = true; + } + } + if (!processed) + { + if (arguments == null) + { + arguments = new CommandArgumentEnumerator(command.Arguments.GetEnumerator()); + } + if (arguments.MoveNext()) + { + processed = true; + arguments.Current.Values.Add(arg); + } + } + if (!processed) + { + HandleUnexpectedArg(command, args, index, argTypeName: "command or argument"); + break; + } + } + + if (option != null) + { + command.ShowHint(); + throw new CommandParsingException(command, $"Missing value for option '{option.LongName}'"); + } + + return command.Invoke(); + } + + // Helper method that adds a help option + public CommandOption HelpOption(string template) + { + // Help option is special because we stop parsing once we see it + // So we store it separately for further use + OptionHelp = Option(template, "Show help information", CommandOptionType.NoValue); + + return OptionHelp; + } + + public CommandOption VersionOption(string template, + string shortFormVersion, + string longFormVersion = null) + { + if (longFormVersion == null) + { + return VersionOption(template, () => shortFormVersion); + } + else + { + return VersionOption(template, () => shortFormVersion, () => longFormVersion); + } + } + + // Helper method that adds a version option + public CommandOption VersionOption(string template, + Func shortFormVersionGetter, + Func longFormVersionGetter = null) + { + // Version option is special because we stop parsing once we see it + // So we store it separately for further use + OptionVersion = Option(template, "Show version information", CommandOptionType.NoValue); + ShortVersionGetter = shortFormVersionGetter; + LongVersionGetter = longFormVersionGetter ?? shortFormVersionGetter; + + return OptionVersion; + } + + // Show short hint that reminds users to use help option + public void ShowHint() + { + if (OptionHelp != null) + { + Out.WriteLine(string.Format("Specify --{0} for a list of available options and commands.", OptionHelp.LongName)); + } + } + + // Show full help + public void ShowHelp(string commandName = null) + { + for (var cmd = this; cmd != null; cmd = cmd.Parent) + { + cmd.IsShowingInformation = true; + } + + Out.WriteLine(GetHelpText(commandName)); + } + + public virtual string GetHelpText(string commandName = null) + { + var headerBuilder = new StringBuilder("Usage:"); + for (var cmd = this; cmd != null; cmd = cmd.Parent) + { + headerBuilder.Insert(6, string.Format(" {0}", cmd.Name)); + } + + CommandLineApplication target; + + if (commandName == null || string.Equals(Name, commandName, StringComparison.OrdinalIgnoreCase)) + { + target = this; + } + else + { + target = Commands.SingleOrDefault(cmd => string.Equals(cmd.Name, commandName, StringComparison.OrdinalIgnoreCase)); + + if (target != null) + { + headerBuilder.AppendFormat(" {0}", commandName); + } + else + { + // The command name is invalid so don't try to show help for something that doesn't exist + target = this; + } + + } + + var optionsBuilder = new StringBuilder(); + var commandsBuilder = new StringBuilder(); + var argumentsBuilder = new StringBuilder(); + + var arguments = target.Arguments.Where(a => a.ShowInHelpText).ToList(); + if (arguments.Any()) + { + headerBuilder.Append(" [arguments]"); + + argumentsBuilder.AppendLine(); + argumentsBuilder.AppendLine("Arguments:"); + var maxArgLen = arguments.Max(a => a.Name.Length); + var outputFormat = string.Format(" {{0, -{0}}}{{1}}", maxArgLen + 2); + foreach (var arg in arguments) + { + argumentsBuilder.AppendFormat(outputFormat, arg.Name, arg.Description); + argumentsBuilder.AppendLine(); + } + } + + var options = target.GetOptions().Where(o => o.ShowInHelpText).ToList(); + if (options.Any()) + { + headerBuilder.Append(" [options]"); + + optionsBuilder.AppendLine(); + optionsBuilder.AppendLine("Options:"); + var maxOptLen = options.Max(o => o.Template.Length); + var outputFormat = string.Format(" {{0, -{0}}}{{1}}", maxOptLen + 2); + foreach (var opt in options) + { + optionsBuilder.AppendFormat(outputFormat, opt.Template, opt.Description); + optionsBuilder.AppendLine(); + } + } + + var commands = target.Commands.Where(c => c.ShowInHelpText).ToList(); + if (commands.Any()) + { + headerBuilder.Append(" [command]"); + + commandsBuilder.AppendLine(); + commandsBuilder.AppendLine("Commands:"); + var maxCmdLen = commands.Max(c => c.Name.Length); + var outputFormat = string.Format(" {{0, -{0}}}{{1}}", maxCmdLen + 2); + foreach (var cmd in commands.OrderBy(c => c.Name)) + { + commandsBuilder.AppendFormat(outputFormat, cmd.Name, cmd.Description); + commandsBuilder.AppendLine(); + } + + if (OptionHelp != null) + { + commandsBuilder.AppendLine(); + commandsBuilder.AppendFormat($"Use \"{target.Name} [command] --{OptionHelp.LongName}\" for more information about a command."); + commandsBuilder.AppendLine(); + } + } + + if (target.AllowArgumentSeparator) + { + headerBuilder.Append(" [[--] ...]"); + } + + headerBuilder.AppendLine(); + + var nameAndVersion = new StringBuilder(); + nameAndVersion.AppendLine(GetFullNameAndVersion()); + nameAndVersion.AppendLine(); + + return nameAndVersion.ToString() + + headerBuilder.ToString() + + argumentsBuilder.ToString() + + optionsBuilder.ToString() + + commandsBuilder.ToString() + + target.ExtendedHelpText; + } + + public void ShowVersion() + { + for (var cmd = this; cmd != null; cmd = cmd.Parent) + { + cmd.IsShowingInformation = true; + } + + Out.WriteLine(FullName); + Out.WriteLine(LongVersionGetter()); + } + + public string GetFullNameAndVersion() + { + return ShortVersionGetter == null ? FullName : string.Format("{0} {1}", FullName, ShortVersionGetter()); + } + + public void ShowRootCommandFullNameAndVersion() + { + var rootCmd = this; + while (rootCmd.Parent != null) + { + rootCmd = rootCmd.Parent; + } + + Out.WriteLine(rootCmd.GetFullNameAndVersion()); + Out.WriteLine(); + } + + private void HandleUnexpectedArg(CommandLineApplication command, string[] args, int index, string argTypeName) + { + if (command._throwOnUnexpectedArg) + { + command.ShowHint(); + throw new CommandParsingException(command, $"Unrecognized {argTypeName} '{args[index]}'"); + } + else + { + // All remaining arguments are stored for further use + command.RemainingArguments.AddRange(new ArraySegment(args, index, args.Length - index)); + } + } + + private class CommandArgumentEnumerator : IEnumerator + { + private readonly IEnumerator _enumerator; + + public CommandArgumentEnumerator(IEnumerator enumerator) + { + _enumerator = enumerator; + } + + public CommandArgument Current + { + get + { + return _enumerator.Current; + } + } + + object IEnumerator.Current + { + get + { + return Current; + } + } + + public void Dispose() + { + _enumerator.Dispose(); + } + + public bool MoveNext() + { + if (Current == null || !Current.MultipleValues) + { + return _enumerator.MoveNext(); + } + + // If current argument allows multiple values, we don't move forward and + // all later values will be added to current CommandArgument.Values + return true; + } + + public void Reset() + { + _enumerator.Reset(); + } + } + } +} diff --git a/src/Shared/CommandLine/CommandOption.cs b/src/Shared/CommandLine/CommandOption.cs new file mode 100644 index 0000000000..8f6d6af4ad --- /dev/null +++ b/src/Shared/CommandLine/CommandOption.cs @@ -0,0 +1,108 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.Extensions.CommandLineUtils +{ + public class CommandOption + { + public CommandOption(string template, CommandOptionType optionType) + { + Template = template; + OptionType = optionType; + Values = new List(); + + foreach (var part in Template.Split(new[] { ' ', '|' }, StringSplitOptions.RemoveEmptyEntries)) + { + if (part.StartsWith("--")) + { + LongName = part.Substring(2); + } + else if (part.StartsWith("-")) + { + var optName = part.Substring(1); + + // If there is only one char and it is not an English letter, it is a symbol option (e.g. "-?") + if (optName.Length == 1 && !IsEnglishLetter(optName[0])) + { + SymbolName = optName; + } + else + { + ShortName = optName; + } + } + else if (part.StartsWith("<") && part.EndsWith(">")) + { + ValueName = part.Substring(1, part.Length - 2); + } + else + { + throw new ArgumentException($"Invalid template pattern '{template}'", nameof(template)); + } + } + + if (string.IsNullOrEmpty(LongName) && string.IsNullOrEmpty(ShortName) && string.IsNullOrEmpty(SymbolName)) + { + throw new ArgumentException($"Invalid template pattern '{template}'", nameof(template)); + } + } + + public string Template { get; set; } + public string ShortName { get; set; } + public string LongName { get; set; } + public string SymbolName { get; set; } + public string ValueName { get; set; } + public string Description { get; set; } + public List Values { get; private set; } + public CommandOptionType OptionType { get; private set; } + public bool ShowInHelpText { get; set; } = true; + public bool Inherited { get; set; } + + public bool TryParse(string value) + { + switch (OptionType) + { + case CommandOptionType.MultipleValue: + Values.Add(value); + break; + case CommandOptionType.SingleValue: + if (Values.Any()) + { + return false; + } + Values.Add(value); + break; + case CommandOptionType.NoValue: + if (value != null) + { + return false; + } + // Add a value to indicate that this option was specified + Values.Add("on"); + break; + default: + break; + } + return true; + } + + public bool HasValue() + { + return Values.Any(); + } + + public string Value() + { + return HasValue() ? Values[0] : null; + } + + private bool IsEnglishLetter(char c) + { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); + } + } +} \ No newline at end of file diff --git a/src/Shared/CommandLine/CommandOptionType.cs b/src/Shared/CommandLine/CommandOptionType.cs new file mode 100644 index 0000000000..759182ca91 --- /dev/null +++ b/src/Shared/CommandLine/CommandOptionType.cs @@ -0,0 +1,13 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + + +namespace Microsoft.Extensions.CommandLineUtils +{ + public enum CommandOptionType + { + MultipleValue, + SingleValue, + NoValue + } +} diff --git a/src/Shared/CommandLine/CommandParsingException.cs b/src/Shared/CommandLine/CommandParsingException.cs new file mode 100644 index 0000000000..b5151c2301 --- /dev/null +++ b/src/Shared/CommandLine/CommandParsingException.cs @@ -0,0 +1,18 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.Extensions.CommandLineUtils +{ + public class CommandParsingException : Exception + { + public CommandParsingException(CommandLineApplication command, string message) + : base(message) + { + Command = command; + } + + public CommandLineApplication Command { get; } + } +} diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index a1a2015d4a..39e6e6ce55 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -11,13 +11,13 @@ }, "dependencies": { "dotnet-test-xunit": "2.2.0-preview2-build1029", - "Microsoft.AspNetCore.Testing": "1.1.0-*", + "Microsoft.AspNetCore.Testing": "1.0.0", "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", "Microsoft.Extensions.Process.Sources": { "type": "build", - "version": "1.1.0-*" + "version": "1.0.0" }, - "xunit": "2.2.0-*" + "xunit": "2.2.0-beta3-build3402" }, "frameworks": { "netcoreapp1.0": { diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json index 49c0a70124..fd2d9874aa 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json @@ -7,7 +7,7 @@ "dependencies": { "dotnet-test-xunit": "2.2.0-preview2-build1029", "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", - "xunit": "2.2.0-*" + "xunit": "2.2.0-beta3-build3402" }, "frameworks": { "netcoreapp1.0": { diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs index b704a87c36..5420aa0ff4 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs @@ -3,9 +3,10 @@ using System.IO; using System.Collections.Generic; -using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.SecretManager.Tools.Internal; +using Microsoft.Extensions.Logging; using Xunit; +using System; namespace Microsoft.Extensions.SecretManager.Tools.Tests { @@ -75,7 +76,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests var secretStore = new TestSecretsStore(); var command = new SetCommand("key", null); - var ex = Assert.Throws< Microsoft.DotNet.Cli.Utils.GracefulException>( + var ex = Assert.Throws( () => command.Execute(new CommandContext(secretStore, NullLogger.Instance, testConsole))); Assert.Equal(Resources.FormatError_MissingArgument("value"), ex.Message); } @@ -98,4 +99,25 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests } } } + + public class NullLogger : ILogger + { + public static NullLogger Instance = new NullLogger(); + + private class NullScope : IDisposable + { + public void Dispose() + { + } + } + public IDisposable BeginScope(TState state) + => new NullScope(); + + public bool IsEnabled(LogLevel logLevel) + => true; + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + } + } } diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json index 3512358403..515a64c422 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json @@ -6,7 +6,7 @@ "dependencies": { "dotnet-test-xunit": "2.2.0-preview2-build1029", "Microsoft.Extensions.SecretManager.Tools": "1.0.0-*", - "xunit": "2.2.0-*" + "xunit": "2.2.0-beta3-build3402" }, "testRunner": "xunit", "frameworks": { diff --git a/tools/NuGetPackager/project.json b/tools/NuGetPackager/project.json index f42b3d92d0..23a32ed3f8 100644 --- a/tools/NuGetPackager/project.json +++ b/tools/NuGetPackager/project.json @@ -6,14 +6,14 @@ "dependencies": { "Microsoft.NETCore.App": { "type": "platform", - "version": "1.1.0-*" + "version": "1.0.1" }, - "Microsoft.DotNet.ProjectModel": "1.0.0-*", - "Microsoft.DotNet.Cli.Utils": "1.0.0-*", - "Microsoft.Extensions.CommandLineUtils": "1.1.0-*" + "Microsoft.DotNet.ProjectModel": "1.0.0-rc3-003121", + "Microsoft.DotNet.Cli.Utils": "1.0.0-preview2-003121", + "Microsoft.Extensions.CommandLineUtils": "1.0.0" }, "frameworks": { - "netcoreapp1.1": { } + "netcoreapp1.0": { } } } \ No newline at end of file From 3b0947b4af920f51881736f66df5d2368320dad8 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 2 Nov 2016 13:46:23 -0700 Subject: [PATCH 0316/1029] Add workaround for bug in Configuration 1.0.1 --- .../Internal/SecretsStore.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs index 588e66dcba..22e03ee6d7 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs @@ -26,7 +26,11 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal } _secretsFilePath = PathHelper.GetSecretsPathFromSecretsId(userSecretsId); - + + // workaround bug in configuration + var secretDir = Path.GetDirectoryName(_secretsFilePath); + Directory.CreateDirectory(secretDir); + logger.LogDebug(Resources.Message_Secret_File_Path, _secretsFilePath); _secrets = Load(userSecretsId); } From fcd6764cd1d0841440fe4feca9b63ed0d365c809 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 2 Nov 2016 14:16:05 -0700 Subject: [PATCH 0317/1029] Add to nuget.config --- NuGet.config | 1 + 1 file changed, 1 insertion(+) diff --git a/NuGet.config b/NuGet.config index 4017b7ad58..90ce61307f 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,6 +1,7 @@  + From 217dab2016fff3c66a2f88051830cf7eab37db74 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 2 Nov 2016 14:36:51 -0700 Subject: [PATCH 0318/1029] Fix packaging on CI --- tools/NuGetPackager/PackCommand.cs | 6 +++--- tools/NuGetPackager/project.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/NuGetPackager/PackCommand.cs b/tools/NuGetPackager/PackCommand.cs index fd76e86692..3c04b27fa6 100644 --- a/tools/NuGetPackager/PackCommand.cs +++ b/tools/NuGetPackager/PackCommand.cs @@ -146,15 +146,15 @@ namespace NuGetPackager return Environment.GetEnvironmentVariable("KOREBUILD_NUGET_EXE"); } - var nugetPath = Path.Combine(_baseDir, ".build", "nuget.3.5.0-rc1.exe"); + var nugetPath = Path.Combine(_baseDir, ".build", "nuget.3.5.0.exe"); if (File.Exists(nugetPath)) { return nugetPath; } - Console.WriteLine("log : Downloading nuget.exe 3.5.0-rc1".Bold().Black()); + Console.WriteLine("log : Downloading nuget.exe 3.5.0"); - var response = await new HttpClient().GetAsync("https://dist.nuget.org/win-x86-commandline/v3.5.0-rc1/NuGet.exe"); + var response = await new HttpClient().GetAsync("https://dist.nuget.org/win-x86-commandline/v3.5.0/NuGet.exe"); using (var file = new FileStream(nugetPath, FileMode.CreateNew)) { response.EnsureSuccessStatusCode(); diff --git a/tools/NuGetPackager/project.json b/tools/NuGetPackager/project.json index 23a32ed3f8..fe0b3987d9 100644 --- a/tools/NuGetPackager/project.json +++ b/tools/NuGetPackager/project.json @@ -6,7 +6,7 @@ "dependencies": { "Microsoft.NETCore.App": { "type": "platform", - "version": "1.0.1" + "version": "1.0.0" }, "Microsoft.DotNet.ProjectModel": "1.0.0-rc3-003121", "Microsoft.DotNet.Cli.Utils": "1.0.0-preview2-003121", From 77122d0246c694e33ecda0fb5def20d64ca01a4c Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 2 Nov 2016 14:44:38 -0700 Subject: [PATCH 0319/1029] Build feature/ branches on CI --- .travis.yml | 1 + appveyor.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index a040cef874..1d6d4144bc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,6 +26,7 @@ branches: - release - dev - /^(.*\/)?ci-.*$/ + - /^feature\// before_install: - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; fi script: diff --git a/appveyor.yml b/appveyor.yml index be95b88d6f..2275c1322c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,6 +6,7 @@ branches: - release - dev - /^(.*\/)?ci-.*$/ + - /^feature\// build_script: - build.cmd --quiet verify clone_depth: 1 From 6d540faf181b79be1264af85255c11da7df06ca6 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 2 Nov 2016 15:40:45 -0700 Subject: [PATCH 0320/1029] Remove custom targets for sxs msbuild installation --- CliToolVersion.txt | 1 - build.ps1 | 7 +- build.sh | 7 +- dotnet-install.ps1 | 427 ---------------------------- dotnet-install.sh | 688 --------------------------------------------- makefile.shade | 19 +- 6 files changed, 3 insertions(+), 1146 deletions(-) delete mode 100644 CliToolVersion.txt delete mode 100644 dotnet-install.ps1 delete mode 100755 dotnet-install.sh diff --git a/CliToolVersion.txt b/CliToolVersion.txt deleted file mode 100644 index 08d0462469..0000000000 --- a/CliToolVersion.txt +++ /dev/null @@ -1 +0,0 @@ -1.0.0-preview3-004007 \ No newline at end of file diff --git a/build.ps1 b/build.ps1 index 6650bad342..f780c43a82 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP @@ -64,9 +64,4 @@ if (!(Test-Path $buildFolder)) { } } -$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 -$dotnetHome = "$buildFolder\.dotnet" -mkdir $dotnetHome -ErrorAction Ignore | Out-Null -& .\dotnet-install.ps1 -Version $(Get-Content .\CliToolVersion.txt) -InstallDir $dotnetHome - &"$buildFile" $args \ No newline at end of file diff --git a/build.sh b/build.sh index 6fde860cce..0a1463b9e4 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi @@ -43,9 +43,4 @@ if test ! -d $buildFolder; then fi fi -export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 -dotnetHome="$buildFolder/.dotnet" -mkdir -p $dotnetHome -./dotnet-install.sh --install-dir $dotnetHome --version $(cat CliToolVersion.txt) - $buildFile -r $repoFolder "$@" \ No newline at end of file diff --git a/dotnet-install.ps1 b/dotnet-install.ps1 deleted file mode 100644 index d656007d5f..0000000000 --- a/dotnet-install.ps1 +++ /dev/null @@ -1,427 +0,0 @@ -# -# Copyright (c) .NET Foundation and contributors. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. -# - -<# -.SYNOPSIS - Installs dotnet cli -.DESCRIPTION - Installs dotnet cli. If dotnet installation already exists in the given directory - it will update it only if the requested version differs from the one already installed. -.PARAMETER Channel - Default: preview - Channel is the way of reasoning about stability and quality of dotnet. This parameter takes one of the values: - - future - Possibly unstable, frequently changing, may contain new finished and unfinished features - - preview - Pre-release stable with known issues and feature gaps - - production - Most stable releases -.PARAMETER Version - Default: latest - Represents a build version on specific channel. Possible values: - - 4-part version in a format A.B.C.D - represents specific version of build - - latest - most latest build on specific channel - - lkg - last known good version on specific channel - Note: LKG work is in progress. Once the work is finished, this will become new default -.PARAMETER InstallDir - Default: %LocalAppData%\Microsoft\dotnet - Path to where to install dotnet. Note that binaries will be placed directly in a given directory. -.PARAMETER Architecture - Default: - this value represents currently running OS architecture - Architecture of dotnet binaries to be installed. - Possible values are: , x64 and x86 -.PARAMETER SharedRuntime - Default: false - Installs just the shared runtime bits, not the entire SDK -.PARAMETER DebugSymbols - If set the installer will include symbols in the installation. -.PARAMETER DryRun - If set it will not perform installation but instead display what command line to use to consistently install - currently requested version of dotnet cli. In example if you specify version 'latest' it will display a link - with specific version so that this command can be used deterministicly in a build script. - It also displays binaries location if you prefer to install or download it yourself. -.PARAMETER NoPath - By default this script will set environment variable PATH for the current process to the binaries folder inside installation folder. - If set it will display binaries location but not set any environment variable. -.PARAMETER Verbose - Displays diagnostics information. -.PARAMETER AzureFeed - Default: https://dotnetcli.azureedge.net/dotnet - This parameter should not be usually changed by user. It allows to change URL for the Azure feed used by this installer. -.PARAMETER ProxyAddress - If set, the installer will use the proxy when making web requests -#> -[cmdletbinding()] -param( - [string]$Channel="rel-1.0.0", - [string]$Version="Latest", - [string]$InstallDir="", - [string]$Architecture="", - [switch]$SharedRuntime, - [switch]$DebugSymbols, # TODO: Switch does not work yet. Symbols zip is not being uploaded yet. - [switch]$DryRun, - [switch]$NoPath, - [string]$AzureFeed="https://dotnetcli.azureedge.net/dotnet", - [string]$UncachedFeed="https://dotnetcli.blob.core.windows.net/dotnet", - [string]$ProxyAddress -) - -Set-StrictMode -Version Latest -$ErrorActionPreference="Stop" -$ProgressPreference="SilentlyContinue" - -$BinFolderRelativePath="" - -# example path with regex: shared/1.0.0-beta-12345/somepath -$VersionRegEx="/\d+\.\d+[^/]+/" -$OverrideNonVersionedFiles=$true - -function Say($str) { - Write-Host "dotnet-install: $str" -} - -function Say-Verbose($str) { - Write-Verbose "dotnet-install: $str" -} - -function Say-Invocation($Invocation) { - $command = $Invocation.MyCommand; - $args = (($Invocation.BoundParameters.Keys | foreach { "-$_ `"$($Invocation.BoundParameters[$_])`"" }) -join " ") - Say-Verbose "$command $args" -} - -function Get-Machine-Architecture() { - Say-Invocation $MyInvocation - - # possible values: AMD64, IA64, x86 - return $ENV:PROCESSOR_ARCHITECTURE -} - -# TODO: Architecture and CLIArchitecture should be unified -function Get-CLIArchitecture-From-Architecture([string]$Architecture) { - Say-Invocation $MyInvocation - - switch ($Architecture.ToLower()) { - { $_ -eq "" } { return Get-CLIArchitecture-From-Architecture $(Get-Machine-Architecture) } - { ($_ -eq "amd64") -or ($_ -eq "x64") } { return "x64" } - { $_ -eq "x86" } { return "x86" } - default { throw "Architecture not supported. If you think this is a bug, please report it at https://github.com/dotnet/cli/issues" } - } -} - -function Get-Version-Info-From-Version-Text([string]$VersionText) { - Say-Invocation $MyInvocation - - $Data = @($VersionText.Split([char[]]@(), [StringSplitOptions]::RemoveEmptyEntries)); - - $VersionInfo = @{} - $VersionInfo.CommitHash = $Data[0].Trim() - $VersionInfo.Version = $Data[1].Trim() - return $VersionInfo -} - -function Load-Assembly([string] $Assembly) { - try { - Add-Type -Assembly $Assembly | Out-Null - } - catch { - # On Nano Server, Powershell Core Edition is used. Add-Type is unable to resolve base class assemblies because they are not GAC'd. - # Loading the base class assemblies is not unnecessary as the types will automatically get resolved. - } -} - -function GetHTTPResponse([Uri] $Uri) -{ - $HttpClient = $null - - try { - # HttpClient is used vs Invoke-WebRequest in order to support Nano Server which doesn't support the Invoke-WebRequest cmdlet. - Load-Assembly -Assembly System.Net.Http - if($ProxyAddress){ - $HttpClientHandler = New-Object System.Net.Http.HttpClientHandler - $HttpClientHandler.Proxy = New-Object System.Net.WebProxy -Property @{Address=$ProxyAddress} - $HttpClient = New-Object System.Net.Http.HttpClient -ArgumentList $HttpClientHandler - } - else { - $HttpClient = New-Object System.Net.Http.HttpClient - } - - $Response = $HttpClient.GetAsync($Uri).Result - if (($Response -eq $null) -or (-not ($Response.IsSuccessStatusCode))) - { - $ErrorMsg = "Failed to download $Uri." - if ($Response -ne $null) - { - $ErrorMsg += " $Response" - } - - throw $ErrorMsg - } - - return $Response - } - finally { - if ($HttpClient -ne $null) { - $HttpClient.Dispose() - } - } -} - - -function Get-Latest-Version-Info([string]$AzureFeed, [string]$AzureChannel, [string]$CLIArchitecture) { - Say-Invocation $MyInvocation - - $VersionFileUrl = $null - if ($SharedRuntime) { - $VersionFileUrl = "$UncachedFeed/$AzureChannel/dnvm/latest.sharedfx.win.$CLIArchitecture.version" - } - else { - $VersionFileUrl = "$UncachedFeed/Sdk/$AzureChannel/latest.version" - } - - $Response = GetHTTPResponse -Uri $VersionFileUrl - $StringContent = $Response.Content.ReadAsStringAsync().Result - - switch ($Response.Content.Headers.ContentType) { - { ($_ -eq "application/octet-stream") } { $VersionText = [Text.Encoding]::UTF8.GetString($StringContent) } - { ($_ -eq "text/plain") } { $VersionText = $StringContent } - default { throw "``$Response.Content.Headers.ContentType`` is an unknown .version file content type." } - } - - $VersionInfo = Get-Version-Info-From-Version-Text $VersionText - - return $VersionInfo -} - -# TODO: AzureChannel and Channel should be unified -function Get-Azure-Channel-From-Channel([string]$Channel) { - Say-Invocation $MyInvocation - - # For compatibility with build scripts accept also directly Azure channels names - switch ($Channel.ToLower()) { - { ($_ -eq "future") -or ($_ -eq "dev") } { return "dev" } - { $_ -eq "production" } { throw "Production channel does not exist yet" } - default { return $_ } - } -} - -function Get-Specific-Version-From-Version([string]$AzureFeed, [string]$AzureChannel, [string]$CLIArchitecture, [string]$Version) { - Say-Invocation $MyInvocation - - switch ($Version.ToLower()) { - { $_ -eq "latest" } { - $LatestVersionInfo = Get-Latest-Version-Info -AzureFeed $AzureFeed -AzureChannel $AzureChannel -CLIArchitecture $CLIArchitecture - return $LatestVersionInfo.Version - } - { $_ -eq "lkg" } { throw "``-Version LKG`` not supported yet." } - default { return $Version } - } -} - -function Get-Download-Links([string]$AzureFeed, [string]$AzureChannel, [string]$SpecificVersion, [string]$CLIArchitecture) { - Say-Invocation $MyInvocation - - $ret = @() - - if ($SharedRuntime) { - $PayloadURL = "$AzureFeed/$AzureChannel/Binaries/$SpecificVersion/dotnet-win-$CLIArchitecture.$SpecificVersion.zip" - } - else { - $PayloadURL = "$AzureFeed/Sdk/$SpecificVersion/dotnet-dev-win-$CLIArchitecture.$SpecificVersion.zip" - } - - Say-Verbose "Constructed payload URL: $PayloadURL" - $ret += $PayloadURL - - return $ret -} - -function Get-User-Share-Path() { - Say-Invocation $MyInvocation - - $InstallRoot = $env:DOTNET_INSTALL_DIR - if (!$InstallRoot) { - $InstallRoot = "$env:LocalAppData\Microsoft\dotnet" - } - return $InstallRoot -} - -function Resolve-Installation-Path([string]$InstallDir) { - Say-Invocation $MyInvocation - - if ($InstallDir -eq "") { - return Get-User-Share-Path - } - return $InstallDir -} - -function Get-Version-Info-From-Version-File([string]$InstallRoot, [string]$RelativePathToVersionFile) { - Say-Invocation $MyInvocation - - $VersionFile = Join-Path -Path $InstallRoot -ChildPath $RelativePathToVersionFile - Say-Verbose "Local version file: $VersionFile" - - if (Test-Path $VersionFile) { - $VersionText = cat $VersionFile - Say-Verbose "Local version file text: $VersionText" - return Get-Version-Info-From-Version-Text $VersionText - } - - Say-Verbose "Local version file not found." - - return $null -} - -function Is-Dotnet-Package-Installed([string]$InstallRoot, [string]$RelativePathToPackage, [string]$SpecificVersion) { - Say-Invocation $MyInvocation - - $DotnetPackagePath = Join-Path -Path $InstallRoot -ChildPath $RelativePathToPackage | Join-Path -ChildPath $SpecificVersion - Say-Verbose "Is-Dotnet-Package-Installed: Path to a package: $DotnetPackagePath" - return Test-Path $DotnetPackagePath -PathType Container -} - -function Get-Absolute-Path([string]$RelativeOrAbsolutePath) { - # Too much spam - # Say-Invocation $MyInvocation - - return $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($RelativeOrAbsolutePath) -} - -function Get-Path-Prefix-With-Version($path) { - $match = [regex]::match($path, $VersionRegEx) - if ($match.Success) { - return $entry.FullName.Substring(0, $match.Index + $match.Length) - } - - return $null -} - -function Get-List-Of-Directories-And-Versions-To-Unpack-From-Dotnet-Package([System.IO.Compression.ZipArchive]$Zip, [string]$OutPath) { - Say-Invocation $MyInvocation - - $ret = @() - foreach ($entry in $Zip.Entries) { - $dir = Get-Path-Prefix-With-Version $entry.FullName - if ($dir -ne $null) { - $path = Get-Absolute-Path $(Join-Path -Path $OutPath -ChildPath $dir) - if (-Not (Test-Path $path -PathType Container)) { - $ret += $dir - } - } - } - - $ret = $ret | Sort-Object | Get-Unique - - $values = ($ret | foreach { "$_" }) -join ";" - Say-Verbose "Directories to unpack: $values" - - return $ret -} - -# Example zip content and extraction algorithm: -# Rule: files if extracted are always being extracted to the same relative path locally -# .\ -# a.exe # file does not exist locally, extract -# b.dll # file exists locally, override only if $OverrideFiles set -# aaa\ # same rules as for files -# ... -# abc\1.0.0\ # directory contains version and exists locally -# ... # do not extract content under versioned part -# abc\asd\ # same rules as for files -# ... -# def\ghi\1.0.1\ # directory contains version and does not exist locally -# ... # extract content -function Extract-Dotnet-Package([string]$ZipPath, [string]$OutPath) { - Say-Invocation $MyInvocation - - Load-Assembly -Assembly System.IO.Compression.FileSystem - Set-Variable -Name Zip - try { - $Zip = [System.IO.Compression.ZipFile]::OpenRead($ZipPath) - - $DirectoriesToUnpack = Get-List-Of-Directories-And-Versions-To-Unpack-From-Dotnet-Package -Zip $Zip -OutPath $OutPath - - foreach ($entry in $Zip.Entries) { - $PathWithVersion = Get-Path-Prefix-With-Version $entry.FullName - if (($PathWithVersion -eq $null) -Or ($DirectoriesToUnpack -contains $PathWithVersion)) { - $DestinationPath = Get-Absolute-Path $(Join-Path -Path $OutPath -ChildPath $entry.FullName) - $DestinationDir = Split-Path -Parent $DestinationPath - $OverrideFiles=$OverrideNonVersionedFiles -Or (-Not (Test-Path $DestinationPath)) - if ((-Not $DestinationPath.EndsWith("\")) -And $OverrideFiles) { - New-Item -ItemType Directory -Force -Path $DestinationDir | Out-Null - [System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $DestinationPath, $OverrideNonVersionedFiles) - } - } - } - } - finally { - if ($Zip -ne $null) { - $Zip.Dispose() - } - } -} - -function DownloadFile([Uri]$Uri, [string]$OutPath) { - $Stream = $null - - try { - $Response = GetHTTPResponse -Uri $Uri - $Stream = $Response.Content.ReadAsStreamAsync().Result - $File = [System.IO.File]::Create($OutPath) - $Stream.CopyTo($File) - $File.Close() - } - finally { - if ($Stream -ne $null) { - $Stream.Dispose() - } - } -} - -$AzureChannel = Get-Azure-Channel-From-Channel -Channel $Channel -$CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture -$SpecificVersion = Get-Specific-Version-From-Version -AzureFeed $AzureFeed -AzureChannel $AzureChannel -CLIArchitecture $CLIArchitecture -Version $Version -$DownloadLinks = Get-Download-Links -AzureFeed $AzureFeed -AzureChannel $AzureChannel -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture - -if ($DryRun) { - Say "Payload URLs:" - foreach ($DownloadLink in $DownloadLinks) { - Say "- $DownloadLink" - } - Say "Repeatable invocation: .\$($MyInvocation.MyCommand) -Version $SpecificVersion -Channel $Channel -Architecture $CLIArchitecture -InstallDir $InstallDir" - exit 0 -} - -$InstallRoot = Resolve-Installation-Path $InstallDir -Say-Verbose "InstallRoot: $InstallRoot" - -$IsSdkInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage "sdk" -SpecificVersion $SpecificVersion -Say-Verbose ".NET SDK installed? $IsSdkInstalled" -if ($IsSdkInstalled) { - Say ".NET SDK version $SpecificVersion is already installed." - exit 0 -} - -New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null - -foreach ($DownloadLink in $DownloadLinks) { - $ZipPath = [System.IO.Path]::GetTempFileName() - Say "Downloading $DownloadLink" - DownloadFile -Uri $DownloadLink -OutPath $ZipPath - - Say "Extracting zip from $DownloadLink" - Extract-Dotnet-Package -ZipPath $ZipPath -OutPath $InstallRoot - - Remove-Item $ZipPath -} - -$BinPath = Get-Absolute-Path $(Join-Path -Path $InstallRoot -ChildPath $BinFolderRelativePath) -if (-Not $NoPath) { - Say "Adding to current process PATH: `"$BinPath`". Note: This change will not be visible if PowerShell was run as a child process." - $env:path = "$BinPath;" + $env:path -} -else { - Say "Binaries of dotnet can be found in $BinPath" -} - -Say "Installation finished" -exit 0 diff --git a/dotnet-install.sh b/dotnet-install.sh deleted file mode 100755 index 7f6f869564..0000000000 --- a/dotnet-install.sh +++ /dev/null @@ -1,688 +0,0 @@ -# Copyright (c) .NET Foundation and contributors. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. -# - -# Note: This script should be compatible with the dash shell used in Ubuntu. So avoid bashisms! See https://wiki.ubuntu.com/DashAsBinSh for more info - -# Stop script on NZEC -set -e -# Stop script if unbound variable found (use ${var:-} if intentional) -set -u -# By default cmd1 | cmd2 returns exit code of cmd2 regardless of cmd1 success -# This is causing it to fail -set -o pipefail - -# Use in the the functions: eval $invocation -invocation='say_verbose "Calling: ${yellow:-}${FUNCNAME[0]} ${green:-}$*${normal:-}"' - -# standard output may be used as a return value in the functions -# we need a way to write text on the screen in the functions so that -# it won't interfere with the return value. -# Exposing stream 3 as a pipe to standard output of the script itself -exec 3>&1 - -# Setup some colors to use. These need to work in fairly limited shells, like the Ubuntu Docker container where there are only 8 colors. -# See if stdout is a terminal -if [ -t 1 ]; then - # see if it supports colors - ncolors=$(tput colors) - if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then - bold="$(tput bold || echo)" - normal="$(tput sgr0 || echo)" - black="$(tput setaf 0 || echo)" - red="$(tput setaf 1 || echo)" - green="$(tput setaf 2 || echo)" - yellow="$(tput setaf 3 || echo)" - blue="$(tput setaf 4 || echo)" - magenta="$(tput setaf 5 || echo)" - cyan="$(tput setaf 6 || echo)" - white="$(tput setaf 7 || echo)" - fi -fi - -say_err() { - printf "%b\n" "${red:-}dotnet_install: Error: $1${normal:-}" >&2 -} - -say() { - # using stream 3 (defined in the beginning) to not interfere with stdout of functions - # which may be used as return value - printf "%b\n" "${cyan:-}dotnet-install:${normal:-} $1" >&3 -} - -say_verbose() { - if [ "$verbose" = true ]; then - say "$1" - fi -} - -get_current_os_name() { - eval $invocation - - local uname=$(uname) - if [ "$uname" = "Darwin" ]; then - echo "osx" - return 0 - else - if [ -e /etc/os-release ]; then - . /etc/os-release - - case "$ID.$VERSION_ID" in - "centos.7") - echo "centos" - return 0 - ;; - "debian.8") - echo "debian" - return 0 - ;; - "fedora.23") - echo "fedora.23" - return 0 - ;; - "fedora.24") - echo "fedora.24" - return 0 - ;; - "opensuse.13.2") - echo "opensuse.13.2" - return 0 - ;; - "opensuse.42.1") - echo "opensuse.42.1" - return 0 - ;; - "rhel.7.0" | "rhel.7.1" | "rhel.7.2") - echo "rhel" - return 0 - ;; - "ubuntu.14.04") - echo "ubuntu" - return 0 - ;; - "ubuntu.16.04") - echo "ubuntu.16.04" - return 0 - ;; - "ubuntu.16.10") - echo "ubuntu.16.10" - return 0 - ;; - "alpine.3.4.3") - echo "alpine" - return 0 - ;; - esac - fi - fi - - say_err "OS name could not be detected: $ID.$VERSION_ID" - return 1 -} - -machine_has() { - eval $invocation - - which "$1" > /dev/null 2>&1 - return $? -} - -check_min_reqs() { - if ! machine_has "curl"; then - say_err "curl is required to download dotnet. Install curl to proceed." - return 1 - fi - - return 0 -} - -check_pre_reqs() { - eval $invocation - - local failing=false; - - if [ "${DOTNET_INSTALL_SKIP_PREREQS:-}" = "1" ]; then - return 0 - fi - - if [ "$(uname)" = "Linux" ]; then - if ! [ -x "$(command -v ldconfig)" ]; then - echo "ldconfig is not in PATH, trying /sbin/ldconfig." - LDCONFIG_COMMAND="/sbin/ldconfig" - else - LDCONFIG_COMMAND="ldconfig" - fi - - [ -z "$($LDCONFIG_COMMAND -p | grep libunwind)" ] && say_err "Unable to locate libunwind. Install libunwind to continue" && failing=true - [ -z "$($LDCONFIG_COMMAND -p | grep libssl)" ] && say_err "Unable to locate libssl. Install libssl to continue" && failing=true - [ -z "$($LDCONFIG_COMMAND -p | grep libcurl)" ] && say_err "Unable to locate libcurl. Install libcurl to continue" && failing=true - [ -z "$($LDCONFIG_COMMAND -p | grep libicu)" ] && say_err "Unable to locate libicu. Install libicu to continue" && failing=true - fi - - if [ "$failing" = true ]; then - return 1 - fi - - return 0 -} - -# args: -# input - $1 -to_lowercase() { - #eval $invocation - - echo "$1" | tr '[:upper:]' '[:lower:]' - return 0 -} - -# args: -# input - $1 -remove_trailing_slash() { - #eval $invocation - - local input=${1:-} - echo "${input%/}" - return 0 -} - -# args: -# input - $1 -remove_beginning_slash() { - #eval $invocation - - local input=${1:-} - echo "${input#/}" - return 0 -} - -# args: -# root_path - $1 -# child_path - $2 - this parameter can be empty -combine_paths() { - eval $invocation - - # TODO: Consider making it work with any number of paths. For now: - if [ ! -z "${3:-}" ]; then - say_err "combine_paths: Function takes two parameters." - return 1 - fi - - local root_path=$(remove_trailing_slash $1) - local child_path=$(remove_beginning_slash ${2:-}) - say_verbose "combine_paths: root_path=$root_path" - say_verbose "combine_paths: child_path=$child_path" - echo "$root_path/$child_path" - return 0 -} - -get_machine_architecture() { - eval $invocation - - # Currently the only one supported - echo "x64" - return 0 -} - -# args: -# architecture - $1 -get_normalized_architecture_from_architecture() { - eval $invocation - - local architecture=$(to_lowercase $1) - case $architecture in - \) - echo "$(get_normalized_architecture_from_architecture $(get_machine_architecture))" - return 0 - ;; - amd64|x64) - echo "x64" - return 0 - ;; - x86) - say_err "Architecture ``x86`` currently not supported" - return 1 - ;; - esac - - say_err "Architecture ``$architecture`` not supported. If you think this is a bug, please report it at https://github.com/dotnet/cli/issues" - return 1 -} - -# version_info is a conceptual two line string representing commit hash and 4-part version -# format: -# Line 1: # commit_hash -# Line 2: # 4-part version - -# args: -# version_text - stdin -get_version_from_version_info() { - eval $invocation - - cat | tail -n 1 - return 0 -} - -# args: -# version_text - stdin -get_commit_hash_from_version_info() { - eval $invocation - - cat | head -n 1 - return 0 -} - -# args: -# install_root - $1 -# relative_path_to_package - $2 -# specific_version - $3 -is_dotnet_package_installed() { - eval $invocation - - local install_root=$1 - local relative_path_to_package=$2 - local specific_version=${3//[$'\t\r\n']} - - local dotnet_package_path=$(combine_paths $(combine_paths $install_root $relative_path_to_package) $specific_version) - say_verbose "is_dotnet_package_installed: dotnet_package_path=$dotnet_package_path" - - if [ -d "$dotnet_package_path" ]; then - return 0 - else - return 1 - fi -} - -# args: -# azure_feed - $1 -# azure_channel - $2 -# normalized_architecture - $3 -get_latest_version_info() { - eval $invocation - - local azure_feed=$1 - local azure_channel=$2 - local normalized_architecture=$3 - - local osname - osname=$(get_current_os_name) || return 1 - - local version_file_url=null - if [ "$shared_runtime" = true ]; then - version_file_url="$uncached_feed/$azure_channel/dnvm/latest.sharedfx.$osname.$normalized_architecture.version" - else - version_file_url="$uncached_feed/Sdk/$azure_channel/latest.version" - fi - say_verbose "get_latest_version_info: latest url: $version_file_url" - - download $version_file_url - return $? -} - -# args: -# channel - $1 -get_azure_channel_from_channel() { - eval $invocation - - local channel=$(to_lowercase $1) - case $channel in - future|dev) - echo "dev" - return 0 - ;; - production) - say_err "Production channel does not exist yet" - return 1 - esac - - echo $channel - return 0 -} - -# args: -# azure_feed - $1 -# azure_channel - $2 -# normalized_architecture - $3 -# version - $4 -get_specific_version_from_version() { - eval $invocation - - local azure_feed=$1 - local azure_channel=$2 - local normalized_architecture=$3 - local version=$(to_lowercase $4) - - case $version in - latest) - local version_info - version_info="$(get_latest_version_info $azure_feed $azure_channel $normalized_architecture)" || return 1 - say_verbose "get_specific_version_from_version: version_info=$version_info" - echo "$version_info" | get_version_from_version_info - return 0 - ;; - lkg) - say_err "``--version LKG`` not supported yet." - return 1 - ;; - *) - echo $version - return 0 - ;; - esac -} - -# args: -# azure_feed - $1 -# azure_channel - $2 -# normalized_architecture - $3 -# specific_version - $4 -construct_download_link() { - eval $invocation - - local azure_feed=$1 - local azure_channel=$2 - local normalized_architecture=$3 - local specific_version=${4//[$'\t\r\n']} - - local osname - osname=$(get_current_os_name) || return 1 - - local download_link=null - if [ "$shared_runtime" = true ]; then - download_link="$azure_feed/$azure_channel/Binaries/$specific_version/dotnet-$osname-$normalized_architecture.$specific_version.tar.gz" - else - download_link="$azure_feed/Sdk/$specific_version/dotnet-dev-$osname-$normalized_architecture.$specific_version.tar.gz" - fi - - echo "$download_link" - return 0 -} - -get_user_share_path() { - eval $invocation - - if [ ! -z "${DOTNET_INSTALL_DIR:-}" ]; then - echo $DOTNET_INSTALL_DIR - else - echo "$HOME/.dotnet" - fi - return 0 -} - -# args: -# install_dir - $1 -resolve_installation_path() { - eval $invocation - - local install_dir=$1 - if [ "$install_dir" = "" ]; then - local user_share_path=$(get_user_share_path) - say_verbose "resolve_installation_path: share_path=$user_share_path" - echo "$user_share_path" - return 0 - fi - - echo "$install_dir" - return 0 -} - -# args: -# install_root - $1 -get_installed_version_info() { - eval $invocation - - local install_root=$1 - local version_file=$(combine_paths "$install_root" "$local_version_file_relative_path") - say_verbose "Local version file: $version_file" - if [ ! -z "$version_file" ] | [ -r "$version_file" ]; then - local version_info="$(cat $version_file)" - echo "$version_info" - return 0 - fi - - say_verbose "Local version file not found." - return 0 -} - -# args: -# relative_or_absolute_path - $1 -get_absolute_path() { - eval $invocation - - local relative_or_absolute_path=$1 - echo $(cd $(dirname "$1") && pwd -P)/$(basename "$1") - return 0 -} - -# args: -# input_files - stdin -# root_path - $1 -# out_path - $2 -# override - $3 -copy_files_or_dirs_from_list() { - eval $invocation - - local root_path=$(remove_trailing_slash $1) - local out_path=$(remove_trailing_slash $2) - local override=$3 - local override_switch=$(if [ "$override" = false ]; then printf -- "-n"; fi) - - cat | uniq | while read -r file_path; do - local path=$(remove_beginning_slash ${file_path#$root_path}) - local target=$out_path/$path - if [ "$override" = true ] || (! ([ -d "$target" ] || [ -e "$target" ])); then - mkdir -p $out_path/$(dirname $path) - cp -R $override_switch $root_path/$path $target - fi - done -} - -# args: -# zip_path - $1 -# out_path - $2 -extract_dotnet_package() { - eval $invocation - - local zip_path=$1 - local out_path=$2 - - local temp_out_path=$(mktemp -d $temporary_file_template) - - local failed=false - tar -xzf "$zip_path" -C "$temp_out_path" > /dev/null || failed=true - - local folders_with_version_regex='^.*/[0-9]+\.[0-9]+[^/]+/' - find $temp_out_path -type f | grep -Eo $folders_with_version_regex | copy_files_or_dirs_from_list $temp_out_path $out_path false - find $temp_out_path -type f | grep -Ev $folders_with_version_regex | copy_files_or_dirs_from_list $temp_out_path $out_path true - - rm -rf $temp_out_path - - if [ "$failed" = true ]; then - say_err "Extraction failed" - return 1 - fi -} - -# args: -# remote_path - $1 -# [out_path] - $2 - stdout if not provided -download() { - eval $invocation - - local remote_path=$1 - local out_path=${2:-} - - local failed=false - if [ -z "$out_path" ]; then - curl --fail -s $remote_path || failed=true - else - curl --fail -s -o $out_path $remote_path || failed=true - fi - - if [ "$failed" = true ]; then - say_err "Download failed" - return 1 - fi -} - -calculate_vars() { - eval $invocation - - azure_channel=$(get_azure_channel_from_channel "$channel") - say_verbose "azure_channel=$azure_channel" - - normalized_architecture=$(get_normalized_architecture_from_architecture "$architecture") - say_verbose "normalized_architecture=$normalized_architecture" - - specific_version=$(get_specific_version_from_version $azure_feed $azure_channel $normalized_architecture $version) - say_verbose "specific_version=$specific_version" - if [ -z "$specific_version" ]; then - say_err "Could not get version information." - return 1 - fi - - download_link=$(construct_download_link $azure_feed $azure_channel $normalized_architecture $specific_version) - say_verbose "download_link=$download_link" - - install_root=$(resolve_installation_path $install_dir) - say_verbose "install_root=$install_root" -} - -install_dotnet() { - eval $invocation - - if is_dotnet_package_installed $install_root "sdk" $specific_version; then - say ".NET SDK version $specific_version is already installed." - return 0 - fi - - mkdir -p $install_root - zip_path=$(mktemp $temporary_file_template) - say_verbose "Zip path: $zip_path" - - say "Downloading $download_link" - download "$download_link" $zip_path - say_verbose "Downloaded file exists and readable? $(if [ -r $zip_path ]; then echo "yes"; else echo "no"; fi)" - - say "Extracting zip" - extract_dotnet_package $zip_path $install_root - - return 0 -} - -local_version_file_relative_path="/.version" -bin_folder_relative_path="" -temporary_file_template="${TMPDIR:-/tmp}/dotnet.XXXXXXXXX" - -channel="rel-1.0.0" -version="Latest" -install_dir="" -architecture="" -debug_symbols=false -dry_run=false -no_path=false -azure_feed="https://dotnetcli.azureedge.net/dotnet" -uncached_feed="https://dotnetcli.blob.core.windows.net/dotnet" -verbose=false -shared_runtime=false - -while [ $# -ne 0 ] -do - name=$1 - case $name in - -c|--channel|-[Cc]hannel) - shift - channel=$1 - ;; - -v|--version|-[Vv]ersion) - shift - version="$1" - ;; - -i|--install-dir|-[Ii]nstall[Dd]ir) - shift - install_dir="$1" - ;; - --arch|--architecture|-[Aa]rch|-[Aa]rchitecture) - shift - architecture="$1" - ;; - --shared-runtime|-[Ss]hared[Rr]untime) - shared_runtime=true - ;; - --debug-symbols|-[Dd]ebug[Ss]ymbols) - debug_symbols=true - ;; - --dry-run|-[Dd]ry[Rr]un) - dry_run=true - ;; - --no-path|-[Nn]o[Pp]ath) - no_path=true - ;; - --verbose|-[Vv]erbose) - verbose=true - ;; - --azure-feed|-[Aa]zure[Ff]eed) - shift - azure_feed="$1" - ;; - -?|--?|-h|--help|-[Hh]elp) - script_name="$(basename $0)" - echo ".NET Tools Installer" - echo "Usage: $script_name [-c|--channel ] [-v|--version ] [-p|--prefix ]" - echo " $script_name -h|-?|--help" - echo "" - echo "$script_name is a simple command line interface for obtaining dotnet cli." - echo "" - echo "Options:" - echo " -c,--channel Download from the CHANNEL specified (default: $channel)." - echo " -Channel" - echo " -v,--version Use specific version, ``latest`` or ``lkg``. Defaults to ``latest``." - echo " -Version" - echo " -i,--install-dir Install under specified location (see Install Location below)" - echo " -InstallDir" - echo " --architecture Architecture of .NET Tools. Currently only x64 is supported." - echo " --arch,-Architecture,-Arch" - echo " --shared-runtime Installs just the shared runtime bits, not the entire SDK." - echo " -SharedRuntime" - echo " --debug-symbols,-DebugSymbols Specifies if symbols should be included in the installation." - echo " --dry-run,-DryRun Do not perform installation. Display download link." - echo " --no-path, -NoPath Do not set PATH for the current process." - echo " --verbose,-Verbose Display diagnostics information." - echo " --azure-feed,-AzureFeed Azure feed location. Defaults to $azure_feed" - echo " -?,--?,-h,--help,-Help Shows this help message" - echo "" - echo "Install Location:" - echo " Location is chosen in following order:" - echo " - --install-dir option" - echo " - Environmental variable DOTNET_INSTALL_DIR" - echo " - /usr/local/share/dotnet" - exit 0 - ;; - *) - say_err "Unknown argument \`$name\`" - exit 1 - ;; - esac - - shift -done - -check_min_reqs -calculate_vars -if [ "$dry_run" = true ]; then - say "Payload URL: $download_link" - say "Repeatable invocation: ./$(basename $0) --version $specific_version --channel $channel --install-dir $install_dir" - exit 0 -fi - -check_pre_reqs -install_dotnet - -bin_path=$(get_absolute_path $(combine_paths $install_root $bin_folder_relative_path)) -if [ "$no_path" = false ]; then - say "Adding to current process PATH: ``$bin_path``. Note: This change will be visible only when sourcing script." - export PATH=$bin_path:$PATH -else - say "Binaries of dotnet can be found in $bin_path" -fi - -say "Installation finished successfully." diff --git a/makefile.shade b/makefile.shade index a20eb95f77..5818e9153e 100644 --- a/makefile.shade +++ b/makefile.shade @@ -11,24 +11,7 @@ var AUTHORS='Microsoft Open Technologies, Inc.' use-standard-lifecycle k-standard-goals -#xunit-test - @{ - foreach (var project in Files.Include("test/*/project.json")) - { - var projectDir = Path.GetDirectoryName(project); - var projectName = Path.GetFileName(projectDir); - var targetDir = Path.Combine(projectDir, "bin", E("Configuration"), "netcoreapp1.0"); - var depsFile = Path.Combine(targetDir, projectName + ".deps.json"); - var configFile = Path.Combine(targetDir, projectName + ".runtimeconfig.json"); - var assembly = Path.Combine(targetDir, projectName + ".dll"); - var home = Environment.GetEnvironmentVariable("USERPROFILE") ?? Environment.GetEnvironmentVariable("HOME"); - var packageCache = Environment.GetEnvironmentVariable("NUGET_PACKAGES") ?? Path.Combine(home, ".nuget/packages"); - Exec(".build/.dotnet/dotnet", "exec --depsfile \"" + depsFile + "\"" - + " --runtimeconfig \"" + configFile + "\" " - + "\"" + Path.Combine(packageCache, "dotnet-test-xunit/2.2.0-preview2-build1029/lib/netcoreapp1.0/dotnet-test-xunit.dll") + "\" " - + "\"" + assembly+ "\" "); - } - } +#xunit-test .xunit-test-msbuild #build-pack .build-compile target='compile' @{ From 90f92fabe3af57813641cbd316178fcad05ce838 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 3 Nov 2016 09:16:08 -0700 Subject: [PATCH 0321/1029] Upgrade Microsoft.NET.Sdk in tests --- .../TestProjects/AppWithDeps/AppWithDeps.csproj | 2 +- .../TestProjects/Dependency/Dependency.csproj | 2 +- .../TestProjects/GlobbingApp/GlobbingApp.csproj | 2 +- .../TestProjects/NoDepsApp/NoDepsApp.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj index 9b081c4e68..00ea5a7ab7 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj @@ -9,7 +9,7 @@ - + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj index 93df17cb59..d8bbbdd6b7 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj @@ -9,7 +9,7 @@ - + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj index 74c2998f65..2389ac538f 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj @@ -8,7 +8,7 @@ - + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj index 71c6a8d4ab..3fe95153a3 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj @@ -8,7 +8,7 @@ - + From ca70ef0b344f538972a8fad14fcd6f327f2c320a Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 3 Nov 2016 12:09:19 -0700 Subject: [PATCH 0322/1029] Change version to msbuild1 --- makefile.shade | 2 +- src/Microsoft.DotNet.Watcher.Tools/README.md | 8 ++++---- src/Microsoft.Extensions.SecretManager.Tools/README.md | 10 ++++++++++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/makefile.shade b/makefile.shade index 5818e9153e..606c572fac 100644 --- a/makefile.shade +++ b/makefile.shade @@ -6,7 +6,7 @@ default BUILD_DIR_LOCAL='${Path.Combine(BASE_DIR_LOCAL, "artifacts", "build")}' var VERSION='0.1' var FULL_VERSION='0.1' var AUTHORS='Microsoft Open Technologies, Inc.' --BuildQuality = "preview4"; +-BuildQuality = "msbuild1"; use-standard-lifecycle k-standard-goals diff --git a/src/Microsoft.DotNet.Watcher.Tools/README.md b/src/Microsoft.DotNet.Watcher.Tools/README.md index 1ad4f241c9..0e6f1142a3 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/README.md +++ b/src/Microsoft.DotNet.Watcher.Tools/README.md @@ -21,20 +21,20 @@ Use the version "1.0.0-preview2-final" if you are using .NET Core 1.0.0 and use ``` **MSBuild** -Install `Microsoft.DotNet.Watcher.Tools` as a `DotNetCliReference` to your project. +Install `Microsoft.DotNet.Watcher.Tools` as a `DotNetCliToolReference` to your project. ```xml - + ``` ### How To Use - dotnet watch [-?|-h|--help] +The command must be executed in the directory that contains the project to be watched. - dotnet watch [options] [[--] ...] + Usage: dotnet watch [options] [[--] ...] Options: -?|-h|--help Show help information diff --git a/src/Microsoft.Extensions.SecretManager.Tools/README.md b/src/Microsoft.Extensions.SecretManager.Tools/README.md index 088485fd7a..ecb2f59709 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/README.md +++ b/src/Microsoft.Extensions.SecretManager.Tools/README.md @@ -5,6 +5,7 @@ dotnet-user-secrets ### How To Install +**project.json** Add `Microsoft.Extensions.SecretManager.Tools` to the `tools` section of your `project.json` file: ```js @@ -17,6 +18,15 @@ Add `Microsoft.Extensions.SecretManager.Tools` to the `tools` section of your `p } ``` +**MSBuild** +Install `Microsoft.Extensions.SecretManager.Tools` as a `DotNetCliToolReference` to your project. + +```xml + + + +``` + ### How To Use Run `dotnet user-secrets --help` for more information about usage. \ No newline at end of file From 7054992254e701a22db049e665d208b8a0d7e8e0 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 3 Nov 2016 12:15:04 -0700 Subject: [PATCH 0323/1029] Bump tools versions to 1.1.0 --- src/Microsoft.DotNet.Watcher.Tools/README.md | 6 ++---- src/Microsoft.DotNet.Watcher.Tools/project.json | 4 ++-- .../project.json | 4 ++-- src/Microsoft.Extensions.SecretManager.Tools/README.md | 2 +- src/Microsoft.Extensions.SecretManager.Tools/project.json | 4 ++-- .../project.json | 6 +++--- test/Microsoft.DotNet.Watcher.Tools.Tests/project.json | 6 +++--- .../project.json | 6 +++--- tools/NuGetPackager/project.json | 2 +- 9 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/README.md b/src/Microsoft.DotNet.Watcher.Tools/README.md index 7a21544e70..ce9b600099 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/README.md +++ b/src/Microsoft.DotNet.Watcher.Tools/README.md @@ -6,13 +6,11 @@ dotnet-watch Add `Microsoft.DotNet.Watcher.Tools` to the `tools` section of your `project.json` file. -Use the version "1.0.0-preview2-final" if you are using .NET Core 1.0.0 and use "1.0.0-preview3-final" if you are using .NET Core 1.1.0. - -``` +```js { ... "tools": { - "Microsoft.DotNet.Watcher.Tools": "1.0.0-preview2-final" //"1.0.0-preview3-final" for .NET Core 1.1.0 + "Microsoft.DotNet.Watcher.Tools": "1.0.0-preview4-final" // "1.1.0-preview4-final" for .NET Core 1.1.0 } ... } diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index e54d7b3774..1f1fc0cf34 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-*", + "version": "1.1.0-*", "description": "Command line tool to watch for source file changes during development and restart the dotnet command.", "packOptions": { "tags": [ @@ -24,7 +24,7 @@ }, "Microsoft.NETCore.App": { "type": "platform", - "version": "1.1.0-*" + "version": "1.1.0" } }, "frameworks": { diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json index b860143998..59a43e6049 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-*", + "version": "1.1.0-*", "buildOptions": { "outputName": "dotnet-sql-cache", "emitEntryPoint": true, @@ -23,7 +23,7 @@ "Microsoft.Extensions.Logging": "1.1.0-*", "Microsoft.Extensions.Logging.Console": "1.1.0-*", "Microsoft.NETCore.App": { - "version": "1.1.0-*", + "version": "1.1.0", "type": "platform" }, "System.Data.SqlClient": "4.3.0-*" diff --git a/src/Microsoft.Extensions.SecretManager.Tools/README.md b/src/Microsoft.Extensions.SecretManager.Tools/README.md index 088485fd7a..4d70d9280f 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/README.md +++ b/src/Microsoft.Extensions.SecretManager.Tools/README.md @@ -11,7 +11,7 @@ Add `Microsoft.Extensions.SecretManager.Tools` to the `tools` section of your `p { .. "tools": { - "Microsoft.Extensions.SecretManager.Tools": "1.0.0-*" + "Microsoft.Extensions.SecretManager.Tools": "1.0.0-preview4-final" // "1.1.0-preview4-final" for .NET Core 1.1.0 } ... } diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index 77d376be2d..03c1b8e582 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-*", + "version": "1.1.0-*", "buildOptions": { "outputName": "dotnet-user-secrets", "emitEntryPoint": true, @@ -23,7 +23,7 @@ "Microsoft.Extensions.Configuration.UserSecrets": "1.1.0-*", "Microsoft.Extensions.Logging": "1.1.0-*", "Microsoft.NETCore.App": { - "version": "1.1.0-*", + "version": "1.1.0", "type": "platform" }, "Newtonsoft.Json": "9.0.1", diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index ecaa2d4046..863b8e1819 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -12,7 +12,7 @@ "dependencies": { "dotnet-test-xunit": "2.2.0-*", "Microsoft.AspNetCore.Testing": "1.1.0-*", - "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", + "Microsoft.DotNet.Watcher.Tools": "1.1.0-*", "Microsoft.Extensions.Process.Sources": { "type": "build", "version": "1.1.0-*" @@ -20,11 +20,11 @@ "xunit": "2.2.0-*" }, "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", - "version": "1.1.0-*" + "version": "1.1.0" } } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json index a084f633f2..d94aba9a22 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json @@ -5,14 +5,14 @@ }, "dependencies": { "dotnet-test-xunit": "2.2.0-*", - "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", + "Microsoft.DotNet.Watcher.Tools": "1.1.0-*", "xunit": "2.2.0-*" }, "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { - "version": "1.1.0-*", + "version": "1.1.0", "type": "platform" } } diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json index 537709e5c8..13397c8da3 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json @@ -5,15 +5,15 @@ }, "dependencies": { "dotnet-test-xunit": "2.2.0-*", - "Microsoft.Extensions.SecretManager.Tools": "1.0.0-*", + "Microsoft.Extensions.SecretManager.Tools": "1.1.0-*", "xunit": "2.2.0-*" }, "testRunner": "xunit", "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { - "version": "1.1.0-*", + "version": "1.1.0", "type": "platform" } } diff --git a/tools/NuGetPackager/project.json b/tools/NuGetPackager/project.json index f42b3d92d0..cef67ac8f0 100644 --- a/tools/NuGetPackager/project.json +++ b/tools/NuGetPackager/project.json @@ -6,7 +6,7 @@ "dependencies": { "Microsoft.NETCore.App": { "type": "platform", - "version": "1.1.0-*" + "version": "1.1.0" }, "Microsoft.DotNet.ProjectModel": "1.0.0-*", "Microsoft.DotNet.Cli.Utils": "1.0.0-*", From 81931e75d48370cf9163254523b1f6c4bcc92acb Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Mon, 31 Oct 2016 15:06:25 -0700 Subject: [PATCH 0324/1029] Handle exceptions for invalid operation types Related to https://github.com/aspnet/Mvc/issues/5463 --- .../Adapters/ObjectAdapter.cs | 26 +++--- .../Internal/ErrorReporter.cs | 16 ++++ .../JsonPatchDocument.cs | 18 +++- .../JsonPatchDocumentOfT.cs | 18 +++- .../Operations/OperationBase.cs | 10 +- .../Operations/OperationOfT.cs | 3 +- .../Properties/Resources.Designer.cs | 16 ++++ .../Resources.resx | 3 + .../JsonPatchDocumentTest.cs | 91 +++++++++++++++++++ 9 files changed, 182 insertions(+), 19 deletions(-) create mode 100644 src/Microsoft.AspNetCore.JsonPatch/Internal/ErrorReporter.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs index ee01fbeba7..0ac2ebbe56 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs @@ -150,14 +150,14 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters if (!visitor.TryVisit(ref target, out adapter, out errorMessage)) { var error = CreatePathNotFoundError(objectToApplyTo, path, operation, errorMessage); - ReportError(error); + ErrorReporter(error); return; } if (!adapter.TryAdd(target, parsedPath.LastSegment, ContractResolver, value, out errorMessage)) { var error = CreateOperationFailedError(objectToApplyTo, path, operation, errorMessage); - ReportError(error); + ErrorReporter(error); return; } } @@ -259,14 +259,14 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters if (!visitor.TryVisit(ref target, out adapter, out errorMessage)) { var error = CreatePathNotFoundError(objectToApplyTo, path, operationToReport, errorMessage); - ReportError(error); + ErrorReporter(error); return; } if (!adapter.TryRemove(target, parsedPath.LastSegment, ContractResolver, out errorMessage)) { var error = CreateOperationFailedError(objectToApplyTo, path, operationToReport, errorMessage); - ReportError(error); + ErrorReporter(error); return; } } @@ -312,14 +312,14 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters if (!visitor.TryVisit(ref target, out adapter, out errorMessage)) { var error = CreatePathNotFoundError(objectToApplyTo, operation.path, operation, errorMessage); - ReportError(error); + ErrorReporter(error); return; } if (!adapter.TryReplace(target, parsedPath.LastSegment, ContractResolver, operation.value, out errorMessage)) { var error = CreateOperationFailedError(objectToApplyTo, operation.path, operation, errorMessage); - ReportError(error); + ErrorReporter(error); return; } } @@ -401,29 +401,25 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters if (!visitor.TryVisit(ref target, out adapter, out errorMessage)) { var error = CreatePathNotFoundError(objectToGetValueFrom, fromLocation, operation, errorMessage); - ReportError(error); + ErrorReporter(error); return false; } if (!adapter.TryGet(target, parsedPath.LastSegment, ContractResolver, out propertyValue, out errorMessage)) { var error = CreateOperationFailedError(objectToGetValueFrom, fromLocation, operation, errorMessage); - ReportError(error); + ErrorReporter(error); return false; } return true; } - private void ReportError(JsonPatchError error) + private Action ErrorReporter { - if (LogErrorAction != null) + get { - LogErrorAction(error); - } - else - { - throw new JsonPatchException(error); + return LogErrorAction ?? Internal.ErrorReporter.Default; } } diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ErrorReporter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ErrorReporter.cs new file mode 100644 index 0000000000..76b55a6144 --- /dev/null +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ErrorReporter.cs @@ -0,0 +1,16 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.AspNetCore.JsonPatch.Exceptions; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + internal static class ErrorReporter + { + public static readonly Action Default = (error) => + { + throw new JsonPatchException(error); + }; + } +} diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs index 72e93e0302..875134ed9d 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using Microsoft.AspNetCore.JsonPatch.Adapters; using Microsoft.AspNetCore.JsonPatch.Converters; +using Microsoft.AspNetCore.JsonPatch.Exceptions; using Microsoft.AspNetCore.JsonPatch.Internal; using Microsoft.AspNetCore.JsonPatch.Operations; using Newtonsoft.Json; @@ -170,7 +171,22 @@ namespace Microsoft.AspNetCore.JsonPatch throw new ArgumentNullException(nameof(objectToApplyTo)); } - ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction)); + var adapter = new ObjectAdapter(ContractResolver, logErrorAction); + foreach (var op in Operations) + { + try + { + op.Apply(objectToApplyTo, adapter); + } + catch (JsonPatchException jsonPatchException) + { + var errorReporter = logErrorAction ?? ErrorReporter.Default; + errorReporter(new JsonPatchError(objectToApplyTo, op, jsonPatchException.Message)); + + // As per JSON Patch spec if an operation results in error, further operations should not be executed. + break; + } + } } /// diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs index afb5eb3ff1..fc660b2b45 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq.Expressions; using Microsoft.AspNetCore.JsonPatch.Adapters; using Microsoft.AspNetCore.JsonPatch.Converters; +using Microsoft.AspNetCore.JsonPatch.Exceptions; using Microsoft.AspNetCore.JsonPatch.Internal; using Microsoft.AspNetCore.JsonPatch.Operations; using Newtonsoft.Json; @@ -648,7 +649,22 @@ namespace Microsoft.AspNetCore.JsonPatch throw new ArgumentNullException(nameof(objectToApplyTo)); } - ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction)); + var adapter = new ObjectAdapter(ContractResolver, logErrorAction); + foreach (var op in Operations) + { + try + { + op.Apply(objectToApplyTo, adapter); + } + catch (JsonPatchException jsonPatchException) + { + var errorReporter = logErrorAction ?? ErrorReporter.Default; + errorReporter(new JsonPatchError(objectToApplyTo, op, jsonPatchException.Message)); + + // As per JSON Patch spec if an operation results in error, further operations should not be executed. + break; + } + } } /// diff --git a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationBase.cs b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationBase.cs index 5f421f41c7..eb35fa7e9d 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationBase.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationBase.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using Microsoft.AspNetCore.JsonPatch.Exceptions; using Newtonsoft.Json; namespace Microsoft.AspNetCore.JsonPatch.Operations @@ -13,7 +14,14 @@ namespace Microsoft.AspNetCore.JsonPatch.Operations { get { - return (OperationType)Enum.Parse(typeof(OperationType), op, true); + OperationType result; + if (!Enum.TryParse(op, ignoreCase: true, result: out result)) + { + throw new JsonPatchException( + Resources.FormatInvalidJsonPatchOperation(op), + innerException: null); + } + return result; } } diff --git a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationOfT.cs b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationOfT.cs index c41454b7ef..5af4f5d3f9 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationOfT.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationOfT.cs @@ -3,6 +3,7 @@ using System; using Microsoft.AspNetCore.JsonPatch.Adapters; +using Microsoft.AspNetCore.JsonPatch.Exceptions; namespace Microsoft.AspNetCore.JsonPatch.Operations { @@ -73,7 +74,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Operations adapter.Copy(this, objectToApplyTo); break; case OperationType.Test: - throw new NotSupportedException(Resources.TestOperationNotSupported); + throw new JsonPatchException(new JsonPatchError(objectToApplyTo, this, Resources.TestOperationNotSupported)); default: break; } diff --git a/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs index 9e00cc2f00..ed567cf003 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs @@ -122,6 +122,22 @@ namespace Microsoft.AspNetCore.JsonPatch return string.Format(CultureInfo.CurrentCulture, GetString("InvalidJsonPatchDocument"), p0); } + /// + /// Invalid JsonPatch operation '{0}'. + /// + internal static string InvalidJsonPatchOperation + { + get { return GetString("InvalidJsonPatchOperation"); } + } + + /// + /// Invalid JsonPatch operation '{0}'. + /// + internal static string FormatInvalidJsonPatchOperation(object p0) + { + return string.Format(CultureInfo.CurrentCulture, GetString("InvalidJsonPatchOperation"), p0); + } + /// /// The provided string '{0}' is an invalid path. /// diff --git a/src/Microsoft.AspNetCore.JsonPatch/Resources.resx b/src/Microsoft.AspNetCore.JsonPatch/Resources.resx index a7b50520ac..7381ad02fc 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Resources.resx +++ b/src/Microsoft.AspNetCore.JsonPatch/Resources.resx @@ -138,6 +138,9 @@ The type '{0}' was malformed and could not be parsed. + + Invalid JsonPatch operation '{0}'. + The provided string '{0}' is an invalid path. diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs new file mode 100644 index 0000000000..723ef15b64 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs @@ -0,0 +1,91 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNetCore.JsonPatch.Exceptions; +using Newtonsoft.Json; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch.Test +{ + public class JsonPatchDocumentTest + { + [Fact] + public void TestOperation_ThrowsException_CallsIntoLogErrorAction() + { + // Arrange + var serialized = "[{\"value\":\"John\",\"path\":\"/Name\",\"op\":\"test\"}]"; + var jsonPatchDocument = JsonConvert.DeserializeObject>(serialized); + var model = new Customer(); + var expectedErrorMessage = "The test operation is not supported."; + string actualErrorMessage = null; + + // Act + jsonPatchDocument.ApplyTo(model, (jsonPatchError) => + { + actualErrorMessage = jsonPatchError.ErrorMessage; + }); + + // Assert + Assert.Equal(expectedErrorMessage, actualErrorMessage); + } + + [Fact] + public void TestOperation_NoLogErrorAction_ThrowsJsonPatchException() + { + // Arrange + var serialized = "[{\"value\":\"John\",\"path\":\"/Name\",\"op\":\"test\"}]"; + var jsonPatchDocument = JsonConvert.DeserializeObject>(serialized); + var model = new Customer(); + var expectedErrorMessage = "The test operation is not supported."; + + // Act + var jsonPatchException = Assert.Throws(() => jsonPatchDocument.ApplyTo(model)); + + // Assert + Assert.Equal(expectedErrorMessage, jsonPatchException.Message); + } + + [Fact] + public void InvalidOperation_ThrowsException_CallsIntoLogErrorAction() + { + // Arrange + var operationName = "foo"; + var serialized = "[{\"value\":\"John\",\"path\":\"/Name\",\"op\":\"" + operationName + "\"}]"; + var jsonPatchDocument = JsonConvert.DeserializeObject>(serialized); + var model = new Customer(); + var expectedErrorMessage = $"Invalid JsonPatch operation '{operationName}'."; + string actualErrorMessage = null; + + // Act + jsonPatchDocument.ApplyTo(model, (jsonPatchError) => + { + actualErrorMessage = jsonPatchError.ErrorMessage; + }); + + // Assert + Assert.Equal(expectedErrorMessage, actualErrorMessage); + } + + [Fact] + public void InvalidOperation_NoLogErrorAction_ThrowsJsonPatchException() + { + // Arrange + var operationName = "foo"; + var serialized = "[{\"value\":\"John\",\"path\":\"/Name\",\"op\":\"" + operationName + "\"}]"; + var jsonPatchDocument = JsonConvert.DeserializeObject>(serialized); + var model = new Customer(); + var expectedErrorMessage = $"Invalid JsonPatch operation '{operationName}'."; + + // Act + var jsonPatchException = Assert.Throws(() => jsonPatchDocument.ApplyTo(model)); + + // Assert + Assert.Equal(expectedErrorMessage, jsonPatchException.Message); + } + + private class Customer + { + public string Name { get; set; } + } + } +} From 42d8ccbc47e00803def90e2f34e193263e764011 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 3 Nov 2016 17:54:09 -0700 Subject: [PATCH 0325/1029] dotnet-watch: add extended help to clarify usage (#218) --- .../CommandLineOptions.cs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs index dfd27756bd..61064652aa 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs @@ -26,7 +26,25 @@ namespace Microsoft.DotNet.Watcher FullName = "Microsoft DotNet File Watcher", Out = stdout, Error = stderr, - AllowArgumentSeparator = true + AllowArgumentSeparator = true, + ExtendedHelpText = @" +Remarks: + The special option '--' is used to delimit the end of the options and + the beginning of arguments that will be passed to the child dotnet process. + Its use is optional. When the special option '--' is not used, + dotnet-watch will use the first unrecognized argument as the beginning + of all arguments passed into the child dotnet process. + + For example: dotnet watch -- --verbose run + + Even though '--verbose' is an option dotnet-watch supports, the use of '--' + indicates that '--verbose' should be treated instead as an argument for + dotnet-run. + +Examples: + dotnet watch run + dotnet watch test +" }; app.HelpOption("-?|-h|--help"); From 5de082e68781ea67ede797b0afca6ba1b05ac0f0 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 4 Nov 2016 10:18:46 -0700 Subject: [PATCH 0326/1029] Upgrade Microsoft.DotNet.Cli.Utils from preview2 to preview3 --- src/Microsoft.DotNet.Watcher.Tools/project.json | 2 +- src/Microsoft.Extensions.SecretManager.Tools/project.json | 2 +- .../Scenario/ProjectToolScenario.cs | 5 ++--- .../project.json | 1 + test/Microsoft.DotNet.Watcher.Tools.Tests/project.json | 1 + .../project.json | 1 + 6 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index 742e7e484c..6306ce1285 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -32,7 +32,7 @@ ] }, "dependencies": { - "Microsoft.DotNet.Cli.Utils": "1.0.0-preview2-003121", + "Microsoft.DotNet.Cli.Utils": "1.0.0-preview3-004050", "Microsoft.Extensions.Logging": "1.0.0", "Microsoft.Extensions.Logging.Console": "1.0.0", "Microsoft.Extensions.Process.Sources": { diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index d7a2e799bf..cec16d5840 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -38,7 +38,7 @@ ] }, "dependencies": { - "Microsoft.DotNet.Cli.Utils": "1.0.0-preview2-003121", + "Microsoft.DotNet.Cli.Utils": "1.0.0-preview3-004050", "Microsoft.Extensions.Configuration.UserSecrets": "1.0.0", "Microsoft.Extensions.Logging": "1.0.0", "Microsoft.NETCore.App": { diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs index a8ce555257..ff124a8703 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -9,7 +9,6 @@ using System.Linq; using System.Reflection; using System.Threading; using Microsoft.DotNet.Cli.Utils; -using Microsoft.DotNet.ProjectModel; using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests @@ -98,10 +97,10 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests args.Add("exec"); args.Add("--depsfile"); - args.Add(Path.Combine(AppContext.BaseDirectory, thisAssembly + FileNameSuffixes.DepsJson)); + args.Add(Path.Combine(AppContext.BaseDirectory, thisAssembly + ".deps.json")); args.Add("--runtimeconfig"); - args.Add(Path.Combine(AppContext.BaseDirectory, thisAssembly + FileNameSuffixes.RuntimeConfigJson)); + args.Add(Path.Combine(AppContext.BaseDirectory, thisAssembly + ".runtimeconfig.json")); args.Add(Path.Combine(AppContext.BaseDirectory, "dotnet-watch.dll")); diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index 39e6e6ce55..645d6f7de4 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -11,6 +11,7 @@ }, "dependencies": { "dotnet-test-xunit": "2.2.0-preview2-build1029", + "Microsoft.DotNet.InternalAbstractions": "1.0.0", "Microsoft.AspNetCore.Testing": "1.0.0", "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", "Microsoft.Extensions.Process.Sources": { diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json index fd2d9874aa..b40ce98d3a 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json @@ -6,6 +6,7 @@ }, "dependencies": { "dotnet-test-xunit": "2.2.0-preview2-build1029", + "Microsoft.DotNet.InternalAbstractions": "1.0.0", "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", "xunit": "2.2.0-beta3-build3402" }, diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json index 515a64c422..b93fb60245 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json @@ -5,6 +5,7 @@ }, "dependencies": { "dotnet-test-xunit": "2.2.0-preview2-build1029", + "Microsoft.DotNet.InternalAbstractions": "1.0.0", "Microsoft.Extensions.SecretManager.Tools": "1.0.0-*", "xunit": "2.2.0-beta3-build3402" }, From 944e99121c3e2fcbfa5dc70ab7bc7625b1b48d8f Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 4 Nov 2016 10:47:13 -0700 Subject: [PATCH 0327/1029] Add nuget feed to restore CLI dependencies --- NuGet.config | 4 +++- .../Scenario/ProjectToolScenario.cs | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/NuGet.config b/NuGet.config index 90ce61307f..5144de9b69 100644 --- a/NuGet.config +++ b/NuGet.config @@ -2,7 +2,9 @@ + + - + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs index ff124a8703..c7fc330aef 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -97,10 +97,10 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests args.Add("exec"); args.Add("--depsfile"); - args.Add(Path.Combine(AppContext.BaseDirectory, thisAssembly + ".deps.json")); + args.Add(Path.Combine(AppContext.BaseDirectory, thisAssembly + FileNameSuffixes.DepsJson)); args.Add("--runtimeconfig"); - args.Add(Path.Combine(AppContext.BaseDirectory, thisAssembly + ".runtimeconfig.json")); + args.Add(Path.Combine(AppContext.BaseDirectory, thisAssembly + FileNameSuffixes.RuntimeConfigJson)); args.Add(Path.Combine(AppContext.BaseDirectory, "dotnet-watch.dll")); From 8dc7ac8623de221b6acb7282052dcba9b32ec21a Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 4 Nov 2016 13:34:19 -0700 Subject: [PATCH 0328/1029] Add DOTNET_USE_POLLING_FILE_WATCHER to help output --- src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs index 61064652aa..ab120038c5 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs @@ -28,6 +28,13 @@ namespace Microsoft.DotNet.Watcher Error = stderr, AllowArgumentSeparator = true, ExtendedHelpText = @" +Environment variables: + + DOTNET_USE_POLLING_FILE_WATCHER + When set to '1' or 'true', dotnet-watch will poll the file system for + changes. This is required for some file systems, such as network shares, + Docker mounted volumes, and other virtual file systems. + Remarks: The special option '--' is used to delimit the end of the options and the beginning of arguments that will be passed to the child dotnet process. From 80cdeceb0b7127ec9be2da2bfbfbba4824978751 Mon Sep 17 00:00:00 2001 From: jacalvar Date: Fri, 4 Nov 2016 15:28:07 -0700 Subject: [PATCH 0329/1029] Created public API baselines --- .../baseline.netcore.json | 618 ++++++++++++++++++ .../baseline.netcore.json | 564 ++++++++++++++++ 2 files changed, 1182 insertions(+) create mode 100644 src/Microsoft.AspNetCore.Html.Abstractions/baseline.netcore.json create mode 100644 src/Microsoft.Extensions.WebEncoders/baseline.netcore.json diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/baseline.netcore.json b/src/Microsoft.AspNetCore.Html.Abstractions/baseline.netcore.json new file mode 100644 index 0000000000..7e3a4d0d00 --- /dev/null +++ b/src/Microsoft.AspNetCore.Html.Abstractions/baseline.netcore.json @@ -0,0 +1,618 @@ +{ + "AssemblyIdentity": "Microsoft.AspNetCore.Html.Abstractions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "Types": [ + { + "Name": "Microsoft.AspNetCore.Html.HtmlContentBuilder", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.Html.IHtmlContentBuilder" + ], + "Members": [ + { + "Kind": "Method", + "Name": "Append", + "Parameters": [ + { + "Name": "unencoded", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "AppendHtml", + "Parameters": [ + { + "Name": "htmlContent", + "Type": "Microsoft.AspNetCore.Html.IHtmlContent" + } + ], + "ReturnType": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "AppendHtml", + "Parameters": [ + { + "Name": "encoded", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Clear", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "CopyTo", + "Parameters": [ + { + "Name": "destination", + "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContentContainer", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "MoveTo", + "Parameters": [ + { + "Name": "destination", + "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContentContainer", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "WriteTo", + "Parameters": [ + { + "Name": "writer", + "Type": "System.IO.TextWriter" + }, + { + "Name": "encoder", + "Type": "System.Text.Encodings.Web.HtmlEncoder" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContent", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "capacity", + "Type": "System.Int32" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "entries", + "Type": "System.Collections.Generic.IList" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Html.HtmlContentBuilderExtensions", + "Visibility": "Public", + "Kind": "Class", + "Abstract": true, + "Static": true, + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "AppendFormat", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" + }, + { + "Name": "format", + "Type": "System.String" + }, + { + "Name": "args", + "Type": "System.Object[]", + "IsParams": true + } + ], + "ReturnType": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "AppendFormat", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" + }, + { + "Name": "formatProvider", + "Type": "System.IFormatProvider" + }, + { + "Name": "format", + "Type": "System.String" + }, + { + "Name": "args", + "Type": "System.Object[]", + "IsParams": true + } + ], + "ReturnType": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "AppendLine", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" + } + ], + "ReturnType": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "AppendLine", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" + }, + { + "Name": "unencoded", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "AppendLine", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" + }, + { + "Name": "content", + "Type": "Microsoft.AspNetCore.Html.IHtmlContent" + } + ], + "ReturnType": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "AppendHtmlLine", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" + }, + { + "Name": "encoded", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "SetContent", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" + }, + { + "Name": "unencoded", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "SetHtmlContent", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" + }, + { + "Name": "content", + "Type": "Microsoft.AspNetCore.Html.IHtmlContent" + } + ], + "ReturnType": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "SetHtmlContent", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" + }, + { + "Name": "encoded", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Html.HtmlFormattableString", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.Html.IHtmlContent" + ], + "Members": [ + { + "Kind": "Method", + "Name": "WriteTo", + "Parameters": [ + { + "Name": "writer", + "Type": "System.IO.TextWriter" + }, + { + "Name": "encoder", + "Type": "System.Text.Encodings.Web.HtmlEncoder" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContent", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "format", + "Type": "System.String" + }, + { + "Name": "args", + "Type": "System.Object[]", + "IsParams": true + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "formatProvider", + "Type": "System.IFormatProvider" + }, + { + "Name": "format", + "Type": "System.String" + }, + { + "Name": "args", + "Type": "System.Object[]", + "IsParams": true + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Html.HtmlString", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.Html.IHtmlContent" + ], + "Members": [ + { + "Kind": "Method", + "Name": "get_Value", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "WriteTo", + "Parameters": [ + { + "Name": "writer", + "Type": "System.IO.TextWriter" + }, + { + "Name": "encoder", + "Type": "System.Text.Encodings.Web.HtmlEncoder" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContent", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ToString", + "Parameters": [], + "ReturnType": "System.String", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Field", + "Name": "NewLine", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Html.HtmlString", + "Static": true, + "ReadOnly": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Field", + "Name": "Empty", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Html.HtmlString", + "Static": true, + "ReadOnly": true, + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Html.IHtmlContent", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "WriteTo", + "Parameters": [ + { + "Name": "writer", + "Type": "System.IO.TextWriter" + }, + { + "Name": "encoder", + "Type": "System.Text.Encodings.Web.HtmlEncoder" + } + ], + "ReturnType": "System.Void", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.Html.IHtmlContentContainer" + ], + "Members": [ + { + "Kind": "Method", + "Name": "AppendHtml", + "Parameters": [ + { + "Name": "content", + "Type": "Microsoft.AspNetCore.Html.IHtmlContent" + } + ], + "ReturnType": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Append", + "Parameters": [ + { + "Name": "unencoded", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "AppendHtml", + "Parameters": [ + { + "Name": "encoded", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Clear", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Html.IHtmlContentBuilder", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Html.IHtmlContentContainer", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.Html.IHtmlContent" + ], + "Members": [ + { + "Kind": "Method", + "Name": "CopyTo", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" + } + ], + "ReturnType": "System.Void", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "MoveTo", + "Parameters": [ + { + "Name": "builder", + "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" + } + ], + "ReturnType": "System.Void", + "GenericParameter": [] + } + ], + "GenericParameters": [] + } + ] +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.WebEncoders/baseline.netcore.json b/src/Microsoft.Extensions.WebEncoders/baseline.netcore.json new file mode 100644 index 0000000000..db16203ed1 --- /dev/null +++ b/src/Microsoft.Extensions.WebEncoders/baseline.netcore.json @@ -0,0 +1,564 @@ +{ + "AssemblyIdentity": "Microsoft.Extensions.WebEncoders, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "Types": [ + { + "Name": "Microsoft.Extensions.WebEncoders.WebEncoderOptions", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_TextEncoderSettings", + "Parameters": [], + "ReturnType": "System.Text.Encodings.Web.TextEncoderSettings", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_TextEncoderSettings", + "Parameters": [ + { + "Name": "value", + "Type": "System.Text.Encodings.Web.TextEncoderSettings" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.Extensions.WebEncoders.Testing.HtmlTestEncoder", + "Visibility": "Public", + "Kind": "Class", + "Sealed": true, + "BaseType": "System.Text.Encodings.Web.HtmlEncoder", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_MaxOutputCharactersPerInputCharacter", + "Parameters": [], + "ReturnType": "System.Int32", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Encode", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.String", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Encode", + "Parameters": [ + { + "Name": "output", + "Type": "System.IO.TextWriter" + }, + { + "Name": "value", + "Type": "System.Char[]" + }, + { + "Name": "startIndex", + "Type": "System.Int32" + }, + { + "Name": "characterCount", + "Type": "System.Int32" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Encode", + "Parameters": [ + { + "Name": "output", + "Type": "System.IO.TextWriter" + }, + { + "Name": "value", + "Type": "System.String" + }, + { + "Name": "startIndex", + "Type": "System.Int32" + }, + { + "Name": "characterCount", + "Type": "System.Int32" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "WillEncode", + "Parameters": [ + { + "Name": "unicodeScalar", + "Type": "System.Int32" + } + ], + "ReturnType": "System.Boolean", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "FindFirstCharacterToEncode", + "Parameters": [ + { + "Name": "text", + "Type": "System.Char*" + }, + { + "Name": "textLength", + "Type": "System.Int32" + } + ], + "ReturnType": "System.Int32", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "TryEncodeUnicodeScalar", + "Parameters": [ + { + "Name": "unicodeScalar", + "Type": "System.Int32" + }, + { + "Name": "buffer", + "Type": "System.Char*" + }, + { + "Name": "bufferLength", + "Type": "System.Int32" + }, + { + "Name": "numberOfCharactersWritten", + "Type": "System.Int32", + "Direction": "Out" + } + ], + "ReturnType": "System.Boolean", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.Extensions.WebEncoders.Testing.JavaScriptTestEncoder", + "Visibility": "Public", + "Kind": "Class", + "BaseType": "System.Text.Encodings.Web.JavaScriptEncoder", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_MaxOutputCharactersPerInputCharacter", + "Parameters": [], + "ReturnType": "System.Int32", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Encode", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.String", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Encode", + "Parameters": [ + { + "Name": "output", + "Type": "System.IO.TextWriter" + }, + { + "Name": "value", + "Type": "System.Char[]" + }, + { + "Name": "startIndex", + "Type": "System.Int32" + }, + { + "Name": "characterCount", + "Type": "System.Int32" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Encode", + "Parameters": [ + { + "Name": "output", + "Type": "System.IO.TextWriter" + }, + { + "Name": "value", + "Type": "System.String" + }, + { + "Name": "startIndex", + "Type": "System.Int32" + }, + { + "Name": "characterCount", + "Type": "System.Int32" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "WillEncode", + "Parameters": [ + { + "Name": "unicodeScalar", + "Type": "System.Int32" + } + ], + "ReturnType": "System.Boolean", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "FindFirstCharacterToEncode", + "Parameters": [ + { + "Name": "text", + "Type": "System.Char*" + }, + { + "Name": "textLength", + "Type": "System.Int32" + } + ], + "ReturnType": "System.Int32", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "TryEncodeUnicodeScalar", + "Parameters": [ + { + "Name": "unicodeScalar", + "Type": "System.Int32" + }, + { + "Name": "buffer", + "Type": "System.Char*" + }, + { + "Name": "bufferLength", + "Type": "System.Int32" + }, + { + "Name": "numberOfCharactersWritten", + "Type": "System.Int32", + "Direction": "Out" + } + ], + "ReturnType": "System.Boolean", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.Extensions.WebEncoders.Testing.UrlTestEncoder", + "Visibility": "Public", + "Kind": "Class", + "BaseType": "System.Text.Encodings.Web.UrlEncoder", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_MaxOutputCharactersPerInputCharacter", + "Parameters": [], + "ReturnType": "System.Int32", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Encode", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.String", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Encode", + "Parameters": [ + { + "Name": "output", + "Type": "System.IO.TextWriter" + }, + { + "Name": "value", + "Type": "System.Char[]" + }, + { + "Name": "startIndex", + "Type": "System.Int32" + }, + { + "Name": "characterCount", + "Type": "System.Int32" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Encode", + "Parameters": [ + { + "Name": "output", + "Type": "System.IO.TextWriter" + }, + { + "Name": "value", + "Type": "System.String" + }, + { + "Name": "startIndex", + "Type": "System.Int32" + }, + { + "Name": "characterCount", + "Type": "System.Int32" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "WillEncode", + "Parameters": [ + { + "Name": "unicodeScalar", + "Type": "System.Int32" + } + ], + "ReturnType": "System.Boolean", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "FindFirstCharacterToEncode", + "Parameters": [ + { + "Name": "text", + "Type": "System.Char*" + }, + { + "Name": "textLength", + "Type": "System.Int32" + } + ], + "ReturnType": "System.Int32", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "TryEncodeUnicodeScalar", + "Parameters": [ + { + "Name": "unicodeScalar", + "Type": "System.Int32" + }, + { + "Name": "buffer", + "Type": "System.Char*" + }, + { + "Name": "bufferLength", + "Type": "System.Int32" + }, + { + "Name": "numberOfCharactersWritten", + "Type": "System.Int32", + "Direction": "Out" + } + ], + "ReturnType": "System.Boolean", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.Extensions.DependencyInjection.EncoderServiceCollectionExtensions", + "Visibility": "Public", + "Kind": "Class", + "Abstract": true, + "Static": true, + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "AddWebEncoders", + "Parameters": [ + { + "Name": "services", + "Type": "Microsoft.Extensions.DependencyInjection.IServiceCollection" + } + ], + "ReturnType": "Microsoft.Extensions.DependencyInjection.IServiceCollection", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "AddWebEncoders", + "Parameters": [ + { + "Name": "services", + "Type": "Microsoft.Extensions.DependencyInjection.IServiceCollection" + }, + { + "Name": "setupAction", + "Type": "System.Action" + } + ], + "ReturnType": "Microsoft.Extensions.DependencyInjection.IServiceCollection", + "Static": true, + "Extension": true, + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + } + ] +} \ No newline at end of file From 373097e0dd772d947603c2e1a316fe323f50a288 Mon Sep 17 00:00:00 2001 From: jacalvar Date: Fri, 4 Nov 2016 17:05:29 -0700 Subject: [PATCH 0330/1029] Created public API baselines --- .../baseline.netcore.json | 1840 +++++++++++++++++ 1 file changed, 1840 insertions(+) create mode 100644 src/Microsoft.AspNetCore.JsonPatch/baseline.netcore.json diff --git a/src/Microsoft.AspNetCore.JsonPatch/baseline.netcore.json b/src/Microsoft.AspNetCore.JsonPatch/baseline.netcore.json new file mode 100644 index 0000000000..c84771a03c --- /dev/null +++ b/src/Microsoft.AspNetCore.JsonPatch/baseline.netcore.json @@ -0,0 +1,1840 @@ +{ + "AssemblyIdentity": "Microsoft.AspNetCore.JsonPatch, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "Types": [ + { + "Name": "Microsoft.AspNetCore.JsonPatch.IJsonPatchDocument", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_ContractResolver", + "Parameters": [], + "ReturnType": "Newtonsoft.Json.Serialization.IContractResolver", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_ContractResolver", + "Parameters": [ + { + "Name": "value", + "Type": "Newtonsoft.Json.Serialization.IContractResolver" + } + ], + "ReturnType": "System.Void", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetOperations", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IList", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.JsonPatch.IJsonPatchDocument" + ], + "Members": [ + { + "Kind": "Method", + "Name": "get_Operations", + "Parameters": [], + "ReturnType": "System.Collections.Generic.List", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ContractResolver", + "Parameters": [], + "ReturnType": "Newtonsoft.Json.Serialization.IContractResolver", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.JsonPatch.IJsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_ContractResolver", + "Parameters": [ + { + "Name": "value", + "Type": "Newtonsoft.Json.Serialization.IContractResolver" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.JsonPatch.IJsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Add", + "Parameters": [ + { + "Name": "path", + "Type": "System.String" + }, + { + "Name": "value", + "Type": "System.Object" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Remove", + "Parameters": [ + { + "Name": "path", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Replace", + "Parameters": [ + { + "Name": "path", + "Type": "System.String" + }, + { + "Name": "value", + "Type": "System.Object" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Move", + "Parameters": [ + { + "Name": "from", + "Type": "System.String" + }, + { + "Name": "path", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Copy", + "Parameters": [ + { + "Name": "from", + "Type": "System.String" + }, + { + "Name": "path", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ApplyTo", + "Parameters": [ + { + "Name": "objectToApplyTo", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ApplyTo", + "Parameters": [ + { + "Name": "objectToApplyTo", + "Type": "System.Object" + }, + { + "Name": "logErrorAction", + "Type": "System.Action" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ApplyTo", + "Parameters": [ + { + "Name": "objectToApplyTo", + "Type": "System.Object" + }, + { + "Name": "adapter", + "Type": "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapter" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "operations", + "Type": "System.Collections.Generic.List" + }, + { + "Name": "contractResolver", + "Type": "Newtonsoft.Json.Serialization.IContractResolver" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.JsonPatch.IJsonPatchDocument" + ], + "Members": [ + { + "Kind": "Method", + "Name": "get_Operations", + "Parameters": [], + "ReturnType": "System.Collections.Generic.List>", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ContractResolver", + "Parameters": [], + "ReturnType": "Newtonsoft.Json.Serialization.IContractResolver", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.JsonPatch.IJsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_ContractResolver", + "Parameters": [ + { + "Name": "value", + "Type": "Newtonsoft.Json.Serialization.IContractResolver" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.JsonPatch.IJsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Add", + "Parameters": [ + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>" + }, + { + "Name": "value", + "Type": "T0" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Add", + "Parameters": [ + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>>" + }, + { + "Name": "value", + "Type": "T0" + }, + { + "Name": "position", + "Type": "System.Int32" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Add", + "Parameters": [ + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>>" + }, + { + "Name": "value", + "Type": "T0" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Remove", + "Parameters": [ + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Remove", + "Parameters": [ + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>>" + }, + { + "Name": "position", + "Type": "System.Int32" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Remove", + "Parameters": [ + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>>" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Replace", + "Parameters": [ + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>" + }, + { + "Name": "value", + "Type": "T0" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Replace", + "Parameters": [ + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>>" + }, + { + "Name": "value", + "Type": "T0" + }, + { + "Name": "position", + "Type": "System.Int32" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Replace", + "Parameters": [ + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>>" + }, + { + "Name": "value", + "Type": "T0" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Move", + "Parameters": [ + { + "Name": "from", + "Type": "System.Linq.Expressions.Expression>" + }, + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Move", + "Parameters": [ + { + "Name": "from", + "Type": "System.Linq.Expressions.Expression>>" + }, + { + "Name": "positionFrom", + "Type": "System.Int32" + }, + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Move", + "Parameters": [ + { + "Name": "from", + "Type": "System.Linq.Expressions.Expression>" + }, + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>>" + }, + { + "Name": "positionTo", + "Type": "System.Int32" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Move", + "Parameters": [ + { + "Name": "from", + "Type": "System.Linq.Expressions.Expression>>" + }, + { + "Name": "positionFrom", + "Type": "System.Int32" + }, + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>>" + }, + { + "Name": "positionTo", + "Type": "System.Int32" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Move", + "Parameters": [ + { + "Name": "from", + "Type": "System.Linq.Expressions.Expression>>" + }, + { + "Name": "positionFrom", + "Type": "System.Int32" + }, + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>>" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Move", + "Parameters": [ + { + "Name": "from", + "Type": "System.Linq.Expressions.Expression>" + }, + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>>" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Copy", + "Parameters": [ + { + "Name": "from", + "Type": "System.Linq.Expressions.Expression>" + }, + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Copy", + "Parameters": [ + { + "Name": "from", + "Type": "System.Linq.Expressions.Expression>>" + }, + { + "Name": "positionFrom", + "Type": "System.Int32" + }, + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Copy", + "Parameters": [ + { + "Name": "from", + "Type": "System.Linq.Expressions.Expression>" + }, + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>>" + }, + { + "Name": "positionTo", + "Type": "System.Int32" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Copy", + "Parameters": [ + { + "Name": "from", + "Type": "System.Linq.Expressions.Expression>>" + }, + { + "Name": "positionFrom", + "Type": "System.Int32" + }, + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>>" + }, + { + "Name": "positionTo", + "Type": "System.Int32" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Copy", + "Parameters": [ + { + "Name": "from", + "Type": "System.Linq.Expressions.Expression>>" + }, + { + "Name": "positionFrom", + "Type": "System.Int32" + }, + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>>" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Copy", + "Parameters": [ + { + "Name": "from", + "Type": "System.Linq.Expressions.Expression>" + }, + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>>" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "ApplyTo", + "Parameters": [ + { + "Name": "objectToApplyTo", + "Type": "T0" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ApplyTo", + "Parameters": [ + { + "Name": "objectToApplyTo", + "Type": "T0" + }, + { + "Name": "logErrorAction", + "Type": "System.Action" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ApplyTo", + "Parameters": [ + { + "Name": "objectToApplyTo", + "Type": "T0" + }, + { + "Name": "adapter", + "Type": "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapter" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "operations", + "Type": "System.Collections.Generic.List>" + }, + { + "Name": "contractResolver", + "Type": "Newtonsoft.Json.Serialization.IContractResolver" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [ + { + "ParameterName": "TModel", + "ParameterPosition": 0, + "Class": true, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Name": "Microsoft.AspNetCore.JsonPatch.JsonPatchError", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_AffectedObject", + "Parameters": [], + "ReturnType": "System.Object", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Operation", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.Operations.Operation", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ErrorMessage", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "affectedObject", + "Type": "System.Object" + }, + { + "Name": "operation", + "Type": "Microsoft.AspNetCore.JsonPatch.Operations.Operation" + }, + { + "Name": "errorMessage", + "Type": "System.String" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.JsonPatch.JsonPatchProperty", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_Property", + "Parameters": [], + "ReturnType": "Newtonsoft.Json.Serialization.JsonProperty", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Property", + "Parameters": [ + { + "Name": "value", + "Type": "Newtonsoft.Json.Serialization.JsonProperty" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Parent", + "Parameters": [], + "ReturnType": "System.Object", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Parent", + "Parameters": [ + { + "Name": "value", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "property", + "Type": "Newtonsoft.Json.Serialization.JsonProperty" + }, + { + "Name": "parent", + "Type": "System.Object" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.JsonPatch.Operations.Operation", + "Visibility": "Public", + "Kind": "Class", + "BaseType": "Microsoft.AspNetCore.JsonPatch.Operations.OperationBase", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_value", + "Parameters": [], + "ReturnType": "System.Object", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_value", + "Parameters": [ + { + "Name": "value", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Apply", + "Parameters": [ + { + "Name": "objectToApplyTo", + "Type": "System.Object" + }, + { + "Name": "adapter", + "Type": "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapter" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ShouldSerializevalue", + "Parameters": [], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "op", + "Type": "System.String" + }, + { + "Name": "path", + "Type": "System.String" + }, + { + "Name": "from", + "Type": "System.String" + }, + { + "Name": "value", + "Type": "System.Object" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "op", + "Type": "System.String" + }, + { + "Name": "path", + "Type": "System.String" + }, + { + "Name": "from", + "Type": "System.String" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.JsonPatch.Operations.OperationBase", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_OperationType", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.Operations.OperationType", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_path", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_path", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_op", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_op", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_from", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_from", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ShouldSerializefrom", + "Parameters": [], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "op", + "Type": "System.String" + }, + { + "Name": "path", + "Type": "System.String" + }, + { + "Name": "from", + "Type": "System.String" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.JsonPatch.Operations.Operation", + "Visibility": "Public", + "Kind": "Class", + "BaseType": "Microsoft.AspNetCore.JsonPatch.Operations.Operation", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "Apply", + "Parameters": [ + { + "Name": "objectToApplyTo", + "Type": "T0" + }, + { + "Name": "adapter", + "Type": "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapter" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "op", + "Type": "System.String" + }, + { + "Name": "path", + "Type": "System.String" + }, + { + "Name": "from", + "Type": "System.String" + }, + { + "Name": "value", + "Type": "System.Object" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "op", + "Type": "System.String" + }, + { + "Name": "path", + "Type": "System.String" + }, + { + "Name": "from", + "Type": "System.String" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [ + { + "ParameterName": "TModel", + "ParameterPosition": 0, + "Class": true, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Name": "Microsoft.AspNetCore.JsonPatch.Operations.OperationType", + "Visibility": "Public", + "Kind": "Enumeration", + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Field", + "Name": "Add", + "Parameters": [], + "GenericParameter": [], + "Literal": "0" + }, + { + "Kind": "Field", + "Name": "Remove", + "Parameters": [], + "GenericParameter": [], + "Literal": "1" + }, + { + "Kind": "Field", + "Name": "Replace", + "Parameters": [], + "GenericParameter": [], + "Literal": "2" + }, + { + "Kind": "Field", + "Name": "Move", + "Parameters": [], + "GenericParameter": [], + "Literal": "3" + }, + { + "Kind": "Field", + "Name": "Copy", + "Parameters": [], + "GenericParameter": [], + "Literal": "4" + }, + { + "Kind": "Field", + "Name": "Test", + "Parameters": [], + "GenericParameter": [], + "Literal": "5" + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.JsonPatch.Helpers.GetValueResult", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_PropertyValue", + "Parameters": [], + "ReturnType": "System.Object", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_HasError", + "Parameters": [], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "propertyValue", + "Type": "System.Object" + }, + { + "Name": "hasError", + "Type": "System.Boolean" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.JsonPatch.Exceptions.JsonPatchException", + "Visibility": "Public", + "Kind": "Class", + "BaseType": "System.Exception", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_FailedOperation", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.Operations.Operation", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_AffectedObject", + "Parameters": [], + "ReturnType": "System.Object", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "jsonPatchError", + "Type": "Microsoft.AspNetCore.JsonPatch.JsonPatchError" + }, + { + "Name": "innerException", + "Type": "System.Exception" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "jsonPatchError", + "Type": "Microsoft.AspNetCore.JsonPatch.JsonPatchError" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "message", + "Type": "System.String" + }, + { + "Name": "innerException", + "Type": "System.Exception" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.JsonPatch.Converters.JsonPatchDocumentConverter", + "Visibility": "Public", + "Kind": "Class", + "BaseType": "Newtonsoft.Json.JsonConverter", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "CanConvert", + "Parameters": [ + { + "Name": "objectType", + "Type": "System.Type" + } + ], + "ReturnType": "System.Boolean", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ReadJson", + "Parameters": [ + { + "Name": "reader", + "Type": "Newtonsoft.Json.JsonReader" + }, + { + "Name": "objectType", + "Type": "System.Type" + }, + { + "Name": "existingValue", + "Type": "System.Object" + }, + { + "Name": "serializer", + "Type": "Newtonsoft.Json.JsonSerializer" + } + ], + "ReturnType": "System.Object", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "WriteJson", + "Parameters": [ + { + "Name": "writer", + "Type": "Newtonsoft.Json.JsonWriter" + }, + { + "Name": "value", + "Type": "System.Object" + }, + { + "Name": "serializer", + "Type": "Newtonsoft.Json.JsonSerializer" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.JsonPatch.Converters.TypedJsonPatchDocumentConverter", + "Visibility": "Public", + "Kind": "Class", + "BaseType": "Microsoft.AspNetCore.JsonPatch.Converters.JsonPatchDocumentConverter", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "ReadJson", + "Parameters": [ + { + "Name": "reader", + "Type": "Newtonsoft.Json.JsonReader" + }, + { + "Name": "objectType", + "Type": "System.Type" + }, + { + "Name": "existingValue", + "Type": "System.Object" + }, + { + "Name": "serializer", + "Type": "Newtonsoft.Json.JsonSerializer" + } + ], + "ReturnType": "System.Object", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapter", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "Add", + "Parameters": [ + { + "Name": "operation", + "Type": "Microsoft.AspNetCore.JsonPatch.Operations.Operation" + }, + { + "Name": "objectToApplyTo", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Copy", + "Parameters": [ + { + "Name": "operation", + "Type": "Microsoft.AspNetCore.JsonPatch.Operations.Operation" + }, + { + "Name": "objectToApplyTo", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Move", + "Parameters": [ + { + "Name": "operation", + "Type": "Microsoft.AspNetCore.JsonPatch.Operations.Operation" + }, + { + "Name": "objectToApplyTo", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Remove", + "Parameters": [ + { + "Name": "operation", + "Type": "Microsoft.AspNetCore.JsonPatch.Operations.Operation" + }, + { + "Name": "objectToApplyTo", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Replace", + "Parameters": [ + { + "Name": "operation", + "Type": "Microsoft.AspNetCore.JsonPatch.Operations.Operation" + }, + { + "Name": "objectToApplyTo", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.JsonPatch.Adapters.ObjectAdapter", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapter" + ], + "Members": [ + { + "Kind": "Method", + "Name": "get_ContractResolver", + "Parameters": [], + "ReturnType": "Newtonsoft.Json.Serialization.IContractResolver", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_LogErrorAction", + "Parameters": [], + "ReturnType": "System.Action", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Add", + "Parameters": [ + { + "Name": "operation", + "Type": "Microsoft.AspNetCore.JsonPatch.Operations.Operation" + }, + { + "Name": "objectToApplyTo", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapter", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Move", + "Parameters": [ + { + "Name": "operation", + "Type": "Microsoft.AspNetCore.JsonPatch.Operations.Operation" + }, + { + "Name": "objectToApplyTo", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapter", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Remove", + "Parameters": [ + { + "Name": "operation", + "Type": "Microsoft.AspNetCore.JsonPatch.Operations.Operation" + }, + { + "Name": "objectToApplyTo", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapter", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Replace", + "Parameters": [ + { + "Name": "operation", + "Type": "Microsoft.AspNetCore.JsonPatch.Operations.Operation" + }, + { + "Name": "objectToApplyTo", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapter", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Copy", + "Parameters": [ + { + "Name": "operation", + "Type": "Microsoft.AspNetCore.JsonPatch.Operations.Operation" + }, + { + "Name": "objectToApplyTo", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapter", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "contractResolver", + "Type": "Newtonsoft.Json.Serialization.IContractResolver" + }, + { + "Name": "logErrorAction", + "Type": "System.Action" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + } + ] +} \ No newline at end of file From c84bdb35d314058faadff19796b4c92efe98e91d Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 3 Nov 2016 17:54:09 -0700 Subject: [PATCH 0331/1029] dotnet-watch: add extended help to clarify usage (#218) --- .../CommandLineOptions.cs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs index 08c9b473f5..6c9cbf9e58 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs @@ -27,7 +27,25 @@ namespace Microsoft.DotNet.Watcher FullName = "Microsoft DotNet File Watcher", Out = stdout, Error = stderr, - AllowArgumentSeparator = true + AllowArgumentSeparator = true, + ExtendedHelpText = @" +Remarks: + The special option '--' is used to delimit the end of the options and + the beginning of arguments that will be passed to the child dotnet process. + Its use is optional. When the special option '--' is not used, + dotnet-watch will use the first unrecognized argument as the beginning + of all arguments passed into the child dotnet process. + + For example: dotnet watch -- --verbose run + + Even though '--verbose' is an option dotnet-watch supports, the use of '--' + indicates that '--verbose' should be treated instead as an argument for + dotnet-run. + +Examples: + dotnet watch run + dotnet watch test +" }; app.HelpOption("-?|-h|--help"); From 349980c89e45f22f7f26980fcf18282e186fdde8 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 4 Nov 2016 13:34:19 -0700 Subject: [PATCH 0332/1029] Add DOTNET_USE_POLLING_FILE_WATCHER to help output --- src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs index 6c9cbf9e58..5c4ac1058a 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs @@ -29,6 +29,13 @@ namespace Microsoft.DotNet.Watcher Error = stderr, AllowArgumentSeparator = true, ExtendedHelpText = @" +Environment variables: + + DOTNET_USE_POLLING_FILE_WATCHER + When set to '1' or 'true', dotnet-watch will poll the file system for + changes. This is required for some file systems, such as network shares, + Docker mounted volumes, and other virtual file systems. + Remarks: The special option '--' is used to delimit the end of the options and the beginning of arguments that will be passed to the child dotnet process. From 363ddf73a63cc08d3cadd3841b61b3329fa971ec Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 7 Nov 2016 09:57:56 -0800 Subject: [PATCH 0333/1029] Pin versions --- build.ps1 | 2 +- build.sh | 2 +- src/Microsoft.DotNet.Watcher.Tools/project.json | 2 +- src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json | 2 +- src/Microsoft.Extensions.SecretManager.Tools/project.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build.ps1 b/build.ps1 index f780c43a82..2a9981098a 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.0.0-msbuild1.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index 0a1463b9e4..6340b3286d 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.0.0-msbuild1.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index 6306ce1285..a402f5010f 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-*", + "version": "1.0.0-msbuild1-final", "description": "Command line tool to watch for source file changes during development and restart the dotnet command.", "packOptions": { "tags": [ diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json index 3ff33ed3bd..371e13ebb2 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-*", + "version": "1.0.0-msbuild1-final", "buildOptions": { "outputName": "dotnet-sql-cache", "emitEntryPoint": true, diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index cec16d5840..d143ce4d9e 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-*", + "version": "1.0.0-msbuild1-final", "buildOptions": { "outputName": "dotnet-user-secrets", "emitEntryPoint": true, From fe2453b93abe4f0bfbfade7abcb737fe10ed4040 Mon Sep 17 00:00:00 2001 From: Cyprien Autexier Date: Sat, 8 Oct 2016 04:43:22 -0700 Subject: [PATCH 0334/1029] Escaping support for JSON pointers --- .../Internal/ParsedPath.cs | 54 ++++++++++++++++++- ...nPatchDocumentJsonPropertyAttributeTest.cs | 23 ++++++++ .../JsonPropertyComplexNameDTO.cs | 16 ++++++ .../ObjectAdapterTests.cs | 27 ++++++++++ .../ParsedPathTests.cs | 39 ++++++++++++++ 5 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyComplexNameDTO.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/ParsedPathTests.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ParsedPath.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ParsedPath.cs index fe786b86c1..8d0e69aa4d 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/ParsedPath.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ParsedPath.cs @@ -1,8 +1,10 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Microsoft.AspNetCore.JsonPatch.Exceptions; using System; using System.Collections.Generic; +using System.Text; namespace Microsoft.AspNetCore.JsonPatch.Internal { @@ -19,7 +21,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal throw new ArgumentNullException(nameof(path)); } - _segments = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + _segments = ParsePath(path); } public string LastSegment @@ -36,5 +38,55 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } public IReadOnlyList Segments => _segments ?? Empty; + + private static string[] ParsePath(string path) + { + var strings = new List(); + var sb = new StringBuilder(path.Length); + + for (var i = 0; i < path.Length; i++) + { + if (path[i] == '/') + { + if (sb.Length > 0) + { + strings.Add(sb.ToString()); + sb.Length = 0; + } + } + else if (path[i] == '~') + { + ++i; + if (i >= path.Length) + { + throw new JsonPatchException(Resources.FormatInvalidValueForPath(path), null); + } + + if (path[i] == '0') + { + sb.Append('~'); + } + else if (path[i] == '1') + { + sb.Append('/'); + } + else + { + throw new JsonPatchException(Resources.FormatInvalidValueForPath(path), null); + } + } + else + { + sb.Append(path[i]); + } + } + + if (sb.Length > 0) + { + strings.Add(sb.ToString()); + } + + return strings.ToArray(); + } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs index ef7d53c21a..0ec0c18afd 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs @@ -144,5 +144,28 @@ namespace Microsoft.AspNetCore.JsonPatch var pathToCheck = deserialized.Operations.First().path; Assert.Equal(pathToCheck, "/anothername"); } + + [Fact] + public void Add_OnApplyFromJson_EscapingHandledOnComplexJsonPropertyNameOnJsonDocument() + { + var doc = new JsonPropertyComplexNameDTO() + { + FooSlashBars = "InitialName", + FooSlashTilde = new SimpleDTO + { + StringProperty = "Initial Value" + } + }; + + // serialization should serialize to "AnotherName" + var serialized = "[{\"value\":\"Kevin\",\"path\":\"/foo~1bar~0\",\"op\":\"add\"},{\"value\":\"Final Value\",\"path\":\"/foo~1~0/StringProperty\",\"op\":\"replace\"}]"; + var deserialized = + JsonConvert.DeserializeObject>(serialized); + + deserialized.ApplyTo(doc); + + Assert.Equal("Kevin", doc.FooSlashBars); + Assert.Equal("Final Value", doc.FooSlashTilde.StringProperty); + } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyComplexNameDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyComplexNameDTO.cs new file mode 100644 index 0000000000..7ff66481ad --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyComplexNameDTO.cs @@ -0,0 +1,16 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Newtonsoft.Json; + +namespace Microsoft.AspNetCore.JsonPatch +{ + public class JsonPropertyComplexNameDTO + { + [JsonProperty("foo/bar~")] + public string FooSlashBars { get; set; } + + [JsonProperty("foo/~")] + public SimpleDTO FooSlashTilde { get; set; } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs index 88693fdbd5..5898311044 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs @@ -1821,6 +1821,33 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters Assert.Equal("James", actualValue1.Name); } + [Fact] + public void Replace_WhenDictionary_ValueAPocoType_WithEscaping_Succeeds() + { + // Arrange + var key1 = "Foo/Name"; + var value1 = new Customer() { Name = "Jamesss" }; + var key2 = "Foo"; + var value2 = new Customer() { Name = "Mike" }; + var model = new Class8(); + model.DictionaryOfStringToCustomer[key1] = value1; + model.DictionaryOfStringToCustomer[key2] = value2; + var patchDocument = new JsonPatchDocument(); + patchDocument.Replace($"/DictionaryOfStringToCustomer/Foo~1Name/Name", "James"); + + // Act + patchDocument.ApplyTo(model); + + // Assert + Assert.Equal(2, model.DictionaryOfStringToCustomer.Count); + var actualValue1 = model.DictionaryOfStringToCustomer[key1]; + var actualValue2 = model.DictionaryOfStringToCustomer[key2]; + Assert.NotNull(actualValue1); + Assert.Equal("James", actualValue1.Name); + Assert.Equal("Mike", actualValue2.Name); + + } + [Fact] public void Replace_DeepNested_DictionaryValue_Succeeds() { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ParsedPathTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ParsedPathTests.cs new file mode 100644 index 0000000000..6b7c2e69cb --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ParsedPathTests.cs @@ -0,0 +1,39 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNetCore.JsonPatch.Exceptions; +using Microsoft.AspNetCore.JsonPatch.Internal; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch.Test +{ + public class ParsedPathTests + { + [Theory] + [InlineData("foo/bar~0baz", new string[] { "foo", "bar~baz" })] + [InlineData("foo/bar~00baz", new string[] { "foo", "bar~0baz" })] + [InlineData("foo/bar~01baz", new string[] { "foo", "bar~1baz" })] + [InlineData("foo/bar~10baz", new string[] { "foo", "bar/0baz" })] + [InlineData("foo/bar~1baz", new string[] { "foo", "bar/baz" })] + [InlineData("foo/bar~0/~0/~1~1/~0~0/baz", new string[] { "foo", "bar~", "~", "//", "~~", "baz" })] + [InlineData("~0~1foo", new string[] { "~/foo" })] + public void ParsingValidPathShouldSucceed(string path, string[] expected) + { + var parsedPath = new ParsedPath(path); + Assert.Equal(expected, parsedPath.Segments); + } + + [Theory] + [InlineData("foo/bar~")] + [InlineData("~")] + [InlineData("~2")] + [InlineData("foo~3bar")] + public void PathWithInvalidEscapeSequenceShouldFail(string path) + { + Assert.Throws(() => + { + var parsedPath = new ParsedPath(path); + }); + } + } +} From 0b0abe054c9533e7486f1db9e26ede4e5d49880f Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 9 Nov 2016 11:30:11 -0800 Subject: [PATCH 0335/1029] Branching for 1.1.0 --- NuGet.config | 4 ++-- build.ps1 | 2 +- build.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/NuGet.config b/NuGet.config index 0fd623ffdd..ad973186eb 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + - + diff --git a/build.ps1 b/build.ps1 index 8f2f99691a..24ca167cf6 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.1.0.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index f4208100eb..fea9ac64ad 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.1.0.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi From 86508f3c44468326384c90b139b1bd4e7328e832 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 9 Nov 2016 11:31:01 -0800 Subject: [PATCH 0336/1029] Branching for 1.1.0 --- NuGet.config | 4 ++-- build.ps1 | 2 +- build.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/NuGet.config b/NuGet.config index 826a1f9035..6197c93176 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + - + \ No newline at end of file diff --git a/build.ps1 b/build.ps1 index 8f2f99691a..24ca167cf6 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.1.0.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index f4208100eb..fea9ac64ad 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.1.0.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi From fd2aec9d343ac0794f4acb27b2bf26ace3242c50 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 9 Nov 2016 11:31:27 -0800 Subject: [PATCH 0337/1029] Branching for 1.1.0 --- NuGet.config | 4 ++-- build.ps1 | 2 +- build.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/NuGet.config b/NuGet.config index 0fd623ffdd..ad973186eb 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + - + diff --git a/build.ps1 b/build.ps1 index 8f2f99691a..24ca167cf6 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.1.0.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index f4208100eb..fea9ac64ad 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.1.0.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi From 9cdb55b59cee496d3b65913c42fff4724ac2e52f Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 9 Nov 2016 14:17:51 -0800 Subject: [PATCH 0338/1029] Updating versions to 1.2.0-* --- src/Microsoft.AspNetCore.Html.Abstractions/project.json | 2 +- src/Microsoft.Extensions.WebEncoders/project.json | 6 +++--- .../project.json | 6 +++--- test/Microsoft.Extensions.WebEncoders.Tests/project.json | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/project.json b/src/Microsoft.AspNetCore.Html.Abstractions/project.json index da6f399828..8c64893f22 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/project.json +++ b/src/Microsoft.AspNetCore.Html.Abstractions/project.json @@ -1,5 +1,5 @@ { - "version": "1.1.0-*", + "version": "1.2.0-*", "description": "ASP.NET Core HTML abstractions used for building HTML content.\r\nCommonly used types:\r\nMicrosoft.AspNetCore.Html.HtmlString\r\nMicrosoft.AspNetCore.Html.IHtmlContent", "packOptions": { "repository": { diff --git a/src/Microsoft.Extensions.WebEncoders/project.json b/src/Microsoft.Extensions.WebEncoders/project.json index 852787db64..f7ded704b5 100644 --- a/src/Microsoft.Extensions.WebEncoders/project.json +++ b/src/Microsoft.Extensions.WebEncoders/project.json @@ -1,5 +1,5 @@ { - "version": "1.1.0-*", + "version": "1.2.0-*", "description": "Contains registration and configuration APIs to add the core framework encoders to a dependency injection container.", "packOptions": { "repository": { @@ -20,8 +20,8 @@ "xmlDoc": true }, "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "1.1.0-*", - "Microsoft.Extensions.Options": "1.1.0-*", + "Microsoft.Extensions.DependencyInjection.Abstractions": "1.2.0-*", + "Microsoft.Extensions.Options": "1.2.0-*", "NETStandard.Library": "1.6.1-*", "System.Text.Encodings.Web": "4.3.0-*" }, diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index 754cf25670..a1e50970d0 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -5,9 +5,9 @@ }, "dependencies": { "dotnet-test-xunit": "2.2.0-*", - "Microsoft.AspNetCore.Html.Abstractions": "1.1.0-*", - "Microsoft.AspNetCore.Testing": "1.1.0-*", - "Microsoft.Extensions.WebEncoders": "1.1.0-*", + "Microsoft.AspNetCore.Html.Abstractions": "1.2.0-*", + "Microsoft.AspNetCore.Testing": "1.2.0-*", + "Microsoft.Extensions.WebEncoders": "1.2.0-*", "xunit": "2.2.0-*" }, "testRunner": "xunit", diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index 9171910c7c..462b1cebfd 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -1,8 +1,8 @@ { "dependencies": { "dotnet-test-xunit": "2.2.0-*", - "Microsoft.Extensions.DependencyInjection": "1.1.0-*", - "Microsoft.Extensions.WebEncoders": "1.1.0-*", + "Microsoft.Extensions.DependencyInjection": "1.2.0-*", + "Microsoft.Extensions.WebEncoders": "1.2.0-*", "xunit": "2.2.0-*" }, "testRunner": "xunit", From 6ee6220e06131584a56d7225e1dcdb5fe4b7a867 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 9 Nov 2016 14:18:11 -0800 Subject: [PATCH 0339/1029] Updating versions to 1.2.0-* --- src/Microsoft.AspNetCore.JsonPatch/project.json | 4 ++-- test/Microsoft.AspNetCore.JsonPatch.Test/project.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index 5b998272ff..a2015980e1 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -1,5 +1,5 @@ { - "version": "1.1.0-*", + "version": "1.2.0-*", "description": "ASP.NET Core support for JSON PATCH.", "buildOptions": { "warningsAsErrors": true, @@ -25,7 +25,7 @@ "Newtonsoft.Json": "9.0.1", "Microsoft.Extensions.ClosedGenericMatcher.Sources": { "type": "build", - "version": "1.1.0-*" + "version": "1.2.0-*" } }, "frameworks": { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index 9e95ee86e0..158192b281 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -4,8 +4,8 @@ }, "dependencies": { "dotnet-test-xunit": "2.2.0-*", - "Microsoft.AspNetCore.JsonPatch": "1.1.0-*", - "Microsoft.AspNetCore.Testing": "1.1.0-*", + "Microsoft.AspNetCore.JsonPatch": "1.2.0-*", + "Microsoft.AspNetCore.Testing": "1.2.0-*", "Moq": "4.6.36-*", "xunit": "2.2.0-*" }, From 3461bf92c6206eb9e8af1b20e4e0f7576fa49cf8 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 9 Nov 2016 15:06:21 -0800 Subject: [PATCH 0340/1029] Update versions --- src/Microsoft.DotNet.Watcher.Tools/project.json | 10 +++++----- .../project.json | 8 ++++---- .../project.json | 8 ++++---- test/Microsoft.DotNet.Watcher.Tools.Tests/project.json | 2 +- .../project.json | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index 1f1fc0cf34..87cd228303 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -1,5 +1,5 @@ { - "version": "1.1.0-*", + "version": "1.2.0-*", "description": "Command line tool to watch for source file changes during development and restart the dotnet command.", "packOptions": { "tags": [ @@ -15,12 +15,12 @@ }, "dependencies": { "Microsoft.DotNet.Cli.Utils": "1.0.0-*", - "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", - "Microsoft.Extensions.Logging": "1.1.0-*", - "Microsoft.Extensions.Logging.Console": "1.1.0-*", + "Microsoft.Extensions.CommandLineUtils": "1.2.0-*", + "Microsoft.Extensions.Logging": "1.2.0-*", + "Microsoft.Extensions.Logging.Console": "1.2.0-*", "Microsoft.Extensions.Process.Sources": { "type": "build", - "version": "1.1.0-*" + "version": "1.2.0-*" }, "Microsoft.NETCore.App": { "type": "platform", diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json index 59a43e6049..34d531cfaa 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json @@ -1,5 +1,5 @@ { - "version": "1.1.0-*", + "version": "1.2.0-*", "buildOptions": { "outputName": "dotnet-sql-cache", "emitEntryPoint": true, @@ -19,9 +19,9 @@ ] }, "dependencies": { - "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", - "Microsoft.Extensions.Logging": "1.1.0-*", - "Microsoft.Extensions.Logging.Console": "1.1.0-*", + "Microsoft.Extensions.CommandLineUtils": "1.2.0-*", + "Microsoft.Extensions.Logging": "1.2.0-*", + "Microsoft.Extensions.Logging.Console": "1.2.0-*", "Microsoft.NETCore.App": { "version": "1.1.0", "type": "platform" diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index 03c1b8e582..09c0bc0bc1 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -1,5 +1,5 @@ { - "version": "1.1.0-*", + "version": "1.2.0-*", "buildOptions": { "outputName": "dotnet-user-secrets", "emitEntryPoint": true, @@ -19,9 +19,9 @@ ] }, "dependencies": { - "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", - "Microsoft.Extensions.Configuration.UserSecrets": "1.1.0-*", - "Microsoft.Extensions.Logging": "1.1.0-*", + "Microsoft.Extensions.CommandLineUtils": "1.2.0-*", + "Microsoft.Extensions.Configuration.UserSecrets": "1.2.0-*", + "Microsoft.Extensions.Logging": "1.2.0-*", "Microsoft.NETCore.App": { "version": "1.1.0", "type": "platform" diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json index d94aba9a22..c5d2134078 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json @@ -5,7 +5,7 @@ }, "dependencies": { "dotnet-test-xunit": "2.2.0-*", - "Microsoft.DotNet.Watcher.Tools": "1.1.0-*", + "Microsoft.DotNet.Watcher.Tools": "1.2.0-*", "xunit": "2.2.0-*" }, "frameworks": { diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json index 13397c8da3..bcfe3a83c2 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json @@ -5,7 +5,7 @@ }, "dependencies": { "dotnet-test-xunit": "2.2.0-*", - "Microsoft.Extensions.SecretManager.Tools": "1.1.0-*", + "Microsoft.Extensions.SecretManager.Tools": "1.2.0-*", "xunit": "2.2.0-*" }, "testRunner": "xunit", From 009609319e88c94e582b15f14fb5dff6767835d6 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 10 Nov 2016 08:34:13 -0800 Subject: [PATCH 0341/1029] Fixing dependency versions --- .../project.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index 863b8e1819..08b52f4060 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -11,11 +11,11 @@ }, "dependencies": { "dotnet-test-xunit": "2.2.0-*", - "Microsoft.AspNetCore.Testing": "1.1.0-*", - "Microsoft.DotNet.Watcher.Tools": "1.1.0-*", + "Microsoft.AspNetCore.Testing": "1.2.0-*", + "Microsoft.DotNet.Watcher.Tools": "1.2.0-*", "Microsoft.Extensions.Process.Sources": { "type": "build", - "version": "1.1.0-*" + "version": "1.2.0-*" }, "xunit": "2.2.0-*" }, From ae48d75e72a4a41c6c257482caf874c351e90a19 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 16 Nov 2016 11:13:34 -0800 Subject: [PATCH 0342/1029] Pin versions of dotnet packages --- src/Microsoft.DotNet.Watcher.Tools/project.json | 2 +- tools/NuGetPackager/project.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index 87cd228303..103eb90c0e 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -14,7 +14,7 @@ "keyFile": "../../tools/Key.snk" }, "dependencies": { - "Microsoft.DotNet.Cli.Utils": "1.0.0-*", + "Microsoft.DotNet.Cli.Utils": "1.0.0-preview2-1-003177", "Microsoft.Extensions.CommandLineUtils": "1.2.0-*", "Microsoft.Extensions.Logging": "1.2.0-*", "Microsoft.Extensions.Logging.Console": "1.2.0-*", diff --git a/tools/NuGetPackager/project.json b/tools/NuGetPackager/project.json index cef67ac8f0..2c858bd4ac 100644 --- a/tools/NuGetPackager/project.json +++ b/tools/NuGetPackager/project.json @@ -8,8 +8,8 @@ "type": "platform", "version": "1.1.0" }, - "Microsoft.DotNet.ProjectModel": "1.0.0-*", - "Microsoft.DotNet.Cli.Utils": "1.0.0-*", + "Microsoft.DotNet.ProjectModel": "1.0.0-rc3-1-003177", + "Microsoft.DotNet.Cli.Utils": "1.0.0-preview2-1-003177", "Microsoft.Extensions.CommandLineUtils": "1.1.0-*" }, From e2c4e36d78dc0879d0f3d4365dda15aab152a618 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 16 Nov 2016 14:10:12 -0800 Subject: [PATCH 0343/1029] Ensure .targets files are included in dotnet-watch --- .../Microsoft.DotNet.Watcher.Tools.nuspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec index 0be0f55cbb..2fe02b3f50 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec @@ -25,6 +25,6 @@ - + \ No newline at end of file From ac5a9b7b7385ccff9f445c6f5e0a254ea8233ccf Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 16 Nov 2016 15:27:33 -0800 Subject: [PATCH 0344/1029] Pin versions --- src/Microsoft.DotNet.Watcher.Tools/project.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index a402f5010f..56767f7415 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-msbuild1-final", + "version": "1.0.0-msbuild1-update1", "description": "Command line tool to watch for source file changes during development and restart the dotnet command.", "packOptions": { "tags": [ @@ -32,7 +32,7 @@ ] }, "dependencies": { - "Microsoft.DotNet.Cli.Utils": "1.0.0-preview3-004050", + "Microsoft.DotNet.Cli.Utils": "1.0.0-preview3-004056", "Microsoft.Extensions.Logging": "1.0.0", "Microsoft.Extensions.Logging.Console": "1.0.0", "Microsoft.Extensions.Process.Sources": { From a6f4a382028f3b964030b10e0be0730d6c742003 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 7 Nov 2016 15:23:37 -0800 Subject: [PATCH 0345/1029] Refactor tests to fix false-positive tests passes --- .travis.yml | 1 - .../AppWithDepsTests.cs | 69 ++-- .../AwaitableProcess.cs | 102 ++++++ .../GlobbingAppTests.cs | 299 ++++++------------ .../NoDepsAppTests.cs | 129 ++------ .../Properties/AssemblyInfo.cs | 3 - .../Scenario/DotNetWatchScenario.cs | 57 ---- .../Scenario/ProjectToolScenario.cs | 52 +-- .../Scenario/WatchableApp.cs | 91 ++++++ .../TaskExtensions.cs | 27 ++ .../AppWithDeps/AppWithDeps.csproj | 2 +- .../TestProjects/AppWithDeps/Program.cs | 24 +- .../TestProjects/Dependency/Dependency.csproj | 2 +- .../GlobbingApp/GlobbingApp.csproj | 2 +- .../TestProjects/GlobbingApp/Program.cs | 29 +- .../TestProjects/NoDepsApp/NoDepsApp.csproj | 2 +- .../TestProjects/NoDepsApp/Program.cs | 30 +- .../WaitForFileToChange.cs | 61 ---- .../Waiters.cs | 84 ----- .../test.cmd | 6 + .../test.sh | 8 + 21 files changed, 422 insertions(+), 658 deletions(-) create mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Properties/AssemblyInfo.cs delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs create mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs create mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TaskExtensions.cs delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/WaitForFileToChange.cs delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Waiters.cs create mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/test.cmd create mode 100755 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/test.sh diff --git a/.travis.yml b/.travis.yml index 1d6d4144bc..93fdc0133c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,6 @@ mono: os: - linux - osx -osx_image: xcode7.1 branches: only: - master diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs index 9e17328c69..253f3643d1 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs @@ -3,80 +3,51 @@ using System; using System.IO; +using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { - public class AppWithDepsTests + public class AppWithDepsTests : IDisposable { - private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30); - - private readonly ITestOutputHelper _logger; + private readonly AppWithDeps _app; public AppWithDepsTests(ITestOutputHelper logger) { - _logger = logger; + _app = new AppWithDeps(logger); + _app.Prepare(); } - // Change a file included in compilation [Fact] - public void ChangeFileInDependency() + public async Task ChangeFileInDependency() { - using (var scenario = new AppWithDepsScenario(_logger)) - { - scenario.Start(); - using (var wait = new WaitForFileToChange(scenario.StartedFile)) - { - var fileToChange = Path.Combine(scenario.DependencyFolder, "Foo.cs"); - var programCs = File.ReadAllText(fileToChange); - File.WriteAllText(fileToChange, programCs); + await _app.StartWatcher().OrTimeout(); - wait.Wait(_defaultTimeout, - expectedToChange: true, - errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); - } - } + var fileToChange = Path.Combine(_app.DependencyFolder, "Foo.cs"); + var programCs = File.ReadAllText(fileToChange); + File.WriteAllText(fileToChange, programCs); + + await _app.HasRestarted().OrTimeout(); } - private class AppWithDepsScenario : DotNetWatchScenario + public void Dispose() + { + _app.Dispose(); + } + + private class AppWithDeps : WatchableApp { - private const string AppWithDeps = "AppWithDeps"; private const string Dependency = "Dependency"; - public AppWithDepsScenario(ITestOutputHelper logger) - : base(logger) + public AppWithDeps(ITestOutputHelper logger) + : base("AppWithDeps", logger) { - StatusFile = Path.Combine(Scenario.TempFolder, "status"); - StartedFile = StatusFile + ".started"; - - Scenario.AddTestProjectFolder(AppWithDeps); Scenario.AddTestProjectFolder(Dependency); - Scenario.Restore(AppWithDeps); // restore3 should be transitive - - AppWithDepsFolder = Path.Combine(Scenario.WorkFolder, AppWithDeps); DependencyFolder = Path.Combine(Scenario.WorkFolder, Dependency); } - public void Start() - { - // Wait for the process to start - using (var wait = new WaitForFileToChange(StatusFile)) - { - RunDotNetWatch(new[] { "run", StatusFile }, Path.Combine(Scenario.WorkFolder, AppWithDeps)); - - wait.Wait(_defaultTimeout, - expectedToChange: true, - errorMessage: $"File not created: {StatusFile}"); - } - - Waiters.WaitForFileToBeReadable(StatusFile, _defaultTimeout); - } - - public string StatusFile { get; private set; } - public string StartedFile { get; private set; } - public string AppWithDepsFolder { get; private set; } public string DependencyFolder { get; private set; } } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs new file mode 100644 index 0000000000..fc920e7eb0 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs @@ -0,0 +1,102 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.IO; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Threading.Tasks.Dataflow; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.Extensions.Internal; +using Xunit.Abstractions; + +namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests +{ + public class AwaitableProcess : IDisposable + { + private Process _process; + private readonly ProcessSpec _spec; + private BufferBlock _source; + private ITestOutputHelper _logger; + private int _reading; + + public AwaitableProcess(ProcessSpec spec, ITestOutputHelper logger) + { + _spec = spec; + _logger = logger; + } + + public void Start() + { + if (_process != null) + { + throw new InvalidOperationException("Already started"); + } + + var psi = new ProcessStartInfo + { + UseShellExecute = false, + FileName = _spec.Executable, + WorkingDirectory = _spec.WorkingDirectory, + Arguments = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(_spec.Arguments), + RedirectStandardOutput = true, + RedirectStandardError = true + }; + _process = Process.Start(psi); + _logger.WriteLine($"{DateTime.Now}: process start: '{psi.FileName} {psi.Arguments}'"); + StartProcessingOutput(_process.StandardOutput); + StartProcessingOutput(_process.StandardError);; + } + + public Task GetOutputLineAsync(string message) + => GetOutputLineAsync(m => message == m); + + public async Task GetOutputLineAsync(Predicate predicate) + { + while (!_source.Completion.IsCompleted) + { + while (await _source.OutputAvailableAsync()) + { + var next = await _source.ReceiveAsync(); + _logger.WriteLine($"{DateTime.Now}: recv: '{next}'"); + if (predicate(next)) + { + return next; + } + } + } + + return null; + } + + private void StartProcessingOutput(StreamReader streamReader) + { + _source = _source ?? new BufferBlock(); + Interlocked.Increment(ref _reading); + Task.Run(() => + { + string line; + while ((line = streamReader.ReadLine()) != null) + { + _logger.WriteLine($"{DateTime.Now} post: {line}"); + _source.Post(line); + } + + if (Interlocked.Decrement(ref _reading) <= 0) + { + _source.Complete(); + } + }).ConfigureAwait(false); + } + + public void Dispose() + { + if (_process != null && !_process.HasExited) + { + _process.KillTree(); + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs index 912b243115..a6ccfaa91c 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs @@ -2,227 +2,134 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Diagnostics; using System.IO; -using System.Threading; +using System.Linq; +using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { - public class GlobbingAppTests + public class GlobbingAppTests : IDisposable { - private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30); - - private static readonly TimeSpan _negativeTestWaitTime = TimeSpan.FromSeconds(10); - - private readonly ITestOutputHelper _logger; - + private GlobbingApp _app; public GlobbingAppTests(ITestOutputHelper logger) { - _logger = logger; + _app = new GlobbingApp(logger); + _app.Prepare(); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task ChangeCompiledFile(bool usePollingWatcher) + { + await _app.StartWatcher().OrTimeout(); + + var types = await _app.GetCompiledAppDefinedTypes().OrTimeout(); + Assert.Equal(2, types); + + var fileToChange = Path.Combine(_app.SourceDirectory, "include", "Foo.cs"); + var programCs = File.ReadAllText(fileToChange); + File.WriteAllText(fileToChange, programCs); + + await _app.HasRestarted().OrTimeout(); + types = await _app.GetCompiledAppDefinedTypes().OrTimeout(); + Assert.Equal(2, types); + } + + [Fact(Skip = "Broken. See https://github.com/aspnet/DotNetTools/issues/212")] + public async Task AddCompiledFile() + { + await _app.StartWatcher().OrTimeout(); + + var types = await _app.GetCompiledAppDefinedTypes().OrTimeout(); + Assert.Equal(2, types); + + var fileToChange = Path.Combine(_app.SourceDirectory, "include", "Bar.cs"); + File.WriteAllText(fileToChange, "public class Bar {}"); + + await _app.HasRestarted().OrTimeout(); + types = await _app.GetCompiledAppDefinedTypes().OrTimeout(); + Assert.Equal(3, types); + } + + // TODO re-enable when MSBuild is updated. See https://github.com/aspnet/DotNetTools/issues/224 + [Fact(Skip = "Broken. See https://github.com/Microsoft/msbuild/issues/701")] + public async Task DeleteCompiledFile() + { + await _app.StartWatcher().OrTimeout(); + + var types = await _app.GetCompiledAppDefinedTypes().OrTimeout(); + Assert.Equal(2, types); + + var fileToChange = Path.Combine(_app.SourceDirectory, "include", "Foo.cs"); + File.Delete(fileToChange); + + await _app.HasRestarted().OrTimeout(); + types = await _app.GetCompiledAppDefinedTypes().OrTimeout(); + Assert.Equal(1, types); + } + + // TODO re-enable when MSBuild is updated. See https://github.com/aspnet/DotNetTools/issues/224 + [Fact(Skip = "Broken. See https://github.com/Microsoft/msbuild/issues/701")] + public async Task DeleteSourceFolder() + { + await _app.StartWatcher().OrTimeout(); + + var types = await _app.GetCompiledAppDefinedTypes().OrTimeout(); + Assert.Equal(2, types); + + var folderToDelete = Path.Combine(_app.SourceDirectory, "include"); + Directory.Delete(folderToDelete, recursive: true); + + await _app.HasRestarted().OrTimeout(); + types = await _app.GetCompiledAppDefinedTypes().OrTimeout(); + Assert.Equal(1, types); } [Fact] - public void ChangeCompiledFile_PollingWatcher() + public async Task RenameCompiledFile() { - ChangeCompiledFile(usePollingWatcher: true); + await _app.StartWatcher().OrTimeout(); + + var oldFile = Path.Combine(_app.SourceDirectory, "include", "Foo.cs"); + var newFile = Path.Combine(_app.SourceDirectory, "include", "Foo_new.cs"); + File.Move(oldFile, newFile); + + await _app.HasRestarted().OrTimeout(); } [Fact] - public void ChangeCompiledFile_DotNetWatcher() + public async Task ChangeExcludedFile() { - ChangeCompiledFile(usePollingWatcher: false); + await _app.StartWatcher().OrTimeout(); + + var changedFile = Path.Combine(_app.SourceDirectory, "exclude", "Baz.cs"); + File.WriteAllText(changedFile, ""); + + var restart = _app.HasRestarted(); + var finished = await Task.WhenAny(Task.Delay(TimeSpan.FromSeconds(10)), restart); + Assert.NotSame(restart, finished); } - // Change a file included in compilation - private void ChangeCompiledFile(bool usePollingWatcher) + public void Dispose() { - using (var scenario = new GlobbingAppScenario(_logger)) - using (var wait = new WaitForFileToChange(scenario.StartedFile)) + _app.Dispose(); + } + + private class GlobbingApp : WatchableApp + { + public GlobbingApp(ITestOutputHelper logger) + : base("GlobbingApp", logger) { - scenario.UsePollingWatcher = usePollingWatcher; - - scenario.Start(); - - var fileToChange = Path.Combine(scenario.TestAppFolder, "include", "Foo.cs"); - var programCs = File.ReadAllText(fileToChange); - File.WriteAllText(fileToChange, programCs); - - wait.Wait(_defaultTimeout, - expectedToChange: true, - errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); } - } - - // Add a file to a folder included in compilation - [Fact] - public void AddCompiledFile() - { - // Add a file in a folder that's included in compilation - using (var scenario = new GlobbingAppScenario(_logger)) - using (var wait = new WaitForFileToChange(scenario.StartedFile)) + public async Task GetCompiledAppDefinedTypes() { - scenario.Start(); - - var fileToChange = Path.Combine(scenario.TestAppFolder, "include", "Bar.cs"); - File.WriteAllText(fileToChange, ""); - - wait.Wait(_defaultTimeout, - expectedToChange: true, - errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); + var definedTypesMessage = await Process.GetOutputLineAsync(m => m.StartsWith("Defined types = ")); + return int.Parse(definedTypesMessage.Split('=').Last()); } } - - // Delete a file included in compilation - [Fact] - public void DeleteCompiledFile() - { - using (var scenario = new GlobbingAppScenario(_logger)) - using (var wait = new WaitForFileToChange(scenario.StartedFile)) - { - scenario.Start(); - - var fileToChange = Path.Combine(scenario.TestAppFolder, "include", "Foo.cs"); - File.Delete(fileToChange); - - wait.Wait(_defaultTimeout, - expectedToChange: true, - errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); - } - } - - // Delete an entire folder - [Fact] - public void DeleteSourceFolder() - { - using (var scenario = new GlobbingAppScenario(_logger)) - using (var wait = new WaitForFileToChange(scenario.StartedFile)) - { - scenario.Start(); - - var folderToDelete = Path.Combine(scenario.TestAppFolder, "include"); - Directory.Delete(folderToDelete, recursive: true); - - wait.Wait(_defaultTimeout, - expectedToChange: true, - errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); - } - } - - // Rename a file included in compilation - [Fact] - public void RenameCompiledFile() - { - using (var scenario = new GlobbingAppScenario(_logger)) - using (var wait = new WaitForFileToChange(scenario.StatusFile)) - { - scenario.Start(); - - var oldFile = Path.Combine(scenario.TestAppFolder, "include", "Foo.cs"); - var newFile = Path.Combine(scenario.TestAppFolder, "include", "Foo_new.cs"); - File.Move(oldFile, newFile); - - wait.Wait(_defaultTimeout, - expectedToChange: true, - errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); - } - } - - [Fact] - public void ChangeNonCompiledFile_PollingWatcher() - { - ChangeNonCompiledFile(usePollingWatcher: true); - } - - [Fact] - public void ChangeNonCompiledFile_DotNetWatcher() - { - ChangeNonCompiledFile(usePollingWatcher: false); - } - - // Add a file that's in a included folder but not matching the globbing pattern - private void ChangeNonCompiledFile(bool usePollingWatcher) - { - using (var scenario = new GlobbingAppScenario(_logger)) - { - scenario.UsePollingWatcher = usePollingWatcher; - - scenario.Start(); - - var ids = File.ReadAllLines(scenario.StatusFile); - var procId = int.Parse(ids[0]); - - var changedFile = Path.Combine(scenario.TestAppFolder, "include", "not_compiled.css"); - File.WriteAllText(changedFile, ""); - - Console.WriteLine($"Waiting {_negativeTestWaitTime.TotalSeconds} seconds to see if the app restarts"); - Waiters.WaitForProcessToStop( - procId, - _negativeTestWaitTime, - expectedToStop: false, - errorMessage: "Test app restarted"); - } - } - - // Change a file that's in an excluded folder - [Fact] - public void ChangeExcludedFile() - { - using (var scenario = new GlobbingAppScenario(_logger)) - { - scenario.Start(); - - var ids = File.ReadAllLines(scenario.StatusFile); - var procId = int.Parse(ids[0]); - - var changedFile = Path.Combine(scenario.TestAppFolder, "exclude", "Baz.cs"); - File.WriteAllText(changedFile, ""); - - Console.WriteLine($"Waiting {_negativeTestWaitTime.TotalSeconds} seconds to see if the app restarts"); - Waiters.WaitForProcessToStop( - procId, - _negativeTestWaitTime, - expectedToStop: false, - errorMessage: "Test app restarted"); - } - } - - private class GlobbingAppScenario : DotNetWatchScenario - { - private const string TestAppName = "GlobbingApp"; - - public GlobbingAppScenario(ITestOutputHelper logger) - : base(logger) - { - StatusFile = Path.Combine(Scenario.TempFolder, "status"); - StartedFile = StatusFile + ".started"; - - Scenario.AddTestProjectFolder(TestAppName); - Scenario.Restore(TestAppName); - - TestAppFolder = Path.Combine(Scenario.WorkFolder, TestAppName); - } - - public void Start() - { - // Wait for the process to start - using (var wait = new WaitForFileToChange(StartedFile)) - { - RunDotNetWatch(new[] { "run", StatusFile }, Path.Combine(Scenario.WorkFolder, TestAppName)); - - wait.Wait(_defaultTimeout, - expectedToChange: true, - errorMessage: $"File not created: {StartedFile}"); - } - - Waiters.WaitForFileToBeReadable(StartedFile, _defaultTimeout); - } - - public string StatusFile { get; private set; } - public string StartedFile { get; private set; } - public string TestAppFolder { get; private set; } - } } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs index 81f5f962dc..73d5ecd982 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs @@ -2,132 +2,63 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Threading; +using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { - public class NoDepsAppTests + public class NoDepsAppTests : IDisposable { - private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30); - private readonly ITestOutputHelper _logger; + private readonly WatchableApp _app; public NoDepsAppTests(ITestOutputHelper logger) { - _logger = logger; + _app = new WatchableApp("NoDepsApp", logger); + _app.Prepare(); } [Fact] - public void RestartProcessOnFileChange() + public async Task RestartProcessOnFileChange() { - using (var scenario = new NoDepsAppScenario(_logger)) - { - // Wait for the process to start - using (var wait = new WaitForFileToChange(scenario.StartedFile)) - { - scenario.RunDotNetWatch(new[] { "run", scenario.StatusFile, "--no-exit" }); + await _app.StartWatcher(new[] { "--no-exit" }).OrTimeout(); + var pid = await _app.GetProcessId().OrTimeout(); - wait.Wait(_defaultTimeout, - expectedToChange: true, - errorMessage: $"File not created: {scenario.StartedFile}"); - } + // Then wait for it to restart when we change a file + var fileToChange = Path.Combine(_app.SourceDirectory, "Program.cs"); + var programCs = File.ReadAllText(fileToChange); + File.WriteAllText(fileToChange, programCs); - // Then wait for it to restart when we change a file - using (var wait = new WaitForFileToChange(scenario.StartedFile)) - { - var fileToChange = Path.Combine(scenario.TestAppFolder, "Program.cs"); - var programCs = File.ReadAllText(fileToChange); - File.WriteAllText(fileToChange, programCs); + await _app.HasRestarted().OrTimeout(); + var pid2 = await _app.GetProcessId().OrTimeout(); + Assert.NotEqual(pid, pid2); - wait.Wait(_defaultTimeout, - expectedToChange: true, - errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); - } - - // Check that the first child process is no longer running - Waiters.WaitForFileToBeReadable(scenario.StatusFile, _defaultTimeout); - var ids = File.ReadAllLines(scenario.StatusFile); - var firstProcessId = int.Parse(ids[0]); - Waiters.WaitForProcessToStop( - firstProcessId, - TimeSpan.FromSeconds(1), - expectedToStop: true, - errorMessage: $"PID: {firstProcessId} is still alive"); - } + // first app should have shut down + Assert.Throws(() => Process.GetProcessById(pid)); } [Fact] - public void RestartProcessThatTerminatesAfterFileChange() + public async Task RestartProcessThatTerminatesAfterFileChange() { - using (var scenario = new NoDepsAppScenario(_logger)) - { - // Wait for the process to start - using (var wait = new WaitForFileToChange(scenario.StartedFile)) - { - scenario.RunDotNetWatch(new[] { "run", scenario.StatusFile }); + await _app.StartWatcher().OrTimeout(); + var pid = await _app.GetProcessId().OrTimeout(); + await _app.HasExited().OrTimeout(); // process should exit after run - wait.Wait(_defaultTimeout, - expectedToChange: true, - errorMessage: $"File not created: {scenario.StartedFile}"); - } + var fileToChange = Path.Combine(_app.SourceDirectory, "Program.cs"); + var programCs = File.ReadAllText(fileToChange); + File.WriteAllText(fileToChange, programCs); - // Then wait for the app to exit - Waiters.WaitForFileToBeReadable(scenario.StartedFile, _defaultTimeout); - var ids = File.ReadAllLines(scenario.StatusFile); - var procId = int.Parse(ids[0]); - Waiters.WaitForProcessToStop( - procId, - _defaultTimeout, - expectedToStop: true, - errorMessage: "Test app did not exit"); - - // Then wait for it to restart when we change a file - using (var wait = new WaitForFileToChange(scenario.StartedFile)) - { - // On Unix the file write time is in 1s increments; - // if we don't wait, there's a chance that the polling - // watcher will not detect the change - Thread.Sleep(1000); - - var fileToChange = Path.Combine(scenario.TestAppFolder, "Program.cs"); - var programCs = File.ReadAllText(fileToChange); - File.WriteAllText(fileToChange, programCs); - - wait.Wait(_defaultTimeout, - expectedToChange: true, - errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); - } - } + await _app.HasRestarted().OrTimeout(); + var pid2 = await _app.GetProcessId().OrTimeout(); + Assert.NotEqual(pid, pid2); + await _app.HasExited().OrTimeout(); // process should exit after run } - private class NoDepsAppScenario : DotNetWatchScenario + public void Dispose() { - private const string TestAppName = "NoDepsApp"; - - public NoDepsAppScenario(ITestOutputHelper logger) - : base(logger) - { - StatusFile = Path.Combine(Scenario.TempFolder, "status"); - StartedFile = StatusFile + ".started"; - - Scenario.AddTestProjectFolder(TestAppName); - Scenario.Restore(TestAppName); - - TestAppFolder = Path.Combine(Scenario.WorkFolder, TestAppName); - } - - public string StatusFile { get; private set; } - public string StartedFile { get; private set; } - public string TestAppFolder { get; private set; } - - public void RunDotNetWatch(IEnumerable args) - { - RunDotNetWatch(args, Path.Combine(Scenario.WorkFolder, TestAppName)); - } + _app.Dispose(); } } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Properties/AssemblyInfo.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Properties/AssemblyInfo.cs deleted file mode 100644 index d776ca34eb..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,3 +0,0 @@ -using Xunit; - -[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)] \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs deleted file mode 100644 index a49a0ed616..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/DotNetWatchScenario.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using Microsoft.Extensions.Internal; -using Xunit.Abstractions; - -namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests -{ - public class DotNetWatchScenario : IDisposable - { - protected ProjectToolScenario Scenario { get; } - public DotNetWatchScenario() - : this(null) - { - } - - public DotNetWatchScenario(ITestOutputHelper logger) - { - Scenario = new ProjectToolScenario(logger); - } - - public Process WatcherProcess { get; private set; } - - public bool UsePollingWatcher { get; set; } - - protected void RunDotNetWatch(IEnumerable arguments, string workingFolder) - { - IDictionary envVariables = null; - if (UsePollingWatcher) - { - envVariables = new Dictionary() - { - ["DOTNET_USE_POLLING_FILE_WATCHER"] = "true" - }; - } - - WatcherProcess = Scenario.ExecuteDotnetWatch(arguments, workingFolder, envVariables); - } - - public virtual void Dispose() - { - if (WatcherProcess != null) - { - if (!WatcherProcess.HasExited) - { - WatcherProcess.KillTree(); - } - WatcherProcess.Dispose(); - } - Scenario.Dispose(); - } - } -} diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs index c7fc330aef..fb7e058d6c 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -3,9 +3,7 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; -using System.Linq; using System.Reflection; using System.Threading; using Microsoft.DotNet.Cli.Utils; @@ -58,12 +56,21 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public void Restore(string project) { - project = Path.Combine(WorkFolder, project); - _logger?.WriteLine($"Restoring msbuild project in {project}"); + ExecuteCommand(project, "restore"); + } - var restore = Command - .Create(new Muxer().MuxerPath, new[] { "restore", "/p:SkipInvalidConfigurations=true" }) + public void Build(string project) + { + _logger?.WriteLine($"Building {project}"); + ExecuteCommand(project, "build"); + } + + private void ExecuteCommand(string project, params string[] arguments) + { + project = Path.Combine(WorkFolder, project); + var command = Command + .Create(new Muxer().MuxerPath, arguments) .WorkingDirectory(project) .CaptureStdErr() .CaptureStdOut() @@ -71,9 +78,9 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests .OnOutputLine(l => _logger?.WriteLine(l)) .Execute(); - if (restore.ExitCode != 0) + if (command.ExitCode != 0) { - throw new Exception($"Exit code {restore.ExitCode}"); + throw new InvalidOperationException($"Exit code {command.ExitCode}"); } } @@ -88,7 +95,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests File.Copy(nugetConfigFilePath, tempNugetConfigFile); } - public Process ExecuteDotnetWatch(IEnumerable arguments, string workDir, IDictionary environmentVariables = null) + public IEnumerable GetDotnetWatchArguments() { // this launches a new .NET Core process using the runtime of the current test app // and the version of dotnet-watch that this test app is compiled against @@ -104,32 +111,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests args.Add(Path.Combine(AppContext.BaseDirectory, "dotnet-watch.dll")); - var argsStr = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args.Concat(arguments)); - - _logger?.WriteLine($"Running dotnet {argsStr} in {workDir}"); - - var psi = new ProcessStartInfo(new Muxer().MuxerPath, argsStr) - { - UseShellExecute = false, - WorkingDirectory = workDir - }; - - if (environmentVariables != null) - { - foreach (var newEnvVar in environmentVariables) - { - var varKey = newEnvVar.Key; - var varValue = newEnvVar.Value; -#if NET451 - psi.EnvironmentVariables[varKey] = varValue; - -#else - psi.Environment[varKey] = varValue; -#endif - } - } - - return Process.Start(psi); + return args; } private static string FindNugetConfig() diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs new file mode 100644 index 0000000000..7e5dc8ee8e --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs @@ -0,0 +1,91 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using Microsoft.DotNet.Cli.Utils; +using Xunit.Abstractions; + +namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests +{ + public class WatchableApp : IDisposable + { + private const string StartedMessage = "Started"; + private const string ExitingMessage = "Exiting"; + + protected ProjectToolScenario Scenario { get; } + private readonly ITestOutputHelper _logger; + protected AwaitableProcess Process { get; set; } + private string _appName; + private bool _prepared; + + public WatchableApp(string appName, ITestOutputHelper logger) + { + _logger = logger; + _appName = appName; + Scenario = new ProjectToolScenario(logger); + Scenario.AddTestProjectFolder(appName); + SourceDirectory = Path.Combine(Scenario.WorkFolder, appName); + } + + public string SourceDirectory { get; } + + public Task HasRestarted() + => Process.GetOutputLineAsync(StartedMessage); + + public Task HasExited() + => Process.GetOutputLineAsync(ExitingMessage); + + public bool UsePollingWatcher { get; set; } + + public Task StartWatcher([CallerMemberName] string name = null) + => StartWatcher(Array.Empty(), name); + + public async Task GetProcessId() + { + var line = await Process.GetOutputLineAsync(l => l.StartsWith("PID =")); + var pid = line.Split('=').Last(); + return int.Parse(pid); + } + + public void Prepare() + { + Scenario.Restore(_appName); + Scenario.Build(_appName); + _prepared = true; + } + + public async Task StartWatcher(string[] arguments, [CallerMemberName] string name = null) + { + if (!_prepared) + { + throw new InvalidOperationException("Call .Prepare() first"); + } + + var args = Scenario + .GetDotnetWatchArguments() + .Concat(new[] { "run", "--" }) + .Concat(arguments); + + var spec = new ProcessSpec + { + Executable = new Muxer().MuxerPath, + Arguments = args, + WorkingDirectory = SourceDirectory + }; + + Process = new AwaitableProcess(spec, _logger); + Process.Start(); + await Process.GetOutputLineAsync(StartedMessage); + } + + public virtual void Dispose() + { + Process.Dispose(); + Scenario.Dispose(); + } + } +} diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TaskExtensions.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TaskExtensions.cs new file mode 100644 index 0000000000..b93d843943 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TaskExtensions.cs @@ -0,0 +1,27 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests +{ + public static class TaskExtensions + { + public static async Task OrTimeout(this Task task, int timeout = 30, [CallerFilePath] string file = null, [CallerLineNumber] int line = 0) + { + await OrTimeout((Task)task, timeout, file, line); + return task.Result; + } + + public static async Task OrTimeout(this Task task, int timeout = 30, [CallerFilePath] string file = null, [CallerLineNumber] int line = 0) + { + var finished = await Task.WhenAny(task, Task.Delay(TimeSpan.FromSeconds(timeout))); + if (!ReferenceEquals(finished, task)) + { + throw new TimeoutException($"Task exceeded max running time of {timeout}s at {file}:{line}"); + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj index 00ea5a7ab7..e5fc0c1ed5 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj @@ -9,7 +9,7 @@ - + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/Program.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/Program.cs index a5aaf90366..c9338cbc98 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/Program.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/Program.cs @@ -3,7 +3,6 @@ using System; using System.Diagnostics; -using System.IO; using System.Threading; namespace ConsoleApplication @@ -14,26 +13,9 @@ namespace ConsoleApplication public static void Main(string[] args) { - ConsoleWrite("AppWithDeps started."); - - File.AppendAllLines(args[0], new string[] { $"{processId}" }); - - File.WriteAllText(args[0] + ".started", ""); - Block(); - } - - private static void ConsoleWrite(string text) - { - Console.WriteLine($"[{processId}] {text}"); - } - - private static void Block() - { - while (true) - { - ConsoleWrite("Blocked..."); - Thread.Sleep(1000); - } + Console.WriteLine("Started"); + Console.WriteLine($"PID = " + Process.GetCurrentProcess().Id); + Thread.Sleep(Timeout.Infinite); } } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj index d8bbbdd6b7..04aad78be1 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj @@ -9,7 +9,7 @@ - + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj index 2389ac538f..904fb1c9ed 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj @@ -8,7 +8,7 @@ - + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/Program.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/Program.cs index 9e89b57a60..768257e074 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/Program.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/Program.cs @@ -3,37 +3,20 @@ using System; using System.Diagnostics; -using System.IO; +using System.Linq; +using System.Reflection; using System.Threading; namespace ConsoleApplication { public class Program { - private static readonly int processId = Process.GetCurrentProcess().Id; - public static void Main(string[] args) { - ConsoleWrite("GlobbingApp started."); - - File.AppendAllLines(args[0], new string[] { $"{processId}" }); - - File.WriteAllText(args[0] + ".started", ""); - Block(); - } - - private static void ConsoleWrite(string text) - { - Console.WriteLine($"[{processId}] {text}"); - } - - private static void Block() - { - while (true) - { - ConsoleWrite("Blocked..."); - Thread.Sleep(1000); - } + Console.WriteLine("Started"); + Console.WriteLine("PID = " + Process.GetCurrentProcess().Id); + Console.WriteLine("Defined types = " + typeof(Program).GetTypeInfo().Assembly.DefinedTypes.Count()); + Thread.Sleep(Timeout.Infinite); } } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj index 3fe95153a3..e218c105dd 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj @@ -8,7 +8,7 @@ - + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/Program.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/Program.cs index cbff2063f8..b503e70ce6 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/Program.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/Program.cs @@ -3,41 +3,21 @@ using System; using System.Diagnostics; -using System.IO; using System.Threading; namespace ConsoleApplication { public class Program { - private static readonly int processId = Process.GetCurrentProcess().Id; - public static void Main(string[] args) { - ConsoleWrite("NoDepsApp started."); - - File.AppendAllLines(args[0], new string[] { $"{processId}" }); - - File.WriteAllText(args[0] + ".started", ""); - - if (args.Length > 1 && args[1] == "--no-exit") + Console.WriteLine("Started"); + Console.WriteLine($"PID = " + Process.GetCurrentProcess().Id); + if (args.Length > 0 && args[0] == "--no-exit") { - Block(); - } - } - - private static void ConsoleWrite(string text) - { - Console.WriteLine($"[{processId}] {text}"); - } - - private static void Block() - { - while (true) - { - ConsoleWrite("Blocked..."); - Thread.Sleep(1000); + Thread.Sleep(Timeout.Infinite); } + Console.WriteLine("Exiting"); } } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/WaitForFileToChange.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/WaitForFileToChange.cs deleted file mode 100644 index 995e61a738..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/WaitForFileToChange.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Threading; -using Microsoft.DotNet.Watcher.Internal; - -namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests -{ - public class WaitForFileToChange : IDisposable - { - private readonly IFileSystemWatcher _watcher; - private readonly string _expectedFile; - - private ManualResetEvent _changed = new ManualResetEvent(false); - - public WaitForFileToChange(string file) - { - _watcher = FileWatcherFactory.CreateWatcher(Path.GetDirectoryName(file), usePollingWatcher: true); - _expectedFile = file; - - _watcher.OnFileChange += WatcherEvent; - - _watcher.EnableRaisingEvents = true; - } - - private void WatcherEvent(object sender, string file) - { - if (file.Equals(_expectedFile, StringComparison.Ordinal)) - { - Waiters.WaitForFileToBeReadable(_expectedFile, TimeSpan.FromSeconds(10)); - _changed?.Set(); - } - } - - public void Wait(TimeSpan timeout, bool expectedToChange, string errorMessage) - { - if (_changed != null) - { - var changed = _changed.WaitOne(timeout); - if (changed != expectedToChange) - { - throw new Exception(errorMessage); - } - } - } - - public void Dispose() - { - _watcher.EnableRaisingEvents = false; - - _watcher.OnFileChange -= WatcherEvent; - - _watcher.Dispose(); - _changed.Dispose(); - - _changed = null; - } - } -} diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Waiters.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Waiters.cs deleted file mode 100644 index de8c0f7f3f..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Waiters.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Diagnostics; -using System.IO; -using System.Threading; - -namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests -{ - public static class Waiters - { - public static void WaitForFileToBeReadable(string file, TimeSpan timeout) - { - var watch = new Stopwatch(); - - Exception lastException = null; - - watch.Start(); - while (watch.Elapsed < timeout) - { - try - { - File.ReadAllText(file); - watch.Stop(); - return; - } - catch (Exception e) - { - lastException = e; - } - Thread.Sleep(500); - } - watch.Stop(); - - if (lastException != null) - { - Console.WriteLine("Last exception:"); - Console.WriteLine(lastException); - } - - throw new InvalidOperationException($"{file} is not readable."); - } - - public static void WaitForProcessToStop(int processId, TimeSpan timeout, bool expectedToStop, string errorMessage) - { - Console.WriteLine($"Waiting for process {processId} to stop..."); - - Process process = null; - - try - { - process = Process.GetProcessById(processId); - } - catch (Exception e) - { - // If we expect the process to stop, then it might have stopped already - if (!expectedToStop) - { - Console.WriteLine($"Could not find process {processId}: {e}"); - } - } - - var watch = new Stopwatch(); - watch.Start(); - while (watch.Elapsed < timeout) - { - if (process == null || process.HasExited) - { - Console.WriteLine($"Process {processId} is no longer running"); - break; - } - Thread.Sleep(500); - } - watch.Stop(); - - bool isStopped = process == null || process.HasExited; - if (isStopped != expectedToStop) - { - throw new InvalidOperationException(errorMessage); - } - } - } -} diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/test.cmd b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/test.cmd new file mode 100644 index 0000000000..0aa8bdf56e --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/test.cmd @@ -0,0 +1,6 @@ +@echo off + +rem For local testing + +dotnet build +..\..\.build\dotnet\dotnet.exe exec --depsfile bin\Debug\netcoreapp1.0\Microsoft.DotNet.Watcher.Tools.FunctionalTests.deps.json --runtimeconfig bin\Debug\netcoreapp1.0\Microsoft.DotNet.Watcher.Tools.FunctionalTests.runtimeconfig.json ..\..\.build\dotnet-test-xunit\2.2.0-preview2-build1029\lib\netcoreapp1.0\dotnet-test-xunit.dll bin\Debug\netcoreapp1.0\Microsoft.DotNet.Watcher.Tools.FunctionalTests.dll %* \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/test.sh b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/test.sh new file mode 100755 index 0000000000..e617f19860 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/test.sh @@ -0,0 +1,8 @@ +dotnet build + +../../.build/dotnet/dotnet exec \ +--depsfile bin/Debug/netcoreapp1.0/Microsoft.DotNet.Watcher.Tools.FunctionalTests.deps.json \ +--runtimeconfig bin/Debug/netcoreapp1.0/Microsoft.DotNet.Watcher.Tools.FunctionalTests.runtimeconfig.json \ +../../.build/dotnet-test-xunit/2.2.0-preview2-build1029/lib/netcoreapp1.0/dotnet-test-xunit.dll \ +bin/Debug/netcoreapp1.0/Microsoft.DotNet.Watcher.Tools.FunctionalTests.dll \ +$@ \ No newline at end of file From 2a0e827f9b6b6161604fb94a687e155e404f005a Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 16 Nov 2016 15:36:47 -0800 Subject: [PATCH 0346/1029] Update dependency version and explicitly require files in nuspec --- .../Microsoft.DotNet.Watcher.Tools.nuspec | 3 +++ src/Microsoft.Extensions.SecretManager.Tools/project.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec index 2fe02b3f50..feb24bb265 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec @@ -25,6 +25,9 @@ + + + \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index cec16d5840..2c2e801dd2 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -38,7 +38,7 @@ ] }, "dependencies": { - "Microsoft.DotNet.Cli.Utils": "1.0.0-preview3-004050", + "Microsoft.DotNet.Cli.Utils": "1.0.0-preview3-004056", "Microsoft.Extensions.Configuration.UserSecrets": "1.0.0", "Microsoft.Extensions.Logging": "1.0.0", "Microsoft.NETCore.App": { From b6b45239938c0deaa0e0a31be8b02f5dc6ce3177 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 17 Nov 2016 00:43:21 -0800 Subject: [PATCH 0347/1029] Remove dependency on Microsoft.DotNet.Cli.Utils --- .gitignore | 3 +- .../CommandLineOptions.cs | 2 +- .../DotNetWatcher.cs | 5 + .../Internal/MsBuildFileSetFactory.cs | 46 +++++--- .../Internal/MsBuildProjectFinder.cs | 7 +- .../Internal/OutputCapture.cs | 14 +++ .../Internal/OutputSink.cs | 15 +-- .../Internal/ProcessRunner.cs | 42 +++++-- .../ProcessSpec.cs | 6 +- src/Microsoft.DotNet.Watcher.Tools/Program.cs | 36 +++++- .../project.json | 1 - src/Shared/ArgumentEscaper.cs | 107 ++++++++++++++++++ src/Shared/DotNetMuxer.cs | 56 +++++++++ src/Shared/StringExtensions.cs | 35 ++++++ .../project.json | 1 + .../ArgumentEscaperTests.cs | 23 ++++ .../CommandLineOptionsTests.cs | 2 +- .../MsBuildFileSetFactoryTest.cs | 4 +- 18 files changed, 348 insertions(+), 57 deletions(-) create mode 100644 src/Microsoft.DotNet.Watcher.Tools/Internal/OutputCapture.cs create mode 100644 src/Shared/ArgumentEscaper.cs create mode 100644 src/Shared/DotNetMuxer.cs create mode 100644 src/Shared/StringExtensions.cs create mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/ArgumentEscaperTests.cs diff --git a/.gitignore b/.gitignore index 29b5f79c9b..61e62b3028 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,5 @@ project.lock.json .vscode/ testWorkDir/ *.nuget.props -*.nuget.targets \ No newline at end of file +*.nuget.targets +.idea/ diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs index 5c4ac1058a..b148ad6f08 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs @@ -1,9 +1,9 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.IO; -using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Watcher.Tools; using Microsoft.DotNet.Watcher.Internal; using Microsoft.Extensions.CommandLineUtils; diff --git a/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs index 58756c33cd..5ee3d8d945 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs @@ -5,6 +5,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.DotNet.Watcher.Internal; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Tools.Internal; namespace Microsoft.DotNet.Watcher { @@ -45,6 +46,10 @@ namespace Microsoft.DotNet.Watcher var fileSetTask = fileSetWatcher.GetChangedFileAsync(combinedCancellationSource.Token); var processTask = _processRunner.RunAsync(processSpec, combinedCancellationSource.Token); + _logger.LogInformation("Running {execName} with the following arguments: {args}", + processSpec.ShortDisplayName(), + ArgumentEscaper.EscapeAndConcatenate(processSpec.Arguments)); + var finishedTask = await Task.WhenAny(processTask, fileSetTask, cancelledTaskSource.Task); // Regardless of the which task finished first, make sure everything is cancelled diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs index f40a43732a..e332ad88f5 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs @@ -7,11 +7,11 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; +using System.Text; using System.Threading; using System.Threading.Tasks; -using Microsoft.DotNet.Cli.Utils; -using Microsoft.DotNet.Watcher.Tools; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Tools.Internal; namespace Microsoft.DotNet.Watcher.Internal { @@ -23,6 +23,7 @@ namespace Microsoft.DotNet.Watcher.Internal private readonly string _projectFile; private readonly string _watchTargetsDir; private readonly OutputSink _outputSink; + private readonly ProcessRunner _processRunner; public MsBuildFileSetFactory(ILogger logger, string projectFile) : this(logger, projectFile, new OutputSink()) @@ -40,6 +41,7 @@ namespace Microsoft.DotNet.Watcher.Internal _projectFile = projectFile; _watchTargetsDir = FindWatchTargetsDir(); _outputSink = outputSink; + _processRunner = new ProcessRunner(logger); } internal List BuildFlags { get; } = new List @@ -71,20 +73,21 @@ namespace Microsoft.DotNet.Watcher.Internal var capture = _outputSink.StartCapture(); // TODO adding files doesn't currently work. Need to provide a way to detect new files // find files - var exitCode = Command.CreateDotNet("msbuild", - new[] + var processSpec = new ProcessSpec + { + Executable = DotNetMuxer.MuxerPathOrDefault(), + WorkingDirectory = projectDir, + Arguments = new[] { - _projectFile, + "msbuild", + _projectFile, $"/p:_DotNetWatchTargetsLocation={_watchTargetsDir}", // add our dotnet-watch targets - $"/p:_DotNetWatchListFile={watchList}", - }.Concat(BuildFlags)) - .CaptureStdErr() - .CaptureStdOut() - .OnErrorLine(l => capture.WriteErrorLine(l)) - .OnOutputLine(l => capture.WriteOutputLine(l)) - .WorkingDirectory(projectDir) - .Execute() - .ExitCode; + $"/p:_DotNetWatchListFile={watchList}" + }.Concat(BuildFlags), + OutputCapture = capture + }; + + var exitCode = await _processRunner.RunAsync(processSpec, cancellationToken); if (exitCode == 0) { @@ -104,9 +107,18 @@ namespace Microsoft.DotNet.Watcher.Internal return fileset; } - _logger.LogError($"Error(s) finding watch items project file '{Path.GetFileName(_projectFile)}': "); - _logger.LogError(capture.GetAllLines("[MSBUILD] : ")); - _logger.LogInformation("Fix the error to continue."); + var sb = new StringBuilder() + .Append("Error(s) finding watch items project file '") + .Append(Path.GetFileName(_projectFile)) + .AppendLine("' :"); + + foreach (var line in capture.Lines) + { + sb.Append(" [MSBUILD] :").AppendLine(line); + } + + _logger.LogError(sb.ToString()); + _logger.LogInformation("Fix the error to continue or press Ctrl+C to exit."); var fileSet = new FileSet(new[] { _projectFile }); diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildProjectFinder.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildProjectFinder.cs index ff3f45b66b..2eefb9a891 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildProjectFinder.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildProjectFinder.cs @@ -4,7 +4,6 @@ using System; using System.IO; using System.Linq; -using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Watcher.Tools; namespace Microsoft.DotNet.Watcher.Internal @@ -35,12 +34,12 @@ namespace Microsoft.DotNet.Watcher.Internal if (projects.Count > 1) { - throw new GracefulException(Resources.FormatError_MultipleProjectsFound(projectPath)); + throw new FileNotFoundException(Resources.FormatError_MultipleProjectsFound(projectPath)); } if (projects.Count == 0) { - throw new GracefulException(Resources.FormatError_NoProjectsFound(projectPath)); + throw new FileNotFoundException(Resources.FormatError_NoProjectsFound(projectPath)); } return projects[0]; @@ -48,7 +47,7 @@ namespace Microsoft.DotNet.Watcher.Internal if (!File.Exists(projectPath)) { - throw new GracefulException(Resources.FormatError_ProjectPath_NotFound(projectPath)); + throw new FileNotFoundException(Resources.FormatError_ProjectPath_NotFound(projectPath)); } return projectPath; diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/OutputCapture.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/OutputCapture.cs new file mode 100644 index 0000000000..08e051f732 --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/OutputCapture.cs @@ -0,0 +1,14 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; + +namespace Microsoft.DotNet.Watcher.Internal +{ + public class OutputCapture + { + private readonly List _lines = new List(); + public IEnumerable Lines => _lines; + public void AddLine(string line) => _lines.Add(line); + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/OutputSink.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/OutputSink.cs index aa764437ad..eb176564ef 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/OutputSink.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/OutputSink.cs @@ -1,27 +1,14 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; -using System.Collections.Generic; -using System.Linq; - namespace Microsoft.DotNet.Watcher.Internal { - internal class OutputSink + public class OutputSink { public OutputCapture Current { get; private set; } public OutputCapture StartCapture() { return (Current = new OutputCapture()); } - - public class OutputCapture - { - private readonly List _lines = new List(); - public IEnumerable Lines => _lines; - public void WriteOutputLine(string line) => _lines.Add(line); - public void WriteErrorLine(string line) => _lines.Add(line); - public string GetAllLines(string prefix) => string.Join(Environment.NewLine, _lines.Select(l => prefix + l)); - } } } \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs index f8d9260039..39f302c71e 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs @@ -3,11 +3,12 @@ using System; using System.Diagnostics; +using System.IO; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Internal; -using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Tools.Internal; namespace Microsoft.DotNet.Watcher.Internal { @@ -35,30 +36,42 @@ namespace Microsoft.DotNet.Watcher.Internal cancellationToken.Register(() => processState.TryKill()); process.Start(); - _logger.LogInformation("{execName} process id: {pid}", processSpec.ShortDisplayName(), process.Id); - await processState.Task; + if (processSpec.IsOutputCaptured) + { + await Task.WhenAll( + processState.Task, + ConsumeStreamAsync(process.StandardOutput, processSpec.OutputCapture.AddLine), + ConsumeStreamAsync(process.StandardError, processSpec.OutputCapture.AddLine) + ); + } + else + { + _logger.LogInformation("{execName} process id: {pid}", processSpec.ShortDisplayName(), process.Id); + await processState.Task; + } exitCode = process.ExitCode; } - LogResult(processSpec, exitCode); + if (!processSpec.IsOutputCaptured) + { + LogResult(processSpec, exitCode); + } return exitCode; } private Process CreateProcess(ProcessSpec processSpec) { - var arguments = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(processSpec.Arguments); - - _logger.LogInformation("Running {execName} with the following arguments: {args}", processSpec.ShortDisplayName(), arguments); - var startInfo = new ProcessStartInfo { FileName = processSpec.Executable, - Arguments = arguments, + Arguments = ArgumentEscaper.EscapeAndConcatenate(processSpec.Arguments), UseShellExecute = false, - WorkingDirectory = processSpec.WorkingDirectory + WorkingDirectory = processSpec.WorkingDirectory, + RedirectStandardOutput = processSpec.IsOutputCaptured, + RedirectStandardError = processSpec.IsOutputCaptured, }; var process = new Process { @@ -81,6 +94,15 @@ namespace Microsoft.DotNet.Watcher.Internal } } + private static async Task ConsumeStreamAsync(StreamReader reader, Action consume) + { + string line; + while ((line = await reader.ReadLineAsync().ConfigureAwait(false)) != null) + { + consume?.Invoke(line); + } + } + private class ProcessState : IDisposable { private readonly Process _process; diff --git a/src/Microsoft.DotNet.Watcher.Tools/ProcessSpec.cs b/src/Microsoft.DotNet.Watcher.Tools/ProcessSpec.cs index 2d18b9a0be..4b1508e5e2 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/ProcessSpec.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/ProcessSpec.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; +using Microsoft.DotNet.Watcher.Internal; namespace Microsoft.DotNet.Watcher { @@ -11,8 +12,11 @@ namespace Microsoft.DotNet.Watcher public string Executable { get; set; } public string WorkingDirectory { get; set; } public IEnumerable Arguments { get; set; } + public OutputCapture OutputCapture { get; set; } - public string ShortDisplayName() + public string ShortDisplayName() => Path.GetFileNameWithoutExtension(Executable); + + public bool IsOutputCaptured => OutputCapture != null; } } diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index 06cedfa8cf..bb1bbfd828 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -2,12 +2,14 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Diagnostics; using System.IO; +using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Watcher.Internal; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Tools.Internal; namespace Microsoft.DotNet.Watcher { @@ -33,7 +35,7 @@ namespace Microsoft.DotNet.Watcher public static int Main(string[] args) { - DebugHelper.HandleDebugSwitch(ref args); + HandleDebugSwitch(ref args); using (CancellationTokenSource ctrlCTokenSource = new CancellationTokenSource()) { @@ -41,7 +43,7 @@ namespace Microsoft.DotNet.Watcher { if (!ctrlCTokenSource.IsCancellationRequested) { - Console.WriteLine($"[{LoggerName}] Shutdown requested. Press CTRL+C again to force exit."); + Console.WriteLine($"[{LoggerName}] Shutdown requested. Press Ctrl+C again to force exit."); ev.Cancel = true; } else @@ -96,12 +98,22 @@ namespace Microsoft.DotNet.Watcher var logger = loggerFactory.CreateLogger(LoggerName); // TODO multiple projects should be easy enough to add here - var projectFile = MsBuildProjectFinder.FindMsBuildProject(_workingDir, options.Project); + string projectFile; + try + { + projectFile = MsBuildProjectFinder.FindMsBuildProject(_workingDir, options.Project); + } + catch (FileNotFoundException ex) + { + _stderr.WriteLine(ex.Message.Bold().Red()); + return 1; + } + var fileSetFactory = new MsBuildFileSetFactory(logger, projectFile); var processInfo = new ProcessSpec { - Executable = new Muxer().MuxerPath, + Executable = DotNetMuxer.MuxerPathOrDefault(), WorkingDirectory = Path.GetDirectoryName(projectFile), Arguments = options.RemainingArguments }; @@ -120,7 +132,7 @@ namespace Microsoft.DotNet.Watcher } bool globalVerbose; - bool.TryParse(Environment.GetEnvironmentVariable(CommandContext.Variables.Verbose), out globalVerbose); + bool.TryParse(Environment.GetEnvironmentVariable("DOTNET_CLI_CONTEXT_VERBOSE"), out globalVerbose); if (options.IsVerbose // dotnet watch --verbose || globalVerbose) // dotnet --verbose watch @@ -130,5 +142,17 @@ namespace Microsoft.DotNet.Watcher return LogLevel.Information; } + + [Conditional("DEBUG")] + private static void HandleDebugSwitch(ref string[] args) + { + if (args.Length > 0 && string.Equals("--debug", args[0], StringComparison.OrdinalIgnoreCase)) + { + args = args.Skip(1).ToArray(); + Console.WriteLine("Waiting for debugger to attach. Press ENTER to continue"); + Console.WriteLine($"Process ID: {Process.GetCurrentProcess().Id}"); + Console.ReadLine(); + } + } } } diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index 57860301d6..d53d354b50 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -32,7 +32,6 @@ ] }, "dependencies": { - "Microsoft.DotNet.Cli.Utils": "1.0.0-preview3-004056", "Microsoft.Extensions.Logging": "1.0.0", "Microsoft.Extensions.Logging.Console": "1.0.0", "Microsoft.Extensions.Process.Sources": { diff --git a/src/Shared/ArgumentEscaper.cs b/src/Shared/ArgumentEscaper.cs new file mode 100644 index 0000000000..91d8ef3086 --- /dev/null +++ b/src/Shared/ArgumentEscaper.cs @@ -0,0 +1,107 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Microsoft.Extensions.Tools.Internal +{ + public static class ArgumentEscaper + { + /// + /// Undo the processing which took place to create string[] args in Main, so that the next process will + /// receive the same string[] args. + /// + /// + /// See https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/ + /// + /// + /// + public static string EscapeAndConcatenate(IEnumerable args) + => string.Join(" ", args.Select(EscapeSingleArg)); + + private static string EscapeSingleArg(string arg) + { + var sb = new StringBuilder(); + + var needsQuotes = ShouldSurroundWithQuotes(arg); + var isQuoted = needsQuotes || IsSurroundedWithQuotes(arg); + + if (needsQuotes) + { + sb.Append('"'); + } + + for (int i = 0; i < arg.Length; ++i) + { + var backslashes = 0; + + // Consume all backslashes + while (i < arg.Length && arg[i] == '\\') + { + backslashes++; + i++; + } + + if (i == arg.Length && isQuoted) + { + // Escape any backslashes at the end of the arg when the argument is also quoted. + // This ensures the outside quote is interpreted as an argument delimiter + sb.Append('\\', 2 * backslashes); + } + else if (i == arg.Length) + { + // At then end of the arg, which isn't quoted, + // just add the backslashes, no need to escape + sb.Append('\\', backslashes); + } + else if (arg[i] == '"') + { + // Escape any preceding backslashes and the quote + sb.Append('\\', (2 * backslashes) + 1); + sb.Append('"'); + } + else + { + // Output any consumed backslashes and the character + sb.Append('\\', backslashes); + sb.Append(arg[i]); + } + } + + if (needsQuotes) + { + sb.Append('"'); + } + + return sb.ToString(); + } + + private static bool ShouldSurroundWithQuotes(string argument) + { + // Don't quote already quoted strings + if (IsSurroundedWithQuotes(argument)) + { + return false; + } + + // Only quote if whitespace exists in the string + return ContainsWhitespace(argument); + } + + private static bool IsSurroundedWithQuotes(string argument) + { + if (argument.Length <= 1) + { + return false; + } + + return argument[0] == '"' && argument[argument.Length - 1] == '"'; + } + + private static bool ContainsWhitespace(string argument) + => argument.IndexOfAny(new [] { ' ', '\t', '\n' }) >= 0; + } +} \ No newline at end of file diff --git a/src/Shared/DotNetMuxer.cs b/src/Shared/DotNetMuxer.cs new file mode 100644 index 0000000000..56e627f192 --- /dev/null +++ b/src/Shared/DotNetMuxer.cs @@ -0,0 +1,56 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Runtime.InteropServices; + +namespace Microsoft.Extensions.Tools.Internal +{ + public static class DotNetMuxer + { + private const string MuxerName = "dotnet"; + + static DotNetMuxer() + { + MuxerPath = TryFindMuxerPath(); + } + + public static string MuxerPath { get; } + + public static string MuxerPathOrDefault() + => MuxerPath ?? MuxerName; + + private static string TryFindMuxerPath() + { + var fileName = MuxerName; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + fileName += ".exe"; + } + + var fxDepsFile = AppContext.GetData("FX_DEPS_FILE") as string; + + if (string.IsNullOrEmpty(fxDepsFile)) + { + return null; + } + + var muxerDir = new FileInfo(fxDepsFile) // Microsoft.NETCore.App.deps.json + .Directory? // (version) + .Parent? // Microsoft.NETCore.App + .Parent? // shared + .Parent; // DOTNET_HOME + + if (muxerDir == null) + { + return null; + } + + var muxer = Path.Combine(muxerDir.FullName, fileName); + return File.Exists(muxer) + ? muxer + : null; + } + } +} \ No newline at end of file diff --git a/src/Shared/StringExtensions.cs b/src/Shared/StringExtensions.cs new file mode 100644 index 0000000000..fdb087cfcd --- /dev/null +++ b/src/Shared/StringExtensions.cs @@ -0,0 +1,35 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace System +{ + public static class StringExtensions + { + public static string Black(this string text) + => "\x1B[30m" + text + "\x1B[39m"; + + public static string Red(this string text) + => "\x1B[31m" + text + "\x1B[39m"; + + public static string Green(this string text) + => "\x1B[32m" + text + "\x1B[39m"; + + public static string Yellow(this string text) + => "\x1B[33m" + text + "\x1B[39m"; + + public static string Blue(this string text) + => "\x1B[34m" + text + "\x1B[39m"; + + public static string Magenta(this string text) + => "\x1B[35m" + text + "\x1B[39m"; + + public static string Cyan(this string text) + => "\x1B[36m" + text + "\x1B[39m"; + + public static string White(this string text) + => "\x1B[37m" + text + "\x1B[39m"; + + public static string Bold(this string text) + => "\x1B[1m" + text + "\x1B[22m"; + } +} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index 645d6f7de4..4e28d24c2f 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -11,6 +11,7 @@ }, "dependencies": { "dotnet-test-xunit": "2.2.0-preview2-build1029", + "Microsoft.DotNet.Cli.Utils": "1.0.0-preview3-004056", "Microsoft.DotNet.InternalAbstractions": "1.0.0", "Microsoft.AspNetCore.Testing": "1.0.0", "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/ArgumentEscaperTests.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/ArgumentEscaperTests.cs new file mode 100644 index 0000000000..70c18b584c --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/ArgumentEscaperTests.cs @@ -0,0 +1,23 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Extensions.Tools.Internal; +using Xunit; + +namespace Microsoft.DotNet.Watcher.Tools.Tests +{ + public class ArgumentEscaperTests + { + [Theory] + [InlineData(new[] { "one", "two", "three" }, "one two three")] + [InlineData(new[] { "line1\nline2", "word1\tword2" }, "\"line1\nline2\" \"word1\tword2\"")] + [InlineData(new[] { "with spaces" }, "\"with spaces\"")] + [InlineData(new[] { @"with\backslash" }, @"with\backslash")] + [InlineData(new[] { @"""quotedwith\backslash""" }, @"\""quotedwith\backslash\""")] + [InlineData(new[] { @"C:\Users\" }, @"C:\Users\")] + [InlineData(new[] { @"C:\Program Files\dotnet\" }, @"""C:\Program Files\dotnet\\""")] + [InlineData(new[] { @"backslash\""preceedingquote" }, @"backslash\\\""preceedingquote")] + public void EscapesArguments(string[] args, string expected) + => Assert.Equal(expected, ArgumentEscaper.EscapeAndConcatenate(args)); + } +} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs index be63a361fc..2957dfe17a 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs @@ -6,7 +6,7 @@ using System.Linq; using System.Text; using Xunit; -namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests +namespace Microsoft.DotNet.Watcher.Tools.Tests { public class CommandLineOptionsTests { diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs index 555be13c70..d236d0078c 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs @@ -264,7 +264,9 @@ namespace Microsoft.DotNetWatcher.Tools.Tests var fileset = await GetFileSet(filesetFactory); - _logger.LogInformation(output.Current.GetAllLines("Sink output: ")); + _logger.LogInformation(string.Join( + Environment.NewLine, + output.Current.Lines.Select(l => "Sink output: " + l))); var includedProjects = new[] { "A", "B", "C", "D", "E", "F", "G" }; AssertEx.EqualFileList( From a0e07744c086b503ac49825d03c9bea46956c3d9 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 17 Nov 2016 14:13:21 -0800 Subject: [PATCH 0348/1029] Pin versions --- build.ps1 | 2 +- build.sh | 2 +- makefile.shade | 2 +- src/Microsoft.DotNet.Watcher.Tools/project.json | 2 +- src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json | 2 +- src/Microsoft.Extensions.SecretManager.Tools/project.json | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build.ps1 b/build.ps1 index f780c43a82..de0625cd86 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.0.0-msbuild2.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index 0a1463b9e4..fe4f70d19d 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.0.0-msbuild2.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi diff --git a/makefile.shade b/makefile.shade index 606c572fac..255a683cf0 100644 --- a/makefile.shade +++ b/makefile.shade @@ -6,7 +6,7 @@ default BUILD_DIR_LOCAL='${Path.Combine(BASE_DIR_LOCAL, "artifacts", "build")}' var VERSION='0.1' var FULL_VERSION='0.1' var AUTHORS='Microsoft Open Technologies, Inc.' --BuildQuality = "msbuild1"; +-BuildQuality = "msbuild2"; use-standard-lifecycle k-standard-goals diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index d53d354b50..bbe5c71fc5 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-*", + "version": "1.0.0-msbuild2-final", "description": "Command line tool to watch for source file changes during development and restart the dotnet command.", "packOptions": { "tags": [ diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json index 3ff33ed3bd..ef277ffc66 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-*", + "version": "1.0.0-msbuild2-final", "buildOptions": { "outputName": "dotnet-sql-cache", "emitEntryPoint": true, diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index 2c2e801dd2..88d09cae94 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-*", + "version": "1.0.0-msbuild2-final", "buildOptions": { "outputName": "dotnet-user-secrets", "emitEntryPoint": true, From e931db804f8505bdf983dc171673801448d4c3e8 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 17 Nov 2016 14:14:06 -0800 Subject: [PATCH 0349/1029] :arrow_up: prerelease version --- makefile.shade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile.shade b/makefile.shade index 606c572fac..c41f9d38a5 100644 --- a/makefile.shade +++ b/makefile.shade @@ -6,7 +6,7 @@ default BUILD_DIR_LOCAL='${Path.Combine(BASE_DIR_LOCAL, "artifacts", "build")}' var VERSION='0.1' var FULL_VERSION='0.1' var AUTHORS='Microsoft Open Technologies, Inc.' --BuildQuality = "msbuild1"; +-BuildQuality = "msbuild3"; use-standard-lifecycle k-standard-goals From c8870a80a7837b7a78cdde41058dfb3f526ef910 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 17 Nov 2016 15:43:52 -0800 Subject: [PATCH 0350/1029] Remove Microsoft.DotNet.Cli.Utils from nuspec --- .../Microsoft.DotNet.Watcher.Tools.nuspec | 7 +++---- tools/NuGetPackager/PackCommand.cs | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec index feb24bb265..ca72bc7b94 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec @@ -14,10 +14,9 @@ - - - - + + + diff --git a/tools/NuGetPackager/PackCommand.cs b/tools/NuGetPackager/PackCommand.cs index 3c04b27fa6..9e318f06b3 100644 --- a/tools/NuGetPackager/PackCommand.cs +++ b/tools/NuGetPackager/PackCommand.cs @@ -31,7 +31,7 @@ namespace NuGetPackager var project = ProjectContext.Create(Path.GetDirectoryName(nuspec), FrameworkConstants.CommonFrameworks.NetCoreApp10); var idx = 0; var props = ""; - var first = false; + var first = true; foreach (var depVersion in GetDependencies(project).OrderBy(p => p.Item1).Select(p => p.Item2)) { if (first) From 192134cad8a9805f41b94052f9d68d17f7d3afb2 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 17 Nov 2016 15:47:10 -0800 Subject: [PATCH 0351/1029] Throw if packing fails --- tools/NuGetPackager/PackCommand.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/NuGetPackager/PackCommand.cs b/tools/NuGetPackager/PackCommand.cs index 9e318f06b3..53ecef3b34 100644 --- a/tools/NuGetPackager/PackCommand.cs +++ b/tools/NuGetPackager/PackCommand.cs @@ -136,7 +136,13 @@ namespace NuGetPackager Console.WriteLine("command: ".Bold().Blue() + pInfo.FileName); Console.WriteLine("arguments: ".Bold().Blue() + pInfo.Arguments); - Process.Start(pInfo).WaitForExit(); + var process = Process.Start(pInfo); + process.WaitForExit(); + + if (process.ExitCode != 0) + { + throw new InvalidOperationException("NuGet exited with non-zero code " + process.ExitCode); + } } private async Task GetNugetExePath() From 758f35835c1a9257fefa8692431d662ed5d53824 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 18 Nov 2016 10:56:54 -0800 Subject: [PATCH 0352/1029] Clean tmp folder after unzipping KoreBuild --- build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sh b/build.sh index f4208100eb..4fd7ede788 100755 --- a/build.sh +++ b/build.sh @@ -38,7 +38,7 @@ if test ! -d $buildFolder; then chmod +x $buildFile # Cleanup - if test ! -d $tempFolder; then + if test -d $tempFolder; then rm -rf $tempFolder fi fi From 6259fd3fb37712fb670e33326c68279c8df3c9b0 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 18 Nov 2016 10:57:00 -0800 Subject: [PATCH 0353/1029] Clean tmp folder after unzipping KoreBuild --- build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sh b/build.sh index f4208100eb..4fd7ede788 100755 --- a/build.sh +++ b/build.sh @@ -38,7 +38,7 @@ if test ! -d $buildFolder; then chmod +x $buildFile # Cleanup - if test ! -d $tempFolder; then + if test -d $tempFolder; then rm -rf $tempFolder fi fi From 40f042dc495f2ee4bbfbedfe0a9eb596ad5f30fd Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 18 Nov 2016 10:57:03 -0800 Subject: [PATCH 0354/1029] Clean tmp folder after unzipping KoreBuild --- build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sh b/build.sh index f4208100eb..4fd7ede788 100755 --- a/build.sh +++ b/build.sh @@ -38,7 +38,7 @@ if test ! -d $buildFolder; then chmod +x $buildFile # Cleanup - if test ! -d $tempFolder; then + if test -d $tempFolder; then rm -rf $tempFolder fi fi From 4faf89030c47e5ee5c7193a26d810a50862a3cf4 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 18 Nov 2016 12:12:17 -0800 Subject: [PATCH 0355/1029] Pinning versions for 1.1.0 release --- NuGet.config | 7 ++++--- src/Microsoft.AspNetCore.JsonPatch/project.json | 14 +++++++------- .../project.json | 8 ++++---- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/NuGet.config b/NuGet.config index ad973186eb..feaadcda87 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,8 @@ - + - - + + + diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index 5b998272ff..6d2ccde5cc 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -1,5 +1,5 @@ { - "version": "1.1.0-*", + "version": "1.1.0", "description": "ASP.NET Core support for JSON PATCH.", "buildOptions": { "warningsAsErrors": true, @@ -21,19 +21,19 @@ ] }, "dependencies": { - "NETStandard.Library": "1.6.1-*", - "Newtonsoft.Json": "9.0.1", "Microsoft.Extensions.ClosedGenericMatcher.Sources": { "type": "build", - "version": "1.1.0-*" - } + "version": "1.1.0-rtm-22752" + }, + "NETStandard.Library": "1.6.1", + "Newtonsoft.Json": "9.0.1" }, "frameworks": { "net451": {}, "netstandard1.3": { "dependencies": { - "Microsoft.CSharp": "4.3.0-*", - "System.Reflection.TypeExtensions": "4.3.0-*" + "Microsoft.CSharp": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0" } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index 9e95ee86e0..196dbcac08 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -4,8 +4,8 @@ }, "dependencies": { "dotnet-test-xunit": "2.2.0-*", - "Microsoft.AspNetCore.JsonPatch": "1.1.0-*", - "Microsoft.AspNetCore.Testing": "1.1.0-*", + "Microsoft.AspNetCore.JsonPatch": "1.1.0", + "Microsoft.AspNetCore.Testing": "1.1.0-rtm-22752", "Moq": "4.6.36-*", "xunit": "2.2.0-*" }, @@ -14,10 +14,10 @@ "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { - "version": "1.1.0-*", + "version": "1.1.0", "type": "platform" }, - "System.Diagnostics.TraceSource": "4.3.0-*" + "System.Diagnostics.TraceSource": "4.3.0" } }, "net451": { From 587376200be0cd35c9e2ba235fcc4c22f9a8f5b7 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 21 Nov 2016 10:16:39 -0800 Subject: [PATCH 0356/1029] Remove CLI NuGet feeds --- NuGet.config | 2 -- 1 file changed, 2 deletions(-) diff --git a/NuGet.config b/NuGet.config index 5144de9b69..146dd774ef 100644 --- a/NuGet.config +++ b/NuGet.config @@ -2,8 +2,6 @@ - - From 40d46704635e6fff9fe51eead8b9408d519825fc Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 16 Nov 2016 21:35:21 -0800 Subject: [PATCH 0357/1029] Abstract the console --- .../CommandLineOptions.cs | 13 ++-- .../Internal/FileSetWatcher.cs | 1 + .../Internal/FileWatcher/DotnetFileWatcher.cs | 1 + .../FileWatcher/PollingFileWatcher.cs | 1 + .../Internal/MsBuildFileSetFactory.cs | 2 +- .../Internal/MsBuildProjectFinder.cs | 1 + src/Microsoft.DotNet.Watcher.Tools/Program.cs | 41 ++++++----- .../Properties/Resources.Designer.cs | 16 ----- .../Resources.resx | 3 - .../Internal/CommandContext.cs | 1 + .../Internal/CommandLineOptions.cs | 1 + .../Internal/MsBuildProjectFinder.cs | 6 +- .../Internal/SecretsStore.cs | 6 +- .../Program.cs | 21 +----- .../Properties/Resources.Designer.cs | 16 ----- .../Resources.resx | 3 - .../Internal => Shared}/Ensure.cs | 5 +- .../Internal => Shared}/IConsole.cs | 4 +- .../Internal => Shared}/PhysicalConsole.cs | 12 +++- .../project.json | 1 + .../test.sh | 2 + .../AssertEx.cs | 2 +- .../CommandLineOptionsTests.cs | 33 +++++---- .../MsBuildFileSetFactoryTest.cs | 3 +- .../ProgramTests.cs | 52 ++++++++++++++ .../Utilities}/TaskExtensions.cs | 4 +- .../Utilities/TemporaryCSharpProject.cs | 2 +- .../Utilities/TemporaryDirectory.cs | 2 +- .../Utilities/TestProjectGraph.cs | 2 +- .../Utilities/XunitLogger.cs | 2 +- .../project.json | 3 +- .../SecretManagerTests.cs | 21 +++--- .../SetCommandTest.cs | 18 +++-- .../TestConsole.cs | 17 ----- .../project.json | 3 +- test/Shared/TestConsole.cs | 69 +++++++++++++++++++ 36 files changed, 235 insertions(+), 155 deletions(-) rename src/{Microsoft.DotNet.Watcher.Tools/Internal => Shared}/Ensure.cs (79%) rename src/{Microsoft.Extensions.SecretManager.Tools/Internal => Shared}/IConsole.cs (76%) rename src/{Microsoft.Extensions.SecretManager.Tools/Internal => Shared}/PhysicalConsole.cs (65%) create mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/ProgramTests.cs rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => Microsoft.DotNet.Watcher.Tools.Tests/Utilities}/TaskExtensions.cs (90%) delete mode 100644 test/Microsoft.Extensions.SecretManager.Tools.Tests/TestConsole.cs create mode 100644 test/Shared/TestConsole.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs index b148ad6f08..aea719428d 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs @@ -1,12 +1,11 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; -using System.IO; using Microsoft.DotNet.Watcher.Tools; -using Microsoft.DotNet.Watcher.Internal; using Microsoft.Extensions.CommandLineUtils; +using Microsoft.Extensions.Tools.Internal; namespace Microsoft.DotNet.Watcher { @@ -17,7 +16,7 @@ namespace Microsoft.DotNet.Watcher public bool IsQuiet { get; private set; } public bool IsVerbose { get; private set; } public IList RemainingArguments { get; private set; } - public static CommandLineOptions Parse(string[] args, TextWriter stdout, TextWriter stderr) + public static CommandLineOptions Parse(string[] args, IConsole console) { Ensure.NotNull(args, nameof(args)); @@ -25,8 +24,8 @@ namespace Microsoft.DotNet.Watcher { Name = "dotnet watch", FullName = "Microsoft DotNet File Watcher", - Out = stdout, - Error = stderr, + Out = console.Out, + Error = console.Error, AllowArgumentSeparator = true, ExtendedHelpText = @" Environment variables: @@ -80,7 +79,7 @@ Examples: if (optQuiet.HasValue() && optVerbose.HasValue()) { - stderr.WriteLine(Resources.Error_QuietAndVerboseSpecified.Bold().Red()); + console.Error.WriteLine(Resources.Error_QuietAndVerboseSpecified.Bold().Red()); return null; } diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSetWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSetWatcher.cs index b97b547a52..597d13cdd1 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSetWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSetWatcher.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Tools.Internal; namespace Microsoft.DotNet.Watcher.Internal { diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/DotnetFileWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/DotnetFileWatcher.cs index 4cda4f0cf8..5064239746 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/DotnetFileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/DotnetFileWatcher.cs @@ -3,6 +3,7 @@ using System; using System.IO; +using Microsoft.Extensions.Tools.Internal; namespace Microsoft.DotNet.Watcher.Internal { diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs index d26dcc54f2..25e4f6f76f 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Threading; +using Microsoft.Extensions.Tools.Internal; namespace Microsoft.DotNet.Watcher.Internal { diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs index e332ad88f5..282b15b8e6 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildProjectFinder.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildProjectFinder.cs index 2eefb9a891..b6cc515aec 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildProjectFinder.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildProjectFinder.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Linq; using Microsoft.DotNet.Watcher.Tools; +using Microsoft.Extensions.Tools.Internal; namespace Microsoft.DotNet.Watcher.Internal { diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index bb1bbfd828..16a7a17288 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -16,34 +16,36 @@ namespace Microsoft.DotNet.Watcher public class Program { private const string LoggerName = "DotNetWatcher"; - private readonly CancellationToken _cancellationToken; - private readonly TextWriter _stdout; - private readonly TextWriter _stderr; + private readonly IConsole _console; private readonly string _workingDir; - public Program(TextWriter consoleOutput, TextWriter consoleError, string workingDir, CancellationToken cancellationToken) + public Program(IConsole console, string workingDir) { - Ensure.NotNull(consoleOutput, nameof(consoleOutput)); - Ensure.NotNull(consoleError, nameof(consoleError)); + Ensure.NotNull(console, nameof(console)); Ensure.NotNullOrEmpty(workingDir, nameof(workingDir)); - _cancellationToken = cancellationToken; - _stdout = consoleOutput; - _stderr = consoleError; + _console = console; _workingDir = workingDir; } public static int Main(string[] args) { HandleDebugSwitch(ref args); + return new Program(PhysicalConsole.Singleton, Directory.GetCurrentDirectory()) + .RunAsync(args) + .GetAwaiter() + .GetResult(); + } + public async Task RunAsync(string[] args) + { using (CancellationTokenSource ctrlCTokenSource = new CancellationTokenSource()) { - Console.CancelKeyPress += (sender, ev) => + _console.CancelKeyPress += (sender, ev) => { if (!ctrlCTokenSource.IsCancellationRequested) { - Console.WriteLine($"[{LoggerName}] Shutdown requested. Press Ctrl+C again to force exit."); + _console.Out.WriteLine($"[{LoggerName}] Shutdown requested. Press Ctrl+C again to force exit."); ev.Cancel = true; } else @@ -55,10 +57,7 @@ namespace Microsoft.DotNet.Watcher try { - return new Program(Console.Out, Console.Error, Directory.GetCurrentDirectory(), ctrlCTokenSource.Token) - .MainInternalAsync(args) - .GetAwaiter() - .GetResult(); + return await MainInternalAsync(args, ctrlCTokenSource.Token); } catch (Exception ex) { @@ -68,16 +67,16 @@ namespace Microsoft.DotNet.Watcher return 0; } - Console.Error.WriteLine(ex.ToString()); - Console.Error.WriteLine($"[{LoggerName}] An unexpected error occurred".Bold().Red()); + _console.Error.WriteLine(ex.ToString()); + _console.Error.WriteLine($"[{LoggerName}] An unexpected error occurred".Bold().Red()); return 1; } } } - private async Task MainInternalAsync(string[] args) + private async Task MainInternalAsync(string[] args, CancellationToken cancellationToken) { - var options = CommandLineOptions.Parse(args, _stdout, _stdout); + var options = CommandLineOptions.Parse(args, _console); if (options == null) { // invalid args syntax @@ -105,7 +104,7 @@ namespace Microsoft.DotNet.Watcher } catch (FileNotFoundException ex) { - _stderr.WriteLine(ex.Message.Bold().Red()); + _console.Error.WriteLine(ex.Message.Bold().Red()); return 1; } @@ -119,7 +118,7 @@ namespace Microsoft.DotNet.Watcher }; await new DotNetWatcher(logger) - .WatchAsync(processInfo, fileSetFactory, _cancellationToken); + .WatchAsync(processInfo, fileSetFactory, cancellationToken); return 0; } diff --git a/src/Microsoft.DotNet.Watcher.Tools/Properties/Resources.Designer.cs b/src/Microsoft.DotNet.Watcher.Tools/Properties/Resources.Designer.cs index 30c1d18cb7..ee248b1342 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Properties/Resources.Designer.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Properties/Resources.Designer.cs @@ -74,22 +74,6 @@ namespace Microsoft.DotNet.Watcher.Tools return GetString("Error_QuietAndVerboseSpecified"); } - /// - /// Value cannot be null or an empty string. - /// - internal static string Error_StringNullOrEmpty - { - get { return GetString("Error_StringNullOrEmpty"); } - } - - /// - /// Value cannot be null or an empty string. - /// - internal static string FormatError_StringNullOrEmpty() - { - return GetString("Error_StringNullOrEmpty"); - } - private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); diff --git a/src/Microsoft.DotNet.Watcher.Tools/Resources.resx b/src/Microsoft.DotNet.Watcher.Tools/Resources.resx index 125a4cfea3..b66821626b 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Resources.resx +++ b/src/Microsoft.DotNet.Watcher.Tools/Resources.resx @@ -129,7 +129,4 @@ Cannot specify both '--quiet' and '--verbose' options. - - Value cannot be null or an empty string. - \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandContext.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandContext.cs index 9503178930..8ad2ffd9f9 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandContext.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandContext.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Tools.Internal; namespace Microsoft.Extensions.SecretManager.Tools.Internal { diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs index 42d826e1e0..2284b2ed25 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs @@ -4,6 +4,7 @@ using System.Reflection; using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.CommandLineUtils; +using Microsoft.Extensions.Tools.Internal; namespace Microsoft.Extensions.SecretManager.Tools.Internal { diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/MsBuildProjectFinder.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/MsBuildProjectFinder.cs index e080b4cb83..ed37e7ad87 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/MsBuildProjectFinder.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/MsBuildProjectFinder.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Linq; using Microsoft.DotNet.Cli.Utils; +using Microsoft.Extensions.Tools.Internal; namespace Microsoft.Extensions.SecretManager.Tools.Internal { @@ -14,10 +15,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal public MsBuildProjectFinder(string directory) { - if (string.IsNullOrEmpty(directory)) - { - throw new ArgumentException(Resources.Common_StringNullOrEmpty, nameof(directory)); - } + Ensure.NotNullOrEmpty(directory, nameof(directory)); _directory = directory; } diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs index 22e03ee6d7..10813b53d4 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs @@ -9,6 +9,7 @@ using System.Text; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.UserSecrets; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Tools.Internal; using Newtonsoft.Json.Linq; namespace Microsoft.Extensions.SecretManager.Tools.Internal @@ -20,10 +21,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal public SecretsStore(string userSecretsId, ILogger logger) { - if (userSecretsId == null) - { - throw new ArgumentNullException(nameof(userSecretsId)); - } + Ensure.NotNull(userSecretsId, nameof(userSecretsId)); _secretsFilePath = PathHelper.GetSecretsPathFromSecretsId(userSecretsId); diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs index 3ef60eb563..810c0a043d 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs @@ -6,6 +6,7 @@ using System.IO; using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.Logging; using Microsoft.Extensions.SecretManager.Tools.Internal; +using Microsoft.Extensions.Tools.Internal; namespace Microsoft.Extensions.SecretManager.Tools { @@ -39,29 +40,13 @@ namespace Microsoft.Extensions.SecretManager.Tools public ILogger Logger { get { return _logger; } - set - { - if (value == null) - { - throw new ArgumentNullException("value"); - } - - _logger = value; - } + set { _logger = Ensure.NotNull(value, nameof(value)); } } public CommandOutputProvider CommandOutputProvider { get { return _loggerProvider; } - set - { - if (value == null) - { - throw new ArgumentNullException("value"); - } - - _loggerProvider = value; - } + set { _loggerProvider = Ensure.NotNull(value, nameof(value)); } } public bool TryRun(string[] args, out int returnCode) diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs b/src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs index a74bdc6798..a75fc0108f 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs @@ -10,22 +10,6 @@ namespace Microsoft.Extensions.SecretManager.Tools private static readonly ResourceManager _resourceManager = new ResourceManager("Microsoft.Extensions.SecretManager.Tools.Resources", typeof(Resources).GetTypeInfo().Assembly); - /// - /// Value cannot be null or an empty string. - /// - internal static string Common_StringNullOrEmpty - { - get { return GetString("Common_StringNullOrEmpty"); } - } - - /// - /// Value cannot be null or an empty string. - /// - internal static string FormatCommon_StringNullOrEmpty() - { - return GetString("Common_StringNullOrEmpty"); - } - /// /// Command failed : {message} /// diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Resources.resx b/src/Microsoft.Extensions.SecretManager.Tools/Resources.resx index 3ee74a41e9..c9222930fc 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Resources.resx +++ b/src/Microsoft.Extensions.SecretManager.Tools/Resources.resx @@ -117,9 +117,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Value cannot be null or an empty string. - Command failed : {message} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/Ensure.cs b/src/Shared/Ensure.cs similarity index 79% rename from src/Microsoft.DotNet.Watcher.Tools/Internal/Ensure.cs rename to src/Shared/Ensure.cs index 12bfe5f05d..5cb8ff7ec7 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/Ensure.cs +++ b/src/Shared/Ensure.cs @@ -2,9 +2,8 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.DotNet.Watcher.Tools; -namespace Microsoft.DotNet.Watcher.Internal +namespace Microsoft.Extensions.Tools.Internal { internal static class Ensure { @@ -22,7 +21,7 @@ namespace Microsoft.DotNet.Watcher.Internal { if (string.IsNullOrEmpty(obj)) { - throw new ArgumentException(Resources.Error_StringNullOrEmpty, paramName); + throw new ArgumentException("Value cannot be null or an empty string.", paramName); } return obj; } diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/IConsole.cs b/src/Shared/IConsole.cs similarity index 76% rename from src/Microsoft.Extensions.SecretManager.Tools/Internal/IConsole.cs rename to src/Shared/IConsole.cs index 819d477106..7f1e5e122a 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/IConsole.cs +++ b/src/Shared/IConsole.cs @@ -1,12 +1,14 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.IO; -namespace Microsoft.Extensions.SecretManager.Tools.Internal +namespace Microsoft.Extensions.Tools.Internal { public interface IConsole { + event ConsoleCancelEventHandler CancelKeyPress; TextWriter Out { get; } TextWriter Error { get; } TextReader In { get; } diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/PhysicalConsole.cs b/src/Shared/PhysicalConsole.cs similarity index 65% rename from src/Microsoft.Extensions.SecretManager.Tools/Internal/PhysicalConsole.cs rename to src/Shared/PhysicalConsole.cs index 6be8ff495f..7b1a98f621 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/PhysicalConsole.cs +++ b/src/Shared/PhysicalConsole.cs @@ -4,13 +4,21 @@ using System; using System.IO; -namespace Microsoft.Extensions.SecretManager.Tools.Internal +namespace Microsoft.Extensions.Tools.Internal { public class PhysicalConsole : IConsole { - private PhysicalConsole() { } + private PhysicalConsole() + { + Console.CancelKeyPress += (o, e) => + { + CancelKeyPress?.Invoke(o, e); + }; + } public static IConsole Singleton { get; } = new PhysicalConsole(); + + public event ConsoleCancelEventHandler CancelKeyPress; public TextWriter Error => Console.Error; public TextReader In => Console.In; public TextWriter Out => Console.Out; diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index 4e28d24c2f..9956ccb244 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -15,6 +15,7 @@ "Microsoft.DotNet.InternalAbstractions": "1.0.0", "Microsoft.AspNetCore.Testing": "1.0.0", "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", + "Microsoft.DotNet.Watcher.Tools.Tests": "1.0.0-*", "Microsoft.Extensions.Process.Sources": { "type": "build", "version": "1.0.0" diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/test.sh b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/test.sh index e617f19860..e8cd20269a 100755 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/test.sh +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/test.sh @@ -1,3 +1,5 @@ +set -e + dotnet build ../../.build/dotnet/dotnet exec \ diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs index 48975a9175..aa4f94b3fa 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs @@ -7,7 +7,7 @@ using System.IO; using System.Linq; using Xunit; -namespace Microsoft.DotNetWatcher.Tools.Tests +namespace Microsoft.DotNet.Watcher.Tools.Tests { public static class AssertEx { diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs index 2957dfe17a..1deb015023 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs @@ -4,12 +4,27 @@ using System.IO; using System.Linq; using System.Text; +using Microsoft.Extensions.Tools.Internal; using Xunit; +using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.Tests { public class CommandLineOptionsTests { + private readonly IConsole _console; + private readonly StringBuilder _stdout = new StringBuilder(); + private readonly StringBuilder _stderr = new StringBuilder(); + + public CommandLineOptionsTests(ITestOutputHelper output) + { + _console = new TestConsole(output) + { + Out = new StringWriter(_stdout), + Error = new StringWriter(_stderr), + }; + } + [Theory] [InlineData(new object[] { new[] { "-h" } })] [InlineData(new object[] { new[] { "-?" } })] @@ -19,12 +34,10 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests [InlineData(new object[] { new string[0] })] public void HelpArgs(string[] args) { - var stdout = new StringBuilder(); - - var options = CommandLineOptions.Parse(args, new StringWriter(stdout), new StringWriter()); + var options = CommandLineOptions.Parse(args, _console); Assert.True(options.IsHelp); - Assert.Contains("Usage: dotnet watch ", stdout.ToString()); + Assert.Contains("Usage: dotnet watch ", _stdout.ToString()); } [Theory] @@ -34,22 +47,18 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests [InlineData(new[] { "--unrecognized-arg" }, new[] { "--unrecognized-arg" })] public void ParsesRemainingArgs(string[] args, string[] expected) { - var stdout = new StringBuilder(); - - var options = CommandLineOptions.Parse(args, new StringWriter(stdout), new StringWriter()); + var options = CommandLineOptions.Parse(args, _console); Assert.Equal(expected, options.RemainingArguments.ToArray()); Assert.False(options.IsHelp); - Assert.Empty(stdout.ToString()); + Assert.Empty(_stdout.ToString()); } [Fact] public void CannotHaveQuietAndVerbose() { - var sb = new StringBuilder(); - var stderr = new StringWriter(sb); - Assert.Null(CommandLineOptions.Parse(new[] { "--quiet", "--verbose" }, new StringWriter(), stderr)); - Assert.Contains(Resources.Error_QuietAndVerboseSpecified, sb.ToString()); + Assert.Null(CommandLineOptions.Parse(new[] { "--quiet", "--verbose" }, _console)); + Assert.Contains(Resources.Error_QuietAndVerboseSpecified, _stderr.ToString()); } } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs index d236d0078c..e196742f15 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs @@ -6,13 +6,12 @@ using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; -using Microsoft.DotNet.Watcher; using Microsoft.DotNet.Watcher.Internal; using Microsoft.Extensions.Logging; using Xunit; using Xunit.Abstractions; -namespace Microsoft.DotNetWatcher.Tools.Tests +namespace Microsoft.DotNet.Watcher.Tools.Tests { using ItemSpec = TemporaryCSharpProject.ItemSpec; diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/ProgramTests.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/ProgramTests.cs new file mode 100644 index 0000000000..e00099acfb --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/ProgramTests.cs @@ -0,0 +1,52 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.Tools.Internal; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.DotNet.Watcher.Tools.Tests +{ + public class ProgramTests : IDisposable + { + private readonly TemporaryDirectory _tempDir; + private readonly TestConsole _console; + + public ProgramTests(ITestOutputHelper output) + { + _tempDir = new TemporaryDirectory(); + _console = new TestConsole(output); + } + + [Fact] + public async Task ConsoleCancelKey() + { + _tempDir + .WithCSharpProject("testproj") + .WithTargetFrameworks("netcoreapp1.0") + .Dir() + .WithFile("Program.cs") + .Create(); + + var stdout = new StringBuilder(); + _console.Out = new StringWriter(stdout); + var program = new Program(_console, _tempDir.Root) + .RunAsync(new [] { "run" }); + + _console.ConsoleCancelKey(); + + var exitCode = await program.OrTimeout(); + + Assert.Contains("Shutdown requested. Press Ctrl+C again to force exit.", stdout.ToString()); + Assert.Equal(0, exitCode); + } + public void Dispose() + { + _tempDir.Dispose(); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TaskExtensions.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TaskExtensions.cs similarity index 90% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TaskExtensions.cs rename to test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TaskExtensions.cs index b93d843943..daaa77918e 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TaskExtensions.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TaskExtensions.cs @@ -1,11 +1,9 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.Runtime.CompilerServices; -using System.Threading.Tasks; -namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests +namespace System.Threading.Tasks { public static class TaskExtensions { diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryCSharpProject.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryCSharpProject.cs index f73ba47f5b..53ee3d38e4 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryCSharpProject.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryCSharpProject.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Text; -namespace Microsoft.DotNetWatcher.Tools.Tests +namespace Microsoft.DotNet.Watcher.Tools.Tests { public class TemporaryCSharpProject { diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryDirectory.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryDirectory.cs index 3ec8d6bbee..26f36ec5f0 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryDirectory.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryDirectory.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.IO; -namespace Microsoft.DotNetWatcher.Tools.Tests +namespace Microsoft.DotNet.Watcher.Tools.Tests { public class TemporaryDirectory : IDisposable { diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TestProjectGraph.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TestProjectGraph.cs index 730f82f0db..a8e615d3c9 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TestProjectGraph.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TestProjectGraph.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; -namespace Microsoft.DotNetWatcher.Tools.Tests +namespace Microsoft.DotNet.Watcher.Tools.Tests { public class TestProjectGraph { diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/XunitLogger.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/XunitLogger.cs index 640a4a0664..0e48fde773 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/XunitLogger.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/XunitLogger.cs @@ -5,7 +5,7 @@ using System; using Microsoft.Extensions.Logging; using Xunit.Abstractions; -namespace Microsoft.DotNetWatcher.Tools.Tests +namespace Microsoft.DotNet.Watcher.Tools.Tests { internal class XunitLogger : ILogger { diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json index b40ce98d3a..1916498359 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json @@ -2,7 +2,8 @@ "buildOptions": { "warningsAsErrors": true, "keyFile": "../../tools/Key.snk", - "debugType": "portable" + "debugType": "portable", + "compile": "../Shared/**/*.cs" }, "dependencies": { "dotnet-test-xunit": "2.2.0-preview2-build1029", diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs index 9420fc2110..fba4b6e25b 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs @@ -9,6 +9,7 @@ using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.Configuration.UserSecrets; using Microsoft.Extensions.Configuration.UserSecrets.Tests; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Tools.Internal; using Xunit; using Xunit.Abstractions; @@ -16,19 +17,20 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests { public class SecretManagerTests : IClassFixture { - private TestLogger _logger; + private readonly TestLogger _logger; + private readonly TestConsole _console; private readonly UserSecretsTestFixture _fixture; public SecretManagerTests(UserSecretsTestFixture fixture, ITestOutputHelper output) { _fixture = fixture; _logger = new TestLogger(output); - + _console = new TestConsole(output); } private Program CreateProgram() { - return new Program(new TestConsole(), Directory.GetCurrentDirectory()) + return new Program(_console, Directory.GetCurrentDirectory()) { Logger = _logger }; @@ -72,7 +74,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests var projectPath = _fixture.GetTempSecretProject(); var cwd = Path.Combine(projectPath, "nested1"); Directory.CreateDirectory(cwd); - var secretManager = new Program(new TestConsole(), cwd) { Logger = _logger, CommandOutputProvider = _logger.CommandOutputProvider }; + var secretManager = new Program(_console, cwd) { Logger = _logger, CommandOutputProvider = _logger.CommandOutputProvider }; secretManager.CommandOutputProvider.LogLevel = LogLevel.Debug; secretManager.RunInternal("list", "-p", ".." + Path.DirectorySeparatorChar, "--verbose"); @@ -97,7 +99,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests var dir = fromCurrentDirectory ? projectPath : Path.GetTempPath(); - var secretManager = new Program(new TestConsole(), dir) { Logger = _logger }; + var secretManager = new Program(_console, dir) { Logger = _logger }; foreach (var secret in secrets) { @@ -237,16 +239,13 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests public void List_Json() { var output = new StringBuilder(); - var testConsole = new TestConsole - { - Out = new StringWriter(output) - }; + _console.Out = new StringWriter(output); string id; var projectPath = _fixture.GetTempSecretProject(out id); var secretsFile = PathHelper.GetSecretsPathFromSecretsId(id); Directory.CreateDirectory(Path.GetDirectoryName(secretsFile)); File.WriteAllText(secretsFile, @"{ ""AzureAd"": { ""ClientSecret"": ""abcd郩˙î""} }", Encoding.UTF8); - var secretManager = new Program(testConsole, Path.GetDirectoryName(projectPath)) { Logger = _logger }; + var secretManager = new Program(_console, Path.GetDirectoryName(projectPath)) { Logger = _logger }; secretManager.RunInternal("list", "--id", id, "--json"); var stdout = output.ToString(); Assert.Contains("//BEGIN", stdout); @@ -297,7 +296,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests ? projectPath : Path.GetTempPath(); - var secretManager = new Program(new TestConsole(), dir) { Logger = _logger }; + var secretManager = new Program(_console, dir) { Logger = _logger }; var secrets = new KeyValuePair[] { diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs index 5420aa0ff4..90952ff5bd 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs @@ -1,17 +1,27 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.IO; using System.Collections.Generic; using Microsoft.Extensions.SecretManager.Tools.Internal; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Tools.Internal; using Xunit; -using System; +using Xunit.Abstractions; namespace Microsoft.Extensions.SecretManager.Tools.Tests { + public class SetCommandTest { + private readonly ITestOutputHelper _output; + + public SetCommandTest(ITestOutputHelper output) + { + _output = output; + } + [Fact] public void SetsFromPipedInput() { @@ -21,7 +31,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests ""Key2"": 1234, ""Key3"": false }"; - var testConsole = new TestConsole + var testConsole = new TestConsole(_output) { IsInputRedirected = true, In = new StringReader(input) @@ -48,7 +58,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests ""array"": [ 1, 2 ] }"; - var testConsole = new TestConsole + var testConsole = new TestConsole(_output) { IsInputRedirected = true, In = new StringReader(input) @@ -68,7 +78,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests [Fact] public void OnlyPipesInIfNoArgs() { - var testConsole = new TestConsole + var testConsole = new TestConsole(_output) { IsInputRedirected = true, In = new StringReader("") diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/TestConsole.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/TestConsole.cs deleted file mode 100644 index 8370ecf065..0000000000 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/TestConsole.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using Microsoft.Extensions.SecretManager.Tools.Internal; - -namespace Microsoft.Extensions.SecretManager.Tools.Tests -{ - public class TestConsole : IConsole - { - public TextWriter Error { get; set; } = Console.Error; - public TextReader In { get; set; } = Console.In; - public TextWriter Out { get; set; } = Console.Out; - public bool IsInputRedirected { get; set; } = false; - } -} diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json index b93fb60245..d2d23cb1fc 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json @@ -1,7 +1,8 @@ { "buildOptions": { "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk" + "keyFile": "../../tools/Key.snk", + "compile": "../Shared/**/*.cs" }, "dependencies": { "dotnet-test-xunit": "2.2.0-preview2-build1029", diff --git a/test/Shared/TestConsole.cs b/test/Shared/TestConsole.cs new file mode 100644 index 0000000000..415cc60499 --- /dev/null +++ b/test/Shared/TestConsole.cs @@ -0,0 +1,69 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using Xunit.Abstractions; + +namespace Microsoft.Extensions.Tools.Internal +{ + public class TestConsole : IConsole + { + public TestConsole(ITestOutputHelper output) + { + var writer = new TestOutputWriter(output); + Error = writer; + Out = writer; + } + + public event ConsoleCancelEventHandler CancelKeyPress; + + public TextWriter Error { get; set; } + public TextWriter Out { get; set; } + public TextReader In { get; set; } = new StringReader(string.Empty); + public bool IsInputRedirected { get; set; } = false; + + public ConsoleCancelEventArgs ConsoleCancelKey() + { + var ctor = typeof(ConsoleCancelEventArgs) + .GetTypeInfo() + .DeclaredConstructors + .Single(c => c.GetParameters().First().ParameterType == typeof(ConsoleSpecialKey)); + var args = (ConsoleCancelEventArgs)ctor.Invoke(new object[] { ConsoleSpecialKey.ControlC }); + CancelKeyPress?.Invoke(this, args); + return args; + } + + private class TestOutputWriter : TextWriter + { + private readonly ITestOutputHelper _output; + private readonly StringBuilder _sb = new StringBuilder(); + + public TestOutputWriter(ITestOutputHelper output) + { + _output = output; + } + + public override Encoding Encoding => Encoding.Unicode; + + public override void Write(char value) + { + if (value == '\r' || value == '\n') + { + if (_sb.Length > 0) + { + _output.WriteLine(_sb.ToString()); + _sb.Clear(); + } + } + else + { + _sb.Append(value); + } + } + } + } +} From 46136e91aba8ad468b4fd2af3f89a5bca7434172 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 21 Nov 2016 17:30:33 -0800 Subject: [PATCH 0358/1029] Resolve mysterious runtime errors caused because Microsoft.Extensions.DependencyModel v1.0.1-beta-000933 does not exist on NuGet.org --- .../Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json | 2 +- .../Microsoft.Extensions.SecretManager.Tools.Tests/project.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index 9956ccb244..6d06758745 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -12,7 +12,7 @@ "dependencies": { "dotnet-test-xunit": "2.2.0-preview2-build1029", "Microsoft.DotNet.Cli.Utils": "1.0.0-preview3-004056", - "Microsoft.DotNet.InternalAbstractions": "1.0.0", + "Microsoft.DotNet.InternalAbstractions": "1.0.500-preview2-1-003177", "Microsoft.AspNetCore.Testing": "1.0.0", "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", "Microsoft.DotNet.Watcher.Tools.Tests": "1.0.0-*", diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json index d2d23cb1fc..5cc4eeb1b1 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json @@ -6,7 +6,7 @@ }, "dependencies": { "dotnet-test-xunit": "2.2.0-preview2-build1029", - "Microsoft.DotNet.InternalAbstractions": "1.0.0", + "Microsoft.DotNet.InternalAbstractions": "1.0.500-preview2-1-003177", "Microsoft.Extensions.SecretManager.Tools": "1.0.0-*", "xunit": "2.2.0-beta3-build3402" }, From 4a64ef857c2eb4077f93ecfa78ab17445c15d9f1 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 21 Nov 2016 13:06:44 -0800 Subject: [PATCH 0359/1029] Remove dependency on Microsoft.DotNet.Cli.Utils from dotnet-user-secrets --- src/Microsoft.DotNet.Watcher.Tools/Program.cs | 14 +-- .../Internal/CommandLineOptions.cs | 7 +- .../Internal/MsBuildProjectFinder.cs | 9 +- .../Internal/ProjectIdResolver.cs | 50 ++++---- .../Internal/RemoveCommand.cs | 9 +- .../Internal/SetCommand.cs | 111 +++++++++--------- ...soft.Extensions.SecretManager.Tools.nuspec | 7 +- .../Program.cs | 29 ++--- .../project.json | 1 - src/Shared/DebugHelper.cs | 24 ++++ .../MsBuildProjectFinderTest.cs | 11 +- .../SecretManagerTests.cs | 13 +- .../SetCommandTest.cs | 12 +- .../test.sh | 10 ++ 14 files changed, 162 insertions(+), 145 deletions(-) create mode 100644 src/Shared/DebugHelper.cs create mode 100755 test/Microsoft.Extensions.SecretManager.Tools.Tests/test.sh diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index 16a7a17288..45b4721b62 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -30,7 +30,7 @@ namespace Microsoft.DotNet.Watcher public static int Main(string[] args) { - HandleDebugSwitch(ref args); + DebugHelper.HandleDebugSwitch(ref args); return new Program(PhysicalConsole.Singleton, Directory.GetCurrentDirectory()) .RunAsync(args) .GetAwaiter() @@ -141,17 +141,5 @@ namespace Microsoft.DotNet.Watcher return LogLevel.Information; } - - [Conditional("DEBUG")] - private static void HandleDebugSwitch(ref string[] args) - { - if (args.Length > 0 && string.Equals("--debug", args[0], StringComparison.OrdinalIgnoreCase)) - { - args = args.Skip(1).ToArray(); - Console.WriteLine("Waiting for debugger to attach. Press ENTER to continue"); - Console.WriteLine($"Process ID: {Process.GetCurrentProcess().Id}"); - Console.ReadLine(); - } - } } } diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs index 2284b2ed25..9a397eee59 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Reflection; -using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Tools.Internal; @@ -37,7 +36,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal var optionProject = app.Option("-p|--project ", "Path to project, default is current directory", CommandOptionType.SingleValue, inherited: true); - var optionConfig = app.Option("-c|--configuration ", $"The project configuration to use. Defaults to {Constants.DefaultConfiguration}", + var optionConfig = app.Option("-c|--configuration ", $"The project configuration to use. Defaults to 'Debug'", CommandOptionType.SingleValue, inherited: true); // the escape hatch if project evaluation fails, or if users want to alter a secret store other than the one @@ -47,8 +46,8 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal var options = new CommandLineOptions(); - app.Command("set", c => SetCommand.Configure(c, options)); - app.Command("remove", c => RemoveCommand.Configure(c, options)); + app.Command("set", c => SetCommand.Configure(c, options, console)); + app.Command("remove", c => RemoveCommand.Configure(c, options, console)); app.Command("list", c => ListCommand.Configure(c, options)); app.Command("clear", c => ClearCommand.Configure(c, options)); diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/MsBuildProjectFinder.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/MsBuildProjectFinder.cs index ed37e7ad87..a24843b04d 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/MsBuildProjectFinder.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/MsBuildProjectFinder.cs @@ -1,10 +1,9 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.IO; using System.Linq; -using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.Tools.Internal; namespace Microsoft.Extensions.SecretManager.Tools.Internal @@ -37,12 +36,12 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal if (projects.Count > 1) { - throw new GracefulException(Resources.FormatError_MultipleProjectsFound(projectPath)); + throw new FileNotFoundException(Resources.FormatError_MultipleProjectsFound(projectPath)); } if (projects.Count == 0) { - throw new GracefulException(Resources.FormatError_NoProjectsFound(projectPath)); + throw new FileNotFoundException(Resources.FormatError_NoProjectsFound(projectPath)); } return projects[0]; @@ -50,7 +49,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal if (!File.Exists(projectPath)) { - throw new GracefulException(Resources.FormatError_ProjectPath_NotFound(projectPath)); + throw new FileNotFoundException(Resources.FormatError_ProjectPath_NotFound(projectPath)); } return projectPath; diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs index 683f412c83..40d3dc52b9 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs @@ -3,11 +3,12 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; -using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Tools.Internal; namespace Microsoft.Extensions.SecretManager.Tools.Internal { @@ -24,7 +25,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal _logger = logger; } - public string Resolve(string project, string configuration = Constants.DefaultConfiguration) + public string Resolve(string project, string configuration = "Debug") { var finder = new MsBuildProjectFinder(_workingDirectory); var projectFile = finder.FindMsBuildProject(project); @@ -35,32 +36,37 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal var outputFile = Path.GetTempFileName(); _tempFiles.Add(outputFile); - var commandOutput = new List(); - var commandResult = Command.CreateDotNet("msbuild", - new[] { - targetFile, - "/nologo", - "/t:_FindUserSecretsProperty", - $"/p:Project={projectFile}", - $"/p:OutputFile={outputFile}", - $"/p:Configuration={configuration}" - }) - .CaptureStdErr() - .CaptureStdOut() - .OnErrorLine(l => commandOutput.Add(l)) - .OnOutputLine(l => commandOutput.Add(l)) - .Execute(); - - if (commandResult.ExitCode != 0) + var args = new[] { - _logger.LogDebug(string.Join(Environment.NewLine, commandOutput)); - throw new GracefulException(Resources.FormatError_ProjectFailedToLoad(projectFile)); + "msbuild", + targetFile, + "/nologo", + "/t:_FindUserSecretsProperty", + $"/p:Project={projectFile}", + $"/p:OutputFile={outputFile}", + $"/p:Configuration={configuration}" + }; + var psi = new ProcessStartInfo + { + FileName = DotNetMuxer.MuxerPathOrDefault(), + Arguments = ArgumentEscaper.EscapeAndConcatenate(args), + RedirectStandardOutput = true, + RedirectStandardError = true + }; + var process = Process.Start(psi); + process.WaitForExit(); + + if (process.ExitCode != 0) + { + _logger.LogDebug(process.StandardOutput.ReadToEnd()); + _logger.LogDebug(process.StandardError.ReadToEnd()); + throw new InvalidOperationException(Resources.FormatError_ProjectFailedToLoad(projectFile)); } var id = File.ReadAllText(outputFile)?.Trim(); if (string.IsNullOrEmpty(id)) { - throw new GracefulException(Resources.FormatError_ProjectMissingId(projectFile)); + throw new InvalidOperationException(Resources.FormatError_ProjectMissingId(projectFile)); } return id; diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs index 6e6e5af027..d896c31a87 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs @@ -1,9 +1,10 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Microsoft.DotNet.Cli.Utils; +using System; using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Tools.Internal; namespace Microsoft.Extensions.SecretManager.Tools.Internal { @@ -11,7 +12,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal { private readonly string _keyName; - public static void Configure(CommandLineApplication command, CommandLineOptions options) + public static void Configure(CommandLineApplication command, CommandLineOptions options, IConsole console) { command.Description = "Removes the specified user secret"; command.HelpOption(); @@ -21,10 +22,12 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal { if (keyArg.Value == null) { - throw new GracefulException("Missing parameter value for 'name'.\nUse the '--help' flag to see info."); + console.Error.WriteLine(Resources.FormatError_MissingArgument("name").Red()); + return 1; } options.Command = new RemoveCommand(keyArg.Value); + return 0; }); } diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs index e8c3855961..013777210e 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs @@ -1,21 +1,18 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System.Diagnostics; +using System; using System.IO; using System.Text; -using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Tools.Internal; namespace Microsoft.Extensions.SecretManager.Tools.Internal { - public class SetCommand : ICommand + public class SetCommand { - private readonly string _keyName; - private readonly string _keyValue; - - public static void Configure(CommandLineApplication command, CommandLineOptions options) + public static void Configure(CommandLineApplication command, CommandLineOptions options, IConsole console) { command.Description = "Sets the user secret to the specified value"; command.ExtendedHelpText = @" @@ -34,72 +31,74 @@ Examples: command.OnExecute(() => { - options.Command = new SetCommand(nameArg.Value, valueArg.Value); + if (console.IsInputRedirected && nameArg.Value == null) + { + options.Command = new FromStdInStrategy(); + return 0; + } + + if (string.IsNullOrEmpty(nameArg.Value)) + { + console.Error.WriteLine(Resources.FormatError_MissingArgument("name").Red()); + return 1; + } + + if (valueArg.Value == null) + { + console.Error.WriteLine(Resources.FormatError_MissingArgument("value").Red()); + return 1; + } + + options.Command = new ForOneValueStrategy(nameArg.Value, valueArg.Value); + return 0; }); } - internal SetCommand(string keyName, string keyValue) + public class FromStdInStrategy : ICommand { - Debug.Assert(keyName != null || keyValue == null, "Inconsistent state. keyValue must not be null if keyName is null."); - _keyName = keyName; - _keyValue = keyValue; - } - - internal SetCommand() - { } - - public void Execute(CommandContext context) - { - if (context.Console.IsInputRedirected && _keyName == null) + public void Execute(CommandContext context) { - ReadFromInput(context); - } - else - { - SetFromArguments(context); - } - } - - private void ReadFromInput(CommandContext context) - { - // parses stdin with the same parser that Microsoft.Extensions.Configuration.Json would use - var provider = new ReadableJsonConfigurationProvider(); - using (var stream = new MemoryStream()) - { - using (var writer = new StreamWriter(stream, Encoding.Unicode, 1024, true)) + // parses stdin with the same parser that Microsoft.Extensions.Configuration.Json would use + var provider = new ReadableJsonConfigurationProvider(); + using (var stream = new MemoryStream()) { - writer.Write(context.Console.In.ReadToEnd()); // TODO buffer? + using (var writer = new StreamWriter(stream, Encoding.Unicode, 1024, true)) + { + writer.Write(context.Console.In.ReadToEnd()); // TODO buffer? + } + + stream.Seek(0, SeekOrigin.Begin); + provider.Load(stream); } - stream.Seek(0, SeekOrigin.Begin); - provider.Load(stream); + foreach (var k in provider.CurrentData) + { + context.SecretStore.Set(k.Key, k.Value); + } + + context.Logger.LogInformation(Resources.Message_Saved_Secrets, provider.CurrentData.Count); + + context.SecretStore.Save(); } - - foreach (var k in provider.CurrentData) - { - context.SecretStore.Set(k.Key, k.Value); - } - - context.Logger.LogInformation(Resources.Message_Saved_Secrets, provider.CurrentData.Count); - - context.SecretStore.Save(); } - private void SetFromArguments(CommandContext context) + public class ForOneValueStrategy : ICommand { - if (_keyName == null) + private readonly string _keyName; + private readonly string _keyValue; + + public ForOneValueStrategy(string keyName, string keyValue) { - throw new GracefulException(Resources.FormatError_MissingArgument("name")); + _keyName = keyName; + _keyValue = keyValue; } - if (_keyValue == null) + public void Execute(CommandContext context) { - throw new GracefulException((Resources.FormatError_MissingArgument("value"))); + context.SecretStore.Set(_keyName, _keyValue); + context.SecretStore.Save(); + context.Logger.LogInformation(Resources.Message_Saved_Secret, _keyName, _keyValue); } - - context.SecretStore.Set(_keyName, _keyValue); - context.SecretStore.Save(); - context.Logger.LogInformation(Resources.Message_Saved_Secret, _keyName, _keyValue); } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec index f8c596e5e9..c9f2903331 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec @@ -16,10 +16,9 @@ - - - - + + + diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs index 810c0a043d..656b0d9c05 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs @@ -3,7 +3,6 @@ using System; using System.IO; -using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.Logging; using Microsoft.Extensions.SecretManager.Tools.Internal; using Microsoft.Extensions.Tools.Internal; @@ -58,20 +57,8 @@ namespace Microsoft.Extensions.SecretManager.Tools } catch (Exception exception) { - if (exception is GracefulException) - { - if (exception.InnerException != null) - { - Logger.LogInformation(exception.InnerException.Message); - } - - Logger.LogError(exception.Message); - } - else - { - Logger.LogDebug(exception.ToString()); - Logger.LogCritical(Resources.Error_Command_Failed, exception.Message); - } + Logger.LogDebug(exception.ToString()); + Logger.LogCritical(Resources.Error_Command_Failed, exception.Message); returnCode = 1; return false; } @@ -96,7 +83,17 @@ namespace Microsoft.Extensions.SecretManager.Tools CommandOutputProvider.LogLevel = LogLevel.Debug; } - var userSecretsId = ResolveId(options); + string userSecretsId; + try + { + userSecretsId = ResolveId(options); + } + catch (Exception ex) when (ex is InvalidOperationException || ex is FileNotFoundException) + { + _logger.LogError(ex.Message); + return 1; + } + var store = new SecretsStore(userSecretsId, Logger); var context = new Internal.CommandContext(store, Logger, _console); options.Command.Execute(context); diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index 2c2e801dd2..f4731bc33d 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -38,7 +38,6 @@ ] }, "dependencies": { - "Microsoft.DotNet.Cli.Utils": "1.0.0-preview3-004056", "Microsoft.Extensions.Configuration.UserSecrets": "1.0.0", "Microsoft.Extensions.Logging": "1.0.0", "Microsoft.NETCore.App": { diff --git a/src/Shared/DebugHelper.cs b/src/Shared/DebugHelper.cs new file mode 100644 index 0000000000..bb7f966d65 --- /dev/null +++ b/src/Shared/DebugHelper.cs @@ -0,0 +1,24 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.Linq; + +namespace Microsoft.Extensions.Tools.Internal +{ + public static class DebugHelper + { + [Conditional("DEBUG")] + public static void HandleDebugSwitch(ref string[] args) + { + if (args.Length > 0 && string.Equals("--debug", args[0], StringComparison.OrdinalIgnoreCase)) + { + args = args.Skip(1).ToArray(); + Console.WriteLine("Waiting for debugger to attach. Press ENTER to continue"); + Console.WriteLine($"Process ID: {Process.GetCurrentProcess().Id}"); + Console.ReadLine(); + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/MsBuildProjectFinderTest.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/MsBuildProjectFinderTest.cs index fad1808677..ec79f8ef4a 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/MsBuildProjectFinderTest.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/MsBuildProjectFinderTest.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.IO; -using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.SecretManager.Tools.Internal; using Xunit; @@ -34,7 +33,7 @@ namespace Microsoft.Extensions.SecretsManager.Tools.Tests { var finder = new MsBuildProjectFinder(files.Root); - Assert.Throws(() => finder.FindMsBuildProject(null)); + Assert.Throws(() => finder.FindMsBuildProject(null)); } } @@ -46,7 +45,7 @@ namespace Microsoft.Extensions.SecretsManager.Tools.Tests var finder = new MsBuildProjectFinder(files.Root); files.Add("test.xproj", ""); - Assert.Throws(() => finder.FindMsBuildProject(null)); + Assert.Throws(() => finder.FindMsBuildProject(null)); } } @@ -59,7 +58,7 @@ namespace Microsoft.Extensions.SecretsManager.Tools.Tests files.Add("Test2.csproj", ""); var finder = new MsBuildProjectFinder(files.Root); - Assert.Throws(() => finder.FindMsBuildProject(null)); + Assert.Throws(() => finder.FindMsBuildProject(null)); } } @@ -70,7 +69,7 @@ namespace Microsoft.Extensions.SecretsManager.Tools.Tests { var finder = new MsBuildProjectFinder(files.Root); - Assert.Throws(() => finder.FindMsBuildProject("test.csproj")); + Assert.Throws(() => finder.FindMsBuildProject("test.csproj")); } } @@ -80,7 +79,7 @@ namespace Microsoft.Extensions.SecretsManager.Tools.Tests var files = new TemporaryFileProvider(); var finder = new MsBuildProjectFinder(files.Root); files.Dispose(); - Assert.Throws(() => finder.FindMsBuildProject(null)); + Assert.Throws(() => finder.FindMsBuildProject(null)); } } } diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs index fba4b6e25b..d003c12234 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.IO; using System.Text; -using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.Configuration.UserSecrets; using Microsoft.Extensions.Configuration.UserSecrets.Tests; using Microsoft.Extensions.Logging; @@ -44,8 +43,8 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests var project = Path.Combine(_fixture.CreateProject(id), "TestProject.csproj"); var secretManager = CreateProgram(); - var ex = Assert.Throws(() => secretManager.RunInternal("list", "-p", project)); - Assert.Equal(Resources.FormatError_ProjectMissingId(project), ex.Message); + secretManager.RunInternal("list", "-p", project); + Assert.Contains(Resources.FormatError_ProjectMissingId(project), _logger.Messages); } [Fact] @@ -54,8 +53,8 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests var project = Path.Combine(_fixture.CreateProject("<"), "TestProject.csproj"); var secretManager = CreateProgram(); - var ex = Assert.Throws(() => secretManager.RunInternal("list", "-p", project)); - Assert.Equal(Resources.FormatError_ProjectFailedToLoad(project), ex.Message); + secretManager.RunInternal("list", "-p", project); + Assert.Contains(Resources.FormatError_ProjectFailedToLoad(project), _logger.Messages); } [Fact] @@ -64,8 +63,8 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests var projectPath = Path.Combine(_fixture.GetTempSecretProject(), "does_not_exist", "TestProject.csproj"); var secretManager = CreateProgram(); - var ex = Assert.Throws(() => secretManager.RunInternal("list", "--project", projectPath)); - Assert.Equal(Resources.FormatError_ProjectPath_NotFound(projectPath), ex.Message); + secretManager.RunInternal("list", "--project", projectPath); + Assert.Contains(Resources.FormatError_ProjectPath_NotFound(projectPath), _logger.Messages); } [Fact] diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs index 90952ff5bd..4a3a94c716 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs @@ -37,7 +37,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests In = new StringReader(input) }; var secretStore = new TestSecretsStore(); - var command = new SetCommand(); + var command = new SetCommand.FromStdInStrategy(); command.Execute(new CommandContext(secretStore, NullLogger.Instance, testConsole)); @@ -64,7 +64,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests In = new StringReader(input) }; var secretStore = new TestSecretsStore(); - var command = new SetCommand(); + var command = new SetCommand.FromStdInStrategy(); command.Execute(new CommandContext(secretStore, NullLogger.Instance, testConsole)); @@ -83,12 +83,8 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests IsInputRedirected = true, In = new StringReader("") }; - var secretStore = new TestSecretsStore(); - var command = new SetCommand("key", null); - - var ex = Assert.Throws( - () => command.Execute(new CommandContext(secretStore, NullLogger.Instance, testConsole))); - Assert.Equal(Resources.FormatError_MissingArgument("value"), ex.Message); + var options = CommandLineOptions.Parse(new [] { "set", "key", "value" }, testConsole); + Assert.IsType(options.Command); } private class TestSecretsStore : SecretsStore diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/test.sh b/test/Microsoft.Extensions.SecretManager.Tools.Tests/test.sh new file mode 100755 index 0000000000..31eb5fd320 --- /dev/null +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/test.sh @@ -0,0 +1,10 @@ +set -e + +~/.dotnet/dotnet build + +../../.build/dotnet/dotnet exec \ +--depsfile bin/Debug/netcoreapp1.0/Microsoft.Extensions.SecretManager.Tools.Tests.deps.json \ +--runtimeconfig bin/Debug/netcoreapp1.0/Microsoft.Extensions.SecretManager.Tools.Tests.runtimeconfig.json \ +../../.build/dotnet-test-xunit/2.2.0-preview2-build1029/lib/netcoreapp1.0/dotnet-test-xunit.dll \ +bin/Debug/netcoreapp1.0/Microsoft.Extensions.SecretManager.Tools.Tests.dll \ +$@ \ No newline at end of file From e0f85971a32c21f4246b41ffabfca60e039b13f4 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 21 Nov 2016 11:59:40 -0800 Subject: [PATCH 0360/1029] Add --version options to dotnet-watch and dotnet-sql-cache --- .../CommandLineOptions.cs | 2 ++ .../Program.cs | 12 ++++--- .../project.json | 3 +- .../{Internal => }/CommandLineOptions.cs | 27 +++++--------- .../CommandLineApplicationExtensions.cs | 24 ------------- .../CommandLineApplicationExtensions.cs | 35 +++++++++++++++++++ 6 files changed, 55 insertions(+), 48 deletions(-) rename src/Microsoft.Extensions.SecretManager.Tools/{Internal => }/CommandLineOptions.cs (76%) delete mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineApplicationExtensions.cs create mode 100644 src/Shared/CommandLineApplicationExtensions.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs index aea719428d..0b09620e00 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Reflection; using Microsoft.DotNet.Watcher.Tools; using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Tools.Internal; @@ -61,6 +62,7 @@ Examples: CommandOptionType.NoValue); var optVerbose = app.Option("-v|--verbose", "Show verbose output", CommandOptionType.NoValue); + app.VersionOptionFromAssemblyAttributes(typeof(Program).GetTypeInfo().Assembly); app.OnExecute(() => { diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs index eb46dcb0a8..c0294c3c41 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs @@ -4,6 +4,7 @@ using System; using System.Data; using System.Data.SqlClient; +using System.Reflection; using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Logging; @@ -36,11 +37,14 @@ namespace Microsoft.Extensions.Caching.SqlConfig.Tools var description = "Creates table and indexes in Microsoft SQL Server database " + "to be used for distributed caching"; - var app = new CommandLineApplication(); - app.Name = "dotnet-sql-cache"; - app.Description = description; - + var app = new CommandLineApplication + { + Name = "dotnet sql-cache", + FullName = "SQL Server Cache Command Line Tool", + Description = description, + }; app.HelpOption("-?|-h|--help"); + app.VersionOptionFromAssemblyAttributes(typeof(Program).GetTypeInfo().Assembly); app.Command("create", command => { diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json index 3ff33ed3bd..546d267e97 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json @@ -4,7 +4,8 @@ "outputName": "dotnet-sql-cache", "emitEntryPoint": true, "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk" + "keyFile": "../../tools/Key.snk", + "compile": "../Shared/CommandLineApplicationExtensions.cs" }, "description": "Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching.", "packOptions": { diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs b/src/Microsoft.Extensions.SecretManager.Tools/CommandLineOptions.cs similarity index 76% rename from src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs rename to src/Microsoft.Extensions.SecretManager.Tools/CommandLineOptions.cs index 9a397eee59..d8e4979838 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineOptions.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/CommandLineOptions.cs @@ -3,18 +3,19 @@ using System.Reflection; using Microsoft.Extensions.CommandLineUtils; +using Microsoft.Extensions.SecretManager.Tools.Internal; using Microsoft.Extensions.Tools.Internal; -namespace Microsoft.Extensions.SecretManager.Tools.Internal +namespace Microsoft.Extensions.SecretManager.Tools { public class CommandLineOptions { - public string Id { get; set; } - public bool IsVerbose { get; set; } - public bool IsHelp { get; set; } - public string Project { get; set; } public ICommand Command { get; set; } - public string Configuration { get; set; } + public string Configuration { get; private set; } + public string Id { get; private set; } + public bool IsHelp { get; private set; } + public bool IsVerbose { get; private set; } + public string Project { get; private set; } public static CommandLineOptions Parse(string[] args, IConsole console) { @@ -28,7 +29,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal }; app.HelpOption(); - app.VersionOption("--version", GetInformationalVersion()); + app.VersionOptionFromAssemblyAttributes(typeof(Program).GetTypeInfo().Assembly); var optionVerbose = app.Option("-v|--verbose", "Verbose output", CommandOptionType.NoValue, inherited: true); @@ -68,17 +69,5 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal return options; } - - private static string GetInformationalVersion() - { - var assembly = typeof(Program).GetTypeInfo().Assembly; - var attribute = assembly.GetCustomAttribute(); - - var versionAttribute = attribute == null ? - assembly.GetName().Version.ToString() : - attribute.InformationalVersion; - - return versionAttribute; - } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineApplicationExtensions.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineApplicationExtensions.cs deleted file mode 100644 index 386a5ddf30..0000000000 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandLineApplicationExtensions.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; - -namespace Microsoft.Extensions.CommandLineUtils -{ - public static class UserSecretsCommandLineExtensions - { - public static CommandOption HelpOption(this CommandLineApplication app) - { - return app.HelpOption("-?|-h|--help"); - } - - public static void OnExecute(this CommandLineApplication app, Action action) - { - app.OnExecute(() => - { - action(); - return 0; - }); - } - } -} \ No newline at end of file diff --git a/src/Shared/CommandLineApplicationExtensions.cs b/src/Shared/CommandLineApplicationExtensions.cs new file mode 100644 index 0000000000..0a7e16a5bf --- /dev/null +++ b/src/Shared/CommandLineApplicationExtensions.cs @@ -0,0 +1,35 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Reflection; + +namespace Microsoft.Extensions.CommandLineUtils +{ + public static class CommandLineApplicationExtensions + { + public static CommandOption HelpOption(this CommandLineApplication app) + => app.HelpOption("-?|-h|--help"); + + public static void OnExecute(this CommandLineApplication app, Action action) + => app.OnExecute(() => + { + action(); + return 0; + }); + + public static void VersionOptionFromAssemblyAttributes(this CommandLineApplication app, Assembly assembly) + => app.VersionOption("--version", GetInformationalVersion(assembly)); + + private static string GetInformationalVersion(Assembly assembly) + { + var attribute = assembly.GetCustomAttribute(); + + var versionAttribute = attribute == null + ? assembly.GetName().Version.ToString() + : attribute.InformationalVersion; + + return versionAttribute; + } + } +} \ No newline at end of file From 4dea3e7512a5ebf0d502c4a01ec0a69650af8270 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Wed, 23 Nov 2016 15:57:04 -0800 Subject: [PATCH 0361/1029] Pin global.json SDK to 1.0.0-preview2-1-003177. --- global.json | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/global.json b/global.json index fad3dfeab0..e04bdfc390 100644 --- a/global.json +++ b/global.json @@ -1,3 +1,10 @@ { - "projects": ["src", "test/WebSites", "samples"] -} + "projects": [ + "src", + "test/WebSites", + "samples" + ], + "sdk": { + "version": "1.0.0-preview2-1-003177" + } +} \ No newline at end of file From e5c4e96705ed93aa923896c085d034f843f1baf4 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Wed, 23 Nov 2016 15:57:49 -0800 Subject: [PATCH 0362/1029] Pin global.json SDK to 1.0.0-preview2-1-003177. --- global.json | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/global.json b/global.json index 1920b5a762..67e54ff84b 100644 --- a/global.json +++ b/global.json @@ -1,3 +1,9 @@ { - "projects": [ "src", "test"] -} + "projects": [ + "src", + "test" + ], + "sdk": { + "version": "1.0.0-preview2-1-003177" + } +} \ No newline at end of file From fe4527d54399bb98c43e0f75633b6d4ea3d812ab Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Wed, 23 Nov 2016 15:57:55 -0800 Subject: [PATCH 0363/1029] Pin global.json SDK to 1.0.0-preview2-1-003177. --- global.json | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/global.json b/global.json index 983ba0401e..f45e8cc925 100644 --- a/global.json +++ b/global.json @@ -1,3 +1,8 @@ { - "projects": ["src"] -} + "projects": [ + "src" + ], + "sdk": { + "version": "1.0.0-preview2-1-003177" + } +} \ No newline at end of file From f63006dc1a48a3db939f356204a4d6e50eb7e590 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 28 Nov 2016 16:39:14 -0800 Subject: [PATCH 0364/1029] Pack with NuGet 3.5.0 RTM --- tools/NuGetPackager/PackCommand.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/NuGetPackager/PackCommand.cs b/tools/NuGetPackager/PackCommand.cs index 687d0e0d64..264fb4af11 100644 --- a/tools/NuGetPackager/PackCommand.cs +++ b/tools/NuGetPackager/PackCommand.cs @@ -36,7 +36,7 @@ namespace NuGetPackager props += $";dep_{++idx}={depVersion}"; } - var buildCommand = Command.CreateDotNet("build", + var buildCommand = Command.CreateDotNet("build", new[] { project.ProjectFile.ProjectFilePath, "--configuration", config }, configuration: config); @@ -129,15 +129,15 @@ namespace NuGetPackager return Environment.GetEnvironmentVariable("KOREBUILD_NUGET_EXE"); } - var nugetPath = Path.Combine(_baseDir, ".build", "nuget.3.5.0-rc1.exe"); + var nugetPath = Path.Combine(_baseDir, ".build", "nuget.3.5.0.exe"); if (File.Exists(nugetPath)) { return nugetPath; } - Console.WriteLine("log : Downloading nuget.exe 3.5.0-rc1".Bold().Black()); - - var response = await new HttpClient().GetAsync("https://dist.nuget.org/win-x86-commandline/v3.5.0-rc1/NuGet.exe"); + Console.WriteLine("log : Downloading nuget.exe 3.5.0".Bold().Black()); + + var response = await new HttpClient().GetAsync("https://dist.nuget.org/win-x86-commandline/v3.5.0/NuGet.exe"); using (var file = new FileStream(nugetPath, FileMode.CreateNew)) { response.EnsureSuccessStatusCode(); From 17da5242e0d6564570cec13cb0aed4250403cff7 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 23 Nov 2016 12:15:23 -0800 Subject: [PATCH 0365/1029] Create console reporter API The reporter API breaks down complex formatter in to composable compontents. Adds 'ReporterBuilder' and 'FormatterBuilder' as syntax sugar for creating reporters with complex formatting rules Changes in dotnet-watch - Remove dependency on Microsoft.Extensions.Logging and instead use IReporter for console output - Only use color output when stdout and stderr are not being redirected - Make the default output less noisy Changes in dotnet-user-secrets - Remove dependency on Microsoft.Extensions.Logging to use IReporter Changes in dotnet-sql-cache - Remove dependency on Microsoft.Extensions.Logging to use IReporter - Add --verbose option --- DotNetTools.sln | 9 +- .../CommandLineOptions.cs | 27 ++- .../CommandOutputLogger.cs | 64 ------- .../CommandOutputProvider.cs | 29 --- .../DotNetWatcher.cs | 40 +++-- .../Internal/FileSet.cs | 2 + .../Internal/MsBuildFileSetFactory.cs | 67 ++++--- .../Internal/ProcessRunner.cs | 34 ++-- .../Microsoft.DotNet.Watcher.Tools.nuspec | 4 +- src/Microsoft.DotNet.Watcher.Tools/Program.cs | 170 +++++++++++------- .../project.json | 2 - ....Extensions.Caching.SqlConfig.Tools.nuspec | 7 +- .../Program.cs | 101 +++++++---- .../project.json | 6 +- .../CommandLineOptions.cs | 5 +- .../CommandOutputLogger.cs | 62 ------- .../CommandOutputProvider.cs | 23 --- .../Internal/CommandContext.cs | 7 +- .../Internal/ListCommand.cs | 12 +- .../Internal/ProjectIdResolver.cs | 25 ++- .../Internal/RemoveCommand.cs | 10 +- .../Internal/SecretsStore.cs | 5 +- .../Internal/SetCommand.cs | 30 ++-- ...soft.Extensions.SecretManager.Tools.nuspec | 3 +- .../Program.cs | 83 +++++---- .../project.json | 1 - src/Shared/CliContext.cs | 21 +++ .../CommandLineApplicationExtensions.cs | 3 + src/Shared/IConsole.cs | 2 + src/Shared/PhysicalConsole.cs | 2 + src/Shared/Reporting/ColorFormatter.cs | 57 ++++++ src/Shared/Reporting/CompositeFormatter.cs | 26 +++ src/Shared/Reporting/ConditionalFormatter.cs | 24 +++ src/Shared/Reporting/DefaultFormatter.cs | 14 ++ src/Shared/Reporting/FormatterBuilder.cs | 46 +++++ src/Shared/Reporting/FormattingReporter.cs | 62 +++++++ src/Shared/Reporting/IFormatter.cs | 10 ++ src/Shared/Reporting/IReporter.cs | 13 ++ src/Shared/Reporting/PrefixFormatter.cs | 20 +++ src/Shared/Reporting/ReporterBuilder.cs | 65 +++++++ src/Shared/StringExtensions.cs | 35 ---- .../CommandLineOptionsTests.cs | 7 +- .../MsBuildFileSetFactoryTest.cs | 12 +- .../Utilities/XunitLogger.cs | 35 ---- .../SecretManagerTests.cs | 116 +++++------- .../SetCommandTest.cs | 35 +--- .../TestLogger.cs | 50 ------ .../ArgumentEscaperTests.cs | 2 +- .../Microsoft.Extensions.Tools.Tests.xproj | 22 +++ .../ReporterTests.cs | 103 +++++++++++ .../project.json | 23 +++ test/Shared/TestConsole.cs | 2 + test/Shared/TestReporter.cs | 37 ++++ 53 files changed, 978 insertions(+), 694 deletions(-) delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/CommandOutputLogger.cs delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs delete mode 100644 src/Microsoft.Extensions.SecretManager.Tools/CommandOutputLogger.cs delete mode 100644 src/Microsoft.Extensions.SecretManager.Tools/CommandOutputProvider.cs create mode 100644 src/Shared/CliContext.cs create mode 100644 src/Shared/Reporting/ColorFormatter.cs create mode 100644 src/Shared/Reporting/CompositeFormatter.cs create mode 100644 src/Shared/Reporting/ConditionalFormatter.cs create mode 100644 src/Shared/Reporting/DefaultFormatter.cs create mode 100644 src/Shared/Reporting/FormatterBuilder.cs create mode 100644 src/Shared/Reporting/FormattingReporter.cs create mode 100644 src/Shared/Reporting/IFormatter.cs create mode 100644 src/Shared/Reporting/IReporter.cs create mode 100644 src/Shared/Reporting/PrefixFormatter.cs create mode 100644 src/Shared/Reporting/ReporterBuilder.cs delete mode 100644 src/Shared/StringExtensions.cs delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/XunitLogger.cs delete mode 100644 test/Microsoft.Extensions.SecretManager.Tools.Tests/TestLogger.cs rename test/{Microsoft.DotNet.Watcher.Tools.Tests => Microsoft.Extensions.Tools.Tests}/ArgumentEscaperTests.cs (95%) create mode 100644 test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.xproj create mode 100644 test/Microsoft.Extensions.Tools.Tests/ReporterTests.cs create mode 100644 test/Microsoft.Extensions.Tools.Tests/project.json create mode 100644 test/Shared/TestReporter.cs diff --git a/DotNetTools.sln b/DotNetTools.sln index 77ef49227e..28d6ae6a63 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -1,4 +1,4 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 +Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 @@ -28,6 +28,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{59E02BDF EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NuGetPackager", "tools\NuGetPackager\NuGetPackager.xproj", "{8B781D87-1FC3-4A34-9089-2BDF6B562B85}" EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.Tools.Tests", "test\Microsoft.Extensions.Tools.Tests\Microsoft.Extensions.Tools.Tests.xproj", "{A24BF1D1-4326-4455-A528-09F1E20EDC83}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -62,6 +64,10 @@ Global {8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Debug|Any CPU.Build.0 = Debug|Any CPU {8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Release|Any CPU.ActiveCfg = Release|Any CPU {8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Release|Any CPU.Build.0 = Release|Any CPU + {A24BF1D1-4326-4455-A528-09F1E20EDC83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A24BF1D1-4326-4455-A528-09F1E20EDC83}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A24BF1D1-4326-4455-A528-09F1E20EDC83}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A24BF1D1-4326-4455-A528-09F1E20EDC83}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -74,5 +80,6 @@ Global {8A2E6961-6B12-4A8E-8215-3E7301D52EAC} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {53F3B53D-303A-4DAA-9C38-4F55195FA5B9} = {66517987-2A5A-4330-B130-207039378FD4} {8B781D87-1FC3-4A34-9089-2BDF6B562B85} = {59E02BDF-98DE-4D64-B576-2D0299D5E052} + {A24BF1D1-4326-4455-A528-09F1E20EDC83} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} EndGlobalSection EndGlobal diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs index 0b09620e00..c602659f11 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.Collections.Generic; using System.Reflection; using Microsoft.DotNet.Watcher.Tools; @@ -17,9 +16,11 @@ namespace Microsoft.DotNet.Watcher public bool IsQuiet { get; private set; } public bool IsVerbose { get; private set; } public IList RemainingArguments { get; private set; } + public static CommandLineOptions Parse(string[] args, IConsole console) { Ensure.NotNull(args, nameof(args)); + Ensure.NotNull(console, nameof(console)); var app = new CommandLineApplication(throwOnUnexpectedArg: false) { @@ -60,20 +61,10 @@ Examples: CommandOptionType.SingleValue); // TODO multiple shouldn't be too hard to support var optQuiet = app.Option("-q|--quiet", "Suppresses all output except warnings and errors", CommandOptionType.NoValue); - var optVerbose = app.Option("-v|--verbose", "Show verbose output", - CommandOptionType.NoValue); + var optVerbose = app.VerboseOption(); + app.VersionOptionFromAssemblyAttributes(typeof(Program).GetTypeInfo().Assembly); - app.OnExecute(() => - { - if (app.RemainingArguments.Count == 0) - { - app.ShowHelp(); - } - - return 0; - }); - if (app.Execute(args) != 0) { return null; @@ -81,8 +72,12 @@ Examples: if (optQuiet.HasValue() && optVerbose.HasValue()) { - console.Error.WriteLine(Resources.Error_QuietAndVerboseSpecified.Bold().Red()); - return null; + throw new CommandParsingException(app, Resources.Error_QuietAndVerboseSpecified); + } + + if (app.RemainingArguments.Count == 0) + { + app.ShowHelp(); } return new CommandLineOptions @@ -95,4 +90,4 @@ Examples: }; } } -} +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandOutputLogger.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandOutputLogger.cs deleted file mode 100644 index 43b2da4507..0000000000 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandOutputLogger.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.Extensions.CommandLineUtils; -using Microsoft.Extensions.Logging; - -namespace Microsoft.DotNet.Watcher -{ - /// - /// Logger to print formatted command output. - /// - public class CommandOutputLogger : ILogger - { - private readonly CommandOutputProvider _provider; - private readonly AnsiConsole _outConsole; - private readonly string _loggerName; - - public CommandOutputLogger(CommandOutputProvider commandOutputProvider, string loggerName, bool useConsoleColor) - { - _provider = commandOutputProvider; - _outConsole = AnsiConsole.GetOutput(useConsoleColor); - _loggerName = loggerName; - } - - public IDisposable BeginScope(TState state) - { - throw new NotImplementedException(); - } - - public bool IsEnabled(LogLevel logLevel) - { - if (logLevel < _provider.LogLevel) - { - return false; - } - - return true; - } - - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) - { - if (IsEnabled(logLevel)) - { - _outConsole.WriteLine($"[{_loggerName}] {Caption(logLevel)}: {formatter(state, exception)}"); - } - } - - private string Caption(LogLevel logLevel) - { - switch (logLevel) - { - case LogLevel.Trace: return "\x1b[35mtrce\x1b[39m"; - case LogLevel.Debug: return "\x1b[35mdbug\x1b[39m"; - case LogLevel.Information: return "\x1b[32minfo\x1b[39m"; - case LogLevel.Warning: return "\x1b[33mwarn\x1b[39m"; - case LogLevel.Error: return "\x1b[31mfail\x1b[39m"; - case LogLevel.Critical: return "\x1b[31mcrit\x1b[39m"; - } - - throw new Exception("Unknown LogLevel"); - } - } -} diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs deleted file mode 100644 index 7d9c2fd808..0000000000 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandOutputProvider.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Runtime.InteropServices; -using Microsoft.Extensions.Logging; - -namespace Microsoft.DotNet.Watcher -{ - public class CommandOutputProvider : ILoggerProvider - { - private readonly bool _isWindows; - - public CommandOutputProvider() - { - _isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - } - - public ILogger CreateLogger(string name) - { - return new CommandOutputLogger(this, name, useConsoleColor: _isWindows); - } - - public void Dispose() - { - } - - public LogLevel LogLevel { get; set; } = LogLevel.Information; - } -} diff --git a/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs index 5ee3d8d945..e326d83ae2 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs @@ -1,33 +1,35 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Threading; using System.Threading.Tasks; using Microsoft.DotNet.Watcher.Internal; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Tools.Internal; namespace Microsoft.DotNet.Watcher { public class DotNetWatcher { - private readonly ILogger _logger; + private readonly IReporter _reporter; private readonly ProcessRunner _processRunner; - public DotNetWatcher(ILogger logger) + public DotNetWatcher(IReporter reporter) { - Ensure.NotNull(logger, nameof(logger)); + Ensure.NotNull(reporter, nameof(reporter)); - _logger = logger; - _processRunner = new ProcessRunner(logger); + _reporter = reporter; + _processRunner = new ProcessRunner(reporter); } - public async Task WatchAsync(ProcessSpec processSpec, IFileSetFactory fileSetFactory, CancellationToken cancellationToken) + public async Task WatchAsync(ProcessSpec processSpec, IFileSetFactory fileSetFactory, + CancellationToken cancellationToken) { Ensure.NotNull(processSpec, nameof(processSpec)); var cancelledTaskSource = new TaskCompletionSource(); - cancellationToken.Register(state => ((TaskCompletionSource)state).TrySetResult(null), cancelledTaskSource); + cancellationToken.Register(state => ((TaskCompletionSource) state).TrySetResult(null), + cancelledTaskSource); while (true) { @@ -46,9 +48,10 @@ namespace Microsoft.DotNet.Watcher var fileSetTask = fileSetWatcher.GetChangedFileAsync(combinedCancellationSource.Token); var processTask = _processRunner.RunAsync(processSpec, combinedCancellationSource.Token); - _logger.LogInformation("Running {execName} with the following arguments: {args}", - processSpec.ShortDisplayName(), - ArgumentEscaper.EscapeAndConcatenate(processSpec.Arguments)); + var args = ArgumentEscaper.EscapeAndConcatenate(processSpec.Arguments); + _reporter.Verbose($"Running {processSpec.ShortDisplayName()} with the following arguments: {args}"); + + _reporter.Output("Started"); var finishedTask = await Task.WhenAny(processTask, fileSetTask, cancelledTaskSource.Task); @@ -58,6 +61,15 @@ namespace Microsoft.DotNet.Watcher await Task.WhenAll(processTask, fileSetTask); + if (processTask.Result == 0) + { + _reporter.Output("Exited"); + } + else + { + _reporter.Error($"Exited with error code {processTask.Result}"); + } + if (finishedTask == cancelledTaskSource.Task || cancellationToken.IsCancellationRequested) { return; @@ -65,7 +77,7 @@ namespace Microsoft.DotNet.Watcher if (finishedTask == processTask) { - _logger.LogInformation("Waiting for a file to change before restarting dotnet..."); + _reporter.Warn("Waiting for a file to change before restarting dotnet..."); // Now wait for a file to change before restarting process await fileSetWatcher.GetChangedFileAsync(cancellationToken); @@ -73,10 +85,10 @@ namespace Microsoft.DotNet.Watcher if (!string.IsNullOrEmpty(fileSetTask.Result)) { - _logger.LogInformation($"File changed: {fileSetTask.Result}"); + _reporter.Output($"File changed: {fileSetTask.Result}"); } } } } } -} +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSet.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSet.cs index 5cc524e79e..736ce43677 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSet.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSet.cs @@ -18,6 +18,8 @@ namespace Microsoft.DotNet.Watcher.Internal public bool Contains(string filePath) => _files.Contains(filePath); + public int Count => _files.Count; + public IEnumerator GetEnumerator() => _files.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => _files.GetEnumerator(); } diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs index 282b15b8e6..1ff1175f76 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs @@ -7,48 +7,47 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; -using System.Text; using System.Threading; using System.Threading.Tasks; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Tools.Internal; namespace Microsoft.DotNet.Watcher.Internal { public class MsBuildFileSetFactory : IFileSetFactory { + private const string TargetName = "GenerateWatchList"; private const string ProjectExtensionFileExtension = ".dotnetwatch.targets"; private const string WatchTargetsFileName = "DotNetWatchCommon.targets"; - private readonly ILogger _logger; + private readonly IReporter _reporter; private readonly string _projectFile; private readonly string _watchTargetsDir; private readonly OutputSink _outputSink; private readonly ProcessRunner _processRunner; - public MsBuildFileSetFactory(ILogger logger, string projectFile) - : this(logger, projectFile, new OutputSink()) + public MsBuildFileSetFactory(IReporter reporter, string projectFile) + : this(reporter, projectFile, new OutputSink()) { } // output sink is for testing - internal MsBuildFileSetFactory(ILogger logger, string projectFile, OutputSink outputSink) + internal MsBuildFileSetFactory(IReporter reporter, string projectFile, OutputSink outputSink) { - Ensure.NotNull(logger, nameof(logger)); + Ensure.NotNull(reporter, nameof(reporter)); Ensure.NotNullOrEmpty(projectFile, nameof(projectFile)); Ensure.NotNull(outputSink, nameof(outputSink)); - _logger = logger; + _reporter = reporter; _projectFile = projectFile; _watchTargetsDir = FindWatchTargetsDir(); _outputSink = outputSink; - _processRunner = new ProcessRunner(logger); + _processRunner = new ProcessRunner(reporter); } internal List BuildFlags { get; } = new List { "/nologo", "/v:n", - "/t:GenerateWatchList", + "/t:" + TargetName, "/p:DotNetWatchBuild=true", // extensibility point for users "/p:DesignTimeBuild=true", // don't do expensive things }; @@ -66,10 +65,6 @@ namespace Microsoft.DotNet.Watcher.Internal { cancellationToken.ThrowIfCancellationRequested(); -#if DEBUG - var stopwatch = new Stopwatch(); - stopwatch.Start(); -#endif var capture = _outputSink.StartCapture(); // TODO adding files doesn't currently work. Need to provide a way to detect new files // find files @@ -80,53 +75,56 @@ namespace Microsoft.DotNet.Watcher.Internal Arguments = new[] { "msbuild", - _projectFile, + _projectFile, $"/p:_DotNetWatchTargetsLocation={_watchTargetsDir}", // add our dotnet-watch targets $"/p:_DotNetWatchListFile={watchList}" }.Concat(BuildFlags), OutputCapture = capture }; + _reporter.Verbose($"Running MSBuild target '{TargetName}' on '{_projectFile}'"); + var exitCode = await _processRunner.RunAsync(processSpec, cancellationToken); if (exitCode == 0) { - var files = File.ReadAllLines(watchList) + var fileset = new FileSet( + File.ReadAllLines(watchList) .Select(l => l?.Trim()) - .Where(l => !string.IsNullOrEmpty(l)); - - var fileset = new FileSet(files); + .Where(l => !string.IsNullOrEmpty(l))); + _reporter.Verbose($"Watching {fileset.Count} file(s) for changes"); #if DEBUG - _logger.LogDebug(string.Join(Environment.NewLine, fileset)); - Debug.Assert(files.All(Path.IsPathRooted), "All files should be rooted paths"); - stopwatch.Stop(); - _logger.LogDebug("Gathered project information in {time}ms", stopwatch.ElapsedMilliseconds); + + foreach (var file in fileset) + { + _reporter.Verbose($" -> {file}"); + } + + Debug.Assert(fileset.All(Path.IsPathRooted), "All files should be rooted paths"); #endif return fileset; } - var sb = new StringBuilder() - .Append("Error(s) finding watch items project file '") - .Append(Path.GetFileName(_projectFile)) - .AppendLine("' :"); + _reporter.Error($"Error(s) finding watch items project file '{Path.GetFileName(_projectFile)}'"); + + _reporter.Output($"MSBuild output from target '{TargetName}'"); foreach (var line in capture.Lines) { - sb.Append(" [MSBUILD] :").AppendLine(line); + _reporter.Output($" [MSBUILD] : {line}"); } - _logger.LogError(sb.ToString()); - _logger.LogInformation("Fix the error to continue or press Ctrl+C to exit."); + _reporter.Warn("Fix the error to continue or press Ctrl+C to exit."); - var fileSet = new FileSet(new[] { _projectFile }); + var fileSet = new FileSet(new[] {_projectFile}); using (var watcher = new FileSetWatcher(fileSet)) { await watcher.GetChangedFileAsync(cancellationToken); - _logger.LogInformation($"File changed: {_projectFile}"); + _reporter.Output($"File changed: {_projectFile}"); } } } @@ -143,7 +141,8 @@ namespace Microsoft.DotNet.Watcher.Internal var projectExtensionsPath = Path.Combine(Path.GetDirectoryName(_projectFile), "obj"); // see https://github.com/Microsoft/msbuild/blob/bf9b21cc7869b96ea2289ff31f6aaa5e1d525a26/src/XMakeTasks/Microsoft.Common.targets#L127 - var projectExtensionFile = Path.Combine(projectExtensionsPath, Path.GetFileName(_projectFile) + ProjectExtensionFileExtension); + var projectExtensionFile = Path.Combine(projectExtensionsPath, + Path.GetFileName(_projectFile) + ProjectExtensionFileExtension); if (!File.Exists(projectExtensionFile)) { @@ -173,4 +172,4 @@ namespace Microsoft.DotNet.Watcher.Internal return Path.GetDirectoryName(targetPath); } } -} +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs index 39f302c71e..f303e8fe53 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs @@ -7,20 +7,19 @@ using System.IO; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Internal; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Tools.Internal; namespace Microsoft.DotNet.Watcher.Internal { public class ProcessRunner { - private readonly ILogger _logger; + private readonly IReporter _reporter; - public ProcessRunner(ILogger logger) + public ProcessRunner(IReporter reporter) { - Ensure.NotNull(logger, nameof(logger)); + Ensure.NotNull(reporter, nameof(reporter)); - _logger = logger; + _reporter = reporter; } // May not be necessary in the future. See https://github.com/dotnet/corefx/issues/12039 @@ -30,12 +29,16 @@ namespace Microsoft.DotNet.Watcher.Internal int exitCode; + var stopwatch = new Stopwatch(); + using (var process = CreateProcess(processSpec)) using (var processState = new ProcessState(process)) { cancellationToken.Register(() => processState.TryKill()); + stopwatch.Start(); process.Start(); + _reporter.Verbose($"Started '{processSpec.Executable}' with process id {process.Id}"); if (processSpec.IsOutputCaptured) { @@ -47,16 +50,12 @@ namespace Microsoft.DotNet.Watcher.Internal } else { - _logger.LogInformation("{execName} process id: {pid}", processSpec.ShortDisplayName(), process.Id); await processState.Task; } exitCode = process.ExitCode; - } - - if (!processSpec.IsOutputCaptured) - { - LogResult(processSpec, exitCode); + stopwatch.Stop(); + _reporter.Verbose($"Process id {process.Id} ran for {stopwatch.ElapsedMilliseconds}ms"); } return exitCode; @@ -81,19 +80,6 @@ namespace Microsoft.DotNet.Watcher.Internal return process; } - private void LogResult(ProcessSpec processSpec, int exitCode) - { - var processName = processSpec.ShortDisplayName(); - if (exitCode == 0) - { - _logger.LogInformation("{execName} exit code: {code}", processName, exitCode); - } - else - { - _logger.LogError("{execName} exit code: {code}", processName, exitCode); - } - } - private static async Task ConsumeStreamAsync(StreamReader reader, Action consume) { string line; diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec index ca72bc7b94..61ccec29df 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec @@ -14,9 +14,7 @@ - - - + diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index 45b4721b62..9c488ff283 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -2,20 +2,18 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Diagnostics; +using System.Collections.Generic; using System.IO; -using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.DotNet.Watcher.Internal; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Tools.Internal; namespace Microsoft.DotNet.Watcher { public class Program { - private const string LoggerName = "DotNetWatcher"; private readonly IConsole _console; private readonly string _workingDir; @@ -39,44 +37,18 @@ namespace Microsoft.DotNet.Watcher public async Task RunAsync(string[] args) { - using (CancellationTokenSource ctrlCTokenSource = new CancellationTokenSource()) + CommandLineOptions options; + try { - _console.CancelKeyPress += (sender, ev) => - { - if (!ctrlCTokenSource.IsCancellationRequested) - { - _console.Out.WriteLine($"[{LoggerName}] Shutdown requested. Press Ctrl+C again to force exit."); - ev.Cancel = true; - } - else - { - ev.Cancel = false; - } - ctrlCTokenSource.Cancel(); - }; - - try - { - return await MainInternalAsync(args, ctrlCTokenSource.Token); - } - catch (Exception ex) - { - if (ex is TaskCanceledException || ex is OperationCanceledException) - { - // swallow when only exception is the CTRL+C forced an exit - return 0; - } - - _console.Error.WriteLine(ex.ToString()); - _console.Error.WriteLine($"[{LoggerName}] An unexpected error occurred".Bold().Red()); - return 1; - } + options = CommandLineOptions.Parse(args, _console); + } + catch (CommandParsingException ex) + { + CreateReporter(verbose: true, quiet: false, console: _console) + .Error(ex.Message); + return 1; } - } - private async Task MainInternalAsync(string[] args, CancellationToken cancellationToken) - { - var options = CommandLineOptions.Parse(args, _console); if (options == null) { // invalid args syntax @@ -88,58 +60,122 @@ namespace Microsoft.DotNet.Watcher return 2; } - var loggerFactory = new LoggerFactory(); - var commandProvider = new CommandOutputProvider - { - LogLevel = ResolveLogLevel(options) - }; - loggerFactory.AddProvider(commandProvider); - var logger = loggerFactory.CreateLogger(LoggerName); + var reporter = CreateReporter(options.IsVerbose, options.IsQuiet, _console); + using (CancellationTokenSource ctrlCTokenSource = new CancellationTokenSource()) + { + _console.CancelKeyPress += (sender, ev) => + { + if (!ctrlCTokenSource.IsCancellationRequested) + { + reporter.Output("Shutdown requested. Press Ctrl+C again to force exit."); + ev.Cancel = true; + } + else + { + ev.Cancel = false; + } + ctrlCTokenSource.Cancel(); + }; + + try + { + return await MainInternalAsync(reporter, options.Project, options.RemainingArguments, ctrlCTokenSource.Token); + } + catch (Exception ex) + { + if (ex is TaskCanceledException || ex is OperationCanceledException) + { + // swallow when only exception is the CTRL+C forced an exit + return 0; + } + + reporter.Error(ex.ToString()); + reporter.Error("An unexpected error occurred"); + return 1; + } + } + } + + private async Task MainInternalAsync( + IReporter reporter, + string project, + ICollection args, + CancellationToken cancellationToken) + { // TODO multiple projects should be easy enough to add here string projectFile; try { - projectFile = MsBuildProjectFinder.FindMsBuildProject(_workingDir, options.Project); + projectFile = MsBuildProjectFinder.FindMsBuildProject(_workingDir, project); } catch (FileNotFoundException ex) { - _console.Error.WriteLine(ex.Message.Bold().Red()); + reporter.Error(ex.Message); return 1; } - var fileSetFactory = new MsBuildFileSetFactory(logger, projectFile); + var fileSetFactory = new MsBuildFileSetFactory(reporter, projectFile); var processInfo = new ProcessSpec { Executable = DotNetMuxer.MuxerPathOrDefault(), WorkingDirectory = Path.GetDirectoryName(projectFile), - Arguments = options.RemainingArguments + Arguments = args }; - await new DotNetWatcher(logger) - .WatchAsync(processInfo, fileSetFactory, cancellationToken); + await new DotNetWatcher(reporter) + .WatchAsync(processInfo, fileSetFactory, cancellationToken); return 0; } - private LogLevel ResolveLogLevel(CommandLineOptions options) + private static IReporter CreateReporter(bool verbose, bool quiet, IConsole console) { - if (options.IsQuiet) - { - return LogLevel.Warning; - } + const string prefix = "watch : "; + var colorPrefix = new ColorFormatter(ConsoleColor.DarkGray).Format(prefix); - bool globalVerbose; - bool.TryParse(Environment.GetEnvironmentVariable("DOTNET_CLI_CONTEXT_VERBOSE"), out globalVerbose); + return new ReporterBuilder() + .WithConsole(console) + .Verbose(f => + { + if (console.IsOutputRedirected) + { + f.WithPrefix(prefix); + } + else + { + f.WithColor(ConsoleColor.DarkGray).WithPrefix(colorPrefix); + } - if (options.IsVerbose // dotnet watch --verbose - || globalVerbose) // dotnet --verbose watch - { - return LogLevel.Debug; - } - - return LogLevel.Information; + f.When(() => verbose || CliContext.IsGlobalVerbose()); + }) + .Output(f => f + .WithPrefix(console.IsOutputRedirected ? prefix : colorPrefix) + .When(() => !quiet)) + .Warn(f => + { + if (console.IsOutputRedirected) + { + f.WithPrefix(prefix); + } + else + { + f.WithColor(ConsoleColor.Yellow).WithPrefix(colorPrefix); + } + }) + .Error(f => + { + if (console.IsOutputRedirected) + { + f.WithPrefix(prefix); + } + else + { + f.WithColor(ConsoleColor.Red).WithPrefix(colorPrefix); + } + }) + .Build(); } } -} +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index d53d354b50..c60e93de77 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -32,8 +32,6 @@ ] }, "dependencies": { - "Microsoft.Extensions.Logging": "1.0.0", - "Microsoft.Extensions.Logging.Console": "1.0.0", "Microsoft.Extensions.Process.Sources": { "type": "build", "version": "1.0.0" diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec index 4b56ae8719..4103770bb4 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec @@ -14,11 +14,8 @@ - - - - - + + diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs index c0294c3c41..190335aded 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs @@ -6,7 +6,7 @@ using System.Data; using System.Data.SqlClient; using System.Reflection; using Microsoft.Extensions.CommandLineUtils; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Tools.Internal; namespace Microsoft.Extensions.Caching.SqlConfig.Tools { @@ -15,54 +15,61 @@ namespace Microsoft.Extensions.Caching.SqlConfig.Tools private string _connectionString = null; private string _schemaName = null; private string _tableName = null; + private readonly IConsole _console; - private readonly ILogger _logger; - - public Program() + public Program(IConsole console) { - var loggerFactory = new LoggerFactory(); - loggerFactory.AddConsole(); - _logger = loggerFactory.CreateLogger(); + Ensure.NotNull(console, nameof(console)); + + _console = console; } public static int Main(string[] args) { - return new Program().Run(args); + return new Program(PhysicalConsole.Singleton).Run(args); } public int Run(string[] args) { + DebugHelper.HandleDebugSwitch(ref args); + try { - var description = "Creates table and indexes in Microsoft SQL Server database " + - "to be used for distributed caching"; - var app = new CommandLineApplication { Name = "dotnet sql-cache", FullName = "SQL Server Cache Command Line Tool", - Description = description, + Description = + "Creates table and indexes in Microsoft SQL Server database to be used for distributed caching", }; - app.HelpOption("-?|-h|--help"); + + app.HelpOption(); app.VersionOptionFromAssemblyAttributes(typeof(Program).GetTypeInfo().Assembly); + var verbose = app.VerboseOption(); app.Command("create", command => { - command.Description = description; + command.Description = app.Description; + var connectionStringArg = command.Argument( - "[connectionString]", - "The connection string to connect to the database."); - var schemaNameArg = command.Argument("[schemaName]", "Name of the table schema."); - var tableNameArg = command.Argument("[tableName]", "Name of the table to be created."); - command.HelpOption("-?|-h|--help"); + "[connectionString]", "The connection string to connect to the database."); + + var schemaNameArg = command.Argument( + "[schemaName]", "Name of the table schema."); + + var tableNameArg = command.Argument( + "[tableName]", "Name of the table to be created."); + + command.HelpOption(); command.OnExecute(() => { + var reporter = CreateReporter(verbose.HasValue()); if (string.IsNullOrEmpty(connectionStringArg.Value) - || string.IsNullOrEmpty(schemaNameArg.Value) - || string.IsNullOrEmpty(tableNameArg.Value)) + || string.IsNullOrEmpty(schemaNameArg.Value) + || string.IsNullOrEmpty(tableNameArg.Value)) { - _logger.LogWarning("Invalid input"); + reporter.Error("Invalid input"); app.ShowHelp(); return 2; } @@ -71,7 +78,7 @@ namespace Microsoft.Extensions.Caching.SqlConfig.Tools _schemaName = schemaNameArg.Value; _tableName = tableNameArg.Value; - return CreateTableAndIndexes(); + return CreateTableAndIndexes(reporter); }); }); @@ -86,12 +93,41 @@ namespace Microsoft.Extensions.Caching.SqlConfig.Tools } catch (Exception exception) { - _logger.LogCritical("An error occurred. {ErrorMessage}", exception.Message); + CreateReporter(verbose: false).Error($"An error occurred. {exception.Message}"); return 1; } } - private int CreateTableAndIndexes() + private IReporter CreateReporter(bool verbose) + { + return new ReporterBuilder() + .WithConsole(_console) + .Verbose(f => + { + f.When(() => verbose); + if (!_console.IsOutputRedirected) + { + f.WithColor(ConsoleColor.DarkGray); + } + }) + .Warn(f => + { + if (!_console.IsOutputRedirected) + { + f.WithColor(ConsoleColor.Yellow); + } + }) + .Error(f => + { + if (!_console.IsErrorRedirected) + { + f.WithColor(ConsoleColor.Red); + } + }) + .Build(); + } + + private int CreateTableAndIndexes(IReporter reporter) { ValidateConnectionString(); @@ -106,7 +142,7 @@ namespace Microsoft.Extensions.Caching.SqlConfig.Tools { if (reader.Read()) { - _logger.LogWarning( + reporter.Warn( $"Table with schema '{_schemaName}' and name '{_tableName}' already exists. " + "Provide a different table name and try again."); return 1; @@ -118,23 +154,26 @@ namespace Microsoft.Extensions.Caching.SqlConfig.Tools try { command = new SqlCommand(sqlQueries.CreateTable, connection, transaction); + + reporter.Verbose($"Executing {command.CommandText}"); command.ExecuteNonQuery(); command = new SqlCommand( sqlQueries.CreateNonClusteredIndexOnExpirationTime, connection, transaction); + + reporter.Verbose($"Executing {command.CommandText}"); command.ExecuteNonQuery(); transaction.Commit(); - _logger.LogInformation("Table and index were created successfully."); + reporter.Output("Table and index were created successfully."); } catch (Exception ex) { - _logger.LogError( - "An error occurred while trying to create the table and index. {ErrorMessage}", - ex.Message); + reporter.Error( + $"An error occurred while trying to create the table and index. {ex.Message}"); transaction.Rollback(); return 1; @@ -154,7 +193,7 @@ namespace Microsoft.Extensions.Caching.SqlConfig.Tools catch (Exception ex) { throw new ArgumentException( - $"Invalid Sql server connection string '{_connectionString}'. {ex.Message}", ex); + $"Invalid SQL Server connection string '{_connectionString}'. {ex.Message}", ex); } } } diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json index 546d267e97..27ce41031d 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json @@ -5,7 +5,8 @@ "emitEntryPoint": true, "warningsAsErrors": true, "keyFile": "../../tools/Key.snk", - "compile": "../Shared/CommandLineApplicationExtensions.cs" + "compile": "../Shared/**/*.cs" + }, "description": "Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching.", "packOptions": { @@ -20,9 +21,6 @@ ] }, "dependencies": { - "Microsoft.Extensions.CommandLineUtils": "1.0.0", - "Microsoft.Extensions.Logging": "1.0.0", - "Microsoft.Extensions.Logging.Console": "1.0.0", "Microsoft.NETCore.App": { "version": "1.0.1", "type": "platform" diff --git a/src/Microsoft.Extensions.SecretManager.Tools/CommandLineOptions.cs b/src/Microsoft.Extensions.SecretManager.Tools/CommandLineOptions.cs index d8e4979838..ff888f9e8b 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/CommandLineOptions.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/CommandLineOptions.cs @@ -31,8 +31,7 @@ namespace Microsoft.Extensions.SecretManager.Tools app.HelpOption(); app.VersionOptionFromAssemblyAttributes(typeof(Program).GetTypeInfo().Assembly); - var optionVerbose = app.Option("-v|--verbose", "Verbose output", - CommandOptionType.NoValue, inherited: true); + var optionVerbose = app.VerboseOption(); var optionProject = app.Option("-p|--project ", "Path to project, default is current directory", CommandOptionType.SingleValue, inherited: true); @@ -48,7 +47,7 @@ namespace Microsoft.Extensions.SecretManager.Tools var options = new CommandLineOptions(); app.Command("set", c => SetCommand.Configure(c, options, console)); - app.Command("remove", c => RemoveCommand.Configure(c, options, console)); + app.Command("remove", c => RemoveCommand.Configure(c, options)); app.Command("list", c => ListCommand.Configure(c, options)); app.Command("clear", c => ClearCommand.Configure(c, options)); diff --git a/src/Microsoft.Extensions.SecretManager.Tools/CommandOutputLogger.cs b/src/Microsoft.Extensions.SecretManager.Tools/CommandOutputLogger.cs deleted file mode 100644 index f648400f65..0000000000 --- a/src/Microsoft.Extensions.SecretManager.Tools/CommandOutputLogger.cs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.Extensions.CommandLineUtils; -using Microsoft.Extensions.Logging; - -namespace Microsoft.Extensions.SecretManager.Tools -{ - /// - /// Logger to print formatted command output. - /// - public class CommandOutputLogger : ILogger - { - private readonly CommandOutputProvider _provider; - private readonly AnsiConsole _outConsole; - - public CommandOutputLogger(CommandOutputProvider commandOutputProvider, bool useConsoleColor) - { - _provider = commandOutputProvider; - _outConsole = AnsiConsole.GetOutput(useConsoleColor); - } - - public IDisposable BeginScope(TState state) - { - throw new NotImplementedException(); - } - - public bool IsEnabled(LogLevel logLevel) - { - if (logLevel < _provider.LogLevel) - { - return false; - } - - return true; - } - - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) - { - if (IsEnabled(logLevel)) - { - _outConsole.WriteLine(string.Format("{0}: {1}", Caption(logLevel), formatter(state, exception))); - } - } - - private string Caption(LogLevel logLevel) - { - switch (logLevel) - { - case LogLevel.Trace: return "\x1b[35mtrace\x1b[39m"; - case LogLevel.Debug: return "\x1b[35mdebug\x1b[39m"; - case LogLevel.Information: return "\x1b[32minfo\x1b[39m"; - case LogLevel.Warning: return "\x1b[33mwarn\x1b[39m"; - case LogLevel.Error: return "\x1b[31mfail\x1b[39m"; - case LogLevel.Critical: return "\x1b[31mcritical\x1b[39m"; - } - - throw new Exception("Unknown LogLevel"); - } - } -} \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/CommandOutputProvider.cs b/src/Microsoft.Extensions.SecretManager.Tools/CommandOutputProvider.cs deleted file mode 100644 index 0791830a69..0000000000 --- a/src/Microsoft.Extensions.SecretManager.Tools/CommandOutputProvider.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Runtime.InteropServices; -using Microsoft.Extensions.Logging; - -namespace Microsoft.Extensions.SecretManager.Tools -{ - public class CommandOutputProvider : ILoggerProvider - { - public ILogger CreateLogger(string name) - { - var useConsoleColor = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - return new CommandOutputLogger(this, useConsoleColor); - } - - public void Dispose() - { - } - - public LogLevel LogLevel { get; set; } = LogLevel.Information; - } -} \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandContext.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandContext.cs index 8ad2ffd9f9..0ac0ea40fe 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandContext.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandContext.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Tools.Internal; namespace Microsoft.Extensions.SecretManager.Tools.Internal @@ -10,16 +9,16 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal { public CommandContext( SecretsStore store, - ILogger logger, + IReporter reporter, IConsole console) { SecretStore = store; - Logger = logger; + Reporter = reporter; Console = console; } public IConsole Console { get; } - public ILogger Logger { get; } + public IReporter Reporter { get; } public SecretsStore SecretStore { get; } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ListCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ListCommand.cs index 16ee59a882..5bfd07db44 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ListCommand.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ListCommand.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.Extensions.CommandLineUtils; -using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -41,13 +40,13 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal if (context.SecretStore.Count == 0) { - context.Logger.LogInformation(Resources.Error_No_Secrets_Found); + context.Reporter.Output(Resources.Error_No_Secrets_Found); } else { foreach (var secret in context.SecretStore.AsEnumerable()) { - context.Logger.LogInformation(Resources.FormatMessage_Secret_Value_Format(secret.Key, secret.Value)); + context.Reporter.Output(Resources.FormatMessage_Secret_Value_Format(secret.Key, secret.Value)); } } } @@ -60,10 +59,9 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal jObject[item.Key] = item.Value; } - // TODO logger would prefix each line. - context.Console.Out.WriteLine("//BEGIN"); - context.Console.Out.WriteLine(jObject.ToString(Formatting.Indented)); - context.Console.Out.WriteLine("//END"); + context.Reporter.Output("//BEGIN"); + context.Reporter.Output(jObject.ToString(Formatting.Indented)); + context.Reporter.Output("//END"); } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs index 40d3dc52b9..26de364cd5 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs @@ -7,7 +7,6 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Tools.Internal; namespace Microsoft.Extensions.SecretManager.Tools.Internal @@ -15,27 +14,32 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal public class ProjectIdResolver : IDisposable { private const string TargetsFileName = "FindUserSecretsProperty.targets"; - private readonly ILogger _logger; + private const string DefaultConfig = "Debug"; + private readonly IReporter _reporter; private readonly string _workingDirectory; private readonly List _tempFiles = new List(); - public ProjectIdResolver(ILogger logger, string workingDirectory) + public ProjectIdResolver(IReporter reporter, string workingDirectory) { _workingDirectory = workingDirectory; - _logger = logger; + _reporter = reporter; } - public string Resolve(string project, string configuration = "Debug") + public string Resolve(string project, string configuration) { var finder = new MsBuildProjectFinder(_workingDirectory); var projectFile = finder.FindMsBuildProject(project); - _logger.LogDebug(Resources.Message_Project_File_Path, projectFile); + _reporter.Verbose(Resources.FormatMessage_Project_File_Path(projectFile)); var targetFile = GetTargetFile(); var outputFile = Path.GetTempFileName(); _tempFiles.Add(outputFile); + configuration = !string.IsNullOrEmpty(configuration) + ? configuration + : DefaultConfig; + var args = new[] { "msbuild", @@ -53,13 +57,18 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal RedirectStandardOutput = true, RedirectStandardError = true }; + +#if DEBUG + _reporter.Verbose($"Invoking '{psi.FileName} {psi.Arguments}'"); +#endif + var process = Process.Start(psi); process.WaitForExit(); if (process.ExitCode != 0) { - _logger.LogDebug(process.StandardOutput.ReadToEnd()); - _logger.LogDebug(process.StandardError.ReadToEnd()); + _reporter.Verbose(process.StandardOutput.ReadToEnd()); + _reporter.Verbose(process.StandardError.ReadToEnd()); throw new InvalidOperationException(Resources.FormatError_ProjectFailedToLoad(projectFile)); } diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs index d896c31a87..60a337ea10 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs @@ -1,9 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using Microsoft.Extensions.CommandLineUtils; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Tools.Internal; namespace Microsoft.Extensions.SecretManager.Tools.Internal @@ -12,7 +10,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal { private readonly string _keyName; - public static void Configure(CommandLineApplication command, CommandLineOptions options, IConsole console) + public static void Configure(CommandLineApplication command, CommandLineOptions options) { command.Description = "Removes the specified user secret"; command.HelpOption(); @@ -22,12 +20,10 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal { if (keyArg.Value == null) { - console.Error.WriteLine(Resources.FormatError_MissingArgument("name").Red()); - return 1; + throw new CommandParsingException(command, Resources.FormatError_MissingArgument("name")); } options.Command = new RemoveCommand(keyArg.Value); - return 0; }); } @@ -41,7 +37,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal { if (!context.SecretStore.ContainsKey(_keyName)) { - context.Logger.LogWarning(Resources.Error_Missing_Secret, _keyName); + context.Reporter.Warn(Resources.FormatError_Missing_Secret(_keyName)); } else { diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs index 10813b53d4..93d46242f2 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs @@ -8,7 +8,6 @@ using System.Linq; using System.Text; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.UserSecrets; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Tools.Internal; using Newtonsoft.Json.Linq; @@ -19,7 +18,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal private readonly string _secretsFilePath; private IDictionary _secrets; - public SecretsStore(string userSecretsId, ILogger logger) + public SecretsStore(string userSecretsId, IReporter reporter) { Ensure.NotNull(userSecretsId, nameof(userSecretsId)); @@ -29,7 +28,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal var secretDir = Path.GetDirectoryName(_secretsFilePath); Directory.CreateDirectory(secretDir); - logger.LogDebug(Resources.Message_Secret_File_Path, _secretsFilePath); + reporter.Verbose(Resources.FormatMessage_Secret_File_Path(_secretsFilePath)); _secrets = Load(userSecretsId); } diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs index 013777210e..c162b72107 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs @@ -1,11 +1,9 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.IO; using System.Text; using Microsoft.Extensions.CommandLineUtils; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Tools.Internal; namespace Microsoft.Extensions.SecretManager.Tools.Internal @@ -34,23 +32,21 @@ Examples: if (console.IsInputRedirected && nameArg.Value == null) { options.Command = new FromStdInStrategy(); - return 0; } - - if (string.IsNullOrEmpty(nameArg.Value)) + else { - console.Error.WriteLine(Resources.FormatError_MissingArgument("name").Red()); - return 1; - } + if (string.IsNullOrEmpty(nameArg.Value)) + { + throw new CommandParsingException(command, Resources.FormatError_MissingArgument("name")); + } - if (valueArg.Value == null) - { - console.Error.WriteLine(Resources.FormatError_MissingArgument("value").Red()); - return 1; - } + if (valueArg.Value == null) + { + throw new CommandParsingException(command, Resources.FormatError_MissingArgument("value")); + } - options.Command = new ForOneValueStrategy(nameArg.Value, valueArg.Value); - return 0; + options.Command = new ForOneValueStrategy(nameArg.Value, valueArg.Value); + } }); } @@ -76,7 +72,7 @@ Examples: context.SecretStore.Set(k.Key, k.Value); } - context.Logger.LogInformation(Resources.Message_Saved_Secrets, provider.CurrentData.Count); + context.Reporter.Output(Resources.FormatMessage_Saved_Secrets(provider.CurrentData.Count)); context.SecretStore.Save(); } @@ -97,7 +93,7 @@ Examples: { context.SecretStore.Set(_keyName, _keyValue); context.SecretStore.Save(); - context.Logger.LogInformation(Resources.Message_Saved_Secret, _keyName, _keyValue); + context.Reporter.Output(Resources.FormatMessage_Saved_Secret(_keyName, _keyValue)); } } } diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec index c9f2903331..eb63c1592c 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec @@ -17,8 +17,7 @@ - - + diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs index 656b0d9c05..5ff2a8e228 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs @@ -3,7 +3,7 @@ using System; using System.IO; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.SecretManager.Tools.Internal; using Microsoft.Extensions.Tools.Internal; @@ -11,8 +11,6 @@ namespace Microsoft.Extensions.SecretManager.Tools { public class Program { - private ILogger _logger; - private CommandOutputProvider _loggerProvider; private readonly IConsole _console; private readonly string _workingDirectory; @@ -29,23 +27,6 @@ namespace Microsoft.Extensions.SecretManager.Tools { _console = console; _workingDirectory = workingDirectory; - - var loggerFactory = new LoggerFactory(); - CommandOutputProvider = new CommandOutputProvider(); - loggerFactory.AddProvider(CommandOutputProvider); - Logger = loggerFactory.CreateLogger(); - } - - public ILogger Logger - { - get { return _logger; } - set { _logger = Ensure.NotNull(value, nameof(value)); } - } - - public CommandOutputProvider CommandOutputProvider - { - get { return _loggerProvider; } - set { _loggerProvider = Ensure.NotNull(value, nameof(value)); } } public bool TryRun(string[] args, out int returnCode) @@ -57,8 +38,9 @@ namespace Microsoft.Extensions.SecretManager.Tools } catch (Exception exception) { - Logger.LogDebug(exception.ToString()); - Logger.LogCritical(Resources.Error_Command_Failed, exception.Message); + var reporter = CreateReporter(verbose: true); + reporter.Verbose(exception.ToString()); + reporter.Error(Resources.FormatError_Command_Failed(exception.Message)); returnCode = 1; return false; } @@ -66,7 +48,16 @@ namespace Microsoft.Extensions.SecretManager.Tools internal int RunInternal(params string[] args) { - var options = CommandLineOptions.Parse(args, _console); + CommandLineOptions options; + try + { + options = CommandLineOptions.Parse(args, _console); + } + catch (CommandParsingException ex) + { + CreateReporter(verbose: false).Error(ex.Message); + return 1; + } if (options == null) { @@ -78,36 +69,62 @@ namespace Microsoft.Extensions.SecretManager.Tools return 2; } - if (options.IsVerbose) - { - CommandOutputProvider.LogLevel = LogLevel.Debug; - } + var reporter = CreateReporter(options.IsVerbose); string userSecretsId; try { - userSecretsId = ResolveId(options); + userSecretsId = ResolveId(options, reporter); } catch (Exception ex) when (ex is InvalidOperationException || ex is FileNotFoundException) { - _logger.LogError(ex.Message); + reporter.Error(ex.Message); return 1; } - var store = new SecretsStore(userSecretsId, Logger); - var context = new Internal.CommandContext(store, Logger, _console); + var store = new SecretsStore(userSecretsId, reporter); + var context = new Internal.CommandContext(store, reporter, _console); options.Command.Execute(context); return 0; } - internal string ResolveId(CommandLineOptions options) + private IReporter CreateReporter(bool verbose) + { + return new ReporterBuilder() + .WithConsole(_console) + .Verbose(f => + { + f.When(() => verbose); + if (!_console.IsOutputRedirected) + { + f.WithColor(ConsoleColor.DarkGray); + } + }) + .Warn(f => + { + if (!_console.IsOutputRedirected) + { + f.WithColor(ConsoleColor.Yellow); + } + }) + .Error(f => + { + if (!_console.IsErrorRedirected) + { + f.WithColor(ConsoleColor.Red); + } + }) + .Build(); + } + + internal string ResolveId(CommandLineOptions options, IReporter reporter) { if (!string.IsNullOrEmpty(options.Id)) { return options.Id; } - using (var resolver = new ProjectIdResolver(Logger, _workingDirectory)) + using (var resolver = new ProjectIdResolver(reporter, _workingDirectory)) { return resolver.Resolve(options.Project, options.Configuration); } diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index f4731bc33d..4b188c420a 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -39,7 +39,6 @@ }, "dependencies": { "Microsoft.Extensions.Configuration.UserSecrets": "1.0.0", - "Microsoft.Extensions.Logging": "1.0.0", "Microsoft.NETCore.App": { "version": "1.0.1", "type": "platform" diff --git a/src/Shared/CliContext.cs b/src/Shared/CliContext.cs new file mode 100644 index 0000000000..ad766a2e3b --- /dev/null +++ b/src/Shared/CliContext.cs @@ -0,0 +1,21 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.Extensions.Tools.Internal +{ + public static class CliContext + { + /// + /// dotnet --verbose subcommand + /// + /// + public static bool IsGlobalVerbose() + { + bool globalVerbose; + bool.TryParse(Environment.GetEnvironmentVariable("DOTNET_CLI_CONTEXT_VERBOSE"), out globalVerbose); + return globalVerbose; + } + } +} \ No newline at end of file diff --git a/src/Shared/CommandLineApplicationExtensions.cs b/src/Shared/CommandLineApplicationExtensions.cs index 0a7e16a5bf..b268cea062 100644 --- a/src/Shared/CommandLineApplicationExtensions.cs +++ b/src/Shared/CommandLineApplicationExtensions.cs @@ -11,6 +11,9 @@ namespace Microsoft.Extensions.CommandLineUtils public static CommandOption HelpOption(this CommandLineApplication app) => app.HelpOption("-?|-h|--help"); + public static CommandOption VerboseOption(this CommandLineApplication app) + => app.Option("-v|--verbose", "Show verbose output", CommandOptionType.NoValue, inherited: true); + public static void OnExecute(this CommandLineApplication app, Action action) => app.OnExecute(() => { diff --git a/src/Shared/IConsole.cs b/src/Shared/IConsole.cs index 7f1e5e122a..20bb36e7f9 100644 --- a/src/Shared/IConsole.cs +++ b/src/Shared/IConsole.cs @@ -13,5 +13,7 @@ namespace Microsoft.Extensions.Tools.Internal TextWriter Error { get; } TextReader In { get; } bool IsInputRedirected { get; } + bool IsOutputRedirected { get; } + bool IsErrorRedirected { get; } } } diff --git a/src/Shared/PhysicalConsole.cs b/src/Shared/PhysicalConsole.cs index 7b1a98f621..bdfb60ac0e 100644 --- a/src/Shared/PhysicalConsole.cs +++ b/src/Shared/PhysicalConsole.cs @@ -23,5 +23,7 @@ namespace Microsoft.Extensions.Tools.Internal public TextReader In => Console.In; public TextWriter Out => Console.Out; public bool IsInputRedirected => Console.IsInputRedirected; + public bool IsOutputRedirected => Console.IsOutputRedirected; + public bool IsErrorRedirected => Console.IsErrorRedirected; } } diff --git a/src/Shared/Reporting/ColorFormatter.cs b/src/Shared/Reporting/ColorFormatter.cs new file mode 100644 index 0000000000..5675d5b367 --- /dev/null +++ b/src/Shared/Reporting/ColorFormatter.cs @@ -0,0 +1,57 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; + +namespace Microsoft.Extensions.Tools.Internal +{ + public class ColorFormatter : IFormatter + { + // resets foreground color only + private const string ResetColor = "\x1B[39m"; + + private static readonly IDictionary AnsiColorCodes + = new Dictionary + { + {ConsoleColor.Black, 30}, + {ConsoleColor.DarkRed, 31}, + {ConsoleColor.DarkGreen, 32}, + {ConsoleColor.DarkYellow, 33}, + {ConsoleColor.DarkBlue, 34}, + {ConsoleColor.DarkMagenta, 35}, + {ConsoleColor.DarkCyan, 36}, + {ConsoleColor.Gray, 37}, + {ConsoleColor.DarkGray, 90}, + {ConsoleColor.Red, 91}, + {ConsoleColor.Green, 92}, + {ConsoleColor.Yellow, 93}, + {ConsoleColor.Blue, 94}, + {ConsoleColor.Magenta, 95}, + {ConsoleColor.Cyan, 96}, + {ConsoleColor.White, 97}, + }; + + private readonly string _prefix; + + public ColorFormatter(ConsoleColor color) + { + _prefix = GetAnsiCode(color); + } + + public string Format(string text) + => text?.Length > 0 + ? $"{_prefix}{text}{ResetColor}" + : text; + + private static string GetAnsiCode(ConsoleColor color) + { + int code; + if (!AnsiColorCodes.TryGetValue(color, out code)) + { + throw new ArgumentOutOfRangeException(nameof(color), color, null); + } + return $"\x1B[{code}m"; + } + } +} \ No newline at end of file diff --git a/src/Shared/Reporting/CompositeFormatter.cs b/src/Shared/Reporting/CompositeFormatter.cs new file mode 100644 index 0000000000..63aa074760 --- /dev/null +++ b/src/Shared/Reporting/CompositeFormatter.cs @@ -0,0 +1,26 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Extensions.Tools.Internal +{ + public class CompositeFormatter : IFormatter + { + private readonly IFormatter[] _formatters; + + public CompositeFormatter(IFormatter[] formatters) + { + Ensure.NotNull(formatters, nameof(formatters)); + _formatters = formatters; + } + + public string Format(string text) + { + foreach (var formatter in _formatters) + { + text = formatter.Format(text); + } + + return text; + } + } +} \ No newline at end of file diff --git a/src/Shared/Reporting/ConditionalFormatter.cs b/src/Shared/Reporting/ConditionalFormatter.cs new file mode 100644 index 0000000000..b0881f2bac --- /dev/null +++ b/src/Shared/Reporting/ConditionalFormatter.cs @@ -0,0 +1,24 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.Extensions.Tools.Internal +{ + public class ConditionalFormatter : IFormatter + { + private readonly Func _predicate; + + public ConditionalFormatter(Func predicate) + { + Ensure.NotNull(predicate, nameof(predicate)); + + _predicate = predicate; + } + + public string Format(string text) + => _predicate() + ? text + : null; + } +} \ No newline at end of file diff --git a/src/Shared/Reporting/DefaultFormatter.cs b/src/Shared/Reporting/DefaultFormatter.cs new file mode 100644 index 0000000000..4d4348b000 --- /dev/null +++ b/src/Shared/Reporting/DefaultFormatter.cs @@ -0,0 +1,14 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Extensions.Tools.Internal +{ + public class DefaultFormatter : IFormatter + { + public static readonly IFormatter Instance = new DefaultFormatter(); + + private DefaultFormatter() {} + public string Format(string text) + => text; + } +} \ No newline at end of file diff --git a/src/Shared/Reporting/FormatterBuilder.cs b/src/Shared/Reporting/FormatterBuilder.cs new file mode 100644 index 0000000000..3d3491487c --- /dev/null +++ b/src/Shared/Reporting/FormatterBuilder.cs @@ -0,0 +1,46 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; + +namespace Microsoft.Extensions.Tools.Internal +{ + public class FormatterBuilder + { + private readonly List _formatters = new List(); + + public FormatterBuilder WithColor(ConsoleColor color) + { + _formatters.Add(new ColorFormatter(color)); + return this; + } + + public FormatterBuilder WithPrefix(string prefix) + { + _formatters.Add(new PrefixFormatter(prefix)); + return this; + } + + public FormatterBuilder When(Func predicate) + { + _formatters.Add(new ConditionalFormatter(predicate)); + return this; + } + + public IFormatter Build() + { + if (_formatters.Count == 0) + { + return DefaultFormatter.Instance; + } + + if (_formatters.Count == 1) + { + return _formatters[0]; + } + + return new CompositeFormatter(_formatters.ToArray()); + } + } +} \ No newline at end of file diff --git a/src/Shared/Reporting/FormattingReporter.cs b/src/Shared/Reporting/FormattingReporter.cs new file mode 100644 index 0000000000..0c49c0d817 --- /dev/null +++ b/src/Shared/Reporting/FormattingReporter.cs @@ -0,0 +1,62 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; + +namespace Microsoft.Extensions.Tools.Internal +{ + public class FormattingReporter : IReporter + { + private readonly object _writelock = new object(); + private readonly IConsole _console; + private readonly IFormatter _verbose; + private readonly IFormatter _warn; + private readonly IFormatter _output; + private readonly IFormatter _error; + + public FormattingReporter(IConsole console, + IFormatter verbose, + IFormatter output, + IFormatter warn, + IFormatter error) + { + Ensure.NotNull(console, nameof(console)); + Ensure.NotNull(verbose, nameof(verbose)); + Ensure.NotNull(output, nameof(output)); + Ensure.NotNull(warn, nameof(warn)); + Ensure.NotNull(error, nameof(error)); + + _console = console; + _verbose = verbose; + _output = output; + _warn = warn; + _error = error; + } + + + public void Verbose(string message) + => Write(_console.Out, _verbose.Format(message)); + + public void Output(string message) + => Write(_console.Out, _output.Format(message)); + + public void Warn(string message) + => Write(_console.Out, _warn.Format(message)); + + public void Error(string message) + => Write(_console.Error, _error.Format(message)); + + private void Write(TextWriter writer, string message) + { + if (message == null) + { + return; + } + + lock (_writelock) + { + writer.WriteLine(message); + } + } + } +} \ No newline at end of file diff --git a/src/Shared/Reporting/IFormatter.cs b/src/Shared/Reporting/IFormatter.cs new file mode 100644 index 0000000000..9094728632 --- /dev/null +++ b/src/Shared/Reporting/IFormatter.cs @@ -0,0 +1,10 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Extensions.Tools.Internal +{ + public interface IFormatter + { + string Format(string text); + } +} \ No newline at end of file diff --git a/src/Shared/Reporting/IReporter.cs b/src/Shared/Reporting/IReporter.cs new file mode 100644 index 0000000000..890dec3f7e --- /dev/null +++ b/src/Shared/Reporting/IReporter.cs @@ -0,0 +1,13 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Extensions.Tools.Internal +{ + public interface IReporter + { + void Verbose(string message); + void Output(string message); + void Warn(string message); + void Error(string message); + } +} \ No newline at end of file diff --git a/src/Shared/Reporting/PrefixFormatter.cs b/src/Shared/Reporting/PrefixFormatter.cs new file mode 100644 index 0000000000..b9602c41ca --- /dev/null +++ b/src/Shared/Reporting/PrefixFormatter.cs @@ -0,0 +1,20 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Extensions.Tools.Internal +{ + public class PrefixFormatter : IFormatter + { + private readonly string _prefix; + + public PrefixFormatter(string prefix) + { + Ensure.NotNullOrEmpty(prefix, nameof(prefix)); + + _prefix = prefix; + } + + public string Format(string text) + => _prefix + text; + } +} \ No newline at end of file diff --git a/src/Shared/Reporting/ReporterBuilder.cs b/src/Shared/Reporting/ReporterBuilder.cs new file mode 100644 index 0000000000..9283642041 --- /dev/null +++ b/src/Shared/Reporting/ReporterBuilder.cs @@ -0,0 +1,65 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.Extensions.Tools.Internal +{ + public class ReporterBuilder + { + private readonly FormatterBuilder _verbose = new FormatterBuilder(); + private readonly FormatterBuilder _output = new FormatterBuilder(); + private readonly FormatterBuilder _warn = new FormatterBuilder(); + private readonly FormatterBuilder _error = new FormatterBuilder(); + private IConsole _console; + + public ReporterBuilder WithConsole(IConsole console) + { + _console = console; + return this; + } + + public FormatterBuilder Verbose() => _verbose; + public FormatterBuilder Output() => _output; + public FormatterBuilder Warn() => _warn; + public FormatterBuilder Error() => _error; + + public ReporterBuilder Verbose(Action configure) + { + configure(_verbose); + return this; + } + + public ReporterBuilder Output(Action configure) + { + configure(_output); + return this; + } + + public ReporterBuilder Warn(Action configure) + { + configure(_warn); + return this; + } + + public ReporterBuilder Error(Action configure) + { + configure(_error); + return this; + } + + public IReporter Build() + { + if (_console == null) + { + throw new InvalidOperationException($"Cannot build without first calling {nameof(WithConsole)}"); + } + + return new FormattingReporter(_console, + _verbose.Build(), + _output.Build(), + _warn.Build(), + _error.Build()); + } + } +} \ No newline at end of file diff --git a/src/Shared/StringExtensions.cs b/src/Shared/StringExtensions.cs deleted file mode 100644 index fdb087cfcd..0000000000 --- a/src/Shared/StringExtensions.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace System -{ - public static class StringExtensions - { - public static string Black(this string text) - => "\x1B[30m" + text + "\x1B[39m"; - - public static string Red(this string text) - => "\x1B[31m" + text + "\x1B[39m"; - - public static string Green(this string text) - => "\x1B[32m" + text + "\x1B[39m"; - - public static string Yellow(this string text) - => "\x1B[33m" + text + "\x1B[39m"; - - public static string Blue(this string text) - => "\x1B[34m" + text + "\x1B[39m"; - - public static string Magenta(this string text) - => "\x1B[35m" + text + "\x1B[39m"; - - public static string Cyan(this string text) - => "\x1B[36m" + text + "\x1B[39m"; - - public static string White(this string text) - => "\x1B[37m" + text + "\x1B[39m"; - - public static string Bold(this string text) - => "\x1B[1m" + text + "\x1B[22m"; - } -} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs index 1deb015023..129d1219fa 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Text; +using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Tools.Internal; using Xunit; using Xunit.Abstractions; @@ -14,14 +15,12 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests { private readonly IConsole _console; private readonly StringBuilder _stdout = new StringBuilder(); - private readonly StringBuilder _stderr = new StringBuilder(); public CommandLineOptionsTests(ITestOutputHelper output) { _console = new TestConsole(output) { Out = new StringWriter(_stdout), - Error = new StringWriter(_stderr), }; } @@ -57,8 +56,8 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests [Fact] public void CannotHaveQuietAndVerbose() { - Assert.Null(CommandLineOptions.Parse(new[] { "--quiet", "--verbose" }, _console)); - Assert.Contains(Resources.Error_QuietAndVerboseSpecified, _stderr.ToString()); + var ex = Assert.Throws(() => CommandLineOptions.Parse(new[] { "--quiet", "--verbose" }, _console)); + Assert.Equal(Resources.Error_QuietAndVerboseSpecified, ex.Message); } } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs index e196742f15..39c69ce4cc 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs @@ -7,7 +7,7 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Microsoft.DotNet.Watcher.Internal; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Tools.Internal; using Xunit; using Xunit.Abstractions; @@ -17,11 +17,11 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests public class MsBuildFileSetFactoryTest : IDisposable { - private ILogger _logger; + private readonly IReporter _reporter; private readonly TemporaryDirectory _tempDir; public MsBuildFileSetFactoryTest(ITestOutputHelper output) { - _logger = new XunitLogger(output); + _reporter = new TestReporter(output); _tempDir = new TemporaryDirectory(); } @@ -255,7 +255,7 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests graph.Find("A").WithProjectReference(graph.Find("W"), watch: false); var output = new OutputSink(); - var filesetFactory = new MsBuildFileSetFactory(_logger, graph.GetOrCreate("A").Path, output) + var filesetFactory = new MsBuildFileSetFactory(_reporter, graph.GetOrCreate("A").Path, output) { // enables capturing markers to know which projects have been visited BuildFlags = { "/p:_DotNetWatchTraceOutput=true" } @@ -263,7 +263,7 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests var fileset = await GetFileSet(filesetFactory); - _logger.LogInformation(string.Join( + _reporter.Output(string.Join( Environment.NewLine, output.Current.Lines.Select(l => "Sink output: " + l))); @@ -297,7 +297,7 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests } private Task GetFileSet(TemporaryCSharpProject target) - => GetFileSet(new MsBuildFileSetFactory(_logger, target.Path)); + => GetFileSet(new MsBuildFileSetFactory(_reporter, target.Path)); private async Task GetFileSet(MsBuildFileSetFactory filesetFactory) { _tempDir.Create(); diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/XunitLogger.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/XunitLogger.cs deleted file mode 100644 index 0e48fde773..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/XunitLogger.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.Extensions.Logging; -using Xunit.Abstractions; - -namespace Microsoft.DotNet.Watcher.Tools.Tests -{ - internal class XunitLogger : ILogger - { - private readonly ITestOutputHelper _output; - public XunitLogger(ITestOutputHelper output) - { - _output = output; - } - - public IDisposable BeginScope(TState state) - => NullScope.Instance; - - public bool IsEnabled(LogLevel logLevel) => true; - - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) - { - _output.WriteLine($"{logLevel}: {formatter(state, exception)}"); - } - - private class NullScope : IDisposable - { - private NullScope() { } - public static NullScope Instance = new NullScope(); - public void Dispose() { } - } - } -} \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs index d003c12234..ee7ca55247 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs @@ -7,7 +7,6 @@ using System.IO; using System.Text; using Microsoft.Extensions.Configuration.UserSecrets; using Microsoft.Extensions.Configuration.UserSecrets.Tests; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Tools.Internal; using Xunit; using Xunit.Abstractions; @@ -16,23 +15,24 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests { public class SecretManagerTests : IClassFixture { - private readonly TestLogger _logger; private readonly TestConsole _console; private readonly UserSecretsTestFixture _fixture; + private readonly StringBuilder _output = new StringBuilder(); public SecretManagerTests(UserSecretsTestFixture fixture, ITestOutputHelper output) { _fixture = fixture; - _logger = new TestLogger(output); - _console = new TestConsole(output); + + _console = new TestConsole(output) + { + Error = new StringWriter(_output), + Out = new StringWriter(_output), + }; } private Program CreateProgram() { - return new Program(_console, Directory.GetCurrentDirectory()) - { - Logger = _logger - }; + return new Program(_console, Directory.GetCurrentDirectory()); } [Theory] @@ -44,7 +44,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests var secretManager = CreateProgram(); secretManager.RunInternal("list", "-p", project); - Assert.Contains(Resources.FormatError_ProjectMissingId(project), _logger.Messages); + Assert.Contains(Resources.FormatError_ProjectMissingId(project), _output.ToString()); } [Fact] @@ -54,7 +54,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests var secretManager = CreateProgram(); secretManager.RunInternal("list", "-p", project); - Assert.Contains(Resources.FormatError_ProjectFailedToLoad(project), _logger.Messages); + Assert.Contains(Resources.FormatError_ProjectFailedToLoad(project), _output.ToString()); } [Fact] @@ -64,7 +64,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests var secretManager = CreateProgram(); secretManager.RunInternal("list", "--project", projectPath); - Assert.Contains(Resources.FormatError_ProjectPath_NotFound(projectPath), _logger.Messages); + Assert.Contains(Resources.FormatError_ProjectPath_NotFound(projectPath), _output.ToString()); } [Fact] @@ -73,12 +73,11 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests var projectPath = _fixture.GetTempSecretProject(); var cwd = Path.Combine(projectPath, "nested1"); Directory.CreateDirectory(cwd); - var secretManager = new Program(_console, cwd) { Logger = _logger, CommandOutputProvider = _logger.CommandOutputProvider }; - secretManager.CommandOutputProvider.LogLevel = LogLevel.Debug; + var secretManager = new Program(_console, cwd); secretManager.RunInternal("list", "-p", ".." + Path.DirectorySeparatorChar, "--verbose"); - Assert.Contains(Resources.FormatMessage_Project_File_Path(Path.Combine(cwd, "..", "TestProject.csproj")), _logger.Messages); + Assert.Contains(Resources.FormatMessage_Project_File_Path(Path.Combine(cwd, "..", "TestProject.csproj")), _output.ToString()); } [Theory] @@ -98,7 +97,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests var dir = fromCurrentDirectory ? projectPath : Path.GetTempPath(); - var secretManager = new Program(_console, dir) { Logger = _logger }; + var secretManager = new Program(_console, dir); foreach (var secret in secrets) { @@ -108,30 +107,27 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests secretManager.RunInternal(parameters); } - Assert.Equal(4, _logger.Messages.Count); - foreach (var keyValue in secrets) { Assert.Contains( string.Format("Successfully saved {0} = {1} to the secret store.", keyValue.Key, keyValue.Value), - _logger.Messages); + _output.ToString()); } - _logger.Messages.Clear(); + _output.Clear(); var args = fromCurrentDirectory ? new string[] { "list" } : new string[] { "list", "-p", projectPath }; secretManager.RunInternal(args); - Assert.Equal(4, _logger.Messages.Count); foreach (var keyValue in secrets) { Assert.Contains( string.Format("{0} = {1}", keyValue.Key, keyValue.Value), - _logger.Messages); + _output.ToString()); } // Remove secrets. - _logger.Messages.Clear(); + _output.Clear(); foreach (var secret in secrets) { var parameters = fromCurrentDirectory ? @@ -141,13 +137,12 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests } // Verify secrets are removed. - _logger.Messages.Clear(); + _output.Clear(); args = fromCurrentDirectory ? new string[] { "list" } : new string[] { "list", "-p", projectPath }; secretManager.RunInternal(args); - Assert.Equal(1, _logger.Messages.Count); - Assert.Contains(Resources.Error_No_Secrets_Found, _logger.Messages); + Assert.Contains(Resources.Error_No_Secrets_Found, _output.ToString()); } [Fact] @@ -157,17 +152,14 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests var secretManager = CreateProgram(); secretManager.RunInternal("set", "secret1", "value1", "-p", projectPath); - Assert.Equal(1, _logger.Messages.Count); - Assert.Contains("Successfully saved secret1 = value1 to the secret store.", _logger.Messages); + Assert.Contains("Successfully saved secret1 = value1 to the secret store.", _output.ToString()); secretManager.RunInternal("set", "secret1", "value2", "-p", projectPath); - Assert.Equal(2, _logger.Messages.Count); - Assert.Contains("Successfully saved secret1 = value2 to the secret store.", _logger.Messages); + Assert.Contains("Successfully saved secret1 = value2 to the secret store.", _output.ToString()); - _logger.Messages.Clear(); + _output.Clear(); secretManager.RunInternal("list", "-p", projectPath); - Assert.Equal(1, _logger.Messages.Count); - Assert.Contains("secret1 = value2", _logger.Messages); + Assert.Contains("secret1 = value2", _output.ToString()); } [Fact] @@ -175,22 +167,19 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests { string secretId; var projectPath = _fixture.GetTempSecretProject(out secretId); - _logger.SetLevel(LogLevel.Debug); var secretManager = CreateProgram(); secretManager.RunInternal("-v", "set", "secret1", "value1", "-p", projectPath); - Assert.Equal(3, _logger.Messages.Count); - Assert.Contains(string.Format("Project file path {0}.", Path.Combine(projectPath, "TestProject.csproj")), _logger.Messages); - Assert.Contains(string.Format("Secrets file path {0}.", PathHelper.GetSecretsPathFromSecretsId(secretId)), _logger.Messages); - Assert.Contains("Successfully saved secret1 = value1 to the secret store.", _logger.Messages); - _logger.Messages.Clear(); + Assert.Contains(string.Format("Project file path {0}.", Path.Combine(projectPath, "TestProject.csproj")), _output.ToString()); + Assert.Contains(string.Format("Secrets file path {0}.", PathHelper.GetSecretsPathFromSecretsId(secretId)), _output.ToString()); + Assert.Contains("Successfully saved secret1 = value1 to the secret store.", _output.ToString()); + _output.Clear(); secretManager.RunInternal("-v", "list", "-p", projectPath); - Assert.Equal(3, _logger.Messages.Count); - Assert.Contains(string.Format("Project file path {0}.", Path.Combine(projectPath, "TestProject.csproj")), _logger.Messages); - Assert.Contains(string.Format("Secrets file path {0}.", PathHelper.GetSecretsPathFromSecretsId(secretId)), _logger.Messages); - Assert.Contains("secret1 = value1", _logger.Messages); + Assert.Contains(string.Format("Project file path {0}.", Path.Combine(projectPath, "TestProject.csproj")), _output.ToString()); + Assert.Contains(string.Format("Secrets file path {0}.", PathHelper.GetSecretsPathFromSecretsId(secretId)), _output.ToString()); + Assert.Contains("secret1 = value1", _output.ToString()); } [Fact] @@ -199,8 +188,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests var projectPath = _fixture.GetTempSecretProject(); var secretManager = CreateProgram(); secretManager.RunInternal("remove", "secret1", "-p", projectPath); - Assert.Equal(1, _logger.Messages.Count); - Assert.Contains("Cannot find 'secret1' in the secret store.", _logger.Messages); + Assert.Contains("Cannot find 'secret1' in the secret store.", _output.ToString()); } [Fact] @@ -210,14 +198,13 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests var secretManager = CreateProgram(); secretManager.RunInternal("set", "SeCreT1", "value", "-p", projectPath); secretManager.RunInternal("list", "-p", projectPath); - Assert.Contains("SeCreT1 = value", _logger.Messages); + Assert.Contains("SeCreT1 = value", _output.ToString()); secretManager.RunInternal("remove", "secret1", "-p", projectPath); - Assert.Equal(2, _logger.Messages.Count); - _logger.Messages.Clear(); + _output.Clear(); secretManager.RunInternal("list", "-p", projectPath); - Assert.Contains(Resources.Error_No_Secrets_Found, _logger.Messages); + Assert.Contains(Resources.Error_No_Secrets_Found, _output.ToString()); } [Fact] @@ -230,23 +217,20 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests File.WriteAllText(secretsFile, @"{ ""AzureAd"": { ""ClientSecret"": ""abcd郩˙î""} }", Encoding.UTF8); var secretManager = CreateProgram(); secretManager.RunInternal("list", "-p", projectPath); - Assert.Equal(1, _logger.Messages.Count); - Assert.Contains("AzureAd:ClientSecret = abcd郩˙î", _logger.Messages); + Assert.Contains("AzureAd:ClientSecret = abcd郩˙î", _output.ToString()); } [Fact] public void List_Json() { - var output = new StringBuilder(); - _console.Out = new StringWriter(output); string id; var projectPath = _fixture.GetTempSecretProject(out id); var secretsFile = PathHelper.GetSecretsPathFromSecretsId(id); Directory.CreateDirectory(Path.GetDirectoryName(secretsFile)); File.WriteAllText(secretsFile, @"{ ""AzureAd"": { ""ClientSecret"": ""abcd郩˙î""} }", Encoding.UTF8); - var secretManager = new Program(_console, Path.GetDirectoryName(projectPath)) { Logger = _logger }; + var secretManager = new Program(_console, Path.GetDirectoryName(projectPath)); secretManager.RunInternal("list", "--id", id, "--json"); - var stdout = output.ToString(); + var stdout = _output.ToString(); Assert.Contains("//BEGIN", stdout); Assert.Contains(@"""AzureAd:ClientSecret"": ""abcd郩˙î""", stdout); Assert.Contains("//END", stdout); @@ -262,11 +246,9 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests File.WriteAllText(secretsFile, @"{ ""AzureAd"": { ""ClientSecret"": ""abcd郩˙î""} }", Encoding.UTF8); var secretManager = CreateProgram(); secretManager.RunInternal("set", "AzureAd:ClientSecret", "¡™£¢∞", "-p", projectPath); - Assert.Equal(1, _logger.Messages.Count); secretManager.RunInternal("list", "-p", projectPath); - Assert.Equal(2, _logger.Messages.Count); - Assert.Contains("AzureAd:ClientSecret = ¡™£¢∞", _logger.Messages); + Assert.Contains("AzureAd:ClientSecret = ¡™£¢∞", _output.ToString()); var fileContents = File.ReadAllText(secretsFile, Encoding.UTF8); Assert.Equal(@"{ ""AzureAd:ClientSecret"": ""¡™£¢∞"" @@ -280,8 +262,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests var projectPath = _fixture.GetTempSecretProject(); var secretManager = CreateProgram(); secretManager.RunInternal("list", "-p", projectPath); - Assert.Equal(1, _logger.Messages.Count); - Assert.Contains(Resources.Error_No_Secrets_Found, _logger.Messages); + Assert.Contains(Resources.Error_No_Secrets_Found, _output.ToString()); } [Theory] @@ -295,7 +276,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests ? projectPath : Path.GetTempPath(); - var secretManager = new Program(_console, dir) { Logger = _logger }; + var secretManager = new Program(_console, dir); var secrets = new KeyValuePair[] { @@ -313,39 +294,34 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests secretManager.RunInternal(parameters); } - Assert.Equal(4, _logger.Messages.Count); - foreach (var keyValue in secrets) { Assert.Contains( string.Format("Successfully saved {0} = {1} to the secret store.", keyValue.Key, keyValue.Value), - _logger.Messages); + _output.ToString()); } // Verify secrets are persisted. - _logger.Messages.Clear(); + _output.Clear(); var args = fromCurrentDirectory ? new string[] { "list" } : new string[] { "list", "-p", projectPath }; secretManager.RunInternal(args); - Assert.Equal(4, _logger.Messages.Count); foreach (var keyValue in secrets) { Assert.Contains( string.Format("{0} = {1}", keyValue.Key, keyValue.Value), - _logger.Messages); + _output.ToString()); } // Clear secrets. - _logger.Messages.Clear(); + _output.Clear(); args = fromCurrentDirectory ? new string[] { "clear" } : new string[] { "clear", "-p", projectPath }; secretManager.RunInternal(args); - Assert.Equal(0, _logger.Messages.Count); args = fromCurrentDirectory ? new string[] { "list" } : new string[] { "list", "-p", projectPath }; secretManager.RunInternal(args); - Assert.Equal(1, _logger.Messages.Count); - Assert.Contains(Resources.Error_No_Secrets_Found, _logger.Messages); + Assert.Contains(Resources.Error_No_Secrets_Found, _output.ToString()); } } } \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs index 4a3a94c716..99941fad91 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs @@ -1,11 +1,9 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.IO; using System.Collections.Generic; using Microsoft.Extensions.SecretManager.Tools.Internal; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Tools.Internal; using Xunit; using Xunit.Abstractions; @@ -36,10 +34,10 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests IsInputRedirected = true, In = new StringReader(input) }; - var secretStore = new TestSecretsStore(); + var secretStore = new TestSecretsStore(_output); var command = new SetCommand.FromStdInStrategy(); - command.Execute(new CommandContext(secretStore, NullLogger.Instance, testConsole)); + command.Execute(new CommandContext(secretStore, new TestReporter(_output), testConsole)); Assert.Equal(3, secretStore.Count); Assert.Equal("str value", secretStore["Key1"]); @@ -63,10 +61,10 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests IsInputRedirected = true, In = new StringReader(input) }; - var secretStore = new TestSecretsStore(); + var secretStore = new TestSecretsStore(_output); var command = new SetCommand.FromStdInStrategy(); - command.Execute(new CommandContext(secretStore, NullLogger.Instance, testConsole)); + command.Execute(new CommandContext(secretStore, new TestReporter(_output), testConsole)); Assert.Equal(3, secretStore.Count); Assert.True(secretStore.ContainsKey("Key1:nested")); @@ -89,8 +87,8 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests private class TestSecretsStore : SecretsStore { - public TestSecretsStore() - : base("xyz", NullLogger.Instance) + public TestSecretsStore(ITestOutputHelper output) + : base("xyz", new TestReporter(output)) { } @@ -105,25 +103,4 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests } } } - - public class NullLogger : ILogger - { - public static NullLogger Instance = new NullLogger(); - - private class NullScope : IDisposable - { - public void Dispose() - { - } - } - public IDisposable BeginScope(TState state) - => new NullScope(); - - public bool IsEnabled(LogLevel logLevel) - => true; - - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) - { - } - } } diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/TestLogger.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/TestLogger.cs deleted file mode 100644 index 94df0ce5b2..0000000000 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/TestLogger.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using Microsoft.Extensions.Logging; -using Xunit.Abstractions; - -namespace Microsoft.Extensions.SecretManager.Tools.Tests -{ - public class TestLogger : ILogger - { - private readonly ILogger _wrapped; - private readonly ITestOutputHelper _output; - - public TestLogger(ITestOutputHelper output = null) - { - CommandOutputProvider = new CommandOutputProvider(); - _wrapped = CommandOutputProvider.CreateLogger(""); - _output = output; - } - public CommandOutputProvider CommandOutputProvider { get;} - - public void SetLevel(LogLevel level) - { - CommandOutputProvider.LogLevel = level; - } - - public List Messages { get; set; } = new List(); - - public IDisposable BeginScope(TState state) - { - throw new NotImplementedException(); - } - - public bool IsEnabled(LogLevel logLevel) - { - return _wrapped.IsEnabled(logLevel); - } - - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) - { - if (IsEnabled(logLevel)) - { - Messages.Add(formatter(state, exception)); - _output?.WriteLine(formatter(state, exception)); - } - } - } -} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/ArgumentEscaperTests.cs b/test/Microsoft.Extensions.Tools.Tests/ArgumentEscaperTests.cs similarity index 95% rename from test/Microsoft.DotNet.Watcher.Tools.Tests/ArgumentEscaperTests.cs rename to test/Microsoft.Extensions.Tools.Tests/ArgumentEscaperTests.cs index 70c18b584c..78119021d9 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/ArgumentEscaperTests.cs +++ b/test/Microsoft.Extensions.Tools.Tests/ArgumentEscaperTests.cs @@ -4,7 +4,7 @@ using Microsoft.Extensions.Tools.Internal; using Xunit; -namespace Microsoft.DotNet.Watcher.Tools.Tests +namespace Microsoft.Extensions.Tools.Tests { public class ArgumentEscaperTests { diff --git a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.xproj b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.xproj new file mode 100644 index 0000000000..fec649a8a5 --- /dev/null +++ b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.xproj @@ -0,0 +1,22 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + {A24BF1D1-4326-4455-A528-09F1E20EDC83} + {8BB2217D-0F2D-49D1-97BC-3654ED321F3B} + Microsoft.Extensions.Tools.Tests + .\obj + .\bin\ + v4.5.1 + + + + 2.0 + + + diff --git a/test/Microsoft.Extensions.Tools.Tests/ReporterTests.cs b/test/Microsoft.Extensions.Tools.Tests/ReporterTests.cs new file mode 100644 index 0000000000..5c6cde5109 --- /dev/null +++ b/test/Microsoft.Extensions.Tools.Tests/ReporterTests.cs @@ -0,0 +1,103 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Text; +using Microsoft.Extensions.Tools.Internal; +using Xunit; + +namespace Microsoft.Extensions.Tools.Tests +{ + public class ReporterTests + { + private static readonly string EOL = Environment.NewLine; + + [Theory] + [InlineData(ConsoleColor.DarkGray, "\x1B[90m")] + [InlineData(ConsoleColor.Red, "\x1B[91m")] + [InlineData(ConsoleColor.Yellow, "\x1B[93m")] + public void WrapsWithAnsiColorCode(ConsoleColor color, string code) + { + Assert.Equal($"{code}sample\x1B[39m", new ColorFormatter(color).Format("sample")); + } + + [Fact] + public void SkipsColorCodesForEmptyOrNullInput() + { + var formatter = new ColorFormatter(ConsoleColor.Blue); + Assert.Empty(formatter.Format(string.Empty)); + Assert.Null(formatter.Format(null)); + } + + [Fact] + public void WritesToStandardStreams() + { + var testConsole = new TestConsole(); + var reporter = new FormattingReporter(testConsole, + DefaultFormatter.Instance, DefaultFormatter.Instance, + DefaultFormatter.Instance, DefaultFormatter.Instance); + + // stdout + reporter.Verbose("verbose"); + Assert.Equal("verbose" + EOL, testConsole.GetOutput()); + testConsole.Clear(); + + reporter.Output("out"); + Assert.Equal("out" + EOL, testConsole.GetOutput()); + testConsole.Clear(); + + reporter.Warn("warn"); + Assert.Equal("warn" + EOL, testConsole.GetOutput()); + testConsole.Clear(); + + // stderr + reporter.Error("error"); + Assert.Equal("error" + EOL, testConsole.GetError()); + testConsole.Clear(); + } + + [Fact] + public void FailsToBuildWithoutConsole() + { + Assert.Throws( + () => new ReporterBuilder().Build()); + } + + private class TestConsole : IConsole + { + private readonly StringBuilder _out; + private readonly StringBuilder _error; + + public TestConsole() + { + _out = new StringBuilder(); + _error = new StringBuilder(); + Out = new StringWriter(_out); + Error = new StringWriter(_error); + } + + event ConsoleCancelEventHandler IConsole.CancelKeyPress + { + add { } + remove { } + } + + public string GetOutput() => _out.ToString(); + public string GetError() => _error.ToString(); + + public void Clear() + { + _out.Clear(); + _error.Clear(); + } + + public TextWriter Out { get; } + public TextWriter Error { get; } + public TextReader In { get; } + public bool IsInputRedirected { get; } + public bool IsOutputRedirected { get; } + public bool IsErrorRedirected { get; } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.Extensions.Tools.Tests/project.json b/test/Microsoft.Extensions.Tools.Tests/project.json new file mode 100644 index 0000000000..2696161c61 --- /dev/null +++ b/test/Microsoft.Extensions.Tools.Tests/project.json @@ -0,0 +1,23 @@ +{ + "buildOptions": { + "warningsAsErrors": true, + "keyFile": "../../tools/Key.snk", + "compile": "../../src/Shared/**/*.cs" + }, + "dependencies": { + "dotnet-test-xunit": "2.2.0-preview2-build1029", + "Microsoft.DotNet.InternalAbstractions": "1.0.500-preview2-1-003177", + "xunit": "2.2.0-beta3-build3402" + }, + "testRunner": "xunit", + "frameworks": { + "netcoreapp1.0": { + "dependencies": { + "Microsoft.NETCore.App": { + "version": "1.0.1", + "type": "platform" + } + } + } + } +} \ No newline at end of file diff --git a/test/Shared/TestConsole.cs b/test/Shared/TestConsole.cs index 415cc60499..fd98ff529b 100644 --- a/test/Shared/TestConsole.cs +++ b/test/Shared/TestConsole.cs @@ -25,6 +25,8 @@ namespace Microsoft.Extensions.Tools.Internal public TextWriter Out { get; set; } public TextReader In { get; set; } = new StringReader(string.Empty); public bool IsInputRedirected { get; set; } = false; + public bool IsOutputRedirected { get; } = false; + public bool IsErrorRedirected { get; } = false; public ConsoleCancelEventArgs ConsoleCancelKey() { diff --git a/test/Shared/TestReporter.cs b/test/Shared/TestReporter.cs new file mode 100644 index 0000000000..e1ed0f5352 --- /dev/null +++ b/test/Shared/TestReporter.cs @@ -0,0 +1,37 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Xunit.Abstractions; + +namespace Microsoft.Extensions.Tools.Internal +{ + public class TestReporter : IReporter + { + private readonly ITestOutputHelper _output; + + public TestReporter(ITestOutputHelper output) + { + _output = output; + } + + public void Verbose(string message) + { + _output.WriteLine("verbose: " + message); + } + + public void Output(string message) + { + _output.WriteLine("output: " + message); + } + + public void Warn(string message) + { + _output.WriteLine("warn: " + message); + } + + public void Error(string message) + { + _output.WriteLine("error: " + message); + } + } +} \ No newline at end of file From 6decb66d8cc34084a0cb79368d357d5d58cd31da Mon Sep 17 00:00:00 2001 From: Prafull Bhosale Date: Mon, 5 Dec 2016 18:24:32 -0800 Subject: [PATCH 0366/1029] Upgrade Cli.Utils to preview4-004215 --- src/Microsoft.Extensions.SecretManager.Tools/project.json | 2 +- .../Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index 88d09cae94..00c33e8d1e 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -38,7 +38,7 @@ ] }, "dependencies": { - "Microsoft.DotNet.Cli.Utils": "1.0.0-preview3-004056", + "Microsoft.DotNet.Cli.Utils": "1.0.0-preview4-004215", "Microsoft.Extensions.Configuration.UserSecrets": "1.0.0", "Microsoft.Extensions.Logging": "1.0.0", "Microsoft.NETCore.App": { diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json index 4e28d24c2f..4634f2d708 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json @@ -11,7 +11,7 @@ }, "dependencies": { "dotnet-test-xunit": "2.2.0-preview2-build1029", - "Microsoft.DotNet.Cli.Utils": "1.0.0-preview3-004056", + "Microsoft.DotNet.Cli.Utils": "1.0.0-preview4-004215", "Microsoft.DotNet.InternalAbstractions": "1.0.0", "Microsoft.AspNetCore.Testing": "1.0.0", "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", From 80e643033272c35a47d310d03fc251c9b358fbf9 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 7 Dec 2016 09:28:55 -0800 Subject: [PATCH 0367/1029] Re-add dotnet-cli feeds in order to use preview4 packages --- NuGet.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NuGet.config b/NuGet.config index 146dd774ef..5144de9b69 100644 --- a/NuGet.config +++ b/NuGet.config @@ -2,6 +2,8 @@ + + From f2778165567614face7c9d3bf8af22c8459066c7 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 7 Dec 2016 09:30:18 -0800 Subject: [PATCH 0368/1029] Update packaging for tools Move targets files in to 'toolassets'. The 'tools' folder has conventions in NuGet that we don't want applied to these packages. Downgrade to Microsoft.NETCore.App 1.0.0 Add 'prefercliruntime' package. --- .../Internal/MsBuildFileSetFactory.cs | 5 ++- .../Microsoft.DotNet.Watcher.Tools.nuspec | 9 +++-- .../prefercliruntime | 0 .../project.json | 17 ++------- .../DotNetWatchCommon.targets | 0 .../DotNetWatchInner.targets | 0 .../DotNetWatchOuter.targets | 0 ....Extensions.Caching.SqlConfig.Tools.nuspec | 1 + .../prefercliruntime | 0 .../project.json | 16 ++------ .../Internal/ProjectIdResolver.cs | 38 +++++-------------- ...soft.Extensions.SecretManager.Tools.nuspec | 3 +- .../prefercliruntime | 0 .../project.json | 29 ++------------ .../FindUserSecretsProperty.targets | 0 .../clean-assets.cmd | 8 ++-- .../clean-assets.sh | 8 ++-- .../copyfiles.cmd | 8 ++-- .../copyfiles.sh | 10 ++--- .../copyfiles.cmd | 9 +++++ .../copyfiles.sh | 12 ++++++ .../project.json | 3 ++ 22 files changed, 73 insertions(+), 103 deletions(-) create mode 100644 src/Microsoft.DotNet.Watcher.Tools/prefercliruntime rename src/Microsoft.DotNet.Watcher.Tools/{tools => toolassets}/DotNetWatchCommon.targets (100%) rename src/Microsoft.DotNet.Watcher.Tools/{tools => toolassets}/DotNetWatchInner.targets (100%) rename src/Microsoft.DotNet.Watcher.Tools/{tools => toolassets}/DotNetWatchOuter.targets (100%) create mode 100644 src/Microsoft.Extensions.Caching.SqlConfig.Tools/prefercliruntime create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/prefercliruntime rename src/Microsoft.Extensions.SecretManager.Tools/{ => toolassets}/FindUserSecretsProperty.targets (100%) create mode 100644 test/Microsoft.Extensions.SecretManager.Tools.Tests/copyfiles.cmd create mode 100755 test/Microsoft.Extensions.SecretManager.Tools.Tests/copyfiles.sh diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs index 1ff1175f76..5aded8f772 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs @@ -164,8 +164,9 @@ namespace Microsoft.DotNet.Watcher.Internal { AppContext.BaseDirectory, assemblyDir, - Path.Combine(assemblyDir, "../../tools"), // from nuget cache - Path.Combine(assemblyDir, "tools") // from local build + Path.Combine(assemblyDir, "../../toolassets"), // from nuget cache + Path.Combine(assemblyDir, "toolassets"), // from local build + Path.Combine(AppContext.BaseDirectory, "../../toolassets"), // relative to packaged deps.json }; var targetPath = searchPaths.Select(p => Path.Combine(p, WatchTargetsFileName)).First(File.Exists); diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec index 61ccec29df..22054d71df 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec @@ -19,12 +19,13 @@ + - - - - + + + + \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/prefercliruntime b/src/Microsoft.DotNet.Watcher.Tools/prefercliruntime new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json index c60e93de77..945f21c9c5 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ b/src/Microsoft.DotNet.Watcher.Tools/project.json @@ -1,22 +1,12 @@ { "version": "1.0.0-*", - "description": "Command line tool to watch for source file changes during development and restart the dotnet command.", - "packOptions": { - "tags": [ - "dotnet", - "watch" - ], - "files": { - "include": "tools/*.targets" - } - }, "buildOptions": { "outputName": "dotnet-watch", "warningsAsErrors": true, "emitEntryPoint": true, "debugType": "portable", "keyFile": "../../tools/Key.snk", - "copyToOutput": "tools/*.targets", + "copyToOutput": "toolassets/*.targets", "embed": { "mappings": { "dotnetwatch.targets": "dotnetwatch.targets" @@ -28,7 +18,8 @@ }, "publishOptions": { "include": [ - "tools/*.targets" + "toolassets/*.targets", + "prefercliruntime" ] }, "dependencies": { @@ -38,7 +29,7 @@ }, "Microsoft.NETCore.App": { "type": "platform", - "version": "1.0.1" + "version": "1.0.0" } }, "frameworks": { diff --git a/src/Microsoft.DotNet.Watcher.Tools/tools/DotNetWatchCommon.targets b/src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatchCommon.targets similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/tools/DotNetWatchCommon.targets rename to src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatchCommon.targets diff --git a/src/Microsoft.DotNet.Watcher.Tools/tools/DotNetWatchInner.targets b/src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatchInner.targets similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/tools/DotNetWatchInner.targets rename to src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatchInner.targets diff --git a/src/Microsoft.DotNet.Watcher.Tools/tools/DotNetWatchOuter.targets b/src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatchOuter.targets similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/tools/DotNetWatchOuter.targets rename to src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatchOuter.targets diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec index 4103770bb4..afe20d84d3 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec @@ -20,6 +20,7 @@ + diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/prefercliruntime b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/prefercliruntime new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json index 27ce41031d..7fbfeae37d 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json @@ -6,23 +6,13 @@ "warningsAsErrors": true, "keyFile": "../../tools/Key.snk", "compile": "../Shared/**/*.cs" - }, - "description": "Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching.", - "packOptions": { - "repository": { - "type": "git", - "url": "https://github.com/aspnet/DotNetTools" - }, - "tags": [ - "cache", - "distributedcache", - "sqlserver" - ] + "publishOptions": { + "include": "prefercliruntime" }, "dependencies": { "Microsoft.NETCore.App": { - "version": "1.0.1", + "version": "1.0.0", "type": "platform" }, "System.Data.SqlClient": "4.1.0" diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs index 26de364cd5..2c891a3755 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs @@ -81,14 +81,6 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal return id; } - public void Dispose() - { - foreach (var file in _tempFiles) - { - TryDelete(file); - } - } - private string GetTargetFile() { var assemblyDir = Path.GetDirectoryName(GetType().GetTypeInfo().Assembly.Location); @@ -98,33 +90,23 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal { AppContext.BaseDirectory, assemblyDir, // next to assembly - Path.Combine(assemblyDir, "../../tools"), // inside the nupkg + Path.Combine(assemblyDir, "../../toolassets"), // inside the nupkg + Path.Combine(assemblyDir, "toolassets"), // for local builds + Path.Combine(AppContext.BaseDirectory, "../../toolassets"), // relative to packaged deps.json }; - var foundFile = searchPaths + return searchPaths .Select(dir => Path.Combine(dir, TargetsFileName)) .Where(File.Exists) - .FirstOrDefault(); + .First(); + } - if (foundFile != null) + public void Dispose() + { + foreach (var file in _tempFiles) { - return foundFile; + TryDelete(file); } - - // This should only really happen during testing. Current build system doesn't give us a good way to ensure the - // test project has an always-up to date version of the targets file. - // TODO cleanup after we switch to an MSBuild system in which can specify "CopyToOutputDirectory: Always" to resolve this issue - var outputPath = Path.GetTempFileName(); - using (var resource = GetType().GetTypeInfo().Assembly.GetManifestResourceStream(TargetsFileName)) - using (var stream = new FileStream(outputPath, FileMode.Create)) - { - resource.CopyTo(stream); - } - - // cleanup - _tempFiles.Add(outputPath); - - return outputPath; } private static void TryDelete(string file) diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec index eb63c1592c..5d47660dd5 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec @@ -22,7 +22,8 @@ - + + diff --git a/src/Microsoft.Extensions.SecretManager.Tools/prefercliruntime b/src/Microsoft.Extensions.SecretManager.Tools/prefercliruntime new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index 4b188c420a..9b198d29f1 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -5,42 +5,21 @@ "emitEntryPoint": true, "warningsAsErrors": true, "keyFile": "../../tools/Key.snk", - "copyToOutput": "*.targets", - "embed": { - "mappings": { - "FindUserSecretsProperty.targets": "./FindUserSecretsProperty.targets" - } - }, + "copyToOutput": "toolassets/*.targets", "compile": { "include": "../Shared/**/*.cs" } }, - "description": "Command line tool to manage user secrets for Microsoft.Extensions.Configuration.", - "packOptions": { - "repository": { - "type": "git", - "url": "https://github.com/aspnet/DotNetTools" - }, - "tags": [ - "configuration", - "secrets", - "usersecrets" - ], - "files": { - "mappings": { - "tools/FindUserSecretsProperty.targets": "FindUserSecretsProperty.targets" - } - } - }, "publishOptions": { "include": [ - "*.targets" + "toolassets/*.targets", + "prefercliruntime" ] }, "dependencies": { "Microsoft.Extensions.Configuration.UserSecrets": "1.0.0", "Microsoft.NETCore.App": { - "version": "1.0.1", + "version": "1.0.0", "type": "platform" } }, diff --git a/src/Microsoft.Extensions.SecretManager.Tools/FindUserSecretsProperty.targets b/src/Microsoft.Extensions.SecretManager.Tools/toolassets/FindUserSecretsProperty.targets similarity index 100% rename from src/Microsoft.Extensions.SecretManager.Tools/FindUserSecretsProperty.targets rename to src/Microsoft.Extensions.SecretManager.Tools/toolassets/FindUserSecretsProperty.targets diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.cmd b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.cmd index 2d1d41f1a8..f8999b5659 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.cmd +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.cmd @@ -3,9 +3,9 @@ if not "%1" == "" ( echo "Deleting %1\TestProjects" rmdir /s /q %1\TestProjects - echo "Deleting %1\tools" - rmdir /s /q %1\tools + echo "Deleting %1\toolassets" + rmdir /s /q %1\toolassets ) -mkdir %1\tools -copy ..\..\src\Microsoft.DotNet.Watcher.Tools\tools\*.targets %1\tools \ No newline at end of file +mkdir %1\toolassets +copy ..\..\src\Microsoft.DotNet.Watcher.Tools\toolassets\*.targets %1\toolassets \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.sh b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.sh index 5b096cd399..21b69ed268 100755 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.sh +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.sh @@ -4,11 +4,11 @@ if [ -z $1 ]; then echo "Deleting $1/TestProjects" rm -rf $1/TestProjects - echo "Deleting $1/tools" - rm -rf $1/tools + echo "Deleting $1/toolassets" + rm -rf $1/toolassets fi -mkdir -p $1/tools -cp ../../src/Microsoft.DotNet.Watcher.Tools/tools/*.targets $1/tools +mkdir -p $1/toolassets +cp ../../src/Microsoft.DotNet.Watcher.Tools/toolassets/*.targets $1/toolassets exit 0 \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.cmd b/test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.cmd index 812690859e..6bd0489a90 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.cmd +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.cmd @@ -1,9 +1,9 @@ @ECHO OFF :again if not "%1" == "" ( - echo "Deleting %1\tools" - rmdir /s /q %1\tools + echo "Deleting %1\toolassets" + rmdir /s /q %1\toolassets ) -mkdir %1\tools -copy ..\..\src\Microsoft.DotNet.Watcher.Tools\tools\*.targets %1\tools \ No newline at end of file +mkdir %1\toolassets +copy ..\..\src\Microsoft.DotNet.Watcher.Tools\toolassets\*.targets %1\toolassets \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.sh b/test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.sh index 8c12918ae7..78ae5ff657 100755 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.sh +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.sh @@ -1,12 +1,12 @@ #!/usr/bin/env bash if [ -z $1 ]; then - echo "Deleting $1/tools" - rm -rf $1/tools + echo "Deleting $1/toolassets" + rm -rf $1/toolassets fi -mkdir -p $1/tools -echo "Copying ./../src/Microsoft.DotNet.Watcher.Tools/tools/*.targets" -cp ../../src/Microsoft.DotNet.Watcher.Tools/tools/*.targets $1/tools +mkdir -p $1/toolassets +echo "Copying ./../src/Microsoft.DotNet.Watcher.Tools/toolassets/*.targets" +cp ../../src/Microsoft.DotNet.Watcher.Tools/toolassets/*.targets $1/toolassets exit 0 \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/copyfiles.cmd b/test/Microsoft.Extensions.SecretManager.Tools.Tests/copyfiles.cmd new file mode 100644 index 0000000000..7f24b7967f --- /dev/null +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/copyfiles.cmd @@ -0,0 +1,9 @@ +@ECHO OFF +:again +if not "%1" == "" ( + echo "Deleting %1\toolassets" + rmdir /s /q %1\toolassets +) + +mkdir %1\toolassets +copy ..\..\src\Microsoft.Extensions.SecretManager.Tools\toolassets\*.targets %1\toolassets \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/copyfiles.sh b/test/Microsoft.Extensions.SecretManager.Tools.Tests/copyfiles.sh new file mode 100755 index 0000000000..a1d6dfe373 --- /dev/null +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/copyfiles.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +if [ -z $1 ]; then + echo "Deleting $1/toolassets" + rm -rf $1/toolassets +fi + +mkdir -p $1/toolassets +echo "Copying ./../src/Microsoft.Extensions.SecretManager.Tools/toolassets/*.targets" +cp ../../src/Microsoft.Extensions.SecretManager.Tools/toolassets/*.targets $1/toolassets + +exit 0 \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json index 5cc4eeb1b1..f0095bea8d 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json @@ -20,5 +20,8 @@ } } } + }, + "scripts": { + "precompile": "copyfiles %compile:OutputDir%" } } \ No newline at end of file From d48f2abc7c460b4ee45f79e0d6276945dd69ddce Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 7 Dec 2016 14:32:41 -0800 Subject: [PATCH 0369/1029] Use MSBuild project extensions instead of importing the users project Implicit imports prevents using on a project file that has the Sdk attribute. This change instead generates a file in the MSBuildProjectExtensionsPath to inject targets require to find the UserSecretsId property in a project. Resolves #242 --- .../Internal/ProjectIdResolver.cs | 116 +++++++++--------- ...soft.Extensions.SecretManager.Tools.nuspec | 1 - .../Program.cs | 6 +- .../project.json | 11 +- .../resources/ProjectIdResolverTargets.xml | 5 + .../FindUserSecretsProperty.targets | 6 - .../UserSecretsTestFixture.cs | 8 +- 7 files changed, 70 insertions(+), 83 deletions(-) create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/resources/ProjectIdResolverTargets.xml delete mode 100644 src/Microsoft.Extensions.SecretManager.Tools/toolassets/FindUserSecretsProperty.targets diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs index 2c891a3755..a2d86da7ae 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs @@ -5,19 +5,16 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Linq; using System.Reflection; using Microsoft.Extensions.Tools.Internal; namespace Microsoft.Extensions.SecretManager.Tools.Internal { - public class ProjectIdResolver : IDisposable + public class ProjectIdResolver { - private const string TargetsFileName = "FindUserSecretsProperty.targets"; private const string DefaultConfig = "Debug"; private readonly IReporter _reporter; private readonly string _workingDirectory; - private readonly List _tempFiles = new List(); public ProjectIdResolver(IReporter reporter, string workingDirectory) { @@ -29,83 +26,82 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal { var finder = new MsBuildProjectFinder(_workingDirectory); var projectFile = finder.FindMsBuildProject(project); + EnsureProjectExtensionTargetsExist(projectFile); _reporter.Verbose(Resources.FormatMessage_Project_File_Path(projectFile)); - var targetFile = GetTargetFile(); - var outputFile = Path.GetTempFileName(); - _tempFiles.Add(outputFile); - configuration = !string.IsNullOrEmpty(configuration) ? configuration : DefaultConfig; - var args = new[] + var outputFile = Path.GetTempFileName(); + try { - "msbuild", - targetFile, - "/nologo", - "/t:_FindUserSecretsProperty", - $"/p:Project={projectFile}", - $"/p:OutputFile={outputFile}", - $"/p:Configuration={configuration}" - }; - var psi = new ProcessStartInfo - { - FileName = DotNetMuxer.MuxerPathOrDefault(), - Arguments = ArgumentEscaper.EscapeAndConcatenate(args), - RedirectStandardOutput = true, - RedirectStandardError = true - }; + var args = new[] + { + "msbuild", + projectFile, + "/nologo", + "/t:_ExtractUserSecretsMetadata", // defined in ProjectIdResolverTargets.xml + $"/p:_UserSecretsMetadataFile={outputFile}", + $"/p:Configuration={configuration}" + }; + var psi = new ProcessStartInfo + { + FileName = DotNetMuxer.MuxerPathOrDefault(), + Arguments = ArgumentEscaper.EscapeAndConcatenate(args), + RedirectStandardOutput = true, + RedirectStandardError = true + }; #if DEBUG - _reporter.Verbose($"Invoking '{psi.FileName} {psi.Arguments}'"); + _reporter.Verbose($"Invoking '{psi.FileName} {psi.Arguments}'"); #endif - var process = Process.Start(psi); - process.WaitForExit(); + var process = Process.Start(psi); + process.WaitForExit(); + + if (process.ExitCode != 0) + { + _reporter.Verbose(process.StandardOutput.ReadToEnd()); + _reporter.Verbose(process.StandardError.ReadToEnd()); + throw new InvalidOperationException(Resources.FormatError_ProjectFailedToLoad(projectFile)); + } + + var id = File.ReadAllText(outputFile)?.Trim(); + if (string.IsNullOrEmpty(id)) + { + throw new InvalidOperationException(Resources.FormatError_ProjectMissingId(projectFile)); + } + return id; - if (process.ExitCode != 0) - { - _reporter.Verbose(process.StandardOutput.ReadToEnd()); - _reporter.Verbose(process.StandardError.ReadToEnd()); - throw new InvalidOperationException(Resources.FormatError_ProjectFailedToLoad(projectFile)); } - - var id = File.ReadAllText(outputFile)?.Trim(); - if (string.IsNullOrEmpty(id)) + finally { - throw new InvalidOperationException(Resources.FormatError_ProjectMissingId(projectFile)); + TryDelete(outputFile); } - - return id; } - private string GetTargetFile() + private void EnsureProjectExtensionTargetsExist(string projectFile) { - var assemblyDir = Path.GetDirectoryName(GetType().GetTypeInfo().Assembly.Location); + // relies on MSBuildProjectExtensionsPath and Microsoft.Common.targets to import this file + // into the target project + var projectExtensionsPath = Path.Combine( + Path.GetDirectoryName(projectFile), + "obj", + $"{Path.GetFileName(projectFile)}.usersecrets.targets"); - // targets should be in one of these locations, depending on test setup and tools installation - var searchPaths = new[] + Directory.CreateDirectory(Path.GetDirectoryName(projectExtensionsPath)); + + // should overwrite the file always. Hypothetically, another version of the user-secrets tool + // could have already put a file here. We want to ensure the target file matches the currently + // running tool + using (var resource = GetType().GetTypeInfo().Assembly.GetManifestResourceStream("ProjectIdResolverTargets.xml")) + using (var stream = new FileStream(projectExtensionsPath, FileMode.Create)) + using (var writer = new StreamWriter(stream)) { - AppContext.BaseDirectory, - assemblyDir, // next to assembly - Path.Combine(assemblyDir, "../../toolassets"), // inside the nupkg - Path.Combine(assemblyDir, "toolassets"), // for local builds - Path.Combine(AppContext.BaseDirectory, "../../toolassets"), // relative to packaged deps.json - }; - - return searchPaths - .Select(dir => Path.Combine(dir, TargetsFileName)) - .Where(File.Exists) - .First(); - } - - public void Dispose() - { - foreach (var file in _tempFiles) - { - TryDelete(file); + writer.WriteLine(""); + resource.CopyTo(stream); } } diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec index 5d47660dd5..d528291728 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec @@ -23,7 +23,6 @@ - diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs index 5ff2a8e228..667c16b27f 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs @@ -124,10 +124,8 @@ namespace Microsoft.Extensions.SecretManager.Tools return options.Id; } - using (var resolver = new ProjectIdResolver(reporter, _workingDirectory)) - { - return resolver.Resolve(options.Project, options.Configuration); - } + var resolver = new ProjectIdResolver(reporter, _workingDirectory); + return resolver.Resolve(options.Project, options.Configuration); } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index 9b198d29f1..e33c4f90e0 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -5,16 +5,17 @@ "emitEntryPoint": true, "warningsAsErrors": true, "keyFile": "../../tools/Key.snk", - "copyToOutput": "toolassets/*.targets", + "embed": { + "mappings": { + "ProjectIdResolverTargets.xml": "./resources/ProjectIdResolverTargets.xml" + } + }, "compile": { "include": "../Shared/**/*.cs" } }, "publishOptions": { - "include": [ - "toolassets/*.targets", - "prefercliruntime" - ] + "include": "prefercliruntime" }, "dependencies": { "Microsoft.Extensions.Configuration.UserSecrets": "1.0.0", diff --git a/src/Microsoft.Extensions.SecretManager.Tools/resources/ProjectIdResolverTargets.xml b/src/Microsoft.Extensions.SecretManager.Tools/resources/ProjectIdResolverTargets.xml new file mode 100644 index 0000000000..a30a87d34a --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/resources/ProjectIdResolverTargets.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/toolassets/FindUserSecretsProperty.targets b/src/Microsoft.Extensions.SecretManager.Tools/toolassets/FindUserSecretsProperty.targets deleted file mode 100644 index 694dc25008..0000000000 --- a/src/Microsoft.Extensions.SecretManager.Tools/toolassets/FindUserSecretsProperty.targets +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs index a3ff3dfbb1..569ee1c6c3 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs @@ -32,9 +32,7 @@ namespace Microsoft.Extensions.Configuration.UserSecrets.Tests return GetTempSecretProject(out userSecretsId); } - private const string ProjectTemplate = @" - - + private const string ProjectTemplate = @" Exe netcoreapp1.0 @@ -43,12 +41,8 @@ namespace Microsoft.Extensions.Configuration.UserSecrets.Tests - - - - "; public string GetTempSecretProject(out string userSecretsId) From 5d8be62037127a1ac102a63e7a9ac7c21c3d8e88 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Thu, 8 Dec 2016 10:01:52 -0800 Subject: [PATCH 0370/1029] Update .travis.yml osx image to xcode7.3. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d7636fa329..a0be886892 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ mono: os: - linux - osx -osx_image: xcode7.1 +osx_image: xcode7.3 branches: only: - master From 00fc430658cb734338e87f6daf1edeaed8bbefe8 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Thu, 8 Dec 2016 10:02:26 -0800 Subject: [PATCH 0371/1029] Update .travis.yml osx image to xcode7.3. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a040cef874..94c466e49f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ mono: os: - linux - osx -osx_image: xcode7.1 +osx_image: xcode7.3 branches: only: - master From 9c90925f81b59a637b86f015d6fbba930c0d56d0 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Thu, 8 Dec 2016 10:02:30 -0800 Subject: [PATCH 0372/1029] Update .travis.yml osx image to xcode7.3. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e2abeda7d4..67d9a88786 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ mono: os: - linux - osx -osx_image: xcode7.1 +osx_image: xcode7.3 branches: only: - master From 9bf8486fe58017b0a0cb586f8a9ca04e9ada8728 Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Mon, 12 Dec 2016 00:42:23 -0800 Subject: [PATCH 0373/1029] Removed packages list in NuGetPackageVerifier.json --- NuGetPackageVerifier.json | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index f68002830f..b153ab1515 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -1,13 +1,5 @@ { - "adx": { // Packages written by the ADX team and that ship on NuGet.org - "rules": [ - "AdxVerificationCompositeRule" - ], - "packages": { - "Microsoft.AspNetCore.JsonPatch": { } - } - }, - "Default": { // Rules to run for packages not listed in any other set. + "Default": { "rules": [ "DefaultCompositeRule" ] From 3a9dff9c1c3884e3919ffa99a64b78485836ede9 Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Mon, 12 Dec 2016 00:42:29 -0800 Subject: [PATCH 0374/1029] Removed packages list in NuGetPackageVerifier.json --- NuGetPackageVerifier.json | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index 8df495e3e0..b153ab1515 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -1,14 +1,5 @@ { - "adx": { // Packages written by the ADX team and that ship on NuGet.org - "rules": [ - "AdxVerificationCompositeRule" - ], - "packages": { - "Microsoft.AspNetCore.Html.Abstractions": { }, - "Microsoft.Extensions.WebEncoders": { } - } - }, - "Default": { // Rules to run for packages not listed in any other set. + "Default": { "rules": [ "DefaultCompositeRule" ] From d6079d6595a1a8d043bae2d1a738ad5146a0bbc3 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 12 Dec 2016 09:48:02 -0800 Subject: [PATCH 0375/1029] update dotnet-user-secrets version to 1.0.0-msbuild2-update1 --- src/Microsoft.Extensions.SecretManager.Tools/project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index 00c33e8d1e..71db102962 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-msbuild2-final", + "version": "1.0.0-msbuild2-update1", "buildOptions": { "outputName": "dotnet-user-secrets", "emitEntryPoint": true, From d1f94460e20df077808aa4c84b7a564e558384e4 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 12 Dec 2016 10:32:50 -0800 Subject: [PATCH 0376/1029] Back-port fix for implicit imports for dotnet-user-secrets (#243) --- .../FindUserSecretsProperty.targets | 6 - .../Internal/ProjectIdResolver.cs | 121 ++++++++---------- ...soft.Extensions.SecretManager.Tools.nuspec | 1 - .../Program.cs | 6 +- .../project.json | 13 +- .../resources/ProjectIdResolverTargets.xml | 5 + .../UserSecretsTestFixture.cs | 8 +- 7 files changed, 59 insertions(+), 101 deletions(-) delete mode 100644 src/Microsoft.Extensions.SecretManager.Tools/FindUserSecretsProperty.targets create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/resources/ProjectIdResolverTargets.xml diff --git a/src/Microsoft.Extensions.SecretManager.Tools/FindUserSecretsProperty.targets b/src/Microsoft.Extensions.SecretManager.Tools/FindUserSecretsProperty.targets deleted file mode 100644 index 694dc25008..0000000000 --- a/src/Microsoft.Extensions.SecretManager.Tools/FindUserSecretsProperty.targets +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs index 683f412c83..88bddcd68e 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs @@ -4,19 +4,16 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Reflection; using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.Logging; namespace Microsoft.Extensions.SecretManager.Tools.Internal { - public class ProjectIdResolver : IDisposable + public class ProjectIdResolver { - private const string TargetsFileName = "FindUserSecretsProperty.targets"; private readonly ILogger _logger; private readonly string _workingDirectory; - private readonly List _tempFiles = new List(); public ProjectIdResolver(ILogger logger, string workingDirectory) { @@ -28,88 +25,70 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal { var finder = new MsBuildProjectFinder(_workingDirectory); var projectFile = finder.FindMsBuildProject(project); + EnsureProjectExtensionTargetsExist(projectFile); _logger.LogDebug(Resources.Message_Project_File_Path, projectFile); - var targetFile = GetTargetFile(); - var outputFile = Path.GetTempFileName(); - _tempFiles.Add(outputFile); - var commandOutput = new List(); - var commandResult = Command.CreateDotNet("msbuild", - new[] { - targetFile, - "/nologo", - "/t:_FindUserSecretsProperty", - $"/p:Project={projectFile}", - $"/p:OutputFile={outputFile}", - $"/p:Configuration={configuration}" - }) - .CaptureStdErr() - .CaptureStdOut() - .OnErrorLine(l => commandOutput.Add(l)) - .OnOutputLine(l => commandOutput.Add(l)) - .Execute(); - - if (commandResult.ExitCode != 0) + var outputFile = Path.GetTempFileName(); + try { - _logger.LogDebug(string.Join(Environment.NewLine, commandOutput)); - throw new GracefulException(Resources.FormatError_ProjectFailedToLoad(projectFile)); + var commandResult = Command.CreateDotNet("msbuild", + new[] { + projectFile, + "/nologo", + "/t:_ExtractUserSecretsMetadata", // defined in ProjectIdResolverTargets.xml + $"/p:_UserSecretsMetadataFile={outputFile}", + $"/p:Configuration={configuration}" + }) + .CaptureStdErr() + .CaptureStdOut() + .OnErrorLine(l => commandOutput.Add(l)) + .OnOutputLine(l => commandOutput.Add(l)) + .Execute(); + + if (commandResult.ExitCode != 0) + { + _logger.LogDebug(string.Join(Environment.NewLine, commandOutput)); + throw new GracefulException(Resources.FormatError_ProjectFailedToLoad(projectFile)); + } + + var id = File.ReadAllText(outputFile)?.Trim(); + if (string.IsNullOrEmpty(id)) + { + throw new GracefulException(Resources.FormatError_ProjectMissingId(projectFile)); + } + + return id; + } - - var id = File.ReadAllText(outputFile)?.Trim(); - if (string.IsNullOrEmpty(id)) + finally { - throw new GracefulException(Resources.FormatError_ProjectMissingId(projectFile)); - } - - return id; - } - - public void Dispose() - { - foreach (var file in _tempFiles) - { - TryDelete(file); + TryDelete(outputFile); } } - private string GetTargetFile() + private void EnsureProjectExtensionTargetsExist(string projectFile) { - var assemblyDir = Path.GetDirectoryName(GetType().GetTypeInfo().Assembly.Location); + // relies on MSBuildProjectExtensionsPath and Microsoft.Common.targets to import this file + // into the target project + var projectExtensionsPath = Path.Combine( + Path.GetDirectoryName(projectFile), + "obj", + $"{Path.GetFileName(projectFile)}.usersecrets.targets"); - // targets should be in one of these locations, depending on test setup and tools installation - var searchPaths = new[] - { - AppContext.BaseDirectory, - assemblyDir, // next to assembly - Path.Combine(assemblyDir, "../../tools"), // inside the nupkg - }; - - var foundFile = searchPaths - .Select(dir => Path.Combine(dir, TargetsFileName)) - .Where(File.Exists) - .FirstOrDefault(); - - if (foundFile != null) - { - return foundFile; - } - - // This should only really happen during testing. Current build system doesn't give us a good way to ensure the - // test project has an always-up to date version of the targets file. - // TODO cleanup after we switch to an MSBuild system in which can specify "CopyToOutputDirectory: Always" to resolve this issue - var outputPath = Path.GetTempFileName(); - using (var resource = GetType().GetTypeInfo().Assembly.GetManifestResourceStream(TargetsFileName)) - using (var stream = new FileStream(outputPath, FileMode.Create)) + Directory.CreateDirectory(Path.GetDirectoryName(projectExtensionsPath)); + + // should overwrite the file always. Hypothetically, another version of the user-secrets tool + // could have already put a file here. We want to ensure the target file matches the currently + // running tool + using (var resource = GetType().GetTypeInfo().Assembly.GetManifestResourceStream("ProjectIdResolverTargets.xml")) + using (var stream = new FileStream(projectExtensionsPath, FileMode.Create)) + using (var writer = new StreamWriter(stream)) { + writer.WriteLine(""); resource.CopyTo(stream); } - - // cleanup - _tempFiles.Add(outputPath); - - return outputPath; } private static void TryDelete(string file) diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec index f8c596e5e9..626339e76d 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec @@ -24,7 +24,6 @@ - diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs index 3ef60eb563..10e491c465 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs @@ -125,10 +125,8 @@ namespace Microsoft.Extensions.SecretManager.Tools return options.Id; } - using (var resolver = new ProjectIdResolver(Logger, _workingDirectory)) - { - return resolver.Resolve(options.Project, options.Configuration); - } + var resolver = new ProjectIdResolver(Logger, _workingDirectory); + return resolver.Resolve(options.Project, options.Configuration); } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json index 71db102962..4a60b24d2c 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ b/src/Microsoft.Extensions.SecretManager.Tools/project.json @@ -5,10 +5,9 @@ "emitEntryPoint": true, "warningsAsErrors": true, "keyFile": "../../tools/Key.snk", - "copyToOutput": "*.targets", "embed": { "mappings": { - "FindUserSecretsProperty.targets": "./FindUserSecretsProperty.targets" + "ProjectIdResolverTargets.xml": "./resources/ProjectIdResolverTargets.xml" } }, "compile": { @@ -25,16 +24,6 @@ "configuration", "secrets", "usersecrets" - ], - "files": { - "mappings": { - "tools/FindUserSecretsProperty.targets": "FindUserSecretsProperty.targets" - } - } - }, - "publishOptions": { - "include": [ - "*.targets" ] }, "dependencies": { diff --git a/src/Microsoft.Extensions.SecretManager.Tools/resources/ProjectIdResolverTargets.xml b/src/Microsoft.Extensions.SecretManager.Tools/resources/ProjectIdResolverTargets.xml new file mode 100644 index 0000000000..a30a87d34a --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/resources/ProjectIdResolverTargets.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs index a3ff3dfbb1..569ee1c6c3 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs @@ -32,9 +32,7 @@ namespace Microsoft.Extensions.Configuration.UserSecrets.Tests return GetTempSecretProject(out userSecretsId); } - private const string ProjectTemplate = @" - - + private const string ProjectTemplate = @" Exe netcoreapp1.0 @@ -43,12 +41,8 @@ namespace Microsoft.Extensions.Configuration.UserSecrets.Tests - - - - "; public string GetTempSecretProject(out string userSecretsId) From 902ff8dce315ff95de84ab82eeb0395bdab54610 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 12 Dec 2016 13:06:54 -0800 Subject: [PATCH 0377/1029] Build with MSBuild --- .gitignore | 1 + DotNetTools.sln | 64 +++---- NuGet.config | 5 +- {tools => build}/Key.snk | Bin build/common.props | 42 +++++ dir.props | 5 + global.json | 3 - makefile.shade | 32 ---- {src/Shared => shared}/ArgumentEscaper.cs | 0 {src/Shared => shared}/CliContext.cs | 0 .../CommandLine/AnsiConsole.cs | 0 .../CommandLine/CommandArgument.cs | 0 .../CommandLine/CommandLineApplication.cs | 0 .../CommandLine/CommandOption.cs | 0 .../CommandLine/CommandOptionType.cs | 0 .../CommandLine/CommandParsingException.cs | 0 .../CommandLineApplicationExtensions.cs | 0 {src/Shared => shared}/DebugHelper.cs | 0 {src/Shared => shared}/DotNetMuxer.cs | 0 {src/Shared => shared}/Ensure.cs | 0 {src/Shared => shared}/IConsole.cs | 0 {src/Shared => shared}/PhysicalConsole.cs | 0 .../Reporting/ColorFormatter.cs | 0 .../Reporting/CompositeFormatter.cs | 0 .../Reporting/ConditionalFormatter.cs | 0 .../Reporting/DefaultFormatter.cs | 0 .../Reporting/FormatterBuilder.cs | 0 .../Reporting/FormattingReporter.cs | 0 .../Shared => shared}/Reporting/IFormatter.cs | 0 {src/Shared => shared}/Reporting/IReporter.cs | 0 .../Reporting/PrefixFormatter.cs | 0 .../Reporting/ReporterBuilder.cs | 0 .../Microsoft.DotNet.Watcher.Tools.csproj | 23 +++ .../Microsoft.DotNet.Watcher.Tools.nuspec | 31 ---- .../Microsoft.DotNet.Watcher.Tools.xproj | 20 -- .../Properties/AssemblyInfo.cs | 9 +- .../Properties/InternalsVisibleTo.cs | 6 - .../Sources/ProcessHelper.cs | 115 ++++++++++++ .../project.json | 38 ---- ....Extensions.Caching.SqlConfig.Tools.csproj | 19 ++ ....Extensions.Caching.SqlConfig.Tools.nuspec | 28 --- ...t.Extensions.Caching.SqlConfig.Tools.xproj | 17 -- .../Properties/AssemblyInfo.cs | 5 - .../prefercliruntime | 0 .../project.json | 23 --- ...soft.Extensions.SecretManager.Tools.csproj | 22 +++ ...soft.Extensions.SecretManager.Tools.nuspec | 30 --- ...osoft.Extensions.SecretManager.Tools.xproj | 17 -- .../Properties/AssemblyInfo.cs | 7 +- .../Properties/InternalsVisibleTo.cs | 6 - .../prefercliruntime | 0 .../project.json | 30 --- src/dir.props | 12 ++ .../prefercliruntime | 0 ...otNet.Watcher.Tools.FunctionalTests.csproj | 22 +++ ...DotNet.Watcher.Tools.FunctionalTests.xproj | 20 -- .../Scenario/ProjectToolScenario.cs | 3 +- .../AppWithDeps/AppWithDeps.csproj | 6 +- .../TestProjects/Dependency/Dependency.csproj | 6 +- .../GlobbingApp/GlobbingApp.csproj | 6 +- .../TestProjects/NoDepsApp/NoDepsApp.csproj | 6 +- .../clean-assets.cmd | 11 -- .../clean-assets.sh | 14 -- .../project.json | 42 ----- .../test.cmd | 6 - .../test.sh | 10 - ...icrosoft.DotNet.Watcher.Tools.Tests.csproj | 15 ++ ...Microsoft.DotNet.Watcher.Tools.Tests.xproj | 21 --- .../copyfiles.cmd | 9 - .../copyfiles.sh | 12 -- .../project.json | 28 --- ...xtensions.SecretManager.Tools.Tests.csproj | 12 ++ ...Extensions.SecretManager.Tools.Tests.xproj | 21 --- .../copyfiles.cmd | 9 - .../copyfiles.sh | 12 -- .../project.json | 27 --- .../test.sh | 10 - .../Microsoft.Extensions.Tools.Tests.csproj | 11 ++ .../Microsoft.Extensions.Tools.Tests.xproj | 22 --- .../project.json | 23 --- test/dir.props | 10 + tools/NuGetPackager/NuGetPackager.xproj | 19 -- tools/NuGetPackager/PackCommand.cs | 173 ------------------ tools/NuGetPackager/Program.cs | 55 ------ tools/NuGetPackager/project.json | 19 -- version.props | 7 + 86 files changed, 355 insertions(+), 922 deletions(-) rename {tools => build}/Key.snk (100%) create mode 100644 build/common.props create mode 100644 dir.props delete mode 100644 global.json delete mode 100644 makefile.shade rename {src/Shared => shared}/ArgumentEscaper.cs (100%) rename {src/Shared => shared}/CliContext.cs (100%) rename {src/Shared => shared}/CommandLine/AnsiConsole.cs (100%) rename {src/Shared => shared}/CommandLine/CommandArgument.cs (100%) rename {src/Shared => shared}/CommandLine/CommandLineApplication.cs (100%) rename {src/Shared => shared}/CommandLine/CommandOption.cs (100%) rename {src/Shared => shared}/CommandLine/CommandOptionType.cs (100%) rename {src/Shared => shared}/CommandLine/CommandParsingException.cs (100%) rename {src/Shared => shared}/CommandLineApplicationExtensions.cs (100%) rename {src/Shared => shared}/DebugHelper.cs (100%) rename {src/Shared => shared}/DotNetMuxer.cs (100%) rename {src/Shared => shared}/Ensure.cs (100%) rename {src/Shared => shared}/IConsole.cs (100%) rename {src/Shared => shared}/PhysicalConsole.cs (100%) rename {src/Shared => shared}/Reporting/ColorFormatter.cs (100%) rename {src/Shared => shared}/Reporting/CompositeFormatter.cs (100%) rename {src/Shared => shared}/Reporting/ConditionalFormatter.cs (100%) rename {src/Shared => shared}/Reporting/DefaultFormatter.cs (100%) rename {src/Shared => shared}/Reporting/FormatterBuilder.cs (100%) rename {src/Shared => shared}/Reporting/FormattingReporter.cs (100%) rename {src/Shared => shared}/Reporting/IFormatter.cs (100%) rename {src/Shared => shared}/Reporting/IReporter.cs (100%) rename {src/Shared => shared}/Reporting/PrefixFormatter.cs (100%) rename {src/Shared => shared}/Reporting/ReporterBuilder.cs (100%) create mode 100644 src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.xproj delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/Properties/InternalsVisibleTo.cs create mode 100644 src/Microsoft.DotNet.Watcher.Tools/Sources/ProcessHelper.cs delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/project.json create mode 100644 src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj delete mode 100644 src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec delete mode 100644 src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.xproj delete mode 100644 src/Microsoft.Extensions.Caching.SqlConfig.Tools/prefercliruntime delete mode 100644 src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj delete mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec delete mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.xproj delete mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Properties/InternalsVisibleTo.cs delete mode 100644 src/Microsoft.Extensions.SecretManager.Tools/prefercliruntime delete mode 100644 src/Microsoft.Extensions.SecretManager.Tools/project.json create mode 100644 src/dir.props rename src/{Microsoft.DotNet.Watcher.Tools => }/prefercliruntime (100%) create mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.xproj delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.cmd delete mode 100755 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.sh delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/test.cmd delete mode 100755 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/test.sh create mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.xproj delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.cmd delete mode 100755 test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.sh delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/project.json create mode 100644 test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj delete mode 100644 test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.xproj delete mode 100644 test/Microsoft.Extensions.SecretManager.Tools.Tests/copyfiles.cmd delete mode 100755 test/Microsoft.Extensions.SecretManager.Tools.Tests/copyfiles.sh delete mode 100644 test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json delete mode 100755 test/Microsoft.Extensions.SecretManager.Tools.Tests/test.sh create mode 100644 test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj delete mode 100644 test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.xproj delete mode 100644 test/Microsoft.Extensions.Tools.Tests/project.json create mode 100644 test/dir.props delete mode 100644 tools/NuGetPackager/NuGetPackager.xproj delete mode 100644 tools/NuGetPackager/PackCommand.cs delete mode 100644 tools/NuGetPackager/Program.cs delete mode 100644 tools/NuGetPackager/project.json create mode 100644 version.props diff --git a/.gitignore b/.gitignore index 61e62b3028..c595526f32 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,4 @@ testWorkDir/ *.nuget.props *.nuget.targets .idea/ +.dotnet/ diff --git a/DotNetTools.sln b/DotNetTools.sln index 28d6ae6a63..a03be635f6 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -1,34 +1,29 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.25807.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66517987-2A5A-4330-B130-207039378FD4}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Watcher.Tools", "src\Microsoft.DotNet.Watcher.Tools\Microsoft.DotNet.Watcher.Tools.xproj", "{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Watcher.Tools", "src\Microsoft.DotNet.Watcher.Tools\Microsoft.DotNet.Watcher.Tools.csproj", "{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8321E0D1-9A47-4D2F-AED8-3AE636D44E35}" ProjectSection(SolutionItems) = preProject - global.json = global.json NuGet.Config = NuGet.Config EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F5B382BC-258F-46E1-AC3D-10E5CCD55134}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Watcher.Tools.FunctionalTests", "test\Microsoft.DotNet.Watcher.Tools.FunctionalTests\Microsoft.DotNet.Watcher.Tools.FunctionalTests.xproj", "{16BADE2F-1184-4518-8A70-B68A19D0805B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Watcher.Tools.FunctionalTests", "test\Microsoft.DotNet.Watcher.Tools.FunctionalTests\Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj", "{16BADE2F-1184-4518-8A70-B68A19D0805B}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.SecretManager.Tools", "src\Microsoft.Extensions.SecretManager.Tools\Microsoft.Extensions.SecretManager.Tools.xproj", "{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.SecretManager.Tools", "src\Microsoft.Extensions.SecretManager.Tools\Microsoft.Extensions.SecretManager.Tools.csproj", "{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.SecretManager.Tools.Tests", "test\Microsoft.Extensions.SecretManager.Tools.Tests\Microsoft.Extensions.SecretManager.Tools.Tests.xproj", "{7B331122-83B1-4F08-A119-DC846959844C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.SecretManager.Tools.Tests", "test\Microsoft.Extensions.SecretManager.Tools.Tests\Microsoft.Extensions.SecretManager.Tools.Tests.csproj", "{7B331122-83B1-4F08-A119-DC846959844C}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Watcher.Tools.Tests", "test\Microsoft.DotNet.Watcher.Tools.Tests\Microsoft.DotNet.Watcher.Tools.Tests.xproj", "{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Watcher.Tools.Tests", "test\Microsoft.DotNet.Watcher.Tools.Tests\Microsoft.DotNet.Watcher.Tools.Tests.csproj", "{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.Caching.SqlConfig.Tools", "src\Microsoft.Extensions.Caching.SqlConfig.Tools\Microsoft.Extensions.Caching.SqlConfig.Tools.xproj", "{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Caching.SqlConfig.Tools", "src\Microsoft.Extensions.Caching.SqlConfig.Tools\Microsoft.Extensions.Caching.SqlConfig.Tools.csproj", "{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{59E02BDF-98DE-4D64-B576-2D0299D5E052}" -EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NuGetPackager", "tools\NuGetPackager\NuGetPackager.xproj", "{8B781D87-1FC3-4A34-9089-2BDF6B562B85}" -EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.Tools.Tests", "test\Microsoft.Extensions.Tools.Tests\Microsoft.Extensions.Tools.Tests.xproj", "{A24BF1D1-4326-4455-A528-09F1E20EDC83}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Tools.Tests", "test\Microsoft.Extensions.Tools.Tests\Microsoft.Extensions.Tools.Tests.csproj", "{9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -38,36 +33,32 @@ Global GlobalSection(ProjectConfigurationPlatforms) = postSolution {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Release|Any CPU.Build.0 = Release|Any CPU + {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Release|Any CPU.ActiveCfg = Debug|Any CPU + {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Release|Any CPU.Build.0 = Debug|Any CPU {16BADE2F-1184-4518-8A70-B68A19D0805B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {16BADE2F-1184-4518-8A70-B68A19D0805B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.Build.0 = Release|Any CPU + {16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.ActiveCfg = Debug|Any CPU + {16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.Build.0 = Debug|Any CPU {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.Build.0 = Release|Any CPU + {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.ActiveCfg = Debug|Any CPU + {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.Build.0 = Debug|Any CPU + {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Release|Any CPU.ActiveCfg = Debug|Any CPU + {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Release|Any CPU.Build.0 = Debug|Any CPU {7B331122-83B1-4F08-A119-DC846959844C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7B331122-83B1-4F08-A119-DC846959844C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.Build.0 = Release|Any CPU + {7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.ActiveCfg = Debug|Any CPU + {7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.Build.0 = Debug|Any CPU {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Release|Any CPU.Build.0 = Release|Any CPU + {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Release|Any CPU.ActiveCfg = Debug|Any CPU + {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Release|Any CPU.Build.0 = Debug|Any CPU {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.Build.0 = Release|Any CPU - {8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Release|Any CPU.Build.0 = Release|Any CPU - {A24BF1D1-4326-4455-A528-09F1E20EDC83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A24BF1D1-4326-4455-A528-09F1E20EDC83}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A24BF1D1-4326-4455-A528-09F1E20EDC83}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A24BF1D1-4326-4455-A528-09F1E20EDC83}.Release|Any CPU.Build.0 = Release|Any CPU + {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.ActiveCfg = Debug|Any CPU + {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -76,10 +67,9 @@ Global {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46} = {66517987-2A5A-4330-B130-207039378FD4} {16BADE2F-1184-4518-8A70-B68A19D0805B} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E} = {66517987-2A5A-4330-B130-207039378FD4} + {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {7B331122-83B1-4F08-A119-DC846959844C} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {8A2E6961-6B12-4A8E-8215-3E7301D52EAC} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {53F3B53D-303A-4DAA-9C38-4F55195FA5B9} = {66517987-2A5A-4330-B130-207039378FD4} - {8B781D87-1FC3-4A34-9089-2BDF6B562B85} = {59E02BDF-98DE-4D64-B576-2D0299D5E052} - {A24BF1D1-4326-4455-A528-09F1E20EDC83} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} EndGlobalSection EndGlobal diff --git a/NuGet.config b/NuGet.config index 5144de9b69..b0b61c2fe0 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,9 +1,6 @@ - - + - - diff --git a/tools/Key.snk b/build/Key.snk similarity index 100% rename from tools/Key.snk rename to build/Key.snk diff --git a/build/common.props b/build/common.props new file mode 100644 index 0000000000..b9ea9b3dfe --- /dev/null +++ b/build/common.props @@ -0,0 +1,42 @@ + + + + en-US + Microsoft Corporation. + Microsoft .NET + + + <_SecondBasedTimeStamp>$([System.DateTime]::UtcNow.Subtract($([System.DateTime]::Parse("2015-01-01"))).TotalSeconds.ToString()) + <_SecondBasedTimeStamp>t$([System.Int64]::Parse($(_SecondBasedTimeStamp.Substring(0, $(_SecondBasedTimeStamp.IndexOf("."))))).ToString("x9")) + + + false + $(_SecondBasedTimeStamp) + $(VersionSuffix)-$(BuildNumber) + $(BuildNumber) + + $(MSBuildProjectName) + Microsoft + © Microsoft Corporation. All rights reserved. + https://github.com/aspnet/DotNetTools + git + https://asp.net + true + + + true + $(MSBuildThisFileDirectory)Key.snk + true + true + + + + $(VersionPrefix) + $(PackageVersion)-$(VersionSuffix)-final + + + + + true + + \ No newline at end of file diff --git a/dir.props b/dir.props new file mode 100644 index 0000000000..72afbf262e --- /dev/null +++ b/dir.props @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/global.json b/global.json deleted file mode 100644 index 1920b5a762..0000000000 --- a/global.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "projects": [ "src", "test"] -} diff --git a/makefile.shade b/makefile.shade deleted file mode 100644 index c41f9d38a5..0000000000 --- a/makefile.shade +++ /dev/null @@ -1,32 +0,0 @@ -use namespace="System.IO" - -default BASE_DIR_LOCAL='${Directory.GetCurrentDirectory()}' -default BUILD_DIR_LOCAL='${Path.Combine(BASE_DIR_LOCAL, "artifacts", "build")}' - -var VERSION='0.1' -var FULL_VERSION='0.1' -var AUTHORS='Microsoft Open Technologies, Inc.' --BuildQuality = "msbuild3"; - -use-standard-lifecycle -k-standard-goals - -#xunit-test .xunit-test-msbuild - -#build-pack .build-compile target='compile' - @{ - if (Directory.Exists("src") && !IsLinux) - { - Directory.CreateDirectory(BUILD_DIR_LOCAL); - Dotnet("run -p tools/NuGetPackager -- -c " + E("Configuration") + - " -o artifacts/build/ "+ - "-n src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec " + - "-n src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec " + - "-n src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec "); - - foreach (var nupkg in Files.Include(Path.Combine(BUILD_DIR_LOCAL, "*/" + E("Configuration") + "/*.nupkg"))) - { - File.Copy(nupkg, Path.Combine(BUILD_DIR_LOCAL, Path.GetFileName(nupkg)), true); - } - } - } \ No newline at end of file diff --git a/src/Shared/ArgumentEscaper.cs b/shared/ArgumentEscaper.cs similarity index 100% rename from src/Shared/ArgumentEscaper.cs rename to shared/ArgumentEscaper.cs diff --git a/src/Shared/CliContext.cs b/shared/CliContext.cs similarity index 100% rename from src/Shared/CliContext.cs rename to shared/CliContext.cs diff --git a/src/Shared/CommandLine/AnsiConsole.cs b/shared/CommandLine/AnsiConsole.cs similarity index 100% rename from src/Shared/CommandLine/AnsiConsole.cs rename to shared/CommandLine/AnsiConsole.cs diff --git a/src/Shared/CommandLine/CommandArgument.cs b/shared/CommandLine/CommandArgument.cs similarity index 100% rename from src/Shared/CommandLine/CommandArgument.cs rename to shared/CommandLine/CommandArgument.cs diff --git a/src/Shared/CommandLine/CommandLineApplication.cs b/shared/CommandLine/CommandLineApplication.cs similarity index 100% rename from src/Shared/CommandLine/CommandLineApplication.cs rename to shared/CommandLine/CommandLineApplication.cs diff --git a/src/Shared/CommandLine/CommandOption.cs b/shared/CommandLine/CommandOption.cs similarity index 100% rename from src/Shared/CommandLine/CommandOption.cs rename to shared/CommandLine/CommandOption.cs diff --git a/src/Shared/CommandLine/CommandOptionType.cs b/shared/CommandLine/CommandOptionType.cs similarity index 100% rename from src/Shared/CommandLine/CommandOptionType.cs rename to shared/CommandLine/CommandOptionType.cs diff --git a/src/Shared/CommandLine/CommandParsingException.cs b/shared/CommandLine/CommandParsingException.cs similarity index 100% rename from src/Shared/CommandLine/CommandParsingException.cs rename to shared/CommandLine/CommandParsingException.cs diff --git a/src/Shared/CommandLineApplicationExtensions.cs b/shared/CommandLineApplicationExtensions.cs similarity index 100% rename from src/Shared/CommandLineApplicationExtensions.cs rename to shared/CommandLineApplicationExtensions.cs diff --git a/src/Shared/DebugHelper.cs b/shared/DebugHelper.cs similarity index 100% rename from src/Shared/DebugHelper.cs rename to shared/DebugHelper.cs diff --git a/src/Shared/DotNetMuxer.cs b/shared/DotNetMuxer.cs similarity index 100% rename from src/Shared/DotNetMuxer.cs rename to shared/DotNetMuxer.cs diff --git a/src/Shared/Ensure.cs b/shared/Ensure.cs similarity index 100% rename from src/Shared/Ensure.cs rename to shared/Ensure.cs diff --git a/src/Shared/IConsole.cs b/shared/IConsole.cs similarity index 100% rename from src/Shared/IConsole.cs rename to shared/IConsole.cs diff --git a/src/Shared/PhysicalConsole.cs b/shared/PhysicalConsole.cs similarity index 100% rename from src/Shared/PhysicalConsole.cs rename to shared/PhysicalConsole.cs diff --git a/src/Shared/Reporting/ColorFormatter.cs b/shared/Reporting/ColorFormatter.cs similarity index 100% rename from src/Shared/Reporting/ColorFormatter.cs rename to shared/Reporting/ColorFormatter.cs diff --git a/src/Shared/Reporting/CompositeFormatter.cs b/shared/Reporting/CompositeFormatter.cs similarity index 100% rename from src/Shared/Reporting/CompositeFormatter.cs rename to shared/Reporting/CompositeFormatter.cs diff --git a/src/Shared/Reporting/ConditionalFormatter.cs b/shared/Reporting/ConditionalFormatter.cs similarity index 100% rename from src/Shared/Reporting/ConditionalFormatter.cs rename to shared/Reporting/ConditionalFormatter.cs diff --git a/src/Shared/Reporting/DefaultFormatter.cs b/shared/Reporting/DefaultFormatter.cs similarity index 100% rename from src/Shared/Reporting/DefaultFormatter.cs rename to shared/Reporting/DefaultFormatter.cs diff --git a/src/Shared/Reporting/FormatterBuilder.cs b/shared/Reporting/FormatterBuilder.cs similarity index 100% rename from src/Shared/Reporting/FormatterBuilder.cs rename to shared/Reporting/FormatterBuilder.cs diff --git a/src/Shared/Reporting/FormattingReporter.cs b/shared/Reporting/FormattingReporter.cs similarity index 100% rename from src/Shared/Reporting/FormattingReporter.cs rename to shared/Reporting/FormattingReporter.cs diff --git a/src/Shared/Reporting/IFormatter.cs b/shared/Reporting/IFormatter.cs similarity index 100% rename from src/Shared/Reporting/IFormatter.cs rename to shared/Reporting/IFormatter.cs diff --git a/src/Shared/Reporting/IReporter.cs b/shared/Reporting/IReporter.cs similarity index 100% rename from src/Shared/Reporting/IReporter.cs rename to shared/Reporting/IReporter.cs diff --git a/src/Shared/Reporting/PrefixFormatter.cs b/shared/Reporting/PrefixFormatter.cs similarity index 100% rename from src/Shared/Reporting/PrefixFormatter.cs rename to shared/Reporting/PrefixFormatter.cs diff --git a/src/Shared/Reporting/ReporterBuilder.cs b/shared/Reporting/ReporterBuilder.cs similarity index 100% rename from src/Shared/Reporting/ReporterBuilder.cs rename to shared/Reporting/ReporterBuilder.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj new file mode 100644 index 0000000000..6858eb7e49 --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj @@ -0,0 +1,23 @@ + + + + netcoreapp1.0 + dotnet-watch + Exe + Command line tool to watch for source file changes during development and restart the dotnet command. + dotnet;watch + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec deleted file mode 100644 index 22054d71df..0000000000 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec +++ /dev/null @@ -1,31 +0,0 @@ - - - - Microsoft.DotNet.Watcher.Tools - $version$ - Microsoft - Microsoft - false - Command line tool to watch for source file changes during development and restart the dotnet command. - dotnet,watch - true - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.xproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.xproj deleted file mode 100644 index 6ce5b43fae..0000000000 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.xproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 8a8ceabc-ac47-43ff-a5df-69224f7e1f46 - .\obj - .\bin\ - - - Microsoft.DotNet.Watcher - - - 2.0 - - - \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs b/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs index df3730569e..db52f83415 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs @@ -2,10 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Reflection; -using System.Resources; +using System.Runtime.CompilerServices; [assembly: AssemblyMetadata("Serviceable", "True")] -[assembly: NeutralResourcesLanguage("en-US")] -[assembly: AssemblyCompany("Microsoft Corporation.")] -[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] -[assembly: AssemblyProduct("Microsoft .NET")] +[assembly: InternalsVisibleTo("Microsoft.DotNet.Watcher.Tools.Tests, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +// TODO remove when .Source packages work +[assembly: InternalsVisibleTo("Microsoft.DotNet.Watcher.Tools.FunctionalTests, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/Microsoft.DotNet.Watcher.Tools/Properties/InternalsVisibleTo.cs b/src/Microsoft.DotNet.Watcher.Tools/Properties/InternalsVisibleTo.cs deleted file mode 100644 index ea9ec15282..0000000000 --- a/src/Microsoft.DotNet.Watcher.Tools/Properties/InternalsVisibleTo.cs +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Microsoft.DotNet.Watcher.Tools.Tests, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Sources/ProcessHelper.cs b/src/Microsoft.DotNet.Watcher.Tools/Sources/ProcessHelper.cs new file mode 100644 index 0000000000..eccf4ddd3c --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/Sources/ProcessHelper.cs @@ -0,0 +1,115 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +// TODO remove and using Microsoft.Extensions.Process.Sources when https://github.com/dotnet/sdk/issues/115 is fixed + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; + +namespace Microsoft.Extensions.Internal +{ + internal static class ProcessExtensions + { + private static readonly bool _isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30); + + public static void KillTree(this Process process) + { + process.KillTree(_defaultTimeout); + } + + public static void KillTree(this Process process, TimeSpan timeout) + { + string stdout; + if (_isWindows) + { + RunProcessAndWaitForExit( + "taskkill", + $"/T /F /PID {process.Id}", + timeout, + out stdout); + } + else + { + var children = new HashSet(); + GetAllChildIdsUnix(process.Id, children, timeout); + foreach (var childId in children) + { + KillProcessUnix(childId, timeout); + } + KillProcessUnix(process.Id, timeout); + } + } + + private static void GetAllChildIdsUnix(int parentId, ISet children, TimeSpan timeout) + { + string stdout; + var exitCode = RunProcessAndWaitForExit( + "pgrep", + $"-P {parentId}", + timeout, + out stdout); + + if (exitCode == 0 && !string.IsNullOrEmpty(stdout)) + { + using (var reader = new StringReader(stdout)) + { + while (true) + { + var text = reader.ReadLine(); + if (text == null) + { + return; + } + + int id; + if (int.TryParse(text, out id)) + { + children.Add(id); + // Recursively get the children + GetAllChildIdsUnix(id, children, timeout); + } + } + } + } + } + + private static void KillProcessUnix(int processId, TimeSpan timeout) + { + string stdout; + RunProcessAndWaitForExit( + "kill", + $"-TERM {processId}", + timeout, + out stdout); + } + + private static int RunProcessAndWaitForExit(string fileName, string arguments, TimeSpan timeout, out string stdout) + { + var startInfo = new ProcessStartInfo + { + FileName = fileName, + Arguments = arguments, + RedirectStandardOutput = true, + UseShellExecute = false + }; + + var process = Process.Start(startInfo); + + stdout = null; + if (process.WaitForExit((int)timeout.TotalMilliseconds)) + { + stdout = process.StandardOutput.ReadToEnd(); + } + else + { + process.Kill(); + } + + return process.ExitCode; + } + } +} diff --git a/src/Microsoft.DotNet.Watcher.Tools/project.json b/src/Microsoft.DotNet.Watcher.Tools/project.json deleted file mode 100644 index 945f21c9c5..0000000000 --- a/src/Microsoft.DotNet.Watcher.Tools/project.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "version": "1.0.0-*", - "buildOptions": { - "outputName": "dotnet-watch", - "warningsAsErrors": true, - "emitEntryPoint": true, - "debugType": "portable", - "keyFile": "../../tools/Key.snk", - "copyToOutput": "toolassets/*.targets", - "embed": { - "mappings": { - "dotnetwatch.targets": "dotnetwatch.targets" - } - }, - "compile": { - "include": "../Shared/**/*.cs" - } - }, - "publishOptions": { - "include": [ - "toolassets/*.targets", - "prefercliruntime" - ] - }, - "dependencies": { - "Microsoft.Extensions.Process.Sources": { - "type": "build", - "version": "1.0.0" - }, - "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.0.0" - } - }, - "frameworks": { - "netcoreapp1.0": {} - } -} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj new file mode 100644 index 0000000000..b80470dad0 --- /dev/null +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj @@ -0,0 +1,19 @@ + + + + netcoreapp1.0 + dotnet-sql-cache + Exe + Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching. + cache;distributedcache;sqlserver + + + + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec deleted file mode 100644 index afe20d84d3..0000000000 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec +++ /dev/null @@ -1,28 +0,0 @@ - - - - Microsoft.Extensions.Caching.SqlConfig.Tools - $version$ - Microsoft - Microsoft - false - Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching. - cache,distributedcache,sqlserver - true - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.xproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.xproj deleted file mode 100644 index 1bba570109..0000000000 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.xproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 53f3b53d-303a-4daa-9c38-4f55195fa5b9 - .\obj - .\bin\ - - - 2.0 - - - \ No newline at end of file diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Properties/AssemblyInfo.cs b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Properties/AssemblyInfo.cs index 8d8d88195c..1c2dd26bbd 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Properties/AssemblyInfo.cs +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Properties/AssemblyInfo.cs @@ -2,10 +2,5 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Reflection; -using System.Resources; [assembly: AssemblyMetadata("Serviceable", "True")] -[assembly: NeutralResourcesLanguage("en-us")] -[assembly: AssemblyCompany("Microsoft Corporation.")] -[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] -[assembly: AssemblyProduct("Microsoft .NET Extensions")] diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/prefercliruntime b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/prefercliruntime deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json deleted file mode 100644 index 7fbfeae37d..0000000000 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/project.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "version": "1.0.0-*", - "buildOptions": { - "outputName": "dotnet-sql-cache", - "emitEntryPoint": true, - "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk", - "compile": "../Shared/**/*.cs" - }, - "publishOptions": { - "include": "prefercliruntime" - }, - "dependencies": { - "Microsoft.NETCore.App": { - "version": "1.0.0", - "type": "platform" - }, - "System.Data.SqlClient": "4.1.0" - }, - "frameworks": { - "netcoreapp1.0": {} - } -} \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj new file mode 100644 index 0000000000..a7a16434b8 --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj @@ -0,0 +1,22 @@ + + + + netcoreapp1.0 + dotnet-user-secrets + Exe + Command line tool to manage user secrets for Microsoft.Extensions.Configuration. + configuration;secrets;usersecrets + false + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec deleted file mode 100644 index d528291728..0000000000 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec +++ /dev/null @@ -1,30 +0,0 @@ - - - - - Microsoft.Extensions.SecretManager.Tools - $version$ - Microsoft - Microsoft - false - Command line tool to manage user secrets for Microsoft.Extensions.Configuration. - configuration,secrets,usersecrets - true - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.xproj b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.xproj deleted file mode 100644 index aad10398ce..0000000000 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.xproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 8730e848-ca0f-4e0a-9a2f-bc22ad0b2c4e - .\obj - .\bin\ - - - 2.0 - - - \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Properties/AssemblyInfo.cs b/src/Microsoft.Extensions.SecretManager.Tools/Properties/AssemblyInfo.cs index 8d8d88195c..98bf46385c 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Properties/AssemblyInfo.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Properties/AssemblyInfo.cs @@ -2,10 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Reflection; -using System.Resources; +using System.Runtime.CompilerServices; +[assembly: InternalsVisibleTo("Microsoft.Extensions.SecretManager.Tools.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: AssemblyMetadata("Serviceable", "True")] -[assembly: NeutralResourcesLanguage("en-us")] -[assembly: AssemblyCompany("Microsoft Corporation.")] -[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] -[assembly: AssemblyProduct("Microsoft .NET Extensions")] diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Properties/InternalsVisibleTo.cs b/src/Microsoft.Extensions.SecretManager.Tools/Properties/InternalsVisibleTo.cs deleted file mode 100644 index 8057e7a4d5..0000000000 --- a/src/Microsoft.Extensions.SecretManager.Tools/Properties/InternalsVisibleTo.cs +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Microsoft.Extensions.SecretManager.Tools.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/prefercliruntime b/src/Microsoft.Extensions.SecretManager.Tools/prefercliruntime deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/Microsoft.Extensions.SecretManager.Tools/project.json b/src/Microsoft.Extensions.SecretManager.Tools/project.json deleted file mode 100644 index e33c4f90e0..0000000000 --- a/src/Microsoft.Extensions.SecretManager.Tools/project.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "version": "1.0.0-*", - "buildOptions": { - "outputName": "dotnet-user-secrets", - "emitEntryPoint": true, - "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk", - "embed": { - "mappings": { - "ProjectIdResolverTargets.xml": "./resources/ProjectIdResolverTargets.xml" - } - }, - "compile": { - "include": "../Shared/**/*.cs" - } - }, - "publishOptions": { - "include": "prefercliruntime" - }, - "dependencies": { - "Microsoft.Extensions.Configuration.UserSecrets": "1.0.0", - "Microsoft.NETCore.App": { - "version": "1.0.0", - "type": "platform" - } - }, - "frameworks": { - "netcoreapp1.0": {} - } -} \ No newline at end of file diff --git a/src/dir.props b/src/dir.props new file mode 100644 index 0000000000..97aeb4d360 --- /dev/null +++ b/src/dir.props @@ -0,0 +1,12 @@ + + + + DotnetCliTool + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/prefercliruntime b/src/prefercliruntime similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/prefercliruntime rename to src/prefercliruntime diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj new file mode 100644 index 0000000000..ffcad2484b --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj @@ -0,0 +1,22 @@ + + + + netcoreapp1.0 + Exe + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.xproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.xproj deleted file mode 100644 index ed54a4cec7..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.xproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 16bade2f-1184-4518-8a70-b68a19d0805b - .\obj - .\bin\ - - - 2.0 - - - - - - \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs index fb7e058d6c..080b07aa8a 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -87,7 +87,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests private void CreateTestDirectory() { Directory.CreateDirectory(WorkFolder); - File.WriteAllText(Path.Combine(WorkFolder, "global.json"), "{}"); var nugetConfigFilePath = FindNugetConfig(); @@ -116,7 +115,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests private static string FindNugetConfig() { - var currentDirPath = Directory.GetCurrentDirectory(); + var currentDirPath = AppContext.BaseDirectory; string nugetConfigFile; while (true) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj index e5fc0c1ed5..a0446a8118 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj @@ -1,6 +1,4 @@ - - - + netcoreapp1.0 Exe @@ -9,8 +7,6 @@ - - \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj index 04aad78be1..c48eaffb24 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj @@ -1,6 +1,4 @@ - - - + netstandard1.5 Library @@ -9,7 +7,5 @@ - - \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj index 904fb1c9ed..380a05f12b 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj @@ -1,6 +1,4 @@ - - - + netcoreapp1.0 Exe @@ -8,8 +6,6 @@ - - \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj index e218c105dd..7ad3f30ac9 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj @@ -1,6 +1,4 @@ - - - + netcoreapp1.0 Exe @@ -8,8 +6,6 @@ - - \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.cmd b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.cmd deleted file mode 100644 index f8999b5659..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.cmd +++ /dev/null @@ -1,11 +0,0 @@ -@ECHO OFF -:again -if not "%1" == "" ( - echo "Deleting %1\TestProjects" - rmdir /s /q %1\TestProjects - echo "Deleting %1\toolassets" - rmdir /s /q %1\toolassets -) - -mkdir %1\toolassets -copy ..\..\src\Microsoft.DotNet.Watcher.Tools\toolassets\*.targets %1\toolassets \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.sh b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.sh deleted file mode 100755 index 21b69ed268..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/clean-assets.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env bash - -if [ -z $1 ]; then - echo "Deleting $1/TestProjects" - rm -rf $1/TestProjects - - echo "Deleting $1/toolassets" - rm -rf $1/toolassets -fi - -mkdir -p $1/toolassets -cp ../../src/Microsoft.DotNet.Watcher.Tools/toolassets/*.targets $1/toolassets - -exit 0 \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json deleted file mode 100644 index 327d701083..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/project.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "buildOptions": { - "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk", - "copyToOutput": { - "include": "TestProjects/" - }, - "compile": { - "exclude": "TestProjects/" - } - }, - "dependencies": { - "dotnet-test-xunit": "2.2.0-preview2-build1029", - "Microsoft.DotNet.Cli.Utils": "1.0.0-preview4-004215", - "Microsoft.DotNet.InternalAbstractions": "1.0.500-preview2-1-003177", - "Microsoft.AspNetCore.Testing": "1.0.0", - "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", - "Microsoft.DotNet.Watcher.Tools.Tests": "1.0.0-*", - "Microsoft.Extensions.Process.Sources": { - "type": "build", - "version": "1.0.0" - }, - "xunit": "2.2.0-beta3-build3402" - }, - "frameworks": { - "netcoreapp1.0": { - "dependencies": { - "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.0.1" - } - } - } - }, - "scripts": { - "precompile": "clean-assets %compile:OutputDir%" - }, - "publishOptions": { - "include": "TestProjects/" - }, - "testRunner": "xunit" -} \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/test.cmd b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/test.cmd deleted file mode 100644 index 0aa8bdf56e..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/test.cmd +++ /dev/null @@ -1,6 +0,0 @@ -@echo off - -rem For local testing - -dotnet build -..\..\.build\dotnet\dotnet.exe exec --depsfile bin\Debug\netcoreapp1.0\Microsoft.DotNet.Watcher.Tools.FunctionalTests.deps.json --runtimeconfig bin\Debug\netcoreapp1.0\Microsoft.DotNet.Watcher.Tools.FunctionalTests.runtimeconfig.json ..\..\.build\dotnet-test-xunit\2.2.0-preview2-build1029\lib\netcoreapp1.0\dotnet-test-xunit.dll bin\Debug\netcoreapp1.0\Microsoft.DotNet.Watcher.Tools.FunctionalTests.dll %* \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/test.sh b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/test.sh deleted file mode 100755 index e8cd20269a..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/test.sh +++ /dev/null @@ -1,10 +0,0 @@ -set -e - -dotnet build - -../../.build/dotnet/dotnet exec \ ---depsfile bin/Debug/netcoreapp1.0/Microsoft.DotNet.Watcher.Tools.FunctionalTests.deps.json \ ---runtimeconfig bin/Debug/netcoreapp1.0/Microsoft.DotNet.Watcher.Tools.FunctionalTests.runtimeconfig.json \ -../../.build/dotnet-test-xunit/2.2.0-preview2-build1029/lib/netcoreapp1.0/dotnet-test-xunit.dll \ -bin/Debug/netcoreapp1.0/Microsoft.DotNet.Watcher.Tools.FunctionalTests.dll \ -$@ \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj new file mode 100644 index 0000000000..c4885a4fab --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj @@ -0,0 +1,15 @@ + + + + netcoreapp1.0 + Exe + + + + + + + + + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.xproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.xproj deleted file mode 100644 index 58c2a08157..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.xproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - 14.0.25420 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 8a2e6961-6b12-4a8e-8215-3e7301d52eac - Microsoft.DotNet.Watcher.Tools.Tests - .\obj - .\bin\ - - - 2.0 - - - - - - \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.cmd b/test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.cmd deleted file mode 100644 index 6bd0489a90..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.cmd +++ /dev/null @@ -1,9 +0,0 @@ -@ECHO OFF -:again -if not "%1" == "" ( - echo "Deleting %1\toolassets" - rmdir /s /q %1\toolassets -) - -mkdir %1\toolassets -copy ..\..\src\Microsoft.DotNet.Watcher.Tools\toolassets\*.targets %1\toolassets \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.sh b/test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.sh deleted file mode 100755 index 78ae5ff657..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/copyfiles.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -if [ -z $1 ]; then - echo "Deleting $1/toolassets" - rm -rf $1/toolassets -fi - -mkdir -p $1/toolassets -echo "Copying ./../src/Microsoft.DotNet.Watcher.Tools/toolassets/*.targets" -cp ../../src/Microsoft.DotNet.Watcher.Tools/toolassets/*.targets $1/toolassets - -exit 0 \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json b/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json deleted file mode 100644 index 1916498359..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/project.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "buildOptions": { - "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk", - "debugType": "portable", - "compile": "../Shared/**/*.cs" - }, - "dependencies": { - "dotnet-test-xunit": "2.2.0-preview2-build1029", - "Microsoft.DotNet.InternalAbstractions": "1.0.0", - "Microsoft.DotNet.Watcher.Tools": "1.0.0-*", - "xunit": "2.2.0-beta3-build3402" - }, - "frameworks": { - "netcoreapp1.0": { - "dependencies": { - "Microsoft.NETCore.App": { - "version": "1.0.1", - "type": "platform" - } - } - } - }, - "scripts": { - "precompile": "copyfiles %compile:OutputDir%" - }, - "testRunner": "xunit" -} \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj new file mode 100644 index 0000000000..503a9ed18f --- /dev/null +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj @@ -0,0 +1,12 @@ + + + + netcoreapp1.0 + Exe + + + + + + + \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.xproj b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.xproj deleted file mode 100644 index 2f0849b6ac..0000000000 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.xproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - 14.0.25420 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 7b331122-83b1-4f08-a119-dc846959844c - Microsoft.Extensions.SecretManager.Tools.Tests - .\obj - .\bin\ - - - 2.0 - - - - - - \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/copyfiles.cmd b/test/Microsoft.Extensions.SecretManager.Tools.Tests/copyfiles.cmd deleted file mode 100644 index 7f24b7967f..0000000000 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/copyfiles.cmd +++ /dev/null @@ -1,9 +0,0 @@ -@ECHO OFF -:again -if not "%1" == "" ( - echo "Deleting %1\toolassets" - rmdir /s /q %1\toolassets -) - -mkdir %1\toolassets -copy ..\..\src\Microsoft.Extensions.SecretManager.Tools\toolassets\*.targets %1\toolassets \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/copyfiles.sh b/test/Microsoft.Extensions.SecretManager.Tools.Tests/copyfiles.sh deleted file mode 100755 index a1d6dfe373..0000000000 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/copyfiles.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -if [ -z $1 ]; then - echo "Deleting $1/toolassets" - rm -rf $1/toolassets -fi - -mkdir -p $1/toolassets -echo "Copying ./../src/Microsoft.Extensions.SecretManager.Tools/toolassets/*.targets" -cp ../../src/Microsoft.Extensions.SecretManager.Tools/toolassets/*.targets $1/toolassets - -exit 0 \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json b/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json deleted file mode 100644 index f0095bea8d..0000000000 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/project.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "buildOptions": { - "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk", - "compile": "../Shared/**/*.cs" - }, - "dependencies": { - "dotnet-test-xunit": "2.2.0-preview2-build1029", - "Microsoft.DotNet.InternalAbstractions": "1.0.500-preview2-1-003177", - "Microsoft.Extensions.SecretManager.Tools": "1.0.0-*", - "xunit": "2.2.0-beta3-build3402" - }, - "testRunner": "xunit", - "frameworks": { - "netcoreapp1.0": { - "dependencies": { - "Microsoft.NETCore.App": { - "version": "1.0.1", - "type": "platform" - } - } - } - }, - "scripts": { - "precompile": "copyfiles %compile:OutputDir%" - } -} \ No newline at end of file diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/test.sh b/test/Microsoft.Extensions.SecretManager.Tools.Tests/test.sh deleted file mode 100755 index 31eb5fd320..0000000000 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/test.sh +++ /dev/null @@ -1,10 +0,0 @@ -set -e - -~/.dotnet/dotnet build - -../../.build/dotnet/dotnet exec \ ---depsfile bin/Debug/netcoreapp1.0/Microsoft.Extensions.SecretManager.Tools.Tests.deps.json \ ---runtimeconfig bin/Debug/netcoreapp1.0/Microsoft.Extensions.SecretManager.Tools.Tests.runtimeconfig.json \ -../../.build/dotnet-test-xunit/2.2.0-preview2-build1029/lib/netcoreapp1.0/dotnet-test-xunit.dll \ -bin/Debug/netcoreapp1.0/Microsoft.Extensions.SecretManager.Tools.Tests.dll \ -$@ \ No newline at end of file diff --git a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj new file mode 100644 index 0000000000..57f7f2c63b --- /dev/null +++ b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj @@ -0,0 +1,11 @@ + + + + netcoreapp1.0 + Exe + + + + + + \ No newline at end of file diff --git a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.xproj b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.xproj deleted file mode 100644 index fec649a8a5..0000000000 --- a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.xproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - - {A24BF1D1-4326-4455-A528-09F1E20EDC83} - {8BB2217D-0F2D-49D1-97BC-3654ED321F3B} - Microsoft.Extensions.Tools.Tests - .\obj - .\bin\ - v4.5.1 - - - - 2.0 - - - diff --git a/test/Microsoft.Extensions.Tools.Tests/project.json b/test/Microsoft.Extensions.Tools.Tests/project.json deleted file mode 100644 index 2696161c61..0000000000 --- a/test/Microsoft.Extensions.Tools.Tests/project.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "buildOptions": { - "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk", - "compile": "../../src/Shared/**/*.cs" - }, - "dependencies": { - "dotnet-test-xunit": "2.2.0-preview2-build1029", - "Microsoft.DotNet.InternalAbstractions": "1.0.500-preview2-1-003177", - "xunit": "2.2.0-beta3-build3402" - }, - "testRunner": "xunit", - "frameworks": { - "netcoreapp1.0": { - "dependencies": { - "Microsoft.NETCore.App": { - "version": "1.0.1", - "type": "platform" - } - } - } - } -} \ No newline at end of file diff --git a/test/dir.props b/test/dir.props new file mode 100644 index 0000000000..1fff509174 --- /dev/null +++ b/test/dir.props @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/tools/NuGetPackager/NuGetPackager.xproj b/tools/NuGetPackager/NuGetPackager.xproj deleted file mode 100644 index 57c243c965..0000000000 --- a/tools/NuGetPackager/NuGetPackager.xproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - 14.0.25420 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 8b781d87-1fc3-4a34-9089-2bdf6b562b85 - NuGetPackager - .\obj - .\bin\ - - - - 2.0 - - - \ No newline at end of file diff --git a/tools/NuGetPackager/PackCommand.cs b/tools/NuGetPackager/PackCommand.cs deleted file mode 100644 index 53ecef3b34..0000000000 --- a/tools/NuGetPackager/PackCommand.cs +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.DotNet.Cli.Utils; -using Microsoft.DotNet.ProjectModel; -using Microsoft.DotNet.ProjectModel.Graph; -using Microsoft.DotNet.ProjectModel.Utilities; -using NuGet.Frameworks; -using NuGet.Versioning; - -namespace NuGetPackager -{ - internal class PackCommand - { - private readonly string _baseDir; - - public PackCommand(string baseDir) - { - _baseDir = baseDir; - } - - public async Task PackAsync(string nuspec, string config, string outputDir) - { - var project = ProjectContext.Create(Path.GetDirectoryName(nuspec), FrameworkConstants.CommonFrameworks.NetCoreApp10); - var idx = 0; - var props = ""; - var first = true; - foreach (var depVersion in GetDependencies(project).OrderBy(p => p.Item1).Select(p => p.Item2)) - { - if (first) - { - first = false; - } - else - { - props += ";"; - } - - props += $"dep_{++idx}={depVersion}"; - } - var publishDir = Path.Combine(Directory.GetCurrentDirectory(), "artifacts/build", project.ProjectFile.Name); - if (Directory.Exists(publishDir)) - { - Directory.Delete(publishDir, recursive: true); - } - Directory.CreateDirectory(publishDir); - - var buildCommand = Command.CreateDotNet("publish", - new[] { project.ProjectFile.ProjectFilePath, "--configuration", config, "--output", publishDir }, - configuration: config); - - if (buildCommand.Execute().ExitCode != 0) - { - throw new GracefulException("Build failed"); - } - - Directory.CreateDirectory(outputDir); - - var version = project.ProjectFile.Version.ToNormalizedString(); - await Nuget("pack", - nuspec, - "-Verbosity", "detailed", - "-OutputDirectory", outputDir, - "-Version", version, - "-Properties", props, - "-BasePath", publishDir); - } - - private IEnumerable> GetDependencies(ProjectContext context) - { - // copied from https://github.com/dotnet/cli/blob/da0e365264e0ab555cdde978bdfd2e504bada49a/src/dotnet/commands/dotnet-pack/PackageGenerator.cs - var project = context.RootProject; - - foreach (var dependency in project.Dependencies) - { - if (dependency.Type.Equals(LibraryDependencyType.Build)) - { - continue; - } - - // TODO: Efficiency - var dependencyDescription = context.LibraryManager.GetLibraries().First(l => l.RequestedRanges.Contains(dependency)); - - // REVIEW: Can we get this far with unresolved dependencies - if (!dependencyDescription.Resolved) - { - continue; - } - - if (dependencyDescription.Identity.Type == LibraryType.Project && - ((ProjectDescription)dependencyDescription).Project.EmbedInteropTypes) - { - continue; - } - - VersionRange dependencyVersion = null; - - if (dependency.VersionRange == null || - dependency.VersionRange.IsFloating) - { - dependencyVersion = new VersionRange(dependencyDescription.Identity.Version); - } - else - { - dependencyVersion = dependency.VersionRange; - } - - Reporter.Verbose.WriteLine($"Adding dependency {dependency.Name.Yellow()} {VersionUtility.RenderVersion(dependencyVersion).Yellow()}"); - - yield return new Tuple(dependency.Name, dependencyVersion.MinVersion.ToString()); - } - } - - private static string GetLockFileVersion(ProjectContext project, string name) => - project - .LockFile - .PackageLibraries - .First(l => l.Name.Equals(name)) - .Version - .ToNormalizedString(); - - private async Task Nuget(params string[] args) - { - var pInfo = new ProcessStartInfo - { - Arguments = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args), - FileName = await GetNugetExePath() - }; - Console.WriteLine("command: ".Bold().Blue() + pInfo.FileName); - Console.WriteLine("arguments: ".Bold().Blue() + pInfo.Arguments); - - var process = Process.Start(pInfo); - process.WaitForExit(); - - if (process.ExitCode != 0) - { - throw new InvalidOperationException("NuGet exited with non-zero code " + process.ExitCode); - } - } - - private async Task GetNugetExePath() - { - if (Environment.GetEnvironmentVariable("KOREBUILD_NUGET_EXE") != null) - { - return Environment.GetEnvironmentVariable("KOREBUILD_NUGET_EXE"); - } - - var nugetPath = Path.Combine(_baseDir, ".build", "nuget.3.5.0.exe"); - if (File.Exists(nugetPath)) - { - return nugetPath; - } - - Console.WriteLine("log : Downloading nuget.exe 3.5.0"); - - var response = await new HttpClient().GetAsync("https://dist.nuget.org/win-x86-commandline/v3.5.0/NuGet.exe"); - using (var file = new FileStream(nugetPath, FileMode.CreateNew)) - { - response.EnsureSuccessStatusCode(); - await response.Content.LoadIntoBufferAsync(); - await response.Content.CopyToAsync(file); - } - return nugetPath; - } - } -} \ No newline at end of file diff --git a/tools/NuGetPackager/Program.cs b/tools/NuGetPackager/Program.cs deleted file mode 100644 index d73a31a39d..0000000000 --- a/tools/NuGetPackager/Program.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.IO; -using System.Linq; -using Microsoft.Extensions.CommandLineUtils; -using Microsoft.DotNet.Cli.Utils; - -namespace NuGetPackager -{ - /// - /// This replaces the "dotnet-pack" command, which doesn't not yet support "package types" - /// and probably won't in time for the next release. - /// TODO remove this once CLI supports package type - /// - public class Program - { - public static int Main(string[] args) - { - var app = new CommandLineApplication(); - var optOutput = app.Option("-o|--output-dir ", "Output dir", CommandOptionType.SingleValue); - var optConfig = app.Option("-c|--configuration ", "Config", CommandOptionType.SingleValue); - var optsNuspec = app.Option("-n|--nuspec ", "nuspec", CommandOptionType.MultipleValue); - - app.OnExecute(async () => - { - if (!optsNuspec.Values.Any()) - { - Reporter.Error.WriteLine("Missing values for --nuspec"); - return 1; - } - - var config = optConfig.HasValue() - ? optConfig.Value() - : "Debug"; - var output = optOutput.Value() ?? Directory.GetCurrentDirectory(); - - if (!Path.IsPathRooted(output)) - { - output = Path.Combine(Directory.GetCurrentDirectory(), output); - } - - var packer = new PackCommand(Directory.GetCurrentDirectory()); - foreach (var nuspec in optsNuspec.Values) - { - await packer.PackAsync(nuspec, config, output); - } - - return 0; - }); - - return app.Execute(args); - } - } -} \ No newline at end of file diff --git a/tools/NuGetPackager/project.json b/tools/NuGetPackager/project.json deleted file mode 100644 index fe0b3987d9..0000000000 --- a/tools/NuGetPackager/project.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "buildOptions": { - "emitEntryPoint": true - }, - - "dependencies": { - "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.0.0" - }, - "Microsoft.DotNet.ProjectModel": "1.0.0-rc3-003121", - "Microsoft.DotNet.Cli.Utils": "1.0.0-preview2-003121", - "Microsoft.Extensions.CommandLineUtils": "1.0.0" - }, - - "frameworks": { - "netcoreapp1.0": { } - } -} \ No newline at end of file diff --git a/version.props b/version.props new file mode 100644 index 0000000000..c7af7a2430 --- /dev/null +++ b/version.props @@ -0,0 +1,7 @@ + + + + 1.0.0 + msbuild3 + + \ No newline at end of file From d4313dae3bd7632c044bdfad30dd5ba66ea50407 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 12 Dec 2016 16:21:18 -0800 Subject: [PATCH 0378/1029] Use props from Korebuild --- build/common.props | 42 --------------------------------------- dir.props | 10 ++++++++-- src/dir.props | 2 ++ {build => tools}/Key.snk | Bin tools/sign.props | 7 +++++++ 5 files changed, 17 insertions(+), 44 deletions(-) delete mode 100644 build/common.props rename {build => tools}/Key.snk (100%) create mode 100644 tools/sign.props diff --git a/build/common.props b/build/common.props deleted file mode 100644 index b9ea9b3dfe..0000000000 --- a/build/common.props +++ /dev/null @@ -1,42 +0,0 @@ - - - - en-US - Microsoft Corporation. - Microsoft .NET - - - <_SecondBasedTimeStamp>$([System.DateTime]::UtcNow.Subtract($([System.DateTime]::Parse("2015-01-01"))).TotalSeconds.ToString()) - <_SecondBasedTimeStamp>t$([System.Int64]::Parse($(_SecondBasedTimeStamp.Substring(0, $(_SecondBasedTimeStamp.IndexOf("."))))).ToString("x9")) - - - false - $(_SecondBasedTimeStamp) - $(VersionSuffix)-$(BuildNumber) - $(BuildNumber) - - $(MSBuildProjectName) - Microsoft - © Microsoft Corporation. All rights reserved. - https://github.com/aspnet/DotNetTools - git - https://asp.net - true - - - true - $(MSBuildThisFileDirectory)Key.snk - true - true - - - - $(VersionPrefix) - $(PackageVersion)-$(VersionSuffix)-final - - - - - true - - \ No newline at end of file diff --git a/dir.props b/dir.props index 72afbf262e..3f3183bc8c 100644 --- a/dir.props +++ b/dir.props @@ -1,5 +1,11 @@ - - + + + + + + + \ No newline at end of file diff --git a/src/dir.props b/src/dir.props index 97aeb4d360..b2d16c9fad 100644 --- a/src/dir.props +++ b/src/dir.props @@ -1,6 +1,8 @@ + + $(MSBuildProjectName) DotnetCliTool diff --git a/build/Key.snk b/tools/Key.snk similarity index 100% rename from build/Key.snk rename to tools/Key.snk diff --git a/tools/sign.props b/tools/sign.props new file mode 100644 index 0000000000..54132d388a --- /dev/null +++ b/tools/sign.props @@ -0,0 +1,7 @@ + + + $(MSBuildThisFileDirectory)Key.snk + true + true + + \ No newline at end of file From 67c540051baf2d7423355761860d2d6d66ece522 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 12 Dec 2016 16:24:15 -0800 Subject: [PATCH 0379/1029] Update README.md --- src/Microsoft.DotNet.Watcher.Tools/README.md | 20 +------------------ .../README.md | 18 +++++++++++++++++ .../README.md | 16 +-------------- 3 files changed, 20 insertions(+), 34 deletions(-) create mode 100644 src/Microsoft.Extensions.Caching.SqlConfig.Tools/README.md diff --git a/src/Microsoft.DotNet.Watcher.Tools/README.md b/src/Microsoft.DotNet.Watcher.Tools/README.md index 0e6f1142a3..a9a36c49eb 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/README.md +++ b/src/Microsoft.DotNet.Watcher.Tools/README.md @@ -4,32 +4,14 @@ dotnet-watch ### How To Install -**project.json** - -Add `Microsoft.DotNet.Watcher.Tools` to the `tools` section of your `project.json` file. - -Use the version "1.0.0-preview2-final" if you are using .NET Core 1.0.0 and use "1.0.0-preview3-final" if you are using .NET Core 1.1.0. - -``` -{ -... - "tools": { - "Microsoft.DotNet.Watcher.Tools": "1.0.0-preview2-final" //"1.0.0-preview3-final" for .NET Core 1.1.0 - } -... -} -``` - -**MSBuild** Install `Microsoft.DotNet.Watcher.Tools` as a `DotNetCliToolReference` to your project. ```xml - + ``` - ### How To Use The command must be executed in the directory that contains the project to be watched. diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/README.md b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/README.md new file mode 100644 index 0000000000..0d989a980d --- /dev/null +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/README.md @@ -0,0 +1,18 @@ +dotnet-sql-cache +================ + +`dotnet-sql-cache` is a command line tool that creates table and indexes in Microsoft SQL Server database to be used for distributed caching + +### How To Install + +Install `Microsoft.Extensions.Caching.SqlConfig.Tools` as a `DotNetCliToolReference` to your project. + +```xml + + + +``` + +### How To Use + +Run `dotnet sql-cache --help` for more information about usage. \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/README.md b/src/Microsoft.Extensions.SecretManager.Tools/README.md index ecb2f59709..b930f9dd71 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/README.md +++ b/src/Microsoft.Extensions.SecretManager.Tools/README.md @@ -5,25 +5,11 @@ dotnet-user-secrets ### How To Install -**project.json** -Add `Microsoft.Extensions.SecretManager.Tools` to the `tools` section of your `project.json` file: - -```js -{ - .. - "tools": { - "Microsoft.Extensions.SecretManager.Tools": "1.0.0-*" - } - ... -} -``` - -**MSBuild** Install `Microsoft.Extensions.SecretManager.Tools` as a `DotNetCliToolReference` to your project. ```xml - + ``` From 346dfe8fe06d58ec2eeb208a95f11e05b72413d9 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 12 Dec 2016 16:40:01 -0800 Subject: [PATCH 0380/1029] Remove dependency on Microsoft.DotNet.Cli.Utils from test project --- .../Microsoft.DotNet.Watcher.Tools.csproj | 4 +- .../AwaitableProcess.cs | 4 +- ...otNet.Watcher.Tools.FunctionalTests.csproj | 1 - .../Scenario/ProjectToolScenario.cs | 47 +++++++++++++------ .../Scenario/WatchableApp.cs | 4 +- 5 files changed, 38 insertions(+), 22 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj index 6858eb7e49..fb08e53fcf 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj @@ -3,11 +3,10 @@ netcoreapp1.0 dotnet-watch - Exe + exe Command line tool to watch for source file changes during development and restart the dotnet command. dotnet;watch - @@ -15,7 +14,6 @@ - diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs index fc920e7eb0..2abbdf9068 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs @@ -8,9 +8,9 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; -using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.Internal; using Xunit.Abstractions; +using Microsoft.Extensions.Tools.Internal; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { @@ -40,7 +40,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests UseShellExecute = false, FileName = _spec.Executable, WorkingDirectory = _spec.WorkingDirectory, - Arguments = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(_spec.Arguments), + Arguments = ArgumentEscaper.EscapeAndConcatenate(_spec.Arguments), RedirectStandardOutput = true, RedirectStandardError = true }; diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj index ffcad2484b..274d05f92e 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj @@ -13,7 +13,6 @@ - diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs index 080b07aa8a..effcb9de32 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -1,12 +1,13 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Microsoft.Extensions.Tools.Internal; using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Reflection; using System.Threading; -using Microsoft.DotNet.Cli.Utils; using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests @@ -69,18 +70,36 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests private void ExecuteCommand(string project, params string[] arguments) { project = Path.Combine(WorkFolder, project); - var command = Command - .Create(new Muxer().MuxerPath, arguments) - .WorkingDirectory(project) - .CaptureStdErr() - .CaptureStdOut() - .OnErrorLine(l => _logger?.WriteLine(l)) - .OnOutputLine(l => _logger?.WriteLine(l)) - .Execute(); - - if (command.ExitCode != 0) + var psi = new ProcessStartInfo { - throw new InvalidOperationException($"Exit code {command.ExitCode}"); + FileName = DotNetMuxer.MuxerPathOrDefault(), + Arguments = ArgumentEscaper.EscapeAndConcatenate(arguments), + WorkingDirectory = project, + RedirectStandardOutput = true, + RedirectStandardError = true + }; + + var process = new Process() + { + StartInfo = psi, + EnableRaisingEvents = true + }; + + void WriteLine(object sender, DataReceivedEventArgs args) + => _logger.WriteLine(args.Data); + + process.ErrorDataReceived += WriteLine; + process.OutputDataReceived += WriteLine; + + process.Start(); + process.WaitForExit(); + + process.ErrorDataReceived -= WriteLine; + process.OutputDataReceived -= WriteLine; + + if (process.ExitCode != 0) + { + throw new InvalidOperationException($"Exit code {process.ExitCode}"); } } @@ -103,10 +122,10 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests args.Add("exec"); args.Add("--depsfile"); - args.Add(Path.Combine(AppContext.BaseDirectory, thisAssembly + FileNameSuffixes.DepsJson)); + args.Add(Path.Combine(AppContext.BaseDirectory, thisAssembly + ".deps.json")); args.Add("--runtimeconfig"); - args.Add(Path.Combine(AppContext.BaseDirectory, thisAssembly + FileNameSuffixes.RuntimeConfigJson)); + args.Add(Path.Combine(AppContext.BaseDirectory, thisAssembly + ".runtimeconfig.json")); args.Add(Path.Combine(AppContext.BaseDirectory, "dotnet-watch.dll")); diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs index 7e5dc8ee8e..797e17f640 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs @@ -1,12 +1,12 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Microsoft.Extensions.Tools.Internal; using System; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; -using Microsoft.DotNet.Cli.Utils; using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests @@ -72,7 +72,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests var spec = new ProcessSpec { - Executable = new Muxer().MuxerPath, + Executable = DotNetMuxer.MuxerPathOrDefault(), Arguments = args, WorkingDirectory = SourceDirectory }; From 44c8920412be3692b4621a45fbbd1f0b15ec5138 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 12 Dec 2016 17:40:07 -0800 Subject: [PATCH 0381/1029] Add RepositoryUrl and RepositoryType properties --- src/dir.props | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dir.props b/src/dir.props index b2d16c9fad..e60794fbbe 100644 --- a/src/dir.props +++ b/src/dir.props @@ -4,6 +4,8 @@ $(MSBuildProjectName) DotnetCliTool + https://github.com/aspnet/DotNetTools + git From 08e3e0b77f39028bd17311efbbeb62c764ad5cbb Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 13 Dec 2016 09:59:11 -0800 Subject: [PATCH 0382/1029] Cleanup dotnet-watch testing --- ...oft.Extensions.Caching.SqlConfig.Tools.csproj | 2 +- ...crosoft.Extensions.SecretManager.Tools.csproj | 4 ++-- src/dir.props | 2 +- ...t.DotNet.Watcher.Tools.FunctionalTests.csproj | 16 ++++++++++++++-- .../Scenario/ProjectToolScenario.cs | 14 ++++++++++++++ .../TestProjects/AppWithDeps/AppWithDeps.csproj | 5 ++++- .../TestProjects/AppWithDeps/NuGet.config | 8 -------- .../TestProjects/Dependency/Dependency.csproj | 5 ++++- .../TestProjects/Dependency/NuGet.config | 8 -------- .../TestProjects/GlobbingApp/GlobbingApp.csproj | 5 ++++- .../TestProjects/GlobbingApp/NuGet.config | 8 -------- .../TestProjects/NoDepsApp/NoDepsApp.csproj | 5 ++++- .../TestProjects/NoDepsApp/NuGet.config | 8 -------- .../Microsoft.DotNet.Watcher.Tools.Tests.csproj | 9 +++++++-- ...t.Extensions.SecretManager.Tools.Tests.csproj | 7 ++++++- .../Microsoft.Extensions.Tools.Tests.csproj | 7 ++++++- test/dir.props | 1 - 17 files changed, 67 insertions(+), 47 deletions(-) delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/NuGet.config delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/NuGet.config delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/NuGet.config delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NuGet.config diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj index b80470dad0..6a05d21dde 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj @@ -3,7 +3,7 @@ netcoreapp1.0 dotnet-sql-cache - Exe + exe Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching. cache;distributedcache;sqlserver diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj index a7a16434b8..142fbcbabe 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj @@ -3,7 +3,7 @@ netcoreapp1.0 dotnet-user-secrets - Exe + exe Command line tool to manage user secrets for Microsoft.Extensions.Configuration. configuration;secrets;usersecrets false @@ -17,6 +17,6 @@ - + \ No newline at end of file diff --git a/src/dir.props b/src/dir.props index e60794fbbe..addeb75498 100644 --- a/src/dir.props +++ b/src/dir.props @@ -11,6 +11,6 @@ - + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj index 274d05f92e..2cb75f63ab 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj @@ -1,9 +1,12 @@  + + - netcoreapp1.0 - Exe + netcoreapp1.0;netcoreapp1.1 + exe + @@ -15,7 +18,16 @@ + + + + + + + + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs index effcb9de32..2b62d17db9 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -127,6 +127,20 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests args.Add("--runtimeconfig"); args.Add(Path.Combine(AppContext.BaseDirectory, thisAssembly + ".runtimeconfig.json")); + var currentFxVersion = AppContext.GetData("FX_DEPS_FILE") as string; + if (currentFxVersion != null) + { + // This overrides the version of shared fx in the runtimeconfig.json file. + // Tests do this to ensure dotnet-watch is executing on the version of Microsoft.NETCore.App + // used by the current test project. The test project can target multiple version of + // netcoreapp1.x in order to ensure the tool runs when it is lifted to higher netcore versions + // due to inclusion of the 'prefercliruntime' file in our nupkg. + + var version = new FileInfo(currentFxVersion).Directory.Name; + args.Add("--fx-version"); + args.Add(version); + } + args.Add(Path.Combine(AppContext.BaseDirectory, "dotnet-watch.dll")); return args; diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj index a0446a8118..40b6fd7ae2 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj @@ -1,12 +1,15 @@ + netcoreapp1.0 - Exe + exe + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/NuGet.config b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/NuGet.config deleted file mode 100644 index d8093c7fa9..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/NuGet.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj index c48eaffb24..f800ba3b09 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj @@ -1,11 +1,14 @@ + netstandard1.5 - Library + library + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/NuGet.config b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/NuGet.config deleted file mode 100644 index d8093c7fa9..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/NuGet.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj index 380a05f12b..7a6df0e8bc 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj @@ -1,11 +1,14 @@  + netcoreapp1.0 - Exe + exe + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/NuGet.config b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/NuGet.config deleted file mode 100644 index d8093c7fa9..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/NuGet.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj index 7ad3f30ac9..5cbd709f53 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj @@ -1,11 +1,14 @@  + netcoreapp1.0 - Exe + exe + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NuGet.config b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NuGet.config deleted file mode 100644 index d8093c7fa9..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NuGet.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj index c4885a4fab..d4201a9e72 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj @@ -1,9 +1,12 @@  + + netcoreapp1.0 - Exe + exe + @@ -11,5 +14,7 @@ + - \ No newline at end of file + + diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj index 503a9ed18f..29ea81b6aa 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj @@ -1,12 +1,17 @@  + + netcoreapp1.0 - Exe + exe + + + \ No newline at end of file diff --git a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj index 57f7f2c63b..775ec194cd 100644 --- a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj @@ -1,11 +1,16 @@  + + netcoreapp1.0 - Exe + exe + + + \ No newline at end of file diff --git a/test/dir.props b/test/dir.props index 1fff509174..a0553297be 100644 --- a/test/dir.props +++ b/test/dir.props @@ -2,7 +2,6 @@ - From e94def7ecaa17b5ba1f04910e3d9eae5f96203c7 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 13 Dec 2016 10:04:19 -0800 Subject: [PATCH 0383/1029] Re-enable tests for file delete detection in dotnet-watch Microsoft.NET.Sdk fixed the underlying issue causing these tests to fail. Resolves #224. --- .../GlobbingAppTests.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs index a6ccfaa91c..cb67bfec9e 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs @@ -54,8 +54,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests Assert.Equal(3, types); } - // TODO re-enable when MSBuild is updated. See https://github.com/aspnet/DotNetTools/issues/224 - [Fact(Skip = "Broken. See https://github.com/Microsoft/msbuild/issues/701")] + [Fact] public async Task DeleteCompiledFile() { await _app.StartWatcher().OrTimeout(); @@ -71,8 +70,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests Assert.Equal(1, types); } - // TODO re-enable when MSBuild is updated. See https://github.com/aspnet/DotNetTools/issues/224 - [Fact(Skip = "Broken. See https://github.com/Microsoft/msbuild/issues/701")] + [Fact] public async Task DeleteSourceFolder() { await _app.StartWatcher().OrTimeout(); From fd632ec65423951a4cd2f180b0667978c1d0c425 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 14 Dec 2016 09:13:00 -0800 Subject: [PATCH 0384/1029] Cleanup msbuild layout Use one props file for whole repo, avoiding layers of dir.props --- {tools => build}/Key.snk | Bin build/common.props | 12 ++++++++++++ build/common.targets | 11 +++++++++++ dir.props | 11 ----------- .../Microsoft.DotNet.Watcher.Tools.csproj | 14 +++++++++++--- .../prefercliruntime | 0 ...ft.Extensions.Caching.SqlConfig.Tools.csproj | 7 ++++++- .../prefercliruntime | 0 ...rosoft.Extensions.SecretManager.Tools.csproj | 7 ++++++- .../prefercliruntime | 0 src/dir.props | 16 ---------------- ....DotNet.Watcher.Tools.FunctionalTests.csproj | 8 +++++++- .../Microsoft.DotNet.Watcher.Tools.Tests.csproj | 8 +++++++- ....Extensions.SecretManager.Tools.Tests.csproj | 8 +++++++- .../Microsoft.Extensions.Tools.Tests.csproj | 8 +++++++- test/dir.props | 9 --------- tools/sign.props | 7 ------- 17 files changed, 74 insertions(+), 52 deletions(-) rename {tools => build}/Key.snk (100%) create mode 100644 build/common.props create mode 100644 build/common.targets delete mode 100644 dir.props rename src/{ => Microsoft.DotNet.Watcher.Tools}/prefercliruntime (100%) create mode 100644 src/Microsoft.Extensions.Caching.SqlConfig.Tools/prefercliruntime create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/prefercliruntime delete mode 100644 src/dir.props delete mode 100644 test/dir.props delete mode 100644 tools/sign.props diff --git a/tools/Key.snk b/build/Key.snk similarity index 100% rename from tools/Key.snk rename to build/Key.snk diff --git a/build/common.props b/build/common.props new file mode 100644 index 0000000000..6feec58008 --- /dev/null +++ b/build/common.props @@ -0,0 +1,12 @@ + + + + + $(MSBuildThisFileDirectory)common.targets + https://github.com/aspnet/DotNetTools + git + $(MSBuildThisFileDirectory)Key.snk + true + true + + \ No newline at end of file diff --git a/build/common.targets b/build/common.targets new file mode 100644 index 0000000000..0d53664e13 --- /dev/null +++ b/build/common.targets @@ -0,0 +1,11 @@ + + + EnsureInitialized;$(BuildDependsOn) + + + + + + \ No newline at end of file diff --git a/dir.props b/dir.props deleted file mode 100644 index 3f3183bc8c..0000000000 --- a/dir.props +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj index fb08e53fcf..5fcd93218a 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj @@ -1,21 +1,29 @@  - + + netcoreapp1.0 dotnet-watch exe Command line tool to watch for source file changes during development and restart the dotnet command. + Microsoft.DotNet.Watcher.Tools dotnet;watch + DotnetCliTool + + + + - - + + + \ No newline at end of file diff --git a/src/prefercliruntime b/src/Microsoft.DotNet.Watcher.Tools/prefercliruntime similarity index 100% rename from src/prefercliruntime rename to src/Microsoft.DotNet.Watcher.Tools/prefercliruntime diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj index 6a05d21dde..d5a6312358 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj @@ -1,19 +1,24 @@  - + netcoreapp1.0 dotnet-sql-cache exe Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching. + Microsoft.Extensions.Caching.SqlConfig.Tools cache;distributedcache;sqlserver + DotnetCliTool + + + \ No newline at end of file diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/prefercliruntime b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/prefercliruntime new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj index 142fbcbabe..af9f5b2dab 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj @@ -1,11 +1,13 @@  - + netcoreapp1.0 dotnet-user-secrets exe Command line tool to manage user secrets for Microsoft.Extensions.Configuration. + Microsoft.Extensions.SecretManager.Tools configuration;secrets;usersecrets + DotnetCliTool false @@ -14,9 +16,12 @@ + + + \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/prefercliruntime b/src/Microsoft.Extensions.SecretManager.Tools/prefercliruntime new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/dir.props b/src/dir.props deleted file mode 100644 index addeb75498..0000000000 --- a/src/dir.props +++ /dev/null @@ -1,16 +0,0 @@ - - - - - $(MSBuildProjectName) - DotnetCliTool - https://github.com/aspnet/DotNetTools - git - - - - - - - - \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj index 2cb75f63ab..4a62605ec6 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj @@ -1,6 +1,6 @@  - + netcoreapp1.0;netcoreapp1.1 @@ -14,8 +14,14 @@ + + + + + + diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj index d4201a9e72..f47ff1cfe0 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj @@ -1,6 +1,6 @@  - + netcoreapp1.0 @@ -13,8 +13,14 @@ + + + + + + diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj index 29ea81b6aa..29e29c39b3 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj @@ -1,6 +1,6 @@  - + netcoreapp1.0 @@ -10,8 +10,14 @@ + + + + + + \ No newline at end of file diff --git a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj index 775ec194cd..af1f80ea25 100644 --- a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj @@ -1,6 +1,6 @@  - + netcoreapp1.0 @@ -10,7 +10,13 @@ + + + + + + \ No newline at end of file diff --git a/test/dir.props b/test/dir.props deleted file mode 100644 index a0553297be..0000000000 --- a/test/dir.props +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/tools/sign.props b/tools/sign.props deleted file mode 100644 index 54132d388a..0000000000 --- a/tools/sign.props +++ /dev/null @@ -1,7 +0,0 @@ - - - $(MSBuildThisFileDirectory)Key.snk - true - true - - \ No newline at end of file From c8c2dfaad97d1e21eacb8ba0bbd1b65a9cc6993f Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 5 Dec 2016 09:02:54 -0800 Subject: [PATCH 0385/1029] Updating to 4.4 CoreFx packages --- global.json | 2 +- src/Microsoft.AspNetCore.JsonPatch/project.json | 6 +++--- test/Microsoft.AspNetCore.JsonPatch.Test/project.json | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/global.json b/global.json index e04bdfc390..a5c02fe221 100644 --- a/global.json +++ b/global.json @@ -5,6 +5,6 @@ "samples" ], "sdk": { - "version": "1.0.0-preview2-1-003177" + "version": "1.0.0-preview2-1-003180" } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json index a2015980e1..7214cde411 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ b/src/Microsoft.AspNetCore.JsonPatch/project.json @@ -21,7 +21,7 @@ ] }, "dependencies": { - "NETStandard.Library": "1.6.1-*", + "NETStandard.Library": "1.6.2-*", "Newtonsoft.Json": "9.0.1", "Microsoft.Extensions.ClosedGenericMatcher.Sources": { "type": "build", @@ -32,8 +32,8 @@ "net451": {}, "netstandard1.3": { "dependencies": { - "Microsoft.CSharp": "4.3.0-*", - "System.Reflection.TypeExtensions": "4.3.0-*" + "Microsoft.CSharp": "4.4.0-*", + "System.Reflection.TypeExtensions": "4.4.0-*" } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json index 158192b281..4790217eba 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json @@ -14,10 +14,10 @@ "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { - "version": "1.1.0-*", + "version": "1.2.0-*", "type": "platform" }, - "System.Diagnostics.TraceSource": "4.3.0-*" + "System.Diagnostics.TraceSource": "4.4.0-*" } }, "net451": { From f6eb86be7838e030173d2c6e7614bccd18d1dec7 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 5 Dec 2016 09:02:41 -0800 Subject: [PATCH 0386/1029] Updating to 4.4 CoreFx packages --- global.json | 2 +- src/Microsoft.AspNetCore.Html.Abstractions/project.json | 4 ++-- src/Microsoft.Extensions.WebEncoders/project.json | 4 ++-- test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json | 2 +- test/Microsoft.Extensions.WebEncoders.Tests/project.json | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/global.json b/global.json index f45e8cc925..0ad1995dd2 100644 --- a/global.json +++ b/global.json @@ -3,6 +3,6 @@ "src" ], "sdk": { - "version": "1.0.0-preview2-1-003177" + "version": "1.0.0-preview2-1-003180" } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/project.json b/src/Microsoft.AspNetCore.Html.Abstractions/project.json index 8c64893f22..4e640d584b 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/project.json +++ b/src/Microsoft.AspNetCore.Html.Abstractions/project.json @@ -19,8 +19,8 @@ "xmlDoc": true }, "dependencies": { - "NETStandard.Library": "1.6.1-*", - "System.Text.Encodings.Web": "4.3.0-*" + "NETStandard.Library": "1.6.2-*", + "System.Text.Encodings.Web": "4.4.0-*" }, "frameworks": { "netstandard1.0": {} diff --git a/src/Microsoft.Extensions.WebEncoders/project.json b/src/Microsoft.Extensions.WebEncoders/project.json index f7ded704b5..b3fe422893 100644 --- a/src/Microsoft.Extensions.WebEncoders/project.json +++ b/src/Microsoft.Extensions.WebEncoders/project.json @@ -22,8 +22,8 @@ "dependencies": { "Microsoft.Extensions.DependencyInjection.Abstractions": "1.2.0-*", "Microsoft.Extensions.Options": "1.2.0-*", - "NETStandard.Library": "1.6.1-*", - "System.Text.Encodings.Web": "4.3.0-*" + "NETStandard.Library": "1.6.2-*", + "System.Text.Encodings.Web": "4.4.0-*" }, "frameworks": { "netstandard1.0": {} diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json index a1e50970d0..0e46d9c52c 100644 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json @@ -15,7 +15,7 @@ "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { - "version": "1.1.0-*", + "version": "1.2.0-*", "type": "platform" } } diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json index 462b1cebfd..d06fb5b18b 100644 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ b/test/Microsoft.Extensions.WebEncoders.Tests/project.json @@ -14,7 +14,7 @@ "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { - "version": "1.1.0-*", + "version": "1.2.0-*", "type": "platform" } }, From c8b37f47d0f95f7fde490c45eafcfefa08d8210f Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 14 Dec 2016 16:34:19 -0800 Subject: [PATCH 0387/1029] Pin functional tests to preview2 of dotnet-cli --- .../Scenario/ProjectToolScenario.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs index c0c2ce0016..783f806aec 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -82,7 +82,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests private void CreateTestDirectory() { Directory.CreateDirectory(WorkFolder); - File.WriteAllText(Path.Combine(WorkFolder, "global.json"), "{}"); + File.WriteAllText(Path.Combine(WorkFolder, "global.json"), "{\"sdk\": {\"version\":\"1.0.0-preview2-1-003177\"} }"); var nugetConfigFilePath = FindNugetConfig(); @@ -92,7 +92,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public Process ExecuteDotnetWatch(IEnumerable arguments, string workDir, IDictionary environmentVariables = null) { - // this launches a new .NET Core process using the runtime of the current test app + // this launches a new .NET Core process using the runtime of the current test app // and the version of dotnet-watch that this test app is compiled against var thisAssembly = Path.GetFileNameWithoutExtension(GetType().GetTypeInfo().Assembly.Location); var args = new List(); From d55948cae384e64fb5aa80132281f3f345891090 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 14 Dec 2016 19:30:44 -0800 Subject: [PATCH 0388/1029] React to changes in KoreBuild --- build/common.props | 10 +++++++++- build/common.targets | 11 ----------- .../Microsoft.DotNet.Watcher.Tools.csproj | 2 +- .../Properties/AssemblyInfo.cs | 2 -- ...icrosoft.Extensions.Caching.SqlConfig.Tools.csproj | 2 +- .../Properties/AssemblyInfo.cs | 6 ------ .../Microsoft.Extensions.SecretManager.Tools.csproj | 2 +- .../Properties/AssemblyInfo.cs | 2 -- ...rosoft.DotNet.Watcher.Tools.FunctionalTests.csproj | 5 ++--- .../TestProjects/AppWithDeps/AppWithDeps.csproj | 2 +- .../TestProjects/Dependency/Dependency.csproj | 2 +- .../TestProjects/GlobbingApp/GlobbingApp.csproj | 2 +- .../TestProjects/NoDepsApp/NoDepsApp.csproj | 2 +- .../Microsoft.DotNet.Watcher.Tools.Tests.csproj | 3 +-- ...rosoft.Extensions.SecretManager.Tools.Tests.csproj | 3 +-- .../Microsoft.Extensions.Tools.Tests.csproj | 3 +-- 16 files changed, 21 insertions(+), 38 deletions(-) delete mode 100644 build/common.targets delete mode 100644 src/Microsoft.Extensions.Caching.SqlConfig.Tools/Properties/AssemblyInfo.cs diff --git a/build/common.props b/build/common.props index 6feec58008..010c8f79aa 100644 --- a/build/common.props +++ b/build/common.props @@ -1,12 +1,20 @@ + - $(MSBuildThisFileDirectory)common.targets https://github.com/aspnet/DotNetTools git $(MSBuildThisFileDirectory)Key.snk true true + + + + + \ No newline at end of file diff --git a/build/common.targets b/build/common.targets deleted file mode 100644 index 0d53664e13..0000000000 --- a/build/common.targets +++ /dev/null @@ -1,11 +0,0 @@ - - - EnsureInitialized;$(BuildDependsOn) - - - - - - \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj index 5fcd93218a..7287ab240f 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs b/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs index db52f83415..e6d00aa36d 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs @@ -1,10 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System.Reflection; using System.Runtime.CompilerServices; -[assembly: AssemblyMetadata("Serviceable", "True")] [assembly: InternalsVisibleTo("Microsoft.DotNet.Watcher.Tools.Tests, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] // TODO remove when .Source packages work [assembly: InternalsVisibleTo("Microsoft.DotNet.Watcher.Tools.FunctionalTests, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj index d5a6312358..62744be02a 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj @@ -1,4 +1,4 @@ - + netcoreapp1.0 diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Properties/AssemblyInfo.cs b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Properties/AssemblyInfo.cs deleted file mode 100644 index 1c2dd26bbd..0000000000 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Reflection; - -[assembly: AssemblyMetadata("Serviceable", "True")] diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj index af9f5b2dab..980cfe6174 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj @@ -1,4 +1,4 @@ - + netcoreapp1.0 diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Properties/AssemblyInfo.cs b/src/Microsoft.Extensions.SecretManager.Tools/Properties/AssemblyInfo.cs index 98bf46385c..ae77d384c1 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Properties/AssemblyInfo.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Properties/AssemblyInfo.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System.Reflection; using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Microsoft.Extensions.SecretManager.Tools.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] -[assembly: AssemblyMetadata("Serviceable", "True")] diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj index 4a62605ec6..f34fb44fc2 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj @@ -1,10 +1,9 @@ - + netcoreapp1.0;netcoreapp1.1 - exe @@ -32,7 +31,7 @@ - + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj index 40b6fd7ae2..72f0c81be3 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj @@ -1,4 +1,4 @@ - + netcoreapp1.0 diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj index f800ba3b09..88921254ff 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj @@ -1,4 +1,4 @@ - + netstandard1.5 diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj index 7a6df0e8bc..b0eeb14f53 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj @@ -1,4 +1,4 @@ - + netcoreapp1.0 diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj index 5cbd709f53..df52967c84 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj @@ -1,4 +1,4 @@ - + netcoreapp1.0 diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj index f47ff1cfe0..476ba8d420 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj @@ -1,10 +1,9 @@ - + netcoreapp1.0 - exe diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj index 29e29c39b3..376bfb6619 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj @@ -1,10 +1,9 @@ - + netcoreapp1.0 - exe diff --git a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj index af1f80ea25..9aaaf8f6d9 100644 --- a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj @@ -1,10 +1,9 @@ - + netcoreapp1.0 - exe From e588c9ea867658778c74391ed56322b2b6c2b72b Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 16 Dec 2016 14:13:35 -0800 Subject: [PATCH 0389/1029] :arrow_up: PrefixSuffix to msbuild4 --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index c7af7a2430..f0f37273fd 100644 --- a/version.props +++ b/version.props @@ -2,6 +2,6 @@ 1.0.0 - msbuild3 + msbuild4 \ No newline at end of file From 15c1bfa71797466f410dc3090da9d59a2cfa378c Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 16 Dec 2016 14:25:15 -0800 Subject: [PATCH 0390/1029] Branch for RC.3 --- build.ps1 | 2 +- build.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.ps1 b/build.ps1 index f780c43a82..5d4694be76 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.0.0-msbuild3.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index ff79789196..cbf06b7553 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.0.0-msbuild3.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi From 5966024d01278bccb4cf2581fdd93575e87da9d8 Mon Sep 17 00:00:00 2001 From: David Rovani Date: Fri, 23 Dec 2016 09:33:39 -0600 Subject: [PATCH 0391/1029] Fixed minor spelling error in comments. --- src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs index 875134ed9d..4da2bdbe1e 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs @@ -123,7 +123,7 @@ namespace Microsoft.AspNetCore.JsonPatch } /// - /// Copy the value at specified location to the target location. Willr esult in, for example: + /// Copy the value at specified location to the target location. Will result in, for example: /// { "op": "copy", "from": "/a/b/c", "path": "/a/b/e" } /// /// source location From cc84b8402d0a607e0d7926e0f3923134dad5c237 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 3 Jan 2017 11:16:34 -0800 Subject: [PATCH 0392/1029] Fix help text for dotnet-user-secrets-set to show the correct Windows example --- .../Internal/SetCommand.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs index c162b72107..5c393f3223 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.IO; +using System.Runtime.InteropServices; using System.Text; using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Tools.Internal; @@ -18,9 +19,13 @@ Additional Info: This command will also handle piped input. Piped input is expected to be a valid JSON format. Examples: - dotnet user-secrets set ConnStr ""User ID=bob;Password=***"" - cat secrets.json | dotnet user-secrets set -"; + dotnet user-secrets set ConnStr ""User ID=bob;Password=***"""; + + var catCmd = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + ? @"type .\secrets.json" + : "cat ./secrets.json"; + + command.ExtendedHelpText += $@" {catCmd} | dotnet user-secrets set"; command.HelpOption(); From e8452821b9a7689853e36c9a10ad4b8c6281817c Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Wed, 28 Dec 2016 13:35:15 -0800 Subject: [PATCH 0393/1029] [Fixes #50] JsonPatchDocument.Replace() yields invalid path when [JsonProperty] is used (1.1.0) --- .../Internal/ExpressionHelpers.cs | 120 ------------- .../JsonPatchDocumentOfT.cs | 170 ++++++++++++++---- ...nPatchDocumentJsonPropertyAttributeTest.cs | 113 +++++++++++- 3 files changed, 245 insertions(+), 158 deletions(-) delete mode 100644 src/Microsoft.AspNetCore.JsonPatch/Internal/ExpressionHelpers.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ExpressionHelpers.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ExpressionHelpers.cs deleted file mode 100644 index c978330e5c..0000000000 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/ExpressionHelpers.cs +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Globalization; -using System.Linq.Expressions; -using System.Reflection; -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.JsonPatch.Internal -{ - public static class ExpressionHelpers - { - public static string GetPath(Expression> expr) where TModel : class - { - return "/" + GetPath(expr.Body, true); - } - - private static string GetPath(Expression expr, bool firstTime) - { - switch (expr.NodeType) - { - case ExpressionType.ArrayIndex: - var binaryExpression = (BinaryExpression)expr; - - if (ContinueWithSubPath(binaryExpression.Left.NodeType, false)) - { - var leftFromBinaryExpression = GetPath(binaryExpression.Left, false); - return leftFromBinaryExpression + "/" + binaryExpression.Right.ToString(); - } - else - { - return binaryExpression.Right.ToString(); - } - case ExpressionType.Call: - var methodCallExpression = (MethodCallExpression)expr; - - if (ContinueWithSubPath(methodCallExpression.Object.NodeType, false)) - { - var leftFromMemberCallExpression = GetPath(methodCallExpression.Object, false); - return leftFromMemberCallExpression + "/" + - GetIndexerInvocation(methodCallExpression.Arguments[0]); - } - else - { - return GetIndexerInvocation(methodCallExpression.Arguments[0]); - } - case ExpressionType.Convert: - return GetPath(((UnaryExpression)expr).Operand, false); - case ExpressionType.MemberAccess: - var memberExpression = expr as MemberExpression; - - if (ContinueWithSubPath(memberExpression.Expression.NodeType, false)) - { - var left = GetPath(memberExpression.Expression, false); - // Get property name, respecting JsonProperty attribute - return left + "/" + GetPropertyNameFromMemberExpression(memberExpression); - } - else - { - // Get property name, respecting JsonProperty attribute - return GetPropertyNameFromMemberExpression(memberExpression); - } - case ExpressionType.Parameter: - // Fits "x => x" (the whole document which is "" as JSON pointer) - return firstTime ? string.Empty : null; - default: - return string.Empty; - } - } - - private static string GetPropertyNameFromMemberExpression(MemberExpression memberExpression) - { - // if there's a JsonProperty attribute, we must return the PropertyName - // from the attribute rather than the member name - var jsonPropertyAttribute = - memberExpression.Member.GetCustomAttribute( - typeof(JsonPropertyAttribute), true); - - if (jsonPropertyAttribute == null) - { - return memberExpression.Member.Name; - } - // get value - var castedAttribute = (JsonPropertyAttribute)jsonPropertyAttribute; - return castedAttribute.PropertyName; - } - - private static bool ContinueWithSubPath(ExpressionType expressionType, bool firstTime) - { - if (firstTime) - { - return (expressionType == ExpressionType.ArrayIndex - || expressionType == ExpressionType.Call - || expressionType == ExpressionType.Convert - || expressionType == ExpressionType.MemberAccess - || expressionType == ExpressionType.Parameter); - } - else - { - return (expressionType == ExpressionType.ArrayIndex - || expressionType == ExpressionType.Call - || expressionType == ExpressionType.Convert - || expressionType == ExpressionType.MemberAccess); - } - } - - private static string GetIndexerInvocation(Expression expression) - { - var converted = Expression.Convert(expression, typeof(object)); - var fakeParameter = Expression.Parameter(typeof(object), null); - var lambda = Expression.Lambda>(converted, fakeParameter); - Func func; - - func = lambda.Compile(); - - return Convert.ToString(func(null), CultureInfo.InvariantCulture); - } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs index fc660b2b45..c81c4e4d6c 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs @@ -2,7 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Linq; using System.Collections.Generic; +using System.Globalization; using System.Linq.Expressions; using Microsoft.AspNetCore.JsonPatch.Adapters; using Microsoft.AspNetCore.JsonPatch.Converters; @@ -66,7 +68,7 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "add", - ExpressionHelpers.GetPath(path).ToLowerInvariant(), + GetPath(path), from: null, value: value)); @@ -93,7 +95,7 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "add", - ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + position, + GetPath(path) + "/" + position, from: null, value: value)); @@ -116,7 +118,7 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "add", - ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-", + GetPath(path) + "/-", from: null, value: value)); @@ -136,7 +138,7 @@ namespace Microsoft.AspNetCore.JsonPatch throw new ArgumentNullException(nameof(path)); } - Operations.Add(new Operation("remove", ExpressionHelpers.GetPath(path).ToLowerInvariant(), from: null)); + Operations.Add(new Operation("remove", GetPath(path), from: null)); return this; } @@ -157,7 +159,7 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "remove", - ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + position, + GetPath(path) + "/" + position, from: null)); return this; @@ -178,7 +180,7 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "remove", - ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-", + GetPath(path) + "/-", from: null)); return this; @@ -200,7 +202,7 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "replace", - ExpressionHelpers.GetPath(path).ToLowerInvariant(), + GetPath(path), from: null, value: value)); @@ -225,7 +227,7 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "replace", - ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + position, + GetPath(path) + "/" + position, from: null, value: value)); @@ -248,7 +250,7 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "replace", - ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-", + GetPath(path) + "/-", from: null, value: value)); @@ -278,8 +280,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "move", - ExpressionHelpers.GetPath(path).ToLowerInvariant(), - ExpressionHelpers.GetPath(from).ToLowerInvariant())); + GetPath(path), + GetPath(from))); return this; } @@ -309,8 +311,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "move", - ExpressionHelpers.GetPath(path).ToLowerInvariant(), - ExpressionHelpers.GetPath(from).ToLowerInvariant() + "/" + positionFrom)); + GetPath(path), + GetPath(from) + "/" + positionFrom)); return this; } @@ -340,8 +342,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "move", - ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + positionTo, - ExpressionHelpers.GetPath(from).ToLowerInvariant())); + GetPath(path) + "/" + positionTo, + GetPath(from))); return this; } @@ -373,8 +375,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "move", - ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + positionTo, - ExpressionHelpers.GetPath(from).ToLowerInvariant() + "/" + positionFrom)); + GetPath(path) + "/" + positionTo, + GetPath(from) + "/" + positionFrom)); return this; } @@ -404,8 +406,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "move", - ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-", - ExpressionHelpers.GetPath(from).ToLowerInvariant() + "/" + positionFrom)); + GetPath(path) + "/-", + GetPath(from) + "/" + positionFrom)); return this; } @@ -433,8 +435,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "move", - ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-", - ExpressionHelpers.GetPath(from).ToLowerInvariant())); + GetPath(path) + "/-", + GetPath(from))); return this; } @@ -462,8 +464,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "copy", - ExpressionHelpers.GetPath(path).ToLowerInvariant() - , ExpressionHelpers.GetPath(from).ToLowerInvariant())); + GetPath(path) + , GetPath(from))); return this; } @@ -493,8 +495,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "copy", - ExpressionHelpers.GetPath(path).ToLowerInvariant(), - ExpressionHelpers.GetPath(from).ToLowerInvariant() + "/" + positionFrom)); + GetPath(path), + GetPath(from) + "/" + positionFrom)); return this; } @@ -524,8 +526,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "copy", - ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + positionTo, - ExpressionHelpers.GetPath(from).ToLowerInvariant())); + GetPath(path) + "/" + positionTo, + GetPath(from))); return this; } @@ -557,8 +559,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "copy", - ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/" + positionTo, - ExpressionHelpers.GetPath(from).ToLowerInvariant() + "/" + positionFrom)); + GetPath(path) + "/" + positionTo, + GetPath(from) + "/" + positionFrom)); return this; } @@ -588,8 +590,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "copy", - ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-", - ExpressionHelpers.GetPath(from).ToLowerInvariant() + "/" + positionFrom)); + GetPath(path) + "/-", + GetPath(from) + "/" + positionFrom)); return this; } @@ -617,8 +619,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "copy", - ExpressionHelpers.GetPath(path).ToLowerInvariant() + "/-", - ExpressionHelpers.GetPath(from).ToLowerInvariant())); + GetPath(path) + "/-", + GetPath(from))); return this; } @@ -712,5 +714,107 @@ namespace Microsoft.AspNetCore.JsonPatch return allOps; } + + private string GetPath(Expression> expr) + { + return "/" + GetPath(expr.Body, true).ToLowerInvariant(); + } + + private string GetPath(Expression expr, bool firstTime) + { + switch (expr.NodeType) + { + case ExpressionType.ArrayIndex: + var binaryExpression = (BinaryExpression)expr; + + if (ContinueWithSubPath(binaryExpression.Left.NodeType, false)) + { + var leftFromBinaryExpression = GetPath(binaryExpression.Left, false); + return leftFromBinaryExpression + "/" + binaryExpression.Right.ToString(); + } + else + { + return binaryExpression.Right.ToString(); + } + case ExpressionType.Call: + var methodCallExpression = (MethodCallExpression)expr; + + if (ContinueWithSubPath(methodCallExpression.Object.NodeType, false)) + { + var leftFromMemberCallExpression = GetPath(methodCallExpression.Object, false); + return leftFromMemberCallExpression + "/" + + GetIndexerInvocation(methodCallExpression.Arguments[0]); + } + else + { + return GetIndexerInvocation(methodCallExpression.Arguments[0]); + } + case ExpressionType.Convert: + return GetPath(((UnaryExpression)expr).Operand, false); + case ExpressionType.MemberAccess: + var memberExpression = expr as MemberExpression; + + if (ContinueWithSubPath(memberExpression.Expression.NodeType, false)) + { + var left = GetPath(memberExpression.Expression, false); + // Get property name, respecting JsonProperty attribute + return left + "/" + GetPropertyNameFromMemberExpression(memberExpression); + } + else + { + // Get property name, respecting JsonProperty attribute + return GetPropertyNameFromMemberExpression(memberExpression); + } + case ExpressionType.Parameter: + // Fits "x => x" (the whole document which is "" as JSON pointer) + return firstTime ? string.Empty : null; + default: + return string.Empty; + } + } + + private string GetPropertyNameFromMemberExpression(MemberExpression memberExpression) + { + var jsonObjectContract = ContractResolver.ResolveContract(memberExpression.Expression.Type) as JsonObjectContract; + if (jsonObjectContract != null) + { + return jsonObjectContract.Properties + .First(jsonProperty => jsonProperty.UnderlyingName == memberExpression.Member.Name) + .PropertyName; + } + + return null; + } + + private static bool ContinueWithSubPath(ExpressionType expressionType, bool firstTime) + { + if (firstTime) + { + return (expressionType == ExpressionType.ArrayIndex + || expressionType == ExpressionType.Call + || expressionType == ExpressionType.Convert + || expressionType == ExpressionType.MemberAccess + || expressionType == ExpressionType.Parameter); + } + else + { + return (expressionType == ExpressionType.ArrayIndex + || expressionType == ExpressionType.Call + || expressionType == ExpressionType.Convert + || expressionType == ExpressionType.MemberAccess); + } + } + + private static string GetIndexerInvocation(Expression expression) + { + var converted = Expression.Convert(expression, typeof(object)); + var fakeParameter = Expression.Parameter(typeof(object), null); + var lambda = Expression.Lambda>(converted, fakeParameter); + Func func; + + func = lambda.Compile(); + + return Convert.ToString(func(null), CultureInfo.InvariantCulture); + } } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs index 0ec0c18afd..182cf1cd6d 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs @@ -1,8 +1,10 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Newtonsoft.Json; using System.Linq; +using System.Reflection; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; using Xunit; namespace Microsoft.AspNetCore.JsonPatch @@ -26,13 +28,47 @@ namespace Microsoft.AspNetCore.JsonPatch Assert.Equal(pathToCheck, "/anothername"); } + [Fact] + public void Add_WithExpressionOnStringProperty_FallsbackToPropertyName_WhenJsonPropertyName_IsEmpty() + { + // Arrange + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(m => m.StringProperty, "Test"); + var serialized = JsonConvert.SerializeObject(patchDoc); + + // Act + var deserialized = + JsonConvert.DeserializeObject>(serialized); + + // Assert + var pathToCheck = deserialized.Operations.First().path; + Assert.Equal("/stringproperty", pathToCheck); + } + + [Fact] + public void Add_WithExpressionOnArrayProperty_FallsbackToPropertyName_WhenJsonPropertyName_IsEmpty() + { + // Arrange + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(m => m.ArrayProperty, "James"); + var serialized = JsonConvert.SerializeObject(patchDoc); + + // Act + var deserialized = + JsonConvert.DeserializeObject>(serialized); + + // Assert + var pathToCheck = deserialized.Operations.First().path; + Assert.Equal("/arrayproperty/-", pathToCheck); + } + [Fact] public void Add_WithExpression_RespectsJsonPropertyName_WhenApplyingToDifferentlyTypedClassWithPropertyMatchingJsonPropertyName() { var patchDocToSerialize = new JsonPatchDocument(); patchDocToSerialize.Add(p => p.Name, "John"); - // the patchdoc will deserialize to "anothername". We should thus be able to apply + // the patchdoc will deserialize to "anothername". We should thus be able to apply // it to a class that HAS that other property name. var doc = new JsonPropertyWithAnotherNameDTO() { @@ -81,7 +117,7 @@ namespace Microsoft.AspNetCore.JsonPatch { Name = "InitialValue" }; - + // serialization should serialize to "AnotherName" var serialized = "[{\"value\":\"Kevin\",\"path\":\"/AnotherName\",\"op\":\"add\"}]"; var deserialized = @@ -151,9 +187,9 @@ namespace Microsoft.AspNetCore.JsonPatch var doc = new JsonPropertyComplexNameDTO() { FooSlashBars = "InitialName", - FooSlashTilde = new SimpleDTO + FooSlashTilde = new SimpleDTO { - StringProperty = "Initial Value" + StringProperty = "Initial Value" } }; @@ -167,5 +203,72 @@ namespace Microsoft.AspNetCore.JsonPatch Assert.Equal("Kevin", doc.FooSlashBars); Assert.Equal("Final Value", doc.FooSlashTilde.StringProperty); } + + [Fact] + public void Move_WithExpression_FallsbackToPropertyName_WhenJsonPropertyName_IsEmpty() + { + // Arrange + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(m => m.StringProperty, m => m.StringProperty2); + var serialized = JsonConvert.SerializeObject(patchDoc); + + // Act + var deserialized = + JsonConvert.DeserializeObject>(serialized); + + // Assert + var fromPath = deserialized.Operations.First().from; + Assert.Equal("/stringproperty", fromPath); + var toPath = deserialized.Operations.First().path; + Assert.Equal("/stringproperty2", toPath); + } + + [Fact] + public void Add_WithExpression_AndCustomContractResolver_UsesPropertyName_SetByContractResolver() + { + // Arrange + var patchDoc = new JsonPatchDocument(); + patchDoc.ContractResolver = new CustomContractResolver(); + patchDoc.Add(m => m.SSN, "123-45-6789"); + var serialized = JsonConvert.SerializeObject(patchDoc); + + // Act + var deserialized = + JsonConvert.DeserializeObject>(serialized); + + // Assert + var path = deserialized.Operations.First().path; + Assert.Equal("/socialsecuritynumber", path); + } + + private class JsonPropertyWithNoPropertyName + { + [JsonProperty] + public string StringProperty { get; set; } + + [JsonProperty] + public string[] ArrayProperty { get; set; } + + [JsonProperty] + public string StringProperty2 { get; set; } + + [JsonProperty] + public string SSN { get; set; } + } + + private class CustomContractResolver : DefaultContractResolver + { + protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) + { + var jsonProperty = base.CreateProperty(member, memberSerialization); + + if (jsonProperty.PropertyName == "SSN") + { + jsonProperty.PropertyName = "SocialSecurityNumber"; + } + + return jsonProperty; + } + } } } From cb3c5d77ade283538af441be9792590422c789a5 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 9 Jan 2017 10:36:52 -0800 Subject: [PATCH 0394/1029] Upgrade appveyor image --- appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 2275c1322c..a2d85c2df3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,4 +11,6 @@ build_script: - build.cmd --quiet verify clone_depth: 1 test: off -deploy: off \ No newline at end of file +deploy: off +# Required for dotnet-test to work +os: Visual Studio 2015 From 7ee45afed40e85652545f037cd9c3e04dd385493 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 11 Jan 2017 14:01:15 -0800 Subject: [PATCH 0395/1029] React to aspnet/KoreBuild#155 This converts to using Internal.AspNetCore.Sdk instead of importing from the KoreBuild folder directly --- NuGet.config | 9 +++++---- build/common.props | 11 ++++------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/NuGet.config b/NuGet.config index b0b61c2fe0..93f1ac47df 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,8 @@ - + + - - + + - \ No newline at end of file + diff --git a/build/common.props b/build/common.props index 010c8f79aa..fd3cb24b9c 100644 --- a/build/common.props +++ b/build/common.props @@ -1,8 +1,8 @@ - + Microsoft .NET https://github.com/aspnet/DotNetTools git $(MSBuildThisFileDirectory)Key.snk @@ -10,11 +10,8 @@ true - - - + + + \ No newline at end of file From e481df3d49f5185faaf12be098dd6b0f4d64d698 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 13 Jan 2017 09:52:32 -0800 Subject: [PATCH 0396/1029] Add better errors, fix help output text, and add 'dotnet watch --list' to help us diagnose issues Fixes #252 - help output shown twice in dotnet-watch Fixes #250 - add dotnet-watch --list. Prints a list of all files discovered Fixes #249 - better error message when GenerateWatchList fails --- .editorconfig | 28 ++++++++++ DotNetTools.sln | 13 +++-- .../CommandLineOptions.cs | 13 ++++- .../DotNetWatcher.cs | 9 ++- .../Internal/MsBuildFileSetFactory.cs | 41 +++++++++----- src/Microsoft.DotNet.Watcher.Tools/Program.cs | 55 +++++++++++++++++-- .../Internal/ProjectIdResolver.cs | 6 +- .../AppWithDepsTests.cs | 2 +- .../AwaitableProcess.cs | 20 ++++++- .../GlobbingAppTests.cs | 30 ++++++++-- .../NoDepsAppTests.cs | 4 +- .../Scenario/ProjectToolScenario.cs | 18 +++--- .../Scenario/WatchableApp.cs | 25 ++++++--- .../MsBuildFileSetFactoryTest.cs | 4 +- 14 files changed, 207 insertions(+), 61 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..98fd05f5b3 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,28 @@ +; EditorConfig to support per-solution formatting. +; Use the EditorConfig VS add-in to make this work. +; http://editorconfig.org/ + +; This is the default for the codeline. +root = true + +[*] +indent_style = space +charset = utf-8 +trim_trailing_whitespace = true + +[*.{cs}] +indent_size = 4 +insert_final_newline = true + +; All XML-based file formats +[*.{config,csproj,nuspec,props,resx,targets,xml}] +indent_size = 2 + +[*.{json}] +indent_size = 2 + +[*.{ps1}] +indent_size = 4 + +[*.{sh}] +indent_size = 4 \ No newline at end of file diff --git a/DotNetTools.sln b/DotNetTools.sln index a03be635f6..f39e982eb5 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.25807.0 +VisualStudioVersion = 15.0.26020.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66517987-2A5A-4330-B130-207039378FD4}" EndProject @@ -8,6 +8,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Watcher.To EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8321E0D1-9A47-4D2F-AED8-3AE636D44E35}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig NuGet.Config = NuGet.Config EndProjectSection EndProject @@ -43,10 +44,6 @@ Global {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Debug|Any CPU.Build.0 = Debug|Any CPU {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.ActiveCfg = Debug|Any CPU {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.Build.0 = Debug|Any CPU - {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Release|Any CPU.ActiveCfg = Debug|Any CPU - {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Release|Any CPU.Build.0 = Debug|Any CPU {7B331122-83B1-4F08-A119-DC846959844C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7B331122-83B1-4F08-A119-DC846959844C}.Debug|Any CPU.Build.0 = Debug|Any CPU {7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.ActiveCfg = Debug|Any CPU @@ -59,6 +56,10 @@ Global {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.Build.0 = Debug|Any CPU {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.ActiveCfg = Debug|Any CPU {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.Build.0 = Debug|Any CPU + {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Release|Any CPU.ActiveCfg = Debug|Any CPU + {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Release|Any CPU.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -67,9 +68,9 @@ Global {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46} = {66517987-2A5A-4330-B130-207039378FD4} {16BADE2F-1184-4518-8A70-B68A19D0805B} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E} = {66517987-2A5A-4330-B130-207039378FD4} - {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {7B331122-83B1-4F08-A119-DC846959844C} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {8A2E6961-6B12-4A8E-8215-3E7301D52EAC} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {53F3B53D-303A-4DAA-9C38-4F55195FA5B9} = {66517987-2A5A-4330-B130-207039378FD4} + {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} EndGlobalSection EndGlobal diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs index c602659f11..8056dff67e 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs @@ -16,6 +16,7 @@ namespace Microsoft.DotNet.Watcher public bool IsQuiet { get; private set; } public bool IsVerbose { get; private set; } public IList RemainingArguments { get; private set; } + public bool ListFiles { get; private set; } public static CommandLineOptions Parse(string[] args, IConsole console) { @@ -63,6 +64,9 @@ Examples: CommandOptionType.NoValue); var optVerbose = app.VerboseOption(); + var optList = app.Option("--list", "Lists all discovered files without starting the watcher", + CommandOptionType.NoValue); + app.VersionOptionFromAssemblyAttributes(typeof(Program).GetTypeInfo().Assembly); if (app.Execute(args) != 0) @@ -75,7 +79,9 @@ Examples: throw new CommandParsingException(app, Resources.Error_QuietAndVerboseSpecified); } - if (app.RemainingArguments.Count == 0) + if (app.RemainingArguments.Count == 0 + && !app.IsShowingInformation + && !optList.HasValue()) { app.ShowHelp(); } @@ -86,8 +92,9 @@ Examples: IsQuiet = optQuiet.HasValue(), IsVerbose = optVerbose.HasValue(), RemainingArguments = app.RemainingArguments, - IsHelp = app.IsShowingInformation + IsHelp = app.IsShowingInformation, + ListFiles = optList.HasValue(), }; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs index e326d83ae2..fb324de797 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs @@ -34,6 +34,13 @@ namespace Microsoft.DotNet.Watcher while (true) { var fileSet = await fileSetFactory.CreateAsync(cancellationToken); + + if (fileSet == null) + { + _reporter.Error("Failed to find a list of files to watch"); + return; + } + if (cancellationToken.IsCancellationRequested) { return; @@ -91,4 +98,4 @@ namespace Microsoft.DotNet.Watcher } } } -} \ No newline at end of file +} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs index 5aded8f772..1a7e900845 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs @@ -16,17 +16,19 @@ namespace Microsoft.DotNet.Watcher.Internal public class MsBuildFileSetFactory : IFileSetFactory { private const string TargetName = "GenerateWatchList"; - private const string ProjectExtensionFileExtension = ".dotnetwatch.targets"; + private const string ProjectExtensionFileExtension = ".dotnetwatch.g.targets"; private const string WatchTargetsFileName = "DotNetWatchCommon.targets"; private readonly IReporter _reporter; private readonly string _projectFile; private readonly string _watchTargetsDir; private readonly OutputSink _outputSink; private readonly ProcessRunner _processRunner; + private readonly bool _waitOnError; - public MsBuildFileSetFactory(IReporter reporter, string projectFile) + public MsBuildFileSetFactory(IReporter reporter, string projectFile, bool waitOnError) : this(reporter, projectFile, new OutputSink()) { + _waitOnError = waitOnError; } // output sink is for testing @@ -86,7 +88,7 @@ namespace Microsoft.DotNet.Watcher.Internal var exitCode = await _processRunner.RunAsync(processSpec, cancellationToken); - if (exitCode == 0) + if (exitCode == 0 && File.Exists(watchList)) { var fileset = new FileSet( File.ReadAllLines(watchList) @@ -109,28 +111,41 @@ namespace Microsoft.DotNet.Watcher.Internal _reporter.Error($"Error(s) finding watch items project file '{Path.GetFileName(_projectFile)}'"); - _reporter.Output($"MSBuild output from target '{TargetName}'"); + _reporter.Output($"MSBuild output from target '{TargetName}':"); + _reporter.Output(string.Empty); foreach (var line in capture.Lines) { - _reporter.Output($" [MSBUILD] : {line}"); + _reporter.Output($" {line}"); } - _reporter.Warn("Fix the error to continue or press Ctrl+C to exit."); + _reporter.Output(string.Empty); - var fileSet = new FileSet(new[] {_projectFile}); - - using (var watcher = new FileSetWatcher(fileSet)) + if (!_waitOnError) { - await watcher.GetChangedFileAsync(cancellationToken); + return null; + } + else + { + _reporter.Warn("Fix the error to continue or press Ctrl+C to exit."); - _reporter.Output($"File changed: {_projectFile}"); + var fileSet = new FileSet(new[] { _projectFile }); + + using (var watcher = new FileSetWatcher(fileSet)) + { + await watcher.GetChangedFileAsync(cancellationToken); + + _reporter.Output($"File changed: {_projectFile}"); + } } } } finally { - File.Delete(watchList); + if (File.Exists(watchList)) + { + File.Delete(watchList); + } } } @@ -173,4 +188,4 @@ namespace Microsoft.DotNet.Watcher.Internal return Path.GetDirectoryName(targetPath); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index 9c488ff283..9d18757d3c 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -80,7 +80,20 @@ namespace Microsoft.DotNet.Watcher try { - return await MainInternalAsync(reporter, options.Project, options.RemainingArguments, ctrlCTokenSource.Token); + if (options.ListFiles) + { + return await ListFilesAsync(reporter, + options.Project, + ctrlCTokenSource.Token); + } + else + { + + return await MainInternalAsync(reporter, + options.Project, + options.RemainingArguments, + ctrlCTokenSource.Token); + } } catch (Exception ex) { @@ -115,8 +128,7 @@ namespace Microsoft.DotNet.Watcher return 1; } - var fileSetFactory = new MsBuildFileSetFactory(reporter, projectFile); - + var fileSetFactory = new MsBuildFileSetFactory(reporter, projectFile, waitOnError: true); var processInfo = new ProcessSpec { Executable = DotNetMuxer.MuxerPathOrDefault(), @@ -130,6 +142,39 @@ namespace Microsoft.DotNet.Watcher return 0; } + private async Task ListFilesAsync( + IReporter reporter, + string project, + CancellationToken cancellationToken) + { + // TODO multiple projects should be easy enough to add here + string projectFile; + try + { + projectFile = MsBuildProjectFinder.FindMsBuildProject(_workingDir, project); + } + catch (FileNotFoundException ex) + { + reporter.Error(ex.Message); + return 1; + } + + var fileSetFactory = new MsBuildFileSetFactory(reporter, projectFile, waitOnError: false); + var files = await fileSetFactory.CreateAsync(cancellationToken); + + if (files == null) + { + return 1; + } + + foreach (var file in files) + { + _console.Out.WriteLine(file); + } + + return 0; + } + private static IReporter CreateReporter(bool verbose, bool quiet, IConsole console) { const string prefix = "watch : "; @@ -178,4 +223,4 @@ namespace Microsoft.DotNet.Watcher .Build(); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs index a2d86da7ae..afea6d7a58 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -98,9 +98,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal // running tool using (var resource = GetType().GetTypeInfo().Assembly.GetManifestResourceStream("ProjectIdResolverTargets.xml")) using (var stream = new FileStream(projectExtensionsPath, FileMode.Create)) - using (var writer = new StreamWriter(stream)) { - writer.WriteLine(""); resource.CopyTo(stream); } } @@ -120,4 +118,4 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal } } } -} \ No newline at end of file +} diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs index 253f3643d1..37bfd618d1 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs @@ -22,7 +22,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [Fact] public async Task ChangeFileInDependency() { - await _app.StartWatcher().OrTimeout(); + await _app.StartWatcherAsync().OrTimeout(); var fileToChange = Path.Combine(_app.DependencyFolder, "Foo.cs"); var programCs = File.ReadAllText(fileToChange); diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs index 2abbdf9068..11583832d0 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text; @@ -9,8 +10,8 @@ using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; using Microsoft.Extensions.Internal; -using Xunit.Abstractions; using Microsoft.Extensions.Tools.Internal; +using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { @@ -71,6 +72,21 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests return null; } + public async Task> GetAllOutputLines() + { + var lines = new List(); + while (!_source.Completion.IsCompleted) + { + while (await _source.OutputAvailableAsync()) + { + var next = await _source.ReceiveAsync(); + _logger.WriteLine($"{DateTime.Now}: recv: '{next}'"); + lines.Add(next); + } + } + return lines; + } + private void StartProcessingOutput(StreamReader streamReader) { _source = _source ?? new BufferBlock(); @@ -80,7 +96,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests string line; while ((line = streamReader.ReadLine()) != null) { - _logger.WriteLine($"{DateTime.Now} post: {line}"); + _logger.WriteLine($"{DateTime.Now}: post: '{line}'"); _source.Post(line); } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs index cb67bfec9e..f2c37077d5 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Linq; using System.Threading.Tasks; +using Microsoft.DotNet.Watcher.Tools.Tests; using Xunit; using Xunit.Abstractions; @@ -24,7 +25,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [InlineData(false)] public async Task ChangeCompiledFile(bool usePollingWatcher) { - await _app.StartWatcher().OrTimeout(); + await _app.StartWatcherAsync().OrTimeout(); var types = await _app.GetCompiledAppDefinedTypes().OrTimeout(); Assert.Equal(2, types); @@ -41,7 +42,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [Fact(Skip = "Broken. See https://github.com/aspnet/DotNetTools/issues/212")] public async Task AddCompiledFile() { - await _app.StartWatcher().OrTimeout(); + await _app.StartWatcherAsync().OrTimeout(); var types = await _app.GetCompiledAppDefinedTypes().OrTimeout(); Assert.Equal(2, types); @@ -57,7 +58,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [Fact] public async Task DeleteCompiledFile() { - await _app.StartWatcher().OrTimeout(); + await _app.StartWatcherAsync().OrTimeout(); var types = await _app.GetCompiledAppDefinedTypes().OrTimeout(); Assert.Equal(2, types); @@ -73,7 +74,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [Fact] public async Task DeleteSourceFolder() { - await _app.StartWatcher().OrTimeout(); + await _app.StartWatcherAsync().OrTimeout(); var types = await _app.GetCompiledAppDefinedTypes().OrTimeout(); Assert.Equal(2, types); @@ -89,7 +90,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [Fact] public async Task RenameCompiledFile() { - await _app.StartWatcher().OrTimeout(); + await _app.StartWatcherAsync().OrTimeout(); var oldFile = Path.Combine(_app.SourceDirectory, "include", "Foo.cs"); var newFile = Path.Combine(_app.SourceDirectory, "include", "Foo_new.cs"); @@ -101,7 +102,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [Fact] public async Task ChangeExcludedFile() { - await _app.StartWatcher().OrTimeout(); + await _app.StartWatcherAsync().OrTimeout(); var changedFile = Path.Combine(_app.SourceDirectory, "exclude", "Baz.cs"); File.WriteAllText(changedFile, ""); @@ -111,6 +112,23 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests Assert.NotSame(restart, finished); } + [Fact] + public async Task ListsFiles() + { + _app.Start(new [] { "--list" }); + var lines = await _app.Process.GetAllOutputLines(); + + AssertEx.EqualFileList( + _app.Scenario.WorkFolder, + new[] + { + "GlobbingApp/Program.cs", + "GlobbingApp/include/Foo.cs", + "GlobbingApp/GlobbingApp.csproj", + }, + lines); + } + public void Dispose() { _app.Dispose(); diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs index 73d5ecd982..6e22a55436 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs @@ -23,7 +23,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [Fact] public async Task RestartProcessOnFileChange() { - await _app.StartWatcher(new[] { "--no-exit" }).OrTimeout(); + await _app.StartWatcherAsync(new[] { "--no-exit" }).OrTimeout(); var pid = await _app.GetProcessId().OrTimeout(); // Then wait for it to restart when we change a file @@ -42,7 +42,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [Fact] public async Task RestartProcessThatTerminatesAfterFileChange() { - await _app.StartWatcher().OrTimeout(); + await _app.StartWatcherAsync().OrTimeout(); var pid = await _app.GetProcessId().OrTimeout(); await _app.HasExited().OrTimeout(); // process should exit after run diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs index 2b62d17db9..1b0f62c7de 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -118,17 +118,17 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // this launches a new .NET Core process using the runtime of the current test app // and the version of dotnet-watch that this test app is compiled against var thisAssembly = Path.GetFileNameWithoutExtension(GetType().GetTypeInfo().Assembly.Location); - var args = new List(); - args.Add("exec"); - args.Add("--depsfile"); - args.Add(Path.Combine(AppContext.BaseDirectory, thisAssembly + ".deps.json")); + var args = new List + { + "exec", + "--depsfile", + Path.Combine(AppContext.BaseDirectory, thisAssembly + ".deps.json"), + "--runtimeconfig", + Path.Combine(AppContext.BaseDirectory, thisAssembly + ".runtimeconfig.json") + }; - args.Add("--runtimeconfig"); - args.Add(Path.Combine(AppContext.BaseDirectory, thisAssembly + ".runtimeconfig.json")); - - var currentFxVersion = AppContext.GetData("FX_DEPS_FILE") as string; - if (currentFxVersion != null) + if (AppContext.GetData("FX_DEPS_FILE") is string currentFxVersion) { // This overrides the version of shared fx in the runtimeconfig.json file. // Tests do this to ensure dotnet-watch is executing on the version of Microsoft.NETCore.App diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs index 797e17f640..6e4d6cc883 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs @@ -1,12 +1,13 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Microsoft.Extensions.Tools.Internal; using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; +using Microsoft.Extensions.Tools.Internal; using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests @@ -16,12 +17,11 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests private const string StartedMessage = "Started"; private const string ExitingMessage = "Exiting"; - protected ProjectToolScenario Scenario { get; } private readonly ITestOutputHelper _logger; - protected AwaitableProcess Process { get; set; } private string _appName; private bool _prepared; + public WatchableApp(string appName, ITestOutputHelper logger) { _logger = logger; @@ -31,6 +31,10 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests SourceDirectory = Path.Combine(Scenario.WorkFolder, appName); } + public ProjectToolScenario Scenario { get; } + + public AwaitableProcess Process { get; protected set; } + public string SourceDirectory { get; } public Task HasRestarted() @@ -41,9 +45,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public bool UsePollingWatcher { get; set; } - public Task StartWatcher([CallerMemberName] string name = null) - => StartWatcher(Array.Empty(), name); - public async Task GetProcessId() { var line = await Process.GetOutputLineAsync(l => l.StartsWith("PID =")); @@ -58,7 +59,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests _prepared = true; } - public async Task StartWatcher(string[] arguments, [CallerMemberName] string name = null) + public void Start(IEnumerable arguments, [CallerMemberName] string name = null) { if (!_prepared) { @@ -67,7 +68,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests var args = Scenario .GetDotnetWatchArguments() - .Concat(new[] { "run", "--" }) .Concat(arguments); var spec = new ProcessSpec @@ -79,6 +79,15 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests Process = new AwaitableProcess(spec, _logger); Process.Start(); + } + + public Task StartWatcherAsync([CallerMemberName] string name = null) + => StartWatcherAsync(Array.Empty(), name); + + public async Task StartWatcherAsync(string[] arguments, [CallerMemberName] string name = null) + { + var args = new[] { "run", "--" }.Concat(arguments); + Start(args, name); await Process.GetOutputLineAsync(StartedMessage); } diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs index 39c69ce4cc..9b46f04c1d 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs @@ -297,7 +297,8 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests } private Task GetFileSet(TemporaryCSharpProject target) - => GetFileSet(new MsBuildFileSetFactory(_reporter, target.Path)); + => GetFileSet(new MsBuildFileSetFactory(_reporter, target.Path, waitOnError: false)); + private async Task GetFileSet(MsBuildFileSetFactory filesetFactory) { _tempDir.Create(); @@ -305,6 +306,7 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests var finished = await Task.WhenAny(createTask, Task.Delay(TimeSpan.FromSeconds(10))); Assert.Same(createTask, finished); + Assert.NotNull(createTask.Result); return createTask.Result; } From 99e35b9651870f4df538fe96e754a01e495fffc1 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 17 Jan 2017 11:57:20 -0800 Subject: [PATCH 0397/1029] :arrow_up: update tool versions to 1.0.1 --- version.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.props b/version.props index f0f37273fd..bd4d4dc76f 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ - 1.0.0 - msbuild4 + 1.0.1 + alpha \ No newline at end of file From 6e246fa583615edd5f7c407d8d71c20a5b94ab97 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 17 Jan 2017 12:06:38 -0800 Subject: [PATCH 0398/1029] Prepare for 1.0.0 release. Pin versions of tools and SDK --- NuGet.config | 2 +- build.ps1 | 2 +- build.sh | 2 +- build/common.props | 2 +- .../Microsoft.DotNet.Watcher.Tools.csproj | 1 - version.props | 2 +- 6 files changed, 5 insertions(+), 6 deletions(-) diff --git a/NuGet.config b/NuGet.config index 93f1ac47df..d5447f08c2 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@  - + diff --git a/build.ps1 b/build.ps1 index f780c43a82..6cd68a4c45 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.0.0-msbuild-rtm.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index ff79789196..b2667494c3 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.0.0-msbuild-rtm.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi diff --git a/build/common.props b/build/common.props index fd3cb24b9c..eda2e3f6a7 100644 --- a/build/common.props +++ b/build/common.props @@ -11,7 +11,7 @@ - + \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj index 7287ab240f..7544415209 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj @@ -23,7 +23,6 @@ - \ No newline at end of file diff --git a/version.props b/version.props index f0f37273fd..cc5693b360 100644 --- a/version.props +++ b/version.props @@ -2,6 +2,6 @@ 1.0.0 - msbuild4 + rtm \ No newline at end of file From 161d101da627ea7eba5fe0d7f9e1674f6af947ea Mon Sep 17 00:00:00 2001 From: BrennanConroy Date: Tue, 17 Jan 2017 16:24:00 -0800 Subject: [PATCH 0399/1029] Change Xunit version --- .../Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj | 4 ++-- .../Microsoft.DotNet.Watcher.Tools.Tests.csproj | 4 ++-- .../Microsoft.Extensions.SecretManager.Tools.Tests.csproj | 4 ++-- .../Microsoft.Extensions.Tools.Tests.csproj | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj index f34fb44fc2..f17eaf1ea3 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj @@ -19,8 +19,8 @@ - - + + diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj index 476ba8d420..bcbea67722 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj @@ -18,8 +18,8 @@ - - + + diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj index 376bfb6619..bba12173eb 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj @@ -15,8 +15,8 @@ - - + + \ No newline at end of file diff --git a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj index 9aaaf8f6d9..4401acb259 100644 --- a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj @@ -14,8 +14,8 @@ - - + + \ No newline at end of file From 3c22b86a95eb094d0f8cf2bc176d0d3ffac12c41 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 18 Jan 2017 14:35:05 -0800 Subject: [PATCH 0400/1029] Create RTM package versions --- build/common.props | 2 +- version.props | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/build/common.props b/build/common.props index eda2e3f6a7..2bbff44a99 100644 --- a/build/common.props +++ b/build/common.props @@ -11,7 +11,7 @@ - + \ No newline at end of file diff --git a/version.props b/version.props index cc5693b360..60314cae6d 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,8 @@ - 1.0.0 - rtm + 1.0.0-rtm + $(Version)-$(BuildNumber) + 1.0.0 \ No newline at end of file From e325d9b52eb9eb240d5eaf648ab9138813cf11ca Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 19 Jan 2017 17:09:38 -0800 Subject: [PATCH 0401/1029] Pin sdk version using global.json --- global.json | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 global.json diff --git a/global.json b/global.json new file mode 100644 index 0000000000..1e3e060e88 --- /dev/null +++ b/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "version": "1.0.0-preview4-004233" + } +} From fac6b44bbdfb71898e51b3cd620b55a8213930b5 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 18 Jan 2017 11:14:43 -0800 Subject: [PATCH 0402/1029] Upgrade to RC.3 --- DotNetTools.sln | 2 +- build/common.props | 3 +- global.json | 5 - .../Microsoft.DotNet.Watcher.Tools.csproj | 12 +- .../Sources/ProcessHelper.cs | 115 ------------------ ....Extensions.Caching.SqlConfig.Tools.csproj | 7 +- ...soft.Extensions.SecretManager.Tools.csproj | 8 +- src/workaround.targets | 23 ++++ ...otNet.Watcher.Tools.FunctionalTests.csproj | 12 +- .../AppWithDeps/AppWithDeps.csproj | 3 - .../TestProjects/Dependency/Dependency.csproj | 7 -- .../GlobbingApp/GlobbingApp.csproj | 3 +- .../TestProjects/NoDepsApp/NoDepsApp.csproj | 6 - ...icrosoft.DotNet.Watcher.Tools.Tests.csproj | 4 +- ...xtensions.SecretManager.Tools.Tests.csproj | 4 +- .../UserSecretsTestFixture.cs | 4 +- .../Microsoft.Extensions.Tools.Tests.csproj | 4 +- 17 files changed, 48 insertions(+), 174 deletions(-) delete mode 100644 global.json delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/Sources/ProcessHelper.cs create mode 100644 src/workaround.targets diff --git a/DotNetTools.sln b/DotNetTools.sln index f39e982eb5..4f9600fad4 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26020.0 +VisualStudioVersion = 15.0.26118.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66517987-2A5A-4330-B130-207039378FD4}" EndProject diff --git a/build/common.props b/build/common.props index fd3cb24b9c..61157a7f65 100644 --- a/build/common.props +++ b/build/common.props @@ -8,10 +8,11 @@ $(MSBuildThisFileDirectory)Key.snk true true + $(VersionSuffix)-$(BuildNumber) - + \ No newline at end of file diff --git a/global.json b/global.json deleted file mode 100644 index 1e3e060e88..0000000000 --- a/global.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "sdk": { - "version": "1.0.0-preview4-004233" - } -} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj index 7287ab240f..ee7f2acb06 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj @@ -9,21 +9,21 @@ Microsoft.DotNet.Watcher.Tools dotnet;watch DotnetCliTool + 1.0.0 + toolassets - - - - + - - + + + \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Sources/ProcessHelper.cs b/src/Microsoft.DotNet.Watcher.Tools/Sources/ProcessHelper.cs deleted file mode 100644 index eccf4ddd3c..0000000000 --- a/src/Microsoft.DotNet.Watcher.Tools/Sources/ProcessHelper.cs +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -// TODO remove and using Microsoft.Extensions.Process.Sources when https://github.com/dotnet/sdk/issues/115 is fixed - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Runtime.InteropServices; - -namespace Microsoft.Extensions.Internal -{ - internal static class ProcessExtensions - { - private static readonly bool _isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30); - - public static void KillTree(this Process process) - { - process.KillTree(_defaultTimeout); - } - - public static void KillTree(this Process process, TimeSpan timeout) - { - string stdout; - if (_isWindows) - { - RunProcessAndWaitForExit( - "taskkill", - $"/T /F /PID {process.Id}", - timeout, - out stdout); - } - else - { - var children = new HashSet(); - GetAllChildIdsUnix(process.Id, children, timeout); - foreach (var childId in children) - { - KillProcessUnix(childId, timeout); - } - KillProcessUnix(process.Id, timeout); - } - } - - private static void GetAllChildIdsUnix(int parentId, ISet children, TimeSpan timeout) - { - string stdout; - var exitCode = RunProcessAndWaitForExit( - "pgrep", - $"-P {parentId}", - timeout, - out stdout); - - if (exitCode == 0 && !string.IsNullOrEmpty(stdout)) - { - using (var reader = new StringReader(stdout)) - { - while (true) - { - var text = reader.ReadLine(); - if (text == null) - { - return; - } - - int id; - if (int.TryParse(text, out id)) - { - children.Add(id); - // Recursively get the children - GetAllChildIdsUnix(id, children, timeout); - } - } - } - } - } - - private static void KillProcessUnix(int processId, TimeSpan timeout) - { - string stdout; - RunProcessAndWaitForExit( - "kill", - $"-TERM {processId}", - timeout, - out stdout); - } - - private static int RunProcessAndWaitForExit(string fileName, string arguments, TimeSpan timeout, out string stdout) - { - var startInfo = new ProcessStartInfo - { - FileName = fileName, - Arguments = arguments, - RedirectStandardOutput = true, - UseShellExecute = false - }; - - var process = Process.Start(startInfo); - - stdout = null; - if (process.WaitForExit((int)timeout.TotalMilliseconds)) - { - stdout = process.StandardOutput.ReadToEnd(); - } - else - { - process.Kill(); - } - - return process.ExitCode; - } - } -} diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj index 62744be02a..468900312f 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj @@ -8,17 +8,18 @@ Microsoft.Extensions.Caching.SqlConfig.Tools cache;distributedcache;sqlserver DotnetCliTool + 1.0.0 - - - + + + \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj index 980cfe6174..9730829536 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj @@ -9,19 +9,19 @@ configuration;secrets;usersecrets DotnetCliTool false + 1.0.0 - - - - + + + \ No newline at end of file diff --git a/src/workaround.targets b/src/workaround.targets new file mode 100644 index 0000000000..4068dffd93 --- /dev/null +++ b/src/workaround.targets @@ -0,0 +1,23 @@ + + + + $(DefaultItemExcludes);lib\**\* + + + + + <_PackageFiles Include="lib\netcoreapp1.0\*.json" BuildAction="None" PackagePath="%(Identity)" /> + + + + + + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj index f17eaf1ea3..1ef391c545 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj @@ -4,10 +4,10 @@ netcoreapp1.0;netcoreapp1.1 + $(DefaultItemExcludes);TestProjects\**\* - @@ -18,19 +18,11 @@ - + - - - - - - - - diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj index 72f0c81be3..93142c90b5 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj @@ -6,10 +6,7 @@ - - - \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj index 88921254ff..cbdcf50173 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj @@ -2,13 +2,6 @@ netstandard1.5 - library - - - - - - \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj index b0eeb14f53..e714c10c3b 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj @@ -3,12 +3,11 @@ netcoreapp1.0 exe + false - - \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj index df52967c84..b10a1c94fc 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj @@ -5,10 +5,4 @@ exe - - - - - - \ No newline at end of file diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj index bcbea67722..424f9ab2cd 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj @@ -7,7 +7,6 @@ - @@ -16,8 +15,7 @@ - - + diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj index bba12173eb..59300c6a2f 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj @@ -7,14 +7,12 @@ - - - + diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs index 569ee1c6c3..acc027e840 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs @@ -37,11 +37,11 @@ namespace Microsoft.Extensions.Configuration.UserSecrets.Tests Exe netcoreapp1.0 {0} + false - - + "; diff --git a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj index 4401acb259..0e2d61d78e 100644 --- a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj @@ -7,13 +7,11 @@ - - - + From 0795ec1d9afdbac6c85990f7beb414bf7241fb3e Mon Sep 17 00:00:00 2001 From: Jass Bagga Date: Thu, 26 Jan 2017 11:28:35 -0800 Subject: [PATCH 0403/1029] Add tests for Replace operation with null checks for property (#56) See #32 --- .../NestedObjectTests.cs | 23 ++++++++++++++ .../ObjectAdapterTests.cs | 20 +++++++++++++ .../SimpleDTOWithNestedDTOWithNullCheck.cs | 15 ++++++++++ .../SimpleDTOWithNullCheck.cs | 30 +++++++++++++++++++ 4 files changed, 88 insertions(+) create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTOWithNullCheck.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNullCheck.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs index 345ffe2201..cc2e990997 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs @@ -907,6 +907,29 @@ namespace Microsoft.AspNetCore.JsonPatch Assert.Equal(12, doc.SimpleDTO.DecimalValue); } + [Fact] + public void Replace_DTOWithNullCheck() + { + // Arrange + var doc = new SimpleDTOWithNestedDTOWithNullCheck() + { + SimpleDTOWithNullCheck = new SimpleDTOWithNullCheck() + { + StringProperty = "A" + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleDTOWithNullCheck.StringProperty, "B"); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal("B", doc.SimpleDTOWithNullCheck.StringProperty); + } + [Fact] public void ReplaceWithSerialization() { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs index 5898311044..d14daadbff 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs @@ -648,6 +648,26 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters Assert.Equal(12, doc.DecimalValue); } + [Fact] + public void Replace_DTOWithNullCheck() + { + // Arrange + var doc = new SimpleDTOWithNullCheck() + { + StringProperty = "A", + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.StringProperty, "B"); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal("B", doc.StringProperty); + } + [Fact] public void ReplaceWithSerialization() { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTOWithNullCheck.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTOWithNullCheck.cs new file mode 100644 index 0000000000..308f23b470 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTOWithNullCheck.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.AspNetCore.JsonPatch +{ + public class SimpleDTOWithNestedDTOWithNullCheck + { + public SimpleDTOWithNullCheck SimpleDTOWithNullCheck { get; set; } + + public SimpleDTOWithNestedDTOWithNullCheck() + { + SimpleDTOWithNullCheck = new SimpleDTOWithNullCheck(); + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNullCheck.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNullCheck.cs new file mode 100644 index 0000000000..d2a5fe51a4 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNullCheck.cs @@ -0,0 +1,30 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.AspNetCore.JsonPatch +{ + public class SimpleDTOWithNullCheck + { + private string stringProperty; + + public string StringProperty + { + get + { + return stringProperty; + } + + set + { + if (value == null) + { + throw new ArgumentNullException(); + } + + stringProperty = value; + } + } + } +} From 7a487a880a6525ced73b2e3d658c8e20b6578afb Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Mon, 23 Jan 2017 12:00:42 -0800 Subject: [PATCH 0404/1029] [Fixes #48] Regression: List add must support adding items where index is same as count of elements --- .../Internal/ListAdapter.cs | 35 ++++-- .../ListAdapterTest.cs | 110 +++++++++++++++++- 2 files changed, 136 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs index c3da14fe5a..343712690a 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs @@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } PositionInfo positionInfo; - if (!TryGetPositionInfo(list, segment, out positionInfo, out errorMessage)) + if (!TryGetPositionInfo(list, segment, OperationType.Add, out positionInfo, out errorMessage)) { return false; } @@ -68,7 +68,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } PositionInfo positionInfo; - if (!TryGetPositionInfo(list, segment, out positionInfo, out errorMessage)) + if (!TryGetPositionInfo(list, segment, OperationType.Get, out positionInfo, out errorMessage)) { value = null; return false; @@ -102,7 +102,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } PositionInfo positionInfo; - if (!TryGetPositionInfo(list, segment, out positionInfo, out errorMessage)) + if (!TryGetPositionInfo(list, segment, OperationType.Remove, out positionInfo, out errorMessage)) { return false; } @@ -136,7 +136,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } PositionInfo positionInfo; - if (!TryGetPositionInfo(list, segment, out positionInfo, out errorMessage)) + if (!TryGetPositionInfo(list, segment, OperationType.Replace, out positionInfo, out errorMessage)) { return false; } @@ -243,7 +243,12 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - private bool TryGetPositionInfo(IList list, string segment, out PositionInfo positionInfo, out string errorMessage) + private bool TryGetPositionInfo( + IList list, + string segment, + OperationType operationType, + out PositionInfo positionInfo, + out string errorMessage) { if (segment == "-") { @@ -261,16 +266,24 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal errorMessage = null; return true; } + // As per JSON Patch spec, for Add operation the index value representing the number of elements is valid, + // where as for other operations like Remove, Replace, Move and Copy the target index MUST exist. + else if (position == list.Count && operationType == OperationType.Add) + { + positionInfo = new PositionInfo(PositionType.EndOfList, -1); + errorMessage = null; + return true; + } else { - positionInfo = default(PositionInfo); + positionInfo = new PositionInfo(PositionType.OutOfBounds, position); errorMessage = Resources.FormatIndexOutOfBounds(segment); return false; } } else { - positionInfo = default(PositionInfo); + positionInfo = new PositionInfo(PositionType.Invalid, -1); errorMessage = Resources.FormatInvalidIndexValue(segment); return false; } @@ -295,5 +308,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Invalid, // Ex: not an integer OutOfBounds } + + private enum OperationType + { + Add, + Remove, + Get, + Replace + } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs index ee331a2b30..799f6e9e89 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs @@ -55,12 +55,31 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal message); } + [Fact] + public void Add_WithIndexSameAsNumberOfElements_Works() + { + // Arrange + var resolver = new Mock(MockBehavior.Strict); + var targetObject = new List() { "James", "Mike" }; + var listAdapter = new ListAdapter(); + string message = null; + var position = targetObject.Count.ToString(); + + // Act + var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, "Rob", out message); + + // Assert + Assert.Null(message); + Assert.True(addStatus); + Assert.Equal(3, targetObject.Count); + Assert.Equal(new List() { "James", "Mike", "Rob" }, targetObject); + } + [Theory] [InlineData("-1")] [InlineData("-2")] - [InlineData("2")] [InlineData("3")] - public void Patch_WithOutOfBoundsIndex_Fails(string position) + public void Add_WithOutOfBoundsIndex_Fails(string position) { // Arrange var resolver = new Mock(MockBehavior.Strict); @@ -225,6 +244,93 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.Equal(expected, targetObject); } + [Theory] + [InlineData(new int[] { }, "0")] + [InlineData(new[] { 10, 20 }, "-1")] + [InlineData(new[] { 10, 20 }, "2")] + public void Get_IndexOutOfBounds(int[] input, string position) + { + // Arrange + var resolver = new Mock(MockBehavior.Strict); + var targetObject = new List(input); + var listAdapter = new ListAdapter(); + string message = null; + object value = null; + + // Act + var getStatus = listAdapter.TryGet(targetObject, position, resolver.Object, out value, out message); + + // Assert + Assert.False(getStatus); + Assert.Equal( + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", position), + message); + } + + [Theory] + [InlineData(new[] { 10, 20 }, "0", 10)] + [InlineData(new[] { 10, 20 }, "1", 20)] + [InlineData(new[] { 10 }, "0", 10)] + public void Get(int[] input, string position, object expected) + { + // Arrange + var resolver = new Mock(MockBehavior.Strict); + var targetObject = new List(input); + var listAdapter = new ListAdapter(); + string message = null; + object value = null; + + // Act + var getStatus = listAdapter.TryGet(targetObject, position, resolver.Object, out value, out message); + + // Assert + Assert.True(getStatus); + Assert.Equal(expected, value); + Assert.Equal(new List(input), targetObject); + } + + [Theory] + [InlineData(new int[] { }, "0")] + [InlineData(new[] { 10, 20 }, "-1")] + [InlineData(new[] { 10, 20 }, "2")] + public void Remove_IndexOutOfBounds(int[] input, string position) + { + // Arrange + var resolver = new Mock(MockBehavior.Strict); + var targetObject = new List(input); + var listAdapter = new ListAdapter(); + string message = null; + + // Act + var removeStatus = listAdapter.TryRemove(targetObject, position, resolver.Object, out message); + + // Assert + Assert.False(removeStatus); + Assert.Equal( + string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", position), + message); + } + + [Theory] + [InlineData(new[] { 10, 20 }, "0", new[] { 20 })] + [InlineData(new[] { 10, 20 }, "1", new[] { 10 })] + [InlineData(new[] { 10 }, "0", new int[] { })] + public void Remove(int[] input, string position, int[] expected) + { + // Arrange + var resolver = new Mock(MockBehavior.Strict); + var targetObject = new List(input); + var listAdapter = new ListAdapter(); + string message = null; + + // Act + var removeStatus = listAdapter.TryRemove(targetObject, position, resolver.Object, out message); + + // Assert + Assert.True(removeStatus); + Assert.Equal(new List(expected), targetObject); + } + [Fact] public void Replace_NonCompatibleType_Fails() { From 48ab68bd2a47d87b1660bdf264898e4bc32aed24 Mon Sep 17 00:00:00 2001 From: Jass Bagga Date: Mon, 30 Jan 2017 15:58:19 -0800 Subject: [PATCH 0405/1029] Upgrade to msbuild Addresses #57 --- JsonPatch.sln | 20 ++- NuGet.config | 1 + appveyor.yml | 4 +- build.ps1 | 2 +- build.sh | 2 +- build/Key.snk | Bin 0 -> 596 bytes build/common.props | 25 ++++ global.json | 10 -- .../Microsoft.AspNetCore.JsonPatch.csproj | 22 +++ .../Microsoft.AspNetCore.JsonPatch.xproj | 17 --- .../Properties/AssemblyInfo.cs | 11 -- .../project.json | 40 ------ ...Microsoft.AspNetCore.JsonPatch.Test.csproj | 25 ++++ .../Microsoft.AspNetCore.JsonPatch.Test.xproj | 20 --- .../ObjectVisitorTest.cs~RF1ad82e13.TMP | 119 ---------------- .../ObjectVisitorTest.cs~RF1ae034c3.TMP | 131 ------------------ .../project.json | 31 ----- version.props | 7 + 18 files changed, 101 insertions(+), 386 deletions(-) create mode 100644 build/Key.snk create mode 100644 build/common.props delete mode 100644 global.json create mode 100644 src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj delete mode 100644 src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.xproj delete mode 100644 src/Microsoft.AspNetCore.JsonPatch/Properties/AssemblyInfo.cs delete mode 100644 src/Microsoft.AspNetCore.JsonPatch/project.json create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.xproj delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs~RF1ad82e13.TMP delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs~RF1ae034c3.TMP delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/project.json create mode 100644 version.props diff --git a/JsonPatch.sln b/JsonPatch.sln index 7149fc4551..ae03b680d3 100644 --- a/JsonPatch.sln +++ b/JsonPatch.sln @@ -1,15 +1,27 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26123.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{430B59ED-F960-4D3A-8FFE-3370008E168D}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{36CD6341-AB44-44EB-B3AA-BF98C89FECDD}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.JsonPatch", "src\Microsoft.AspNetCore.JsonPatch\Microsoft.AspNetCore.JsonPatch.xproj", "{4D55F4D8-633B-462F-A5B1-FEB84BD2D534}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.JsonPatch", "src\Microsoft.AspNetCore.JsonPatch\Microsoft.AspNetCore.JsonPatch.csproj", "{4D55F4D8-633B-462F-A5B1-FEB84BD2D534}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.JsonPatch.Test", "test\Microsoft.AspNetCore.JsonPatch.Test\Microsoft.AspNetCore.JsonPatch.Test.xproj", "{81C20848-E063-4E12-AC40-0B55A532C16C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.JsonPatch.Test", "test\Microsoft.AspNetCore.JsonPatch.Test\Microsoft.AspNetCore.JsonPatch.Test.csproj", "{81C20848-E063-4E12-AC40-0B55A532C16C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C430C499-382D-47BD-B351-CF8F89C08CD2}" + ProjectSection(SolutionItems) = preProject + NuGet.config = NuGet.config + EndProjectSection +EndProject + +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{6DC6B416-C8C4-4BFA-8C1E-A55A6D7EFD08}" + ProjectSection(SolutionItems) = preProject + build\common.props = build\common.props + build\Key.snk = build\Key.snk + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/NuGet.config b/NuGet.config index 0fd623ffdd..93f1ac47df 100644 --- a/NuGet.config +++ b/NuGet.config @@ -2,6 +2,7 @@ + diff --git a/appveyor.yml b/appveyor.yml index be95b88d6f..06545db9f6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -10,4 +10,6 @@ build_script: - build.cmd --quiet verify clone_depth: 1 test: off -deploy: off \ No newline at end of file +deploy: off +# Required for dotnet-test to work +os: Visual Studio 2015 \ No newline at end of file diff --git a/build.ps1 b/build.ps1 index 8f2f99691a..0605b59c01 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index 4fd7ede788..07997d6c83 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi diff --git a/build/Key.snk b/build/Key.snk new file mode 100644 index 0000000000000000000000000000000000000000..e10e4889c125d3120cd9e81582243d70f7cbb806 GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098=Iw=HCsnz~#iVhm& zj%TU(_THUee?3yHBjk$37ysB?i5#7WD$={H zV4B!OxRPrb|8)HPg~A}8P>^=#y<)56#=E&NzcjOtPK~<4n6GHt=K$ro*T(lhby_@U zEk(hLzk1H)0yXj{A_5>fk-TgNoP|q6(tP2xo8zt8i%212CWM#AeCd?`hS|4~L({h~Moo(~vy&3Z z1uI}`fd^*>o=rwbAGymj6RM^pZm(*Kfhs+Y1#`-2JPWZMK8@;ZWCk2+9bX4YP);~fj-BU*R zQPvWv$89!{Rl9wM+zR>_TSkn^voYxA?2G iKnV#iZ6Ah`K>b=@=IjYJXrxL124zR(38)nxe+&q_$QXwJ literal 0 HcmV?d00001 diff --git a/build/common.props b/build/common.props new file mode 100644 index 0000000000..813c202b7f --- /dev/null +++ b/build/common.props @@ -0,0 +1,25 @@ + + + + + + Microsoft ASP.NET Core + https://github.com/aspnet/JsonPatch + git + $(MSBuildThisFileDirectory)Key.snk + true + true + 1.2.0-* + 1.6.2-* + $(VersionSuffix)-$(BuildNumber) + + + + + + + + + + + \ No newline at end of file diff --git a/global.json b/global.json deleted file mode 100644 index a5c02fe221..0000000000 --- a/global.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "projects": [ - "src", - "test/WebSites", - "samples" - ], - "sdk": { - "version": "1.0.0-preview2-1-003180" - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj new file mode 100644 index 0000000000..5bf2f0f74e --- /dev/null +++ b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj @@ -0,0 +1,22 @@ + + + + + ASP.NET Core support for JSON PATCH. + net451;netstandard1.3 + $(NoWarn);CS1591 + true + aspnetcore;json;jsonpatch + + + + + + + + + + + + + diff --git a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.xproj b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.xproj deleted file mode 100644 index 0ebf789691..0000000000 --- a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.xproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 4d55f4d8-633b-462f-a5b1-feb84bd2d534 - .\obj - .\bin\ - - - 2.0 - - - \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.JsonPatch/Properties/AssemblyInfo.cs b/src/Microsoft.AspNetCore.JsonPatch/Properties/AssemblyInfo.cs deleted file mode 100644 index 76feceeff0..0000000000 --- a/src/Microsoft.AspNetCore.JsonPatch/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Reflection; -using System.Resources; - -[assembly: AssemblyMetadata("Serviceable", "True")] -[assembly: NeutralResourcesLanguage("en-us")] -[assembly: AssemblyCompany("Microsoft Corporation.")] -[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] -[assembly: AssemblyProduct("Microsoft ASP.NET Core")] diff --git a/src/Microsoft.AspNetCore.JsonPatch/project.json b/src/Microsoft.AspNetCore.JsonPatch/project.json deleted file mode 100644 index 7214cde411..0000000000 --- a/src/Microsoft.AspNetCore.JsonPatch/project.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "version": "1.2.0-*", - "description": "ASP.NET Core support for JSON PATCH.", - "buildOptions": { - "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk", - "nowarn": [ - "CS1591" - ], - "xmlDoc": true - }, - "packOptions": { - "repository": { - "type": "git", - "url": "git://github.com/aspnet/jsonpatch" - }, - "tags": [ - "aspnetcore", - "json", - "jsonpatch" - ] - }, - "dependencies": { - "NETStandard.Library": "1.6.2-*", - "Newtonsoft.Json": "9.0.1", - "Microsoft.Extensions.ClosedGenericMatcher.Sources": { - "type": "build", - "version": "1.2.0-*" - } - }, - "frameworks": { - "net451": {}, - "netstandard1.3": { - "dependencies": { - "Microsoft.CSharp": "4.4.0-*", - "System.Reflection.TypeExtensions": "4.4.0-*" - } - } - } -} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj new file mode 100644 index 0000000000..6715989b4e --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj @@ -0,0 +1,25 @@ + + + + netcoreapp1.1;net451 + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.xproj b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.xproj deleted file mode 100644 index c8942c121e..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.xproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 81c20848-e063-4e12-ac40-0b55a532c16c - .\obj - .\bin\ - - - 2.0 - - - - - - \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs~RF1ad82e13.TMP b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs~RF1ad82e13.TMP deleted file mode 100644 index 694c33c633..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs~RF1ad82e13.TMP +++ /dev/null @@ -1,119 +0,0 @@ -using System.Collections.Generic; -using Newtonsoft.Json.Serialization; -using Xunit; - -namespace Microsoft.AspNetCore.JsonPatch.Internal -{ - public class ObjectVisitorTest - { - private class Class1 - { - public IList States { get; set; } = new List(); - public IDictionary Countries = new Dictionary(); - } - - [Fact] - public void Visit_ValidPathToArray_ReturnsListAdapter() - { - // Arrange - var visitor = new ObjectVisitor(new ParsedPath("/States/-"), new DefaultContractResolver()); - var model = new Class1(); - object targetObject = model; - IAdapter adapter = null; - string message = null; - - // Act - var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); - - // Assert - Assert.True(visitStatus); - Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Same(model.States, targetObject); - Assert.IsType(adapter); - } - - [Fact] - public void Visit_ValidPathToDictionary_ReturnsDictionaryAdapter() - { - // Arrange - var visitor = new ObjectVisitor(new ParsedPath("/Countries/USA"), new DefaultContractResolver()); - var model = new Class1(); - object targetObject = model; - IAdapter adapter = null; - string message = null; - - // Act - var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); - - // Assert - Assert.True(visitStatus); - Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Same(model.Countries, targetObject); - Assert.IsType(adapter); - } - - private class AutomobileDepartment - { - public List Customers { get; set; } = new List(); - } - - [Fact] - public void Visit_ValidPathToArray_ReturnsListAdapter_ForDeepNestedPath() - { - // Arrange - var visitor = new ObjectVisitor(new ParsedPath("/Customers/0/States/-"), new DefaultContractResolver()); - var customer = new Class1(); - var automobileDepartment = new AutomobileDepartment(); - automobileDepartment.Customers.Add(customer); - object targetObject = automobileDepartment; - IAdapter adapter = null; - string message = null; - - // Act - var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); - - // Assert - Assert.True(visitStatus); - Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Same(customer.States, targetObject); - Assert.IsType(adapter); - } - - [Fact] - public void Visit_InvalidPathToArray_Fails() - { - // Arrange - var invalidIndex = 2; - var visitor = new ObjectVisitor(new ParsedPath($"/Customers/{invalidIndex}/States/-"), new DefaultContractResolver()); - var automobileDepartment = new AutomobileDepartment(); - object targetObject = automobileDepartment; - IAdapter adapter = null; - string message = null; - - // Act - var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); - - // Assert - Assert.False(visitStatus); - Assert.Equal(string.Format(ErrorMessageFormats.IndexOutOfBounds, invalidIndex), message); - } - - [Fact] - public void Visit_DoesNotValidate_FinalPathSegment() - { - // Arrange - var visitor = new ObjectVisitor(new ParsedPath($"/NonExisting"), new DefaultContractResolver()); - var model = new Class1(); - object targetObject = model; - IAdapter adapter = null; - string message = null; - - // Act - var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); - - // Assert - Assert.False(visitStatus); - Assert.Equal(string.Format(ErrorMessageFormats.TargetLocationAtPathSegmentNotFound, "NonExisting"), message); - } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs~RF1ae034c3.TMP b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs~RF1ae034c3.TMP deleted file mode 100644 index 88139198ac..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs~RF1ae034c3.TMP +++ /dev/null @@ -1,131 +0,0 @@ -using System.Collections.Generic; -using Newtonsoft.Json.Serialization; -using Xunit; - -namespace Microsoft.AspNetCore.JsonPatch.Internal -{ - public class ObjectVisitorTest - { - private class Class1 - { - public IList States { get; set; } = new List(); - public IDictionary Countries = new Dictionary(); - } - - public static IEnumerable ReturnsListAdapterData - { - get - { - var model = new Class1(); - yield return new object[] { model, "/States/-", model.States }; - - yield return new object[] { model.States, "/-", model.States }; - } - } - - [Theory] - [MemberData(nameof(ReturnsListAdapterData))] - public void Visit_ValidPathToArray_ReturnsListAdapter(object targetObject, string path, object expectedTargetObject) - { - // Arrange - var visitor = new ObjectVisitor(new ParsedPath(path), new DefaultContractResolver()); - IAdapter adapter = null; - string message = null; - - // Act - var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); - - // Assert - Assert.True(visitStatus); - Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Same(expectedTargetObject, targetObject); - Assert.IsType(adapter); - } - - [Fact] - public void Visit_ValidPathToDictionary_ReturnsDictionaryAdapter() - { - // Arrange - var visitor = new ObjectVisitor(new ParsedPath("/Countries/USA"), new DefaultContractResolver()); - var model = new Class1(); - object targetObject = model; - IAdapter adapter = null; - string message = null; - - // Act - var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); - - // Assert - Assert.True(visitStatus); - Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Same(model.Countries, targetObject); - Assert.IsType(adapter); - } - - private class AutomobileDepartment - { - public List Customers { get; set; } = new List(); - } - - [Fact] - public void Visit_ValidPathToArray_ReturnsListAdapter_ForDeepNestedPath() - { - // Arrange - var visitor = new ObjectVisitor(new ParsedPath("/Customers/0/States/-"), new DefaultContractResolver()); - var customer = new Class1(); - var automobileDepartment = new AutomobileDepartment(); - automobileDepartment.Customers.Add(customer); - object targetObject = automobileDepartment; - IAdapter adapter = null; - string message = null; - - // Act - var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); - - // Assert - Assert.True(visitStatus); - Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Same(customer.States, targetObject); - Assert.IsType(adapter); - } - - [Fact] - public void Visit_InvalidPathToArray_Fails() - { - // Arrange - var invalidIndex = 2; - var visitor = new ObjectVisitor(new ParsedPath($"/Customers/{invalidIndex}/States/-"), new DefaultContractResolver()); - var automobileDepartment = new AutomobileDepartment(); - object targetObject = automobileDepartment; - IAdapter adapter = null; - string message = null; - - // Act - var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); - - // Assert - Assert.False(visitStatus); - Assert.Equal(string.Format(ErrorMessageFormats.IndexOutOfBounds, invalidIndex), message); - } - - // The adapter takes care of the responsibility of validating the final segment - [Fact] - public void Visit_DoesNotValidate_FinalPathSegment() - { - // Arrange - var visitor = new ObjectVisitor(new ParsedPath($"/NonExisting"), new DefaultContractResolver()); - var model = new Class1(); - object targetObject = model; - IAdapter adapter = null; - string message = null; - - // Act - var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); - - // Assert - Assert.True(visitStatus); - Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.IsType(adapter); - } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json b/test/Microsoft.AspNetCore.JsonPatch.Test/project.json deleted file mode 100644 index 4790217eba..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/project.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "buildOptions": { - "warningsAsErrors": true - }, - "dependencies": { - "dotnet-test-xunit": "2.2.0-*", - "Microsoft.AspNetCore.JsonPatch": "1.2.0-*", - "Microsoft.AspNetCore.Testing": "1.2.0-*", - "Moq": "4.6.36-*", - "xunit": "2.2.0-*" - }, - "testRunner": "xunit", - "frameworks": { - "netcoreapp1.1": { - "dependencies": { - "Microsoft.NETCore.App": { - "version": "1.2.0-*", - "type": "platform" - }, - "System.Diagnostics.TraceSource": "4.4.0-*" - } - }, - "net451": { - "frameworkAssemblies": { - "System.Linq.Expressions": { - "type": "build" - } - } - } - } -} \ No newline at end of file diff --git a/version.props b/version.props new file mode 100644 index 0000000000..e77c8d9c38 --- /dev/null +++ b/version.props @@ -0,0 +1,7 @@ + + + + 1.2.0 + preview1 + + \ No newline at end of file From ca7b6f65e945e396c68dd336bdee2b96c0408751 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 31 Jan 2017 10:57:05 -0800 Subject: [PATCH 0406/1029] Update appveyor image and README badges --- README.md | 4 ++-- appveyor.yml | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f5c04352e2..55e0dae86e 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ DotNetTools =========== [![Travis build status](https://img.shields.io/travis/aspnet/DotNetTools.svg?label=travis-ci&branch=dev&style=flat-square)](https://travis-ci.org/aspnet/DotNetTools/branches) -[![AppVeyor build status](https://img.shields.io/appveyor/ci/aspnetci/dnx-watch/dev.svg?label=appveyor&style=flat-square)](https://ci.appveyor.com/project/aspnetci/dnx-watch/branch/dev) +[![AppVeyor build status](https://img.shields.io/appveyor/ci/aspnetci/DotNetTools/dev.svg?label=appveyor&style=flat-square)](https://ci.appveyor.com/project/aspnetci/DotNetTools/branch/dev) -The project contains command-line tools for the .NET Core SDK. +The project contains command-line tools for the .NET Core CLI. - [dotnet-watch](src/Microsoft.DotNet.Watcher.Tools/) - [dotnet-user-secrets](src/Microsoft.Extensions.SecretManager.Tools/) diff --git a/appveyor.yml b/appveyor.yml index a2d85c2df3..13c0650228 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,11 +6,9 @@ branches: - release - dev - /^(.*\/)?ci-.*$/ - - /^feature\// build_script: - build.cmd --quiet verify clone_depth: 1 test: off deploy: off -# Required for dotnet-test to work -os: Visual Studio 2015 +os: Visual Studio 2017 RC From 81acef9238622249c95229ce2d6205a48b85d514 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 1 Feb 2017 13:24:34 -0800 Subject: [PATCH 0407/1029] Upgrade to VS 2017 --- HtmlAbstractions.sln | 13 ++++---- NuGet.config | 5 +-- appveyor.yml | 3 +- build.ps1 | 2 +- build.sh | 2 +- {tools => build}/Key.snk | Bin build/common.props | 19 +++++++++++ global.json | 8 ----- ...rosoft.AspNetCore.Html.Abstractions.csproj | 21 ++++++++++++ ...crosoft.AspNetCore.Html.Abstractions.xproj | 17 ---------- .../Properties/AssemblyInfo.cs | 5 --- .../project.json | 28 ---------------- .../Microsoft.Extensions.WebEncoders.csproj | 21 ++++++++++++ .../Microsoft.Extensions.WebEncoders.xproj | 17 ---------- .../Properties/AssemblyInfo.cs | 11 ------- .../project.json | 31 ------------------ ...t.AspNetCore.Html.Abstractions.Test.csproj | 18 ++++++++++ ...ft.AspNetCore.Html.Abstractions.Test.xproj | 20 ----------- .../project.json | 25 -------------- ...rosoft.Extensions.WebEncoders.Tests.csproj | 18 ++++++++++ ...crosoft.Extensions.WebEncoders.Tests.xproj | 20 ----------- .../project.json | 28 ---------------- version.props | 7 ++++ 23 files changed, 117 insertions(+), 222 deletions(-) rename {tools => build}/Key.snk (100%) create mode 100644 build/common.props delete mode 100644 global.json create mode 100755 src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj delete mode 100644 src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.xproj delete mode 100644 src/Microsoft.AspNetCore.Html.Abstractions/project.json create mode 100755 src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj delete mode 100644 src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.xproj delete mode 100644 src/Microsoft.Extensions.WebEncoders/Properties/AssemblyInfo.cs delete mode 100644 src/Microsoft.Extensions.WebEncoders/project.json create mode 100755 test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj delete mode 100644 test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.xproj delete mode 100644 test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json create mode 100755 test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj delete mode 100644 test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.xproj delete mode 100644 test/Microsoft.Extensions.WebEncoders.Tests/project.json create mode 100644 version.props diff --git a/HtmlAbstractions.sln b/HtmlAbstractions.sln index 81189bb447..5b6b09416f 100644 --- a/HtmlAbstractions.sln +++ b/HtmlAbstractions.sln @@ -1,24 +1,23 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.24711.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26127.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A5A15F1C-885A-452A-A731-B0173DDBD913}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F31FF137-390C-49BF-A3BD-7C6ED3597C21}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Html.Abstractions", "src\Microsoft.AspNetCore.Html.Abstractions\Microsoft.AspNetCore.Html.Abstractions.xproj", "{68A28E4A-3ADE-4187-9625-4FF185887CB3}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Html.Abstractions", "src\Microsoft.AspNetCore.Html.Abstractions\Microsoft.AspNetCore.Html.Abstractions.csproj", "{68A28E4A-3ADE-4187-9625-4FF185887CB3}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Html.Abstractions.Test", "test\Microsoft.AspNetCore.Html.Abstractions.Test\Microsoft.AspNetCore.Html.Abstractions.Test.xproj", "{2D187B88-94BD-4A39-AC97-F8F8B9363301}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Html.Abstractions.Test", "test\Microsoft.AspNetCore.Html.Abstractions.Test\Microsoft.AspNetCore.Html.Abstractions.Test.csproj", "{2D187B88-94BD-4A39-AC97-F8F8B9363301}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B4962A29-BE69-4A18-9B4F-B803EEE31EAA}" ProjectSection(SolutionItems) = preProject - global.json = global.json NuGetPackageVerifier.json = NuGetPackageVerifier.json EndProjectSection EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.WebEncoders", "src\Microsoft.Extensions.WebEncoders\Microsoft.Extensions.WebEncoders.xproj", "{DD2CE416-765E-4000-A03E-C2FF165DA1B6}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Extensions.WebEncoders", "src\Microsoft.Extensions.WebEncoders\Microsoft.Extensions.WebEncoders.csproj", "{DD2CE416-765E-4000-A03E-C2FF165DA1B6}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.WebEncoders.Tests", "test\Microsoft.Extensions.WebEncoders.Tests\Microsoft.Extensions.WebEncoders.Tests.xproj", "{7AE2731D-43CD-4CF8-850A-4914DE2CE930}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Extensions.WebEncoders.Tests", "test\Microsoft.Extensions.WebEncoders.Tests\Microsoft.Extensions.WebEncoders.Tests.csproj", "{7AE2731D-43CD-4CF8-850A-4914DE2CE930}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/NuGet.config b/NuGet.config index 826a1f9035..8e65695611 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,8 @@ - + + - \ No newline at end of file + diff --git a/appveyor.yml b/appveyor.yml index be95b88d6f..13c0650228 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -10,4 +10,5 @@ build_script: - build.cmd --quiet verify clone_depth: 1 test: off -deploy: off \ No newline at end of file +deploy: off +os: Visual Studio 2017 RC diff --git a/build.ps1 b/build.ps1 index 8f2f99691a..0605b59c01 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index 4fd7ede788..07997d6c83 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi diff --git a/tools/Key.snk b/build/Key.snk similarity index 100% rename from tools/Key.snk rename to build/Key.snk diff --git a/build/common.props b/build/common.props new file mode 100644 index 0000000000..c39a1694c3 --- /dev/null +++ b/build/common.props @@ -0,0 +1,19 @@ + + + + + https://github.com/aspnet/HtmlAbstractions + git + $(MSBuildThisFileDirectory)Key.snk + true + true + 1.2.0-* + 1.6.2-* + $(VersionSuffix)-$(BuildNumber) + + + + + + + diff --git a/global.json b/global.json deleted file mode 100644 index 0ad1995dd2..0000000000 --- a/global.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "projects": [ - "src" - ], - "sdk": { - "version": "1.0.0-preview2-1-003180" - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj b/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj new file mode 100755 index 0000000000..3baa9641ae --- /dev/null +++ b/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj @@ -0,0 +1,21 @@ + + + + + + Microsoft ASP.NET Core + ASP.NET Core HTML abstractions used for building HTML content. +Commonly used types: +Microsoft.AspNetCore.Html.HtmlString +Microsoft.AspNetCore.Html.IHtmlContent + netstandard1.0 + $(NoWarn);CS1591 + true + aspnetcore + + + + + + + diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.xproj b/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.xproj deleted file mode 100644 index 25d87d97bb..0000000000 --- a/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.xproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 68a28e4a-3ade-4187-9625-4ff185887cb3 - .\obj - .\bin\ - - - 2.0 - - - \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/Properties/AssemblyInfo.cs b/src/Microsoft.AspNetCore.Html.Abstractions/Properties/AssemblyInfo.cs index 403f0e3c52..bde0132dbb 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/Properties/AssemblyInfo.cs +++ b/src/Microsoft.AspNetCore.Html.Abstractions/Properties/AssemblyInfo.cs @@ -5,9 +5,4 @@ using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; -[assembly: AssemblyMetadata("Serviceable", "True")] -[assembly: NeutralResourcesLanguage("en-us")] [assembly: InternalsVisibleTo("Microsoft.AspNetCore.Html.Abstractions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] -[assembly: AssemblyCompany("Microsoft Corporation.")] -[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] -[assembly: AssemblyProduct("Microsoft ASP.NET Core")] diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/project.json b/src/Microsoft.AspNetCore.Html.Abstractions/project.json deleted file mode 100644 index 4e640d584b..0000000000 --- a/src/Microsoft.AspNetCore.Html.Abstractions/project.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "version": "1.2.0-*", - "description": "ASP.NET Core HTML abstractions used for building HTML content.\r\nCommonly used types:\r\nMicrosoft.AspNetCore.Html.HtmlString\r\nMicrosoft.AspNetCore.Html.IHtmlContent", - "packOptions": { - "repository": { - "type": "git", - "url": "git://github.com/aspnet/htmlabstractions" - }, - "tags": [ - "aspnetcore" - ] - }, - "buildOptions": { - "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk", - "nowarn": [ - "CS1591" - ], - "xmlDoc": true - }, - "dependencies": { - "NETStandard.Library": "1.6.2-*", - "System.Text.Encodings.Web": "4.4.0-*" - }, - "frameworks": { - "netstandard1.0": {} - } -} \ No newline at end of file diff --git a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj new file mode 100755 index 0000000000..231359c110 --- /dev/null +++ b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj @@ -0,0 +1,21 @@ + + + + + + Microsoft .NET Extensions + Contains registration and configuration APIs to add the core framework encoders to a dependency injection container. + netstandard1.0 + $(NoWarn);CS1591 + true + true + aspnetcore + + + + + + + + + diff --git a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.xproj b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.xproj deleted file mode 100644 index f458d42cf1..0000000000 --- a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.xproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - dd2ce416-765e-4000-a03e-c2ff165da1b6 - .\obj - .\bin\ - - - 2.0 - - - \ No newline at end of file diff --git a/src/Microsoft.Extensions.WebEncoders/Properties/AssemblyInfo.cs b/src/Microsoft.Extensions.WebEncoders/Properties/AssemblyInfo.cs deleted file mode 100644 index 8d8d88195c..0000000000 --- a/src/Microsoft.Extensions.WebEncoders/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Reflection; -using System.Resources; - -[assembly: AssemblyMetadata("Serviceable", "True")] -[assembly: NeutralResourcesLanguage("en-us")] -[assembly: AssemblyCompany("Microsoft Corporation.")] -[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] -[assembly: AssemblyProduct("Microsoft .NET Extensions")] diff --git a/src/Microsoft.Extensions.WebEncoders/project.json b/src/Microsoft.Extensions.WebEncoders/project.json deleted file mode 100644 index b3fe422893..0000000000 --- a/src/Microsoft.Extensions.WebEncoders/project.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "version": "1.2.0-*", - "description": "Contains registration and configuration APIs to add the core framework encoders to a dependency injection container.", - "packOptions": { - "repository": { - "type": "git", - "url": "git://github.com/aspnet/httpabstractions" - }, - "tags": [ - "aspnetcore" - ] - }, - "buildOptions": { - "warningsAsErrors": true, - "allowUnsafe": true, - "keyFile": "../../tools/Key.snk", - "nowarn": [ - "CS1591" - ], - "xmlDoc": true - }, - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "1.2.0-*", - "Microsoft.Extensions.Options": "1.2.0-*", - "NETStandard.Library": "1.6.2-*", - "System.Text.Encodings.Web": "4.4.0-*" - }, - "frameworks": { - "netstandard1.0": {} - } -} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj new file mode 100755 index 0000000000..160e0ab478 --- /dev/null +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj @@ -0,0 +1,18 @@ + + + + + + netcoreapp1.1;net451 + + + + + + + + + + + + diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.xproj b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.xproj deleted file mode 100644 index 3d3d10b2ac..0000000000 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.xproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 2d187b88-94bd-4a39-ac97-f8f8b9363301 - .\obj - .\bin\ - - - 2.0 - - - - - - \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json b/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json deleted file mode 100644 index 0e46d9c52c..0000000000 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/project.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "buildOptions": { - "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk" - }, - "dependencies": { - "dotnet-test-xunit": "2.2.0-*", - "Microsoft.AspNetCore.Html.Abstractions": "1.2.0-*", - "Microsoft.AspNetCore.Testing": "1.2.0-*", - "Microsoft.Extensions.WebEncoders": "1.2.0-*", - "xunit": "2.2.0-*" - }, - "testRunner": "xunit", - "frameworks": { - "netcoreapp1.1": { - "dependencies": { - "Microsoft.NETCore.App": { - "version": "1.2.0-*", - "type": "platform" - } - } - }, - "net451": {} - } -} \ No newline at end of file diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj new file mode 100755 index 0000000000..9ad4edbc0b --- /dev/null +++ b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj @@ -0,0 +1,18 @@ + + + + + + netcoreapp1.1;net451 + $(PackageTargetFallback);dnxcore50;portable-net451+win8 + + + + + + + + + + + diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.xproj b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.xproj deleted file mode 100644 index a7810a9e17..0000000000 --- a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.xproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - 14.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - 7ae2731d-43cd-4cf8-850a-4914de2ce930 - .\obj - .\bin\ - - - 2.0 - - - - - - \ No newline at end of file diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/project.json b/test/Microsoft.Extensions.WebEncoders.Tests/project.json deleted file mode 100644 index d06fb5b18b..0000000000 --- a/test/Microsoft.Extensions.WebEncoders.Tests/project.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "dependencies": { - "dotnet-test-xunit": "2.2.0-*", - "Microsoft.Extensions.DependencyInjection": "1.2.0-*", - "Microsoft.Extensions.WebEncoders": "1.2.0-*", - "xunit": "2.2.0-*" - }, - "testRunner": "xunit", - "buildOptions": { - "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk" - }, - "frameworks": { - "netcoreapp1.1": { - "dependencies": { - "Microsoft.NETCore.App": { - "version": "1.2.0-*", - "type": "platform" - } - }, - "imports": [ - "dnxcore50", - "portable-net451+win8" - ] - }, - "net451": {} - } -} \ No newline at end of file diff --git a/version.props b/version.props new file mode 100644 index 0000000000..17fd5ac36d --- /dev/null +++ b/version.props @@ -0,0 +1,7 @@ + + + + 1.2.0 + preview1 + + From 7019c552197a50074c77a6eb91b23cf1f822b9ec Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 3 Feb 2017 10:15:28 -0800 Subject: [PATCH 0408/1029] Fix package path issues --- .editorconfig | 28 ++++++++----------- .../Microsoft.DotNet.Watcher.Tools.csproj | 5 +--- ....Extensions.Caching.SqlConfig.Tools.csproj | 2 -- ...soft.Extensions.SecretManager.Tools.csproj | 2 -- src/workaround.targets | 23 --------------- 5 files changed, 13 insertions(+), 47 deletions(-) delete mode 100644 src/workaround.targets diff --git a/.editorconfig b/.editorconfig index 98fd05f5b3..e2566a262e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,28 +1,24 @@ -; EditorConfig to support per-solution formatting. -; Use the EditorConfig VS add-in to make this work. -; http://editorconfig.org/ +# EditorConfig is awesome:http://EditorConfig.org -; This is the default for the codeline. +# top-most EditorConfig file root = true [*] indent_style = space charset = utf-8 trim_trailing_whitespace = true - -[*.{cs}] -indent_size = 4 insert_final_newline = true -; All XML-based file formats -[*.{config,csproj,nuspec,props,resx,targets,xml}] -indent_size = 2 - -[*.{json}] -indent_size = 2 - -[*.{ps1}] +[*.cs] indent_size = 4 +dotnet_sort_system_directives_first = true:warning -[*.{sh}] +# Xml files +[*.{csproj,config,props,targets,ruleset,config,resx,xml}] +indent_size = 2 + +[*.{json, yml}] +indent_size = 2 + +[*.{ps1,sh}] indent_size = 4 \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj index ee7f2acb06..193cfa8ac3 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj @@ -10,20 +10,17 @@ dotnet;watch DotnetCliTool 1.0.0 - toolassets - + - - \ No newline at end of file diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj index 468900312f..19f3aa9175 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj @@ -20,6 +20,4 @@ - - \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj index 9730829536..dc050cfa32 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj @@ -22,6 +22,4 @@ - - \ No newline at end of file diff --git a/src/workaround.targets b/src/workaround.targets deleted file mode 100644 index 4068dffd93..0000000000 --- a/src/workaround.targets +++ /dev/null @@ -1,23 +0,0 @@ - - - - $(DefaultItemExcludes);lib\**\* - - - - - <_PackageFiles Include="lib\netcoreapp1.0\*.json" BuildAction="None" PackagePath="%(Identity)" /> - - - - - - - \ No newline at end of file From 5a444fa75ccbd3eba1df2df50362bf048d761e64 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 10 Feb 2017 08:26:17 -0800 Subject: [PATCH 0409/1029] Cleanup project files and workaround, run tests on .NET Core 1.1 --- NuGetPackageVerifier.json | 61 ++++++++----------- .../Microsoft.DotNet.Watcher.Tools.csproj | 6 +- .../Properties/AssemblyInfo.cs | 2 - ....Extensions.Caching.SqlConfig.Tools.csproj | 7 ++- ...soft.Extensions.SecretManager.Tools.csproj | 7 ++- ...otNet.Watcher.Tools.FunctionalTests.csproj | 10 ++- .../AppWithDeps/AppWithDeps.csproj | 2 +- .../TestProjects/Dependency/Dependency.csproj | 2 +- .../GlobbingApp/GlobbingApp.csproj | 2 +- .../TestProjects/NoDepsApp/NoDepsApp.csproj | 2 +- ...icrosoft.DotNet.Watcher.Tools.Tests.csproj | 4 +- .../MsBuildFileSetFactoryTest.cs | 45 +++++--------- .../Utilities/TemporaryCSharpProject.cs | 23 ++----- ...xtensions.SecretManager.Tools.Tests.csproj | 6 +- .../Microsoft.Extensions.Tools.Tests.csproj | 6 +- version.props | 2 +- 16 files changed, 76 insertions(+), 111 deletions(-) diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index aa4710b372..92dad6ebe4 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -1,38 +1,29 @@ { - "adx": { - "rules": [ - "AdxVerificationCompositeRule" - ], - "packages": { - "Microsoft.DotNet.Watcher.Tools": { - "exclusions": { - "DOC_MISSING": { - "lib/netcoreapp1.0/dotnet-watch.dll": "xmldocs not required for DotnetCliTool packages" - } - }, - "packageTypes": ["DotnetCliTool"] - }, - "Microsoft.Extensions.Caching.SqlConfig.Tools": { - "exclusions": { - "DOC_MISSING": { - "lib/netcoreapp1.0/dotnet-sql-cache.dll": "xmldocs not required for DotnetCliTool packages" - } - }, - "packageTypes": ["DotnetCliTool"] - }, - "Microsoft.Extensions.SecretManager.Tools": { - "exclusions": { - "DOC_MISSING": { - "lib/netcoreapp1.0/dotnet-user-secrets.dll": "xmldocs not required for DotnetCliTool packages" - } - }, - "packageTypes": ["DotnetCliTool"] - } - } - }, - "Default": { - "rules": [ - "DefaultCompositeRule" + "adx": { + "rules": [ + "AdxVerificationCompositeRule" + ], + "packages": { + "Microsoft.DotNet.Watcher.Tools": { + "packageTypes": [ + "DotnetCliTool" ] + }, + "Microsoft.Extensions.Caching.SqlConfig.Tools": { + "packageTypes": [ + "DotnetCliTool" + ] + }, + "Microsoft.Extensions.SecretManager.Tools": { + "packageTypes": [ + "DotnetCliTool" + ] + } } -} \ No newline at end of file + }, + "Default": { + "rules": [ + "DefaultCompositeRule" + ] + } +} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj index 193cfa8ac3..547e8fcf6d 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj @@ -1,4 +1,5 @@ - + + @@ -9,7 +10,6 @@ Microsoft.DotNet.Watcher.Tools dotnet;watch DotnetCliTool - 1.0.0 @@ -23,4 +23,4 @@ - \ No newline at end of file + diff --git a/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs b/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs index e6d00aa36d..70797aee7c 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs @@ -4,5 +4,3 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Microsoft.DotNet.Watcher.Tools.Tests, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] -// TODO remove when .Source packages work -[assembly: InternalsVisibleTo("Microsoft.DotNet.Watcher.Tools.FunctionalTests, PublicKey = 0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj index 19f3aa9175..d3a16d3946 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj @@ -1,5 +1,7 @@ - + + + netcoreapp1.0 dotnet-sql-cache @@ -8,7 +10,6 @@ Microsoft.Extensions.Caching.SqlConfig.Tools cache;distributedcache;sqlserver DotnetCliTool - 1.0.0 @@ -20,4 +21,4 @@ - \ No newline at end of file + diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj index dc050cfa32..3683e22c37 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj @@ -1,5 +1,7 @@ - + + + netcoreapp1.0 dotnet-user-secrets @@ -9,7 +11,6 @@ configuration;secrets;usersecrets DotnetCliTool false - 1.0.0 @@ -22,4 +23,4 @@ - \ No newline at end of file + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj index 1ef391c545..19088145f1 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj @@ -1,9 +1,9 @@ - + - netcoreapp1.0;netcoreapp1.1 + netcoreapp1.1 $(DefaultItemExcludes);TestProjects\**\* @@ -18,6 +18,10 @@ + + + + @@ -27,4 +31,4 @@ - \ No newline at end of file + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj index 93142c90b5..8afd97e37b 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj @@ -1,4 +1,4 @@ - + netcoreapp1.0 diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj index cbdcf50173..22361d48cb 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj @@ -1,4 +1,4 @@ - + netstandard1.5 diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj index e714c10c3b..fa5c47e125 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj @@ -1,4 +1,4 @@ - + netcoreapp1.0 diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj index b10a1c94fc..80621241e8 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj @@ -1,4 +1,4 @@ - + netcoreapp1.0 diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj index 424f9ab2cd..285d18f0cf 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj @@ -1,9 +1,9 @@ - + - netcoreapp1.0 + netcoreapp1.1 diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs index 9b46f04c1d..41602fc0d8 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -28,11 +28,9 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests [Fact] public async Task FindsCustomWatchItems() { - TemporaryCSharpProject target; _tempDir - .WithCSharpProject("Project1", out target) + .WithCSharpProject("Project1", out var target) .WithTargetFrameworks("netcoreapp1.0") - .WithDefaultGlobs() .WithItem(new ItemSpec { Name = "Watch", Include = "*.js", Exclude = "gulpfile.js" }) .Dir() .WithFile("Program.cs") @@ -56,12 +54,10 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests [Fact] public async Task ExcludesDefaultItemsWithWatchFalseMetadata() { - TemporaryCSharpProject target; _tempDir - .WithCSharpProject("Project1", out target) + .WithCSharpProject("Project1", out var target) .WithTargetFrameworks("net40") - .WithItem(new ItemSpec { Name = "Compile", Include = "*.cs" }) - .WithItem(new ItemSpec { Name = "EmbeddedResource", Include = "*.resx", Watch = false }) + .WithItem(new ItemSpec { Name = "EmbeddedResource", Update = "*.resx", Watch = false }) .Dir() .WithFile("Program.cs") .WithFile("Strings.resx"); @@ -82,14 +78,11 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests [Fact] public async Task SingleTfm() { - TemporaryCSharpProject target; - _tempDir .SubDir("src") .SubDir("Project1") - .WithCSharpProject("Project1", out target) + .WithCSharpProject("Project1", out var target) .WithTargetFrameworks("netcoreapp1.0") - .WithDefaultGlobs() .Dir() .WithFile("Program.cs") .WithFile("Class1.cs") @@ -117,12 +110,12 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests [Fact] public async Task MultiTfm() { - TemporaryCSharpProject target; - _tempDir + _tempDir .SubDir("src") .SubDir("Project1") - .WithCSharpProject("Project1", out target) + .WithCSharpProject("Project1", out var target) .WithTargetFrameworks("netcoreapp1.0", "net451") + .WithProperty("EnableDefaultCompileItems", "false") .WithItem("Compile", "Class1.netcore.cs", "'$(TargetFramework)'=='netcoreapp1.0'") .WithItem("Compile", "Class1.desktop.cs", "'$(TargetFramework)'=='net451'") .Dir() @@ -147,22 +140,18 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests [Fact] public async Task ProjectReferences_OneLevel() { - TemporaryCSharpProject target; - TemporaryCSharpProject proj2; _tempDir .SubDir("src") .SubDir("Project2") - .WithCSharpProject("Project2", out proj2) + .WithCSharpProject("Project2", out var proj2) .WithTargetFrameworks("netstandard1.1") - .WithDefaultGlobs() .Dir() .WithFile("Class2.cs") .Up() .SubDir("Project1") - .WithCSharpProject("Project1", out target) + .WithCSharpProject("Project1", out var target) .WithTargetFrameworks("netcoreapp1.0", "net451") .WithProjectReference(proj2) - .WithDefaultGlobs() .Dir() .WithFile("Class1.cs"); @@ -184,31 +173,25 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests [Fact] public async Task TransitiveProjectReferences_TwoLevels() { - TemporaryCSharpProject target; - TemporaryCSharpProject proj2; - TemporaryCSharpProject proj3; _tempDir .SubDir("src") .SubDir("Project3") - .WithCSharpProject("Project3", out proj3) + .WithCSharpProject("Project3", out var proj3) .WithTargetFrameworks("netstandard1.0") - .WithDefaultGlobs() .Dir() .WithFile("Class3.cs") .Up() .SubDir("Project2") - .WithCSharpProject("Project2", out proj2) + .WithCSharpProject("Project2", out TemporaryCSharpProject proj2) .WithTargetFrameworks("netstandard1.1") .WithProjectReference(proj3) - .WithDefaultGlobs() .Dir() .WithFile("Class2.cs") .Up() .SubDir("Project1") - .WithCSharpProject("Project1", out target) + .WithCSharpProject("Project1", out TemporaryCSharpProject target) .WithTargetFrameworks("netcoreapp1.0", "net451") .WithProjectReference(proj2) - .WithDefaultGlobs() .Dir() .WithFile("Class1.cs"); @@ -233,7 +216,7 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests public async Task ProjectReferences_Graph() { var graph = new TestProjectGraph(_tempDir); - graph.OnCreate(p => p.WithTargetFrameworks("net45").WithDefaultGlobs()); + graph.OnCreate(p => p.WithTargetFrameworks("net45")); var matches = Regex.Matches(@" A->B B->C C->D D->E B->E diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryCSharpProject.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryCSharpProject.cs index 53ee3d38e4..7156cf85cf 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryCSharpProject.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryCSharpProject.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -11,8 +11,7 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests public class TemporaryCSharpProject { private const string Template = - @" - + @" {0} Exe @@ -20,13 +19,8 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests {1} - "; - private const string DefaultGlobs = -@" -"; - private readonly string _filename; private readonly TemporaryDirectory _directory; private List _items = new List(); @@ -37,9 +31,6 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests Name = name; _filename = name + ".csproj"; _directory = directory; - - // workaround CLI issue - WithProperty("SkipInvalidConfigurations", "true"); } public string Name { get; } @@ -81,6 +72,7 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests sb.Append(item.Name).Append(" "); if (item.Include != null) sb.Append(" Include=\"").Append(item.Include).Append('"'); if (item.Remove != null) sb.Append(" Remove=\"").Append(item.Remove).Append('"'); + if (item.Update != null) sb.Append(" Update=\"").Append(item.Update).Append('"'); if (item.Exclude != null) sb.Append(" Exclude=\"").Append(item.Exclude).Append('"'); if (item.Condition != null) sb.Append(" Exclude=\"").Append(item.Condition).Append('"'); if (!item.Watch) sb.Append(" Watch=\"false\" "); @@ -99,12 +91,6 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests return WithItem(new ItemSpec { Name = "ProjectReference", Include = reference.Path, Watch = watch }); } - public TemporaryCSharpProject WithDefaultGlobs() - { - _items.Add(DefaultGlobs); - return this; - } - public TemporaryDirectory Dir() => _directory; public void Create() @@ -117,6 +103,7 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests public string Name { get; set; } public string Include { get; set; } public string Exclude { get; set; } + public string Update { get; set; } public string Remove { get; set; } public bool Watch { get; set; } = true; public string Condition { get; set; } @@ -128,4 +115,4 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests public string Value { get; set; } } } -} \ No newline at end of file +} diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj index 59300c6a2f..9a9dc14b24 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj @@ -1,9 +1,9 @@ - + - netcoreapp1.0 + netcoreapp1.1 @@ -17,4 +17,4 @@ - \ No newline at end of file + diff --git a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj index 0e2d61d78e..0c151d0a68 100644 --- a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj @@ -1,9 +1,9 @@ - + - netcoreapp1.0 + netcoreapp1.1 @@ -16,4 +16,4 @@ - \ No newline at end of file + diff --git a/version.props b/version.props index bd4d4dc76f..e143c25f8e 100644 --- a/version.props +++ b/version.props @@ -4,4 +4,4 @@ 1.0.1 alpha - \ No newline at end of file + From 3611adb894bed409707c7fa049acefcfe894764b Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 10 Feb 2017 19:35:36 -0800 Subject: [PATCH 0410/1029] Fix mispaired solution configurations --- DotNetTools.sln | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/DotNetTools.sln b/DotNetTools.sln index 4f9600fad4..8b681184c6 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26118.1 +VisualStudioVersion = 15.0.26210.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66517987-2A5A-4330-B130-207039378FD4}" EndProject @@ -34,32 +34,32 @@ Global GlobalSection(ProjectConfigurationPlatforms) = postSolution {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Release|Any CPU.ActiveCfg = Debug|Any CPU - {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Release|Any CPU.Build.0 = Debug|Any CPU + {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Release|Any CPU.Build.0 = Release|Any CPU {16BADE2F-1184-4518-8A70-B68A19D0805B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {16BADE2F-1184-4518-8A70-B68A19D0805B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.ActiveCfg = Debug|Any CPU - {16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.Build.0 = Debug|Any CPU + {16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.Build.0 = Release|Any CPU {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.ActiveCfg = Debug|Any CPU - {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.Build.0 = Debug|Any CPU + {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.Build.0 = Release|Any CPU {7B331122-83B1-4F08-A119-DC846959844C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7B331122-83B1-4F08-A119-DC846959844C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.ActiveCfg = Debug|Any CPU - {7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.Build.0 = Debug|Any CPU + {7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.Build.0 = Release|Any CPU {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Release|Any CPU.ActiveCfg = Debug|Any CPU - {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Release|Any CPU.Build.0 = Debug|Any CPU + {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Release|Any CPU.Build.0 = Release|Any CPU {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.ActiveCfg = Debug|Any CPU - {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.Build.0 = Debug|Any CPU + {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.Build.0 = Release|Any CPU {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Release|Any CPU.ActiveCfg = Debug|Any CPU - {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Release|Any CPU.Build.0 = Debug|Any CPU + {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 50abb557fc31b6803897cc4b9a8ce03e2e6efbec Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Mon, 13 Feb 2017 11:13:17 -0800 Subject: [PATCH 0411/1029] Bump test projects up to .NET 4.5.2 - aspnet/Testing#248 - xUnit no longer supports .NET 4.5.1 - build tests for desktop .NET only on Windows --- .../Microsoft.AspNetCore.JsonPatch.Test.csproj | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj index 6715989b4e..0825a33ba9 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj @@ -1,7 +1,8 @@  - netcoreapp1.1;net451 + netcoreapp1.1;net452 + netcoreapp1.1 @@ -14,7 +15,7 @@ - + From 859aad081e3ce334b7b604bf2175beb1b6a91496 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Tue, 14 Feb 2017 08:31:52 -0800 Subject: [PATCH 0412/1029] Bump test projects up to .NET 4.5.2 - aspnet/Testing#248 - xUnit no longer supports .NET 4.5.1 - build tests for desktop .NET only on Windows --- .../Microsoft.AspNetCore.Html.Abstractions.Test.csproj | 3 ++- .../Microsoft.Extensions.WebEncoders.Tests.csproj | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj index 160e0ab478..1fe9581c45 100755 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj @@ -3,7 +3,8 @@ - netcoreapp1.1;net451 + netcoreapp1.1;net452 + netcoreapp1.1 diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj index 9ad4edbc0b..77b807e9dd 100755 --- a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj +++ b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj @@ -3,7 +3,8 @@ - netcoreapp1.1;net451 + netcoreapp1.1;net452 + netcoreapp1.1 $(PackageTargetFallback);dnxcore50;portable-net451+win8 From 60a06b2e07287753384a86bbf07eb7229d07aca0 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 14 Feb 2017 12:11:39 -0800 Subject: [PATCH 0413/1029] Update README.md [ci skip] --- src/Microsoft.DotNet.Watcher.Tools/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/README.md b/src/Microsoft.DotNet.Watcher.Tools/README.md index a9a36c49eb..894ef42864 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/README.md +++ b/src/Microsoft.DotNet.Watcher.Tools/README.md @@ -8,7 +8,7 @@ Install `Microsoft.DotNet.Watcher.Tools` as a `DotNetCliToolReference` to your p ```xml - + ``` @@ -95,4 +95,4 @@ Example: -``` \ No newline at end of file +``` From 0c714cf61b908e5e39c8d06a0109aa2305b7e9b0 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 14 Feb 2017 16:03:53 -0800 Subject: [PATCH 0414/1029] Downgrade to stable packages --- build/common.props | 3 +-- build/dependencies.props | 6 ++++++ .../Microsoft.AspNetCore.Html.Abstractions.csproj | 2 +- .../Microsoft.Extensions.WebEncoders.csproj | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 build/dependencies.props diff --git a/build/common.props b/build/common.props index c39a1694c3..de08271afe 100644 --- a/build/common.props +++ b/build/common.props @@ -1,4 +1,5 @@ + @@ -7,8 +8,6 @@ $(MSBuildThisFileDirectory)Key.snk true true - 1.2.0-* - 1.6.2-* $(VersionSuffix)-$(BuildNumber) diff --git a/build/dependencies.props b/build/dependencies.props new file mode 100644 index 0000000000..e704edaec0 --- /dev/null +++ b/build/dependencies.props @@ -0,0 +1,6 @@ + + + 1.6.1 + 4.3.0 + + diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj b/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj index 3baa9641ae..85948d6df7 100755 --- a/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj +++ b/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj @@ -15,7 +15,7 @@ Microsoft.AspNetCore.Html.IHtmlContent - + diff --git a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj index 231359c110..70766d649f 100755 --- a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj +++ b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj @@ -15,7 +15,7 @@ - + From 8051f3671b273fd1b8118563b2022e2e2078f4f0 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 14 Feb 2017 16:03:53 -0800 Subject: [PATCH 0415/1029] Downgrade to stable packages --- build/common.props | 7 +++---- build/dependencies.props | 6 ++++++ .../Microsoft.AspNetCore.JsonPatch.csproj | 6 +++--- .../Microsoft.AspNetCore.JsonPatch.Test.csproj | 6 +----- 4 files changed, 13 insertions(+), 12 deletions(-) create mode 100644 build/dependencies.props diff --git a/build/common.props b/build/common.props index 813c202b7f..17a0ccb4d8 100644 --- a/build/common.props +++ b/build/common.props @@ -1,5 +1,6 @@ - + + @@ -9,8 +10,6 @@ $(MSBuildThisFileDirectory)Key.snk true true - 1.2.0-* - 1.6.2-* $(VersionSuffix)-$(BuildNumber) @@ -22,4 +21,4 @@ - \ No newline at end of file + diff --git a/build/dependencies.props b/build/dependencies.props new file mode 100644 index 0000000000..e704edaec0 --- /dev/null +++ b/build/dependencies.props @@ -0,0 +1,6 @@ + + + 1.6.1 + 4.3.0 + + diff --git a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj index 5bf2f0f74e..d3d5b01a89 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj +++ b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj @@ -13,10 +13,10 @@ - + - - + + diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj index 0825a33ba9..e939e5d62c 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj @@ -12,15 +12,11 @@ - - - - - \ No newline at end of file + From 8764af8a3633d8910eaad02b0c3a5005367f3708 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 14 Feb 2017 16:03:54 -0800 Subject: [PATCH 0416/1029] Downgrade to stable packages --- build/common.props | 3 ++- build/dependencies.props | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 build/dependencies.props diff --git a/build/common.props b/build/common.props index 61157a7f65..506f240784 100644 --- a/build/common.props +++ b/build/common.props @@ -1,4 +1,5 @@ + @@ -15,4 +16,4 @@ - \ No newline at end of file + diff --git a/build/dependencies.props b/build/dependencies.props new file mode 100644 index 0000000000..e704edaec0 --- /dev/null +++ b/build/dependencies.props @@ -0,0 +1,6 @@ + + + 1.6.1 + 4.3.0 + + From ec7df544ede96a553ec0a6c8e8634ce387b44339 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 16 Feb 2017 13:46:11 -0800 Subject: [PATCH 0417/1029] Use latest LTS packages --- NuGet.config | 1 + appveyor.yml | 1 - .../Microsoft.Extensions.SecretManager.Tools.csproj | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NuGet.config b/NuGet.config index d5447f08c2..f941fe96c6 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,6 +1,7 @@  + diff --git a/appveyor.yml b/appveyor.yml index a2d85c2df3..2cdf2ca986 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,7 +6,6 @@ branches: - release - dev - /^(.*\/)?ci-.*$/ - - /^feature\// build_script: - build.cmd --quiet verify clone_depth: 1 diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj index 980cfe6174..77331a914d 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj @@ -22,6 +22,6 @@ - + \ No newline at end of file From b312a84ff488d7acd06d8e9510961bce86ffbfee Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Fri, 24 Feb 2017 15:55:59 -0800 Subject: [PATCH 0418/1029] Fixed solution file --- JsonPatch.sln | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/JsonPatch.sln b/JsonPatch.sln index ae03b680d3..b75721a487 100644 --- a/JsonPatch.sln +++ b/JsonPatch.sln @@ -1,7 +1,6 @@ - Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26123.0 +VisualStudioVersion = 15.0.26222.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{430B59ED-F960-4D3A-8FFE-3370008E168D}" EndProject @@ -12,16 +11,9 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.JsonPatch.Test", "test\Microsoft.AspNetCore.JsonPatch.Test\Microsoft.AspNetCore.JsonPatch.Test.csproj", "{81C20848-E063-4E12-AC40-0B55A532C16C}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C430C499-382D-47BD-B351-CF8F89C08CD2}" - ProjectSection(SolutionItems) = preProject - NuGet.config = NuGet.config - EndProjectSection -EndProject - -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{6DC6B416-C8C4-4BFA-8C1E-A55A6D7EFD08}" ProjectSection(SolutionItems) = preProject - build\common.props = build\common.props - build\Key.snk = build\Key.snk - EndProjectSection + NuGet.config = NuGet.config + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution From e2e0c8dadf93704621ccdafb1c50d7053d25b0f0 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 27 Feb 2017 11:00:04 -0800 Subject: [PATCH 0419/1029] Add install instructions to README.md [ci skip] --- README.md | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 55e0dae86e..1a54694858 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,39 @@ DotNetTools [![Travis build status](https://img.shields.io/travis/aspnet/DotNetTools.svg?label=travis-ci&branch=dev&style=flat-square)](https://travis-ci.org/aspnet/DotNetTools/branches) [![AppVeyor build status](https://img.shields.io/appveyor/ci/aspnetci/DotNetTools/dev.svg?label=appveyor&style=flat-square)](https://ci.appveyor.com/project/aspnetci/DotNetTools/branch/dev) -The project contains command-line tools for the .NET Core CLI. +This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at . - - [dotnet-watch](src/Microsoft.DotNet.Watcher.Tools/) - - [dotnet-user-secrets](src/Microsoft.Extensions.SecretManager.Tools/) - - [dotnet-sql-cache](src/Microsoft.Extensions.Caching.SqlConfig.Tools/) +## Projects -This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo. +The repository contains command-line tools for the .NET Core CLI. Follow the links below for more details on each tool. + + - [dotnet-watch](src/Microsoft.DotNet.Watcher.Tools/) (Microsoft.DotNet.Watcher.Tools) + - [dotnet-user-secrets](src/Microsoft.Extensions.SecretManager.Tools/) (Microsoft.Extensions.SecretManager.Tools) + - [dotnet-sql-cache](src/Microsoft.Extensions.Caching.SqlConfig.Tools/) (Microsoft.Extensions.Caching.SqlConfig.Tools) + +## How to Install + +Install tools by editing your \*.csproj file and adding a `DotNetCliToolReference` with the package name and version. + +```xml + + + + + +``` + +Then, from command line, change directories to your project and run the following commands: + +```sh +# Location of MyProject.csproj which includes DotNetCliToolReference's +cd C:\Source\MyProject\ + +# Download tools into the project +dotnet restore + +# Execute tools +dotnet watch +dotnet user-secrets +dotnet sql-cache +``` From 1f74ceca1b670c249f8118415e16afc4ba3f6ef7 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 1 Mar 2017 18:14:13 -0800 Subject: [PATCH 0420/1029] Change korebuild branch and fix argument forwarding in bootstrapper --- build.ps1 | 16 ++++++++-------- build.sh | 22 +++++++++++----------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/build.ps1 b/build.ps1 index 0605b59c01..5bf0e2c113 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,6 +1,6 @@ $ErrorActionPreference = "Stop" -function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $retries) +function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $retries) { while($true) { @@ -19,7 +19,7 @@ function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $ret Start-Sleep -Seconds 10 } - else + else { $exception = $_.Exception throw $exception @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP @@ -43,18 +43,18 @@ $buildFolder = ".build" $buildFile="$buildFolder\KoreBuild.ps1" if (!(Test-Path $buildFolder)) { - Write-Host "Downloading KoreBuild from $koreBuildZip" - + Write-Host "Downloading KoreBuild from $koreBuildZip" + $tempFolder=$env:TEMP + "\KoreBuild-" + [guid]::NewGuid() New-Item -Path "$tempFolder" -Type directory | Out-Null $localZipFile="$tempFolder\korebuild.zip" - + DownloadWithRetry -url $koreBuildZip -downloadLocation $localZipFile -retries 6 Add-Type -AssemblyName System.IO.Compression.FileSystem [System.IO.Compression.ZipFile]::ExtractToDirectory($localZipFile, $tempFolder) - + New-Item -Path "$buildFolder" -Type directory | Out-Null copy-item "$tempFolder\**\build\*" $buildFolder -Recurse @@ -64,4 +64,4 @@ if (!(Test-Path $buildFolder)) { } } -&"$buildFile" $args \ No newline at end of file +&"$buildFile" @args diff --git a/build.sh b/build.sh index 07997d6c83..b0bcadb579 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi @@ -12,12 +12,12 @@ buildFile="$buildFolder/KoreBuild.sh" if test ! -d $buildFolder; then echo "Downloading KoreBuild from $koreBuildZip" - - tempFolder="/tmp/KoreBuild-$(uuidgen)" + + tempFolder="/tmp/KoreBuild-$(uuidgen)" mkdir $tempFolder - + localZipFile="$tempFolder/korebuild.zip" - + retries=6 until (wget -O $localZipFile $koreBuildZip 2>/dev/null || curl -o $localZipFile --location $koreBuildZip 2>/dev/null) do @@ -29,18 +29,18 @@ if test ! -d $buildFolder; then echo "Waiting 10 seconds before retrying. Retries left: $retries" sleep 10s done - + unzip -q -d $tempFolder $localZipFile - + mkdir $buildFolder cp -r $tempFolder/**/build/** $buildFolder - + chmod +x $buildFile - + # Cleanup if test -d $tempFolder; then - rm -rf $tempFolder + rm -rf $tempFolder fi fi -$buildFile -r $repoFolder "$@" \ No newline at end of file +$buildFile -r $repoFolder "$@" From 4f83e641a733d372e57898921a31c9a6f3b5b71c Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 1 Mar 2017 18:14:13 -0800 Subject: [PATCH 0421/1029] Change korebuild branch and fix argument forwarding in bootstrapper --- build.ps1 | 4 ++-- build.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.ps1 b/build.ps1 index f780c43a82..5bf0e2c113 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP @@ -64,4 +64,4 @@ if (!(Test-Path $buildFolder)) { } } -&"$buildFile" $args \ No newline at end of file +&"$buildFile" @args diff --git a/build.sh b/build.sh index ff79789196..b0bcadb579 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi @@ -43,4 +43,4 @@ if test ! -d $buildFolder; then fi fi -$buildFile -r $repoFolder "$@" \ No newline at end of file +$buildFile -r $repoFolder "$@" From fbb2360f872437247a55cb47bfdc4c2bcc7c75d4 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 1 Mar 2017 18:14:13 -0800 Subject: [PATCH 0422/1029] Change korebuild branch and fix argument forwarding in bootstrapper --- build.ps1 | 16 ++++++++-------- build.sh | 22 +++++++++++----------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/build.ps1 b/build.ps1 index 0605b59c01..5bf0e2c113 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,6 +1,6 @@ $ErrorActionPreference = "Stop" -function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $retries) +function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $retries) { while($true) { @@ -19,7 +19,7 @@ function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $ret Start-Sleep -Seconds 10 } - else + else { $exception = $_.Exception throw $exception @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP @@ -43,18 +43,18 @@ $buildFolder = ".build" $buildFile="$buildFolder\KoreBuild.ps1" if (!(Test-Path $buildFolder)) { - Write-Host "Downloading KoreBuild from $koreBuildZip" - + Write-Host "Downloading KoreBuild from $koreBuildZip" + $tempFolder=$env:TEMP + "\KoreBuild-" + [guid]::NewGuid() New-Item -Path "$tempFolder" -Type directory | Out-Null $localZipFile="$tempFolder\korebuild.zip" - + DownloadWithRetry -url $koreBuildZip -downloadLocation $localZipFile -retries 6 Add-Type -AssemblyName System.IO.Compression.FileSystem [System.IO.Compression.ZipFile]::ExtractToDirectory($localZipFile, $tempFolder) - + New-Item -Path "$buildFolder" -Type directory | Out-Null copy-item "$tempFolder\**\build\*" $buildFolder -Recurse @@ -64,4 +64,4 @@ if (!(Test-Path $buildFolder)) { } } -&"$buildFile" $args \ No newline at end of file +&"$buildFile" @args diff --git a/build.sh b/build.sh index 07997d6c83..b0bcadb579 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/feature/msbuild.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi @@ -12,12 +12,12 @@ buildFile="$buildFolder/KoreBuild.sh" if test ! -d $buildFolder; then echo "Downloading KoreBuild from $koreBuildZip" - - tempFolder="/tmp/KoreBuild-$(uuidgen)" + + tempFolder="/tmp/KoreBuild-$(uuidgen)" mkdir $tempFolder - + localZipFile="$tempFolder/korebuild.zip" - + retries=6 until (wget -O $localZipFile $koreBuildZip 2>/dev/null || curl -o $localZipFile --location $koreBuildZip 2>/dev/null) do @@ -29,18 +29,18 @@ if test ! -d $buildFolder; then echo "Waiting 10 seconds before retrying. Retries left: $retries" sleep 10s done - + unzip -q -d $tempFolder $localZipFile - + mkdir $buildFolder cp -r $tempFolder/**/build/** $buildFolder - + chmod +x $buildFile - + # Cleanup if test -d $tempFolder; then - rm -rf $tempFolder + rm -rf $tempFolder fi fi -$buildFile -r $repoFolder "$@" \ No newline at end of file +$buildFile -r $repoFolder "$@" From dcfbbab005c1fe59e131a0795fff05abf64f76d9 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 1 Mar 2017 18:25:39 -0800 Subject: [PATCH 0423/1029] Update AppVeyor and Travis settings --- .travis.yml | 2 +- appveyor.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index a0be886892..af659e9ae9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,4 +29,4 @@ branches: before_install: - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; fi script: - - ./build.sh --quiet verify + - ./build.sh diff --git a/appveyor.yml b/appveyor.yml index 06545db9f6..944c23c8ba 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,9 +7,9 @@ branches: - dev - /^(.*\/)?ci-.*$/ build_script: - - build.cmd --quiet verify + - ps: .\build.ps1 clone_depth: 1 test: off deploy: off # Required for dotnet-test to work -os: Visual Studio 2015 \ No newline at end of file +os: Visual Studio 2015 From 047e4a8533bbcdf22831c40dd9d9aaf0c80d1953 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 1 Mar 2017 18:25:45 -0800 Subject: [PATCH 0424/1029] Update AppVeyor and Travis settings --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6d31c20ab2..058b4421ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ branches: before_install: - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; fi script: - - ./build.sh --quiet verify + - ./build.sh notifications: webhooks: secure: "dhjfYLtihxx3zDdj0TLMJjiN4YJ37Qu0L9ySx7ek+YsfOAqKPHUsI6JNDtChauQxUB2NoL/i80+47oHhMelPyXniu1xA0MWaHV8bddZHzNQs1N8vGjjPmtbC5DQ7jmy+p7Xa5+ZscZ9NWEvJRqBInNdqugDAstDEIWbC35bq8H9t+6tZYu1sJctp1zF/k/w4OjJUoI1ZNLuusYIB1E+G/irvVT2x4GOC2QY3wXM4lJ2ORcZE9NgUBLNx/Hy5Rst5i4zO/mrFkYM/wOY6bAM6/gjjanK+d1wQnD9HuZH1ZVQqJRH3lveurYq9ih4zxV8MbW3FdLL1cXswEZbUBeqHlxVE32KwWF18nFUwdmrNQebnYnrZ/VWsa4pl+bOFNy2nomI3ibJ4F4+RwqTPXXE13qCr0CsC5RKu5bVQTpi0t4CKlUMsVlevN2jJcmAA641bnETNTDwk5WdT7Mjf9Pnn+krLZ7im9li3Plc/d8ynR1oiRzwFdp3u/9m3Oc8K+zMsNO5IOxHul9WsWbIkh3sNecqKHPSyVHB4FgdUoQ65xpc0887YKorbuBTOnlZugP8M/FmowkcwLo5xDD7kchkxyq9X8dPjej+tzpTsNVJjrOg4LP+nKxmOa+qc1r62eF0GdnIjwU30y6NdfvBCXoQJE1y063/zyGPIxSfCRmVzq4A=" diff --git a/appveyor.yml b/appveyor.yml index 13c0650228..3f828ce38e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,7 +7,7 @@ branches: - dev - /^(.*\/)?ci-.*$/ build_script: - - build.cmd --quiet verify + - ps: .\build.ps1 clone_depth: 1 test: off deploy: off From 35ab125ba64ae21a581f051d986c75c0f2919391 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 1 Mar 2017 18:25:51 -0800 Subject: [PATCH 0425/1029] Update AppVeyor and Travis settings --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 67d9a88786..d9285f178d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ branches: before_install: - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; fi script: - - ./build.sh --quiet verify + - ./build.sh notifications: webhooks: secure: "d87o+y2WUx204s8TfSaEuekYudnSyyPaFEXkuzgs3uAyzkKAm/Hx0xcMSuKDqWhYmKaxL7VtgEd2z7mltr2cHZ4oyCrsf6V5v4iI48ojaGykqFXfv8ld6khmLwtdkC32lF2YyuDNL8kUvKNdP9jkrWlpoO/WC6QEqAUxdOuuLo/wLyfrPLbzIvbojwveXbmcwvsfDizLdZdVd88FZSV41h+yBKLnyhpeqRvHG85BTgT/GmVB7Vyjs3yChiS639Aq5DoOP8jBaRdB8Bqs09KibFXzJwDBlKvALIqiwzog3hpd5SVxrgOTCkWbOwqq4TSkahDE425W3vFbmLDANgdfsyAkqgt8daE2BkFTojEHQED+u9CEd8oJVX6FoGnYpuDzge4FVh9iG3HSuKwoVdlONzzew4oJ75iQ+0f67ZNV9oDuScdva/SGb2gYgVUkeJIjDoMxKuaZyhbBT9jRXRBI+LsIjziEhLU/649FjTSmQx0HLpcT7+kaeSmhqT9JffVLidMdvZwhPZsLxPSG9UVBH9G8rdyHXP2e0ZlicHNjjNV6kbDqfDPhHx2/MfZGugsJXjOONKu/5LZduQzmAOysqdLKqkBVkMq2xl7aGV+yVZAtTmZB3nqOWGyKlFC9kLGO+qlJ4tBac26lHCZWTK+4VOAtN5Dag0DkDikgGdZaq78=" diff --git a/appveyor.yml b/appveyor.yml index 13c0650228..3f828ce38e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,7 +7,7 @@ branches: - dev - /^(.*\/)?ci-.*$/ build_script: - - build.cmd --quiet verify + - ps: .\build.ps1 clone_depth: 1 test: off deploy: off From 42d0d40b36df498f6367326810852ac546c81352 Mon Sep 17 00:00:00 2001 From: Thierry Fleury Date: Tue, 7 Feb 2017 14:20:42 -0800 Subject: [PATCH 0426/1029] [Fixes #61] Move must keep object reference --- .../Adapters/ObjectAdapter.cs | 19 +- .../Internal/ConversionResultProvider.cs | 53 ++++- .../Properties/Resources.Designer.cs | 16 ++ .../Resources.resx | 3 + .../InheritedDTO.cs | 10 + .../ListAdapterTest.cs | 75 +++++++ .../NestedObjectTests.cs | 211 ++++++++++++++++++ .../SimpleDTOWithNestedDTO.cs | 3 + 8 files changed, 385 insertions(+), 5 deletions(-) create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/InheritedDTO.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs index 0ac2ebbe56..b1a487f088 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs @@ -362,10 +362,21 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters // Get value at 'from' location and add that value to the 'path' location if (TryGetValue(operation.from, objectToApplyTo, operation, out propertyValue)) { - Add(operation.path, - propertyValue, - objectToApplyTo, - operation); + // Create deep copy + var copyResult = ConversionResultProvider.CopyTo(propertyValue, propertyValue.GetType()); + if (copyResult.CanBeConverted) + { + Add(operation.path, + copyResult.ConvertedInstance, + objectToApplyTo, + operation); + } + else + { + var error = CreateOperationFailedError(objectToApplyTo, operation.path, operation, Resources.FormatCannotCopyProperty(operation.from)); + ErrorReporter(error); + return; + } } } diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ConversionResultProvider.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ConversionResultProvider.cs index bdf4122394..71af0d27fc 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/ConversionResultProvider.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ConversionResultProvider.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Reflection; using Newtonsoft.Json; namespace Microsoft.AspNetCore.JsonPatch.Internal @@ -10,9 +11,44 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { public static ConversionResult ConvertTo(object value, Type typeToConvertTo) { + if (value == null) + { + return new ConversionResult(IsNullableType(typeToConvertTo), null); + } + else if (typeToConvertTo.IsAssignableFrom(value.GetType())) + { + // No need to convert + return new ConversionResult(true, value); + } + else + { + try + { + var deserialized = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(value), typeToConvertTo); + return new ConversionResult(true, deserialized); + } + catch + { + return new ConversionResult(canBeConverted: false, convertedInstance: null); + } + } + } + + public static ConversionResult CopyTo(object value, Type typeToConvertTo) + { + var targetType = typeToConvertTo; + if (value == null) + { + return new ConversionResult(IsNullableType(typeToConvertTo), null); + } + else if (typeToConvertTo.IsAssignableFrom(value.GetType())) + { + // Keep original type + targetType = value.GetType(); + } try { - var deserialized = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(value), typeToConvertTo); + var deserialized = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(value), targetType); return new ConversionResult(true, deserialized); } catch @@ -20,5 +56,20 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return new ConversionResult(canBeConverted: false, convertedInstance: null); } } + + private static bool IsNullableType(Type type) + { + var typeInfo = type.GetTypeInfo(); + if (typeInfo.IsValueType) + { + // value types are only nullable if they are Nullable + return typeInfo.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>); + } + else + { + // reference types are always nullable + return true; + } + } } } diff --git a/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs index ed567cf003..97c98c2b05 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs @@ -26,6 +26,22 @@ namespace Microsoft.AspNetCore.JsonPatch return string.Format(CultureInfo.CurrentCulture, GetString("CannotDeterminePropertyType"), p0); } + /// + /// The property at '{0}' could not be copied. + /// + internal static string CannotCannotCopyProperty + { + get { return GetString("CannotCannotCopyProperty"); } + } + + /// + /// The property at '{0}' could not be copied. + /// + internal static string FormatCannotCopyProperty(object p0) + { + return string.Format(CultureInfo.CurrentCulture, GetString("CannotCannotCopyProperty"), p0); + } + /// /// The '{0}' operation at path '{1}' could not be performed. /// diff --git a/src/Microsoft.AspNetCore.JsonPatch/Resources.resx b/src/Microsoft.AspNetCore.JsonPatch/Resources.resx index 7381ad02fc..87ed5c0a17 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Resources.resx +++ b/src/Microsoft.AspNetCore.JsonPatch/Resources.resx @@ -117,6 +117,9 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + The property at '{0}' could not be copied. + The type of the property at path '{0}' could not be determined. diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/InheritedDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/InheritedDTO.cs new file mode 100644 index 0000000000..a784a6304b --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/InheritedDTO.cs @@ -0,0 +1,10 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.AspNetCore.JsonPatch +{ + public class InheritedDTO : SimpleDTO + { + public string AdditionalStringProperty { get; set; } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs index 799f6e9e89..077a179a40 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs @@ -174,6 +174,27 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.Equal(new List() { "James", "Mike", null }, targetObject); } + [Fact] + public void Add_CompatibleTypeWorks() + { + // Arrange + var sDto = new SimpleDTO(); + var iDto = new InheritedDTO(); + var resolver = new Mock(MockBehavior.Strict); + var targetObject = (new List() { sDto }); + var listAdapter = new ListAdapter(); + string message = null; + + // Act + var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, iDto, out message); + + // Assert + Assert.True(addStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Equal(2, targetObject.Count); + Assert.Equal(new List() { sDto, iDto }, targetObject); + } + [Fact] public void Add_NonCompatibleType_Fails() { @@ -244,6 +265,60 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.Equal(expected, targetObject); } + public static TheoryData AddingKeepsObjectReferenceData { + get { + var sDto1 = new SimpleDTO(); + var sDto2 = new SimpleDTO(); + var sDto3 = new SimpleDTO(); + return new TheoryData() + { + { + new List() { }, + sDto1, + "-", + new List() { sDto1 } + }, + { + new List() { sDto1, sDto2 }, + sDto3, + "-", + new List() { sDto1, sDto2, sDto3 } + }, + { + new List() { sDto1, sDto2 }, + sDto3, + "0", + new List() { sDto3, sDto1, sDto2 } + }, + { + new List() { sDto1, sDto2 }, + sDto3, + "1", + new List() { sDto1, sDto3, sDto2 } + } + }; + } + } + + [Theory] + [MemberData(nameof(AddingKeepsObjectReferenceData))] + public void Add_KeepsObjectReference(IList targetObject, object value, string position, IList expected) + { + // Arrange + var resolver = new Mock(MockBehavior.Strict); + var listAdapter = new ListAdapter(); + string message = null; + + // Act + var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, value, out message); + + // Assert + Assert.True(addStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Equal(expected.Count, targetObject.Count); + Assert.Equal(expected, targetObject); + } + [Theory] [InlineData(new int[] { }, "0")] [InlineData(new[] { 10, 20 }, "-1")] diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs index cc2e990997..ece1a6e3d6 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs @@ -1699,6 +1699,81 @@ namespace Microsoft.AspNetCore.JsonPatch Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleDTO.IntegerList); } + [Fact] + public void Copy_DeepClonesObject() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO() + { + StringProperty = "A", + AnotherStringProperty = "B" + }, + InheritedDTO = new InheritedDTO() + { + StringProperty = "C", + AnotherStringProperty = "D" + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.InheritedDTO, o => o.SimpleDTO); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal("C", doc.SimpleDTO.StringProperty); + Assert.Equal("D", doc.SimpleDTO.AnotherStringProperty); + Assert.Equal("C", doc.InheritedDTO.StringProperty); + Assert.Equal("D", doc.InheritedDTO.AnotherStringProperty); + Assert.NotSame(doc.SimpleDTO.StringProperty, doc.InheritedDTO.StringProperty); + } + + [Fact] + public void Copy_KeepsObjectType() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO(), + InheritedDTO = new InheritedDTO() + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.InheritedDTO, o => o.SimpleDTO); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(typeof(InheritedDTO), doc.SimpleDTO.GetType()); + } + + [Fact] + public void Copy_BreaksObjectReference() + { + // Arrange + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = new SimpleDTO(), + InheritedDTO = new InheritedDTO() + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.InheritedDTO, o => o.SimpleDTO); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.NotSame(doc.SimpleDTO, doc.InheritedDTO); + } + [Fact] public void Move() { @@ -1752,6 +1827,77 @@ namespace Microsoft.AspNetCore.JsonPatch Assert.Equal(null, doc.SimpleDTO.StringProperty); } + [Fact] + public void Move_KeepsObjectReference() + { + // Arrange + var sDto = new SimpleDTO() + { + StringProperty = "A", + AnotherStringProperty = "B" + }; + var iDto = new InheritedDTO() + { + StringProperty = "C", + AnotherStringProperty = "D" + }; + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = sDto, + InheritedDTO = iDto + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.InheritedDTO, o => o.SimpleDTO); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal("C", doc.SimpleDTO.StringProperty); + Assert.Equal("D", doc.SimpleDTO.AnotherStringProperty); + Assert.Same(iDto, doc.SimpleDTO); + Assert.Equal(null, doc.InheritedDTO); + } + + [Fact] + public void Move_KeepsObjectReferenceWithSerialization() + { + // Arrange + var sDto = new SimpleDTO() + { + StringProperty = "A", + AnotherStringProperty = "B" + }; + var iDto = new InheritedDTO() + { + StringProperty = "C", + AnotherStringProperty = "D" + }; + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTO = sDto, + InheritedDTO = iDto + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.InheritedDTO, o => o.SimpleDTO); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(doc); + + // Assert + Assert.Equal("C", doc.SimpleDTO.StringProperty); + Assert.Equal("D", doc.SimpleDTO.AnotherStringProperty); + Assert.Same(iDto, doc.SimpleDTO); + Assert.Equal(null, doc.InheritedDTO); + } + [Fact] public void MoveInList() { @@ -1801,6 +1947,71 @@ namespace Microsoft.AspNetCore.JsonPatch Assert.Equal(new List() { 2, 1, 3 }, doc.SimpleDTO.IntegerList); } + [Fact] + public void Move_KeepsObjectReferenceInList() + { + // Arrange + var sDto1 = new SimpleDTO() { IntegerValue = 1 }; + var sDto2 = new SimpleDTO() { IntegerValue = 2 }; + var sDto3 = new SimpleDTO() { IntegerValue = 3 }; + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTOList = new List() { + sDto1, + sDto2, + sDto3 + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleDTOList, 0, o => o.SimpleDTOList, 1); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { sDto2, sDto1, sDto3 }, doc.SimpleDTOList); + Assert.Equal(2, doc.SimpleDTOList[0].IntegerValue); + Assert.Equal(1, doc.SimpleDTOList[1].IntegerValue); + Assert.Same(sDto2, doc.SimpleDTOList[0]); + Assert.Same(sDto1, doc.SimpleDTOList[1]); + } + + [Fact] + public void Move_KeepsObjectReferenceInListWithSerialization() + { + // Arrange + var sDto1 = new SimpleDTO() { IntegerValue = 1 }; + var sDto2 = new SimpleDTO() { IntegerValue = 2 }; + var sDto3 = new SimpleDTO() { IntegerValue = 3 }; + var doc = new SimpleDTOWithNestedDTO() + { + SimpleDTOList = new List() { + sDto1, + sDto2, + sDto3 + } + }; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleDTOList, 0, o => o.SimpleDTOList, 1); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + patchDoc.ApplyTo(doc); + + // Assert + Assert.Equal(new List() { sDto2, sDto1, sDto3 }, doc.SimpleDTOList); + Assert.Equal(2, doc.SimpleDTOList[0].IntegerValue); + Assert.Equal(1, doc.SimpleDTOList[1].IntegerValue); + Assert.Same(sDto2, doc.SimpleDTOList[0]); + Assert.Same(sDto1, doc.SimpleDTOList[1]); + } + [Fact] public void MoveFromListToEndOfList() { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTO.cs index 879d820277..de089eb25f 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTO.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTO.cs @@ -13,6 +13,8 @@ namespace Microsoft.AspNetCore.JsonPatch public SimpleDTO SimpleDTO { get; set; } + public InheritedDTO InheritedDTO { get; set; } + public List SimpleDTOList { get; set; } public IList SimpleDTOIList { get; set; } @@ -21,6 +23,7 @@ namespace Microsoft.AspNetCore.JsonPatch { this.NestedDTO = new NestedDTO(); this.SimpleDTO = new SimpleDTO(); + this.InheritedDTO = new InheritedDTO(); this.SimpleDTOList = new List(); } } From d3a09ca9e879507fb7b7c5a8825da59b3bfa63ef Mon Sep 17 00:00:00 2001 From: Thierry Fleury Date: Tue, 7 Feb 2017 13:38:10 -0800 Subject: [PATCH 0427/1029] Correct ListAdapter tests Modifying a ReadOnlyCollection will always fail --- test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs index 077a179a40..6a087edd8f 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs @@ -181,7 +181,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var sDto = new SimpleDTO(); var iDto = new InheritedDTO(); var resolver = new Mock(MockBehavior.Strict); - var targetObject = (new List() { sDto }); + var targetObject = new List() { sDto }; var listAdapter = new ListAdapter(); string message = null; @@ -200,7 +200,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { // Arrange var resolver = new Mock(MockBehavior.Strict); - var targetObject = (new List() { 10, 20 }).AsReadOnly(); + var targetObject = new List() { 10, 20 }; var listAdapter = new ListAdapter(); string message = null; @@ -411,7 +411,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { // Arrange var resolver = new Mock(MockBehavior.Strict); - var targetObject = (new List() { 10, 20 }).AsReadOnly(); + var targetObject = new List() { 10, 20 }; var listAdapter = new ListAdapter(); string message = null; From 9c618c8600b1748146f5454cf4e25ad3cbb1980c Mon Sep 17 00:00:00 2001 From: David Fowler Date: Wed, 8 Mar 2017 20:00:41 -0800 Subject: [PATCH 0428/1029] Update .travis.yml --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index af659e9ae9..b8f60ce2e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,8 +14,7 @@ env: global: - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - DOTNET_CLI_TELEMETRY_OPTOUT: 1 -mono: - - 4.0.5 +mono: none os: - linux - osx From 533373d6365be73c72ee8fe003dcb09cb6fbc23e Mon Sep 17 00:00:00 2001 From: David Fowler Date: Wed, 8 Mar 2017 20:32:33 -0800 Subject: [PATCH 0429/1029] Update .travis.yml --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index d9285f178d..4f28213da4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,8 +14,7 @@ env: global: - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - DOTNET_CLI_TELEMETRY_OPTOUT: 1 -mono: - - 4.0.5 +mono: none os: - linux - osx From c97dd446eb2aafd65e8bd5a9531c6d9713510aae Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 10 Mar 2017 09:18:38 -0800 Subject: [PATCH 0430/1029] Simplify console output and fix color output on CMD --- shared/IConsole.cs | 2 + shared/PhysicalConsole.cs | 7 ++ shared/Reporting/ColorFormatter.cs | 57 --------------- shared/Reporting/CompositeFormatter.cs | 26 ------- shared/Reporting/ConditionalFormatter.cs | 24 ------- shared/Reporting/ConsoleReporter.cs | 72 +++++++++++++++++++ shared/Reporting/DefaultFormatter.cs | 14 ---- shared/Reporting/FormatterBuilder.cs | 46 ------------ shared/Reporting/FormattingReporter.cs | 62 ---------------- shared/Reporting/IFormatter.cs | 10 --- shared/Reporting/PrefixFormatter.cs | 20 ------ shared/Reporting/ReporterBuilder.cs | 65 ----------------- .../PrefixConsoleReporter.cs | 32 +++++++++ src/Microsoft.DotNet.Watcher.Tools/Program.cs | 47 +----------- .../Program.cs | 31 +------- .../Program.cs | 30 +------- ...porterTests.cs => ConsoleReporterTests.cs} | 36 +++------- test/Shared/TestConsole.cs | 5 ++ 18 files changed, 131 insertions(+), 455 deletions(-) delete mode 100644 shared/Reporting/ColorFormatter.cs delete mode 100644 shared/Reporting/CompositeFormatter.cs delete mode 100644 shared/Reporting/ConditionalFormatter.cs create mode 100644 shared/Reporting/ConsoleReporter.cs delete mode 100644 shared/Reporting/DefaultFormatter.cs delete mode 100644 shared/Reporting/FormatterBuilder.cs delete mode 100644 shared/Reporting/FormattingReporter.cs delete mode 100644 shared/Reporting/IFormatter.cs delete mode 100644 shared/Reporting/PrefixFormatter.cs delete mode 100644 shared/Reporting/ReporterBuilder.cs create mode 100644 src/Microsoft.DotNet.Watcher.Tools/PrefixConsoleReporter.cs rename test/Microsoft.Extensions.Tools.Tests/{ReporterTests.cs => ConsoleReporterTests.cs} (68%) diff --git a/shared/IConsole.cs b/shared/IConsole.cs index 20bb36e7f9..7216c267a0 100644 --- a/shared/IConsole.cs +++ b/shared/IConsole.cs @@ -15,5 +15,7 @@ namespace Microsoft.Extensions.Tools.Internal bool IsInputRedirected { get; } bool IsOutputRedirected { get; } bool IsErrorRedirected { get; } + ConsoleColor ForegroundColor { get; set; } + void ResetColor(); } } diff --git a/shared/PhysicalConsole.cs b/shared/PhysicalConsole.cs index bdfb60ac0e..9a93323d5c 100644 --- a/shared/PhysicalConsole.cs +++ b/shared/PhysicalConsole.cs @@ -25,5 +25,12 @@ namespace Microsoft.Extensions.Tools.Internal public bool IsInputRedirected => Console.IsInputRedirected; public bool IsOutputRedirected => Console.IsOutputRedirected; public bool IsErrorRedirected => Console.IsErrorRedirected; + public ConsoleColor ForegroundColor + { + get => Console.ForegroundColor; + set => Console.ForegroundColor = value; + } + + public void ResetColor() => Console.ResetColor(); } } diff --git a/shared/Reporting/ColorFormatter.cs b/shared/Reporting/ColorFormatter.cs deleted file mode 100644 index 5675d5b367..0000000000 --- a/shared/Reporting/ColorFormatter.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; - -namespace Microsoft.Extensions.Tools.Internal -{ - public class ColorFormatter : IFormatter - { - // resets foreground color only - private const string ResetColor = "\x1B[39m"; - - private static readonly IDictionary AnsiColorCodes - = new Dictionary - { - {ConsoleColor.Black, 30}, - {ConsoleColor.DarkRed, 31}, - {ConsoleColor.DarkGreen, 32}, - {ConsoleColor.DarkYellow, 33}, - {ConsoleColor.DarkBlue, 34}, - {ConsoleColor.DarkMagenta, 35}, - {ConsoleColor.DarkCyan, 36}, - {ConsoleColor.Gray, 37}, - {ConsoleColor.DarkGray, 90}, - {ConsoleColor.Red, 91}, - {ConsoleColor.Green, 92}, - {ConsoleColor.Yellow, 93}, - {ConsoleColor.Blue, 94}, - {ConsoleColor.Magenta, 95}, - {ConsoleColor.Cyan, 96}, - {ConsoleColor.White, 97}, - }; - - private readonly string _prefix; - - public ColorFormatter(ConsoleColor color) - { - _prefix = GetAnsiCode(color); - } - - public string Format(string text) - => text?.Length > 0 - ? $"{_prefix}{text}{ResetColor}" - : text; - - private static string GetAnsiCode(ConsoleColor color) - { - int code; - if (!AnsiColorCodes.TryGetValue(color, out code)) - { - throw new ArgumentOutOfRangeException(nameof(color), color, null); - } - return $"\x1B[{code}m"; - } - } -} \ No newline at end of file diff --git a/shared/Reporting/CompositeFormatter.cs b/shared/Reporting/CompositeFormatter.cs deleted file mode 100644 index 63aa074760..0000000000 --- a/shared/Reporting/CompositeFormatter.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.Extensions.Tools.Internal -{ - public class CompositeFormatter : IFormatter - { - private readonly IFormatter[] _formatters; - - public CompositeFormatter(IFormatter[] formatters) - { - Ensure.NotNull(formatters, nameof(formatters)); - _formatters = formatters; - } - - public string Format(string text) - { - foreach (var formatter in _formatters) - { - text = formatter.Format(text); - } - - return text; - } - } -} \ No newline at end of file diff --git a/shared/Reporting/ConditionalFormatter.cs b/shared/Reporting/ConditionalFormatter.cs deleted file mode 100644 index b0881f2bac..0000000000 --- a/shared/Reporting/ConditionalFormatter.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; - -namespace Microsoft.Extensions.Tools.Internal -{ - public class ConditionalFormatter : IFormatter - { - private readonly Func _predicate; - - public ConditionalFormatter(Func predicate) - { - Ensure.NotNull(predicate, nameof(predicate)); - - _predicate = predicate; - } - - public string Format(string text) - => _predicate() - ? text - : null; - } -} \ No newline at end of file diff --git a/shared/Reporting/ConsoleReporter.cs b/shared/Reporting/ConsoleReporter.cs new file mode 100644 index 0000000000..ffcd1e8705 --- /dev/null +++ b/shared/Reporting/ConsoleReporter.cs @@ -0,0 +1,72 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; + +namespace Microsoft.Extensions.Tools.Internal +{ + public class ConsoleReporter : IReporter + { + private object _writeLock = new object(); + + public ConsoleReporter(IConsole console) + : this(console, verbose: false, quiet: false) + { } + + public ConsoleReporter(IConsole console, bool verbose, bool quiet) + { + Ensure.NotNull(console, nameof(console)); + + Console = console; + IsVerbose = verbose; + IsQuiet = quiet; + } + + protected IConsole Console { get; } + public bool IsVerbose { get; set; } + public bool IsQuiet { get; set; } + + protected virtual void WriteLine(TextWriter writer, string message, ConsoleColor? color) + { + lock (_writeLock) + { + if (color.HasValue) + { + Console.ForegroundColor = color.Value; + } + + writer.WriteLine(message); + + if (color.HasValue) + { + Console.ResetColor(); + } + } + } + + public virtual void Error(string message) + => WriteLine(Console.Error, message, ConsoleColor.Red); + public virtual void Warn(string message) + => WriteLine(Console.Out, message, ConsoleColor.Yellow); + + public virtual void Output(string message) + { + if (IsQuiet) + { + return; + } + WriteLine(Console.Out, message, color: null); + } + + public virtual void Verbose(string message) + { + if (!IsVerbose) + { + return; + } + + WriteLine(Console.Out, message, ConsoleColor.DarkGray); + } + } +} diff --git a/shared/Reporting/DefaultFormatter.cs b/shared/Reporting/DefaultFormatter.cs deleted file mode 100644 index 4d4348b000..0000000000 --- a/shared/Reporting/DefaultFormatter.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.Extensions.Tools.Internal -{ - public class DefaultFormatter : IFormatter - { - public static readonly IFormatter Instance = new DefaultFormatter(); - - private DefaultFormatter() {} - public string Format(string text) - => text; - } -} \ No newline at end of file diff --git a/shared/Reporting/FormatterBuilder.cs b/shared/Reporting/FormatterBuilder.cs deleted file mode 100644 index 3d3491487c..0000000000 --- a/shared/Reporting/FormatterBuilder.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; - -namespace Microsoft.Extensions.Tools.Internal -{ - public class FormatterBuilder - { - private readonly List _formatters = new List(); - - public FormatterBuilder WithColor(ConsoleColor color) - { - _formatters.Add(new ColorFormatter(color)); - return this; - } - - public FormatterBuilder WithPrefix(string prefix) - { - _formatters.Add(new PrefixFormatter(prefix)); - return this; - } - - public FormatterBuilder When(Func predicate) - { - _formatters.Add(new ConditionalFormatter(predicate)); - return this; - } - - public IFormatter Build() - { - if (_formatters.Count == 0) - { - return DefaultFormatter.Instance; - } - - if (_formatters.Count == 1) - { - return _formatters[0]; - } - - return new CompositeFormatter(_formatters.ToArray()); - } - } -} \ No newline at end of file diff --git a/shared/Reporting/FormattingReporter.cs b/shared/Reporting/FormattingReporter.cs deleted file mode 100644 index 0c49c0d817..0000000000 --- a/shared/Reporting/FormattingReporter.cs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.IO; - -namespace Microsoft.Extensions.Tools.Internal -{ - public class FormattingReporter : IReporter - { - private readonly object _writelock = new object(); - private readonly IConsole _console; - private readonly IFormatter _verbose; - private readonly IFormatter _warn; - private readonly IFormatter _output; - private readonly IFormatter _error; - - public FormattingReporter(IConsole console, - IFormatter verbose, - IFormatter output, - IFormatter warn, - IFormatter error) - { - Ensure.NotNull(console, nameof(console)); - Ensure.NotNull(verbose, nameof(verbose)); - Ensure.NotNull(output, nameof(output)); - Ensure.NotNull(warn, nameof(warn)); - Ensure.NotNull(error, nameof(error)); - - _console = console; - _verbose = verbose; - _output = output; - _warn = warn; - _error = error; - } - - - public void Verbose(string message) - => Write(_console.Out, _verbose.Format(message)); - - public void Output(string message) - => Write(_console.Out, _output.Format(message)); - - public void Warn(string message) - => Write(_console.Out, _warn.Format(message)); - - public void Error(string message) - => Write(_console.Error, _error.Format(message)); - - private void Write(TextWriter writer, string message) - { - if (message == null) - { - return; - } - - lock (_writelock) - { - writer.WriteLine(message); - } - } - } -} \ No newline at end of file diff --git a/shared/Reporting/IFormatter.cs b/shared/Reporting/IFormatter.cs deleted file mode 100644 index 9094728632..0000000000 --- a/shared/Reporting/IFormatter.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.Extensions.Tools.Internal -{ - public interface IFormatter - { - string Format(string text); - } -} \ No newline at end of file diff --git a/shared/Reporting/PrefixFormatter.cs b/shared/Reporting/PrefixFormatter.cs deleted file mode 100644 index b9602c41ca..0000000000 --- a/shared/Reporting/PrefixFormatter.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.Extensions.Tools.Internal -{ - public class PrefixFormatter : IFormatter - { - private readonly string _prefix; - - public PrefixFormatter(string prefix) - { - Ensure.NotNullOrEmpty(prefix, nameof(prefix)); - - _prefix = prefix; - } - - public string Format(string text) - => _prefix + text; - } -} \ No newline at end of file diff --git a/shared/Reporting/ReporterBuilder.cs b/shared/Reporting/ReporterBuilder.cs deleted file mode 100644 index 9283642041..0000000000 --- a/shared/Reporting/ReporterBuilder.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; - -namespace Microsoft.Extensions.Tools.Internal -{ - public class ReporterBuilder - { - private readonly FormatterBuilder _verbose = new FormatterBuilder(); - private readonly FormatterBuilder _output = new FormatterBuilder(); - private readonly FormatterBuilder _warn = new FormatterBuilder(); - private readonly FormatterBuilder _error = new FormatterBuilder(); - private IConsole _console; - - public ReporterBuilder WithConsole(IConsole console) - { - _console = console; - return this; - } - - public FormatterBuilder Verbose() => _verbose; - public FormatterBuilder Output() => _output; - public FormatterBuilder Warn() => _warn; - public FormatterBuilder Error() => _error; - - public ReporterBuilder Verbose(Action configure) - { - configure(_verbose); - return this; - } - - public ReporterBuilder Output(Action configure) - { - configure(_output); - return this; - } - - public ReporterBuilder Warn(Action configure) - { - configure(_warn); - return this; - } - - public ReporterBuilder Error(Action configure) - { - configure(_error); - return this; - } - - public IReporter Build() - { - if (_console == null) - { - throw new InvalidOperationException($"Cannot build without first calling {nameof(WithConsole)}"); - } - - return new FormattingReporter(_console, - _verbose.Build(), - _output.Build(), - _warn.Build(), - _error.Build()); - } - } -} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/PrefixConsoleReporter.cs b/src/Microsoft.DotNet.Watcher.Tools/PrefixConsoleReporter.cs new file mode 100644 index 0000000000..b2453276ef --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/PrefixConsoleReporter.cs @@ -0,0 +1,32 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using Microsoft.Extensions.Tools.Internal; + +namespace Microsoft.DotNet.Watcher +{ + public class PrefixConsoleReporter : ConsoleReporter + { + private object _lock = new object(); + + public PrefixConsoleReporter(IConsole console, bool verbose, bool quiet) + : base(console, verbose, quiet) + { } + + protected override void WriteLine(TextWriter writer, string message, ConsoleColor? color) + { + const string prefix = "watch : "; + + lock (_lock) + { + Console.ForegroundColor = ConsoleColor.DarkGray; + writer.Write(prefix); + Console.ResetColor(); + + base.WriteLine(writer, message, color); + } + } + } +} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index 9d18757d3c..261a92f31d 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -176,51 +176,6 @@ namespace Microsoft.DotNet.Watcher } private static IReporter CreateReporter(bool verbose, bool quiet, IConsole console) - { - const string prefix = "watch : "; - var colorPrefix = new ColorFormatter(ConsoleColor.DarkGray).Format(prefix); - - return new ReporterBuilder() - .WithConsole(console) - .Verbose(f => - { - if (console.IsOutputRedirected) - { - f.WithPrefix(prefix); - } - else - { - f.WithColor(ConsoleColor.DarkGray).WithPrefix(colorPrefix); - } - - f.When(() => verbose || CliContext.IsGlobalVerbose()); - }) - .Output(f => f - .WithPrefix(console.IsOutputRedirected ? prefix : colorPrefix) - .When(() => !quiet)) - .Warn(f => - { - if (console.IsOutputRedirected) - { - f.WithPrefix(prefix); - } - else - { - f.WithColor(ConsoleColor.Yellow).WithPrefix(colorPrefix); - } - }) - .Error(f => - { - if (console.IsOutputRedirected) - { - f.WithPrefix(prefix); - } - else - { - f.WithColor(ConsoleColor.Red).WithPrefix(colorPrefix); - } - }) - .Build(); - } + => new PrefixConsoleReporter(console, verbose || CliContext.IsGlobalVerbose(), quiet); } } diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs index 190335aded..874244f603 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs @@ -99,34 +99,7 @@ namespace Microsoft.Extensions.Caching.SqlConfig.Tools } private IReporter CreateReporter(bool verbose) - { - return new ReporterBuilder() - .WithConsole(_console) - .Verbose(f => - { - f.When(() => verbose); - if (!_console.IsOutputRedirected) - { - f.WithColor(ConsoleColor.DarkGray); - } - }) - .Warn(f => - { - if (!_console.IsOutputRedirected) - { - f.WithColor(ConsoleColor.Yellow); - } - }) - .Error(f => - { - if (!_console.IsErrorRedirected) - { - f.WithColor(ConsoleColor.Red); - } - }) - .Build(); - } - + => new ConsoleReporter(_console, verbose, quiet: false); private int CreateTableAndIndexes(IReporter reporter) { ValidateConnectionString(); @@ -197,4 +170,4 @@ namespace Microsoft.Extensions.Caching.SqlConfig.Tools } } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs index 667c16b27f..187e40128f 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs @@ -89,33 +89,7 @@ namespace Microsoft.Extensions.SecretManager.Tools } private IReporter CreateReporter(bool verbose) - { - return new ReporterBuilder() - .WithConsole(_console) - .Verbose(f => - { - f.When(() => verbose); - if (!_console.IsOutputRedirected) - { - f.WithColor(ConsoleColor.DarkGray); - } - }) - .Warn(f => - { - if (!_console.IsOutputRedirected) - { - f.WithColor(ConsoleColor.Yellow); - } - }) - .Error(f => - { - if (!_console.IsErrorRedirected) - { - f.WithColor(ConsoleColor.Red); - } - }) - .Build(); - } + => new ConsoleReporter(_console, verbose, quiet: false); internal string ResolveId(CommandLineOptions options, IReporter reporter) { @@ -128,4 +102,4 @@ namespace Microsoft.Extensions.SecretManager.Tools return resolver.Resolve(options.Project, options.Configuration); } } -} \ No newline at end of file +} diff --git a/test/Microsoft.Extensions.Tools.Tests/ReporterTests.cs b/test/Microsoft.Extensions.Tools.Tests/ConsoleReporterTests.cs similarity index 68% rename from test/Microsoft.Extensions.Tools.Tests/ReporterTests.cs rename to test/Microsoft.Extensions.Tools.Tests/ConsoleReporterTests.cs index 5c6cde5109..34cfd42850 100644 --- a/test/Microsoft.Extensions.Tools.Tests/ReporterTests.cs +++ b/test/Microsoft.Extensions.Tools.Tests/ConsoleReporterTests.cs @@ -13,30 +13,11 @@ namespace Microsoft.Extensions.Tools.Tests { private static readonly string EOL = Environment.NewLine; - [Theory] - [InlineData(ConsoleColor.DarkGray, "\x1B[90m")] - [InlineData(ConsoleColor.Red, "\x1B[91m")] - [InlineData(ConsoleColor.Yellow, "\x1B[93m")] - public void WrapsWithAnsiColorCode(ConsoleColor color, string code) - { - Assert.Equal($"{code}sample\x1B[39m", new ColorFormatter(color).Format("sample")); - } - - [Fact] - public void SkipsColorCodesForEmptyOrNullInput() - { - var formatter = new ColorFormatter(ConsoleColor.Blue); - Assert.Empty(formatter.Format(string.Empty)); - Assert.Null(formatter.Format(null)); - } - [Fact] public void WritesToStandardStreams() { var testConsole = new TestConsole(); - var reporter = new FormattingReporter(testConsole, - DefaultFormatter.Instance, DefaultFormatter.Instance, - DefaultFormatter.Instance, DefaultFormatter.Instance); + var reporter = new ConsoleReporter(testConsole, verbose: true, quiet: false); // stdout reporter.Verbose("verbose"); @@ -57,13 +38,6 @@ namespace Microsoft.Extensions.Tools.Tests testConsole.Clear(); } - [Fact] - public void FailsToBuildWithoutConsole() - { - Assert.Throws( - () => new ReporterBuilder().Build()); - } - private class TestConsole : IConsole { private readonly StringBuilder _out; @@ -92,12 +66,18 @@ namespace Microsoft.Extensions.Tools.Tests _error.Clear(); } + public void ResetColor() + { + ForegroundColor = default(ConsoleColor); + } + public TextWriter Out { get; } public TextWriter Error { get; } public TextReader In { get; } public bool IsInputRedirected { get; } public bool IsOutputRedirected { get; } public bool IsErrorRedirected { get; } + public ConsoleColor ForegroundColor { get; set; } } } -} \ No newline at end of file +} diff --git a/test/Shared/TestConsole.cs b/test/Shared/TestConsole.cs index fd98ff529b..6804c0265e 100644 --- a/test/Shared/TestConsole.cs +++ b/test/Shared/TestConsole.cs @@ -27,6 +27,7 @@ namespace Microsoft.Extensions.Tools.Internal public bool IsInputRedirected { get; set; } = false; public bool IsOutputRedirected { get; } = false; public bool IsErrorRedirected { get; } = false; + public ConsoleColor ForegroundColor { get; set; } public ConsoleCancelEventArgs ConsoleCancelKey() { @@ -39,6 +40,10 @@ namespace Microsoft.Extensions.Tools.Internal return args; } + public void ResetColor() + { + } + private class TestOutputWriter : TextWriter { private readonly ITestOutputHelper _output; From 1bfa9c4b4bf805e019a23a1444502c2311753cc8 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 10 Mar 2017 09:56:26 -0800 Subject: [PATCH 0431/1029] Make it possible to detect that a process is running inside dotnet-watch by setting 'DOTNET_WATCH=1' --- .../Internal/ProcessRunner.cs | 29 +++++++----- .../ProcessSpec.cs | 1 + src/Microsoft.DotNet.Watcher.Tools/Program.cs | 6 ++- .../DotNetWatcherTests.cs | 46 +++++++++++++++++++ .../Scenario/WatchableApp.cs | 2 +- .../KitchenSink/KitchenSink.csproj | 8 ++++ .../TestProjects/KitchenSink/Program.cs | 18 ++++++++ 7 files changed, 96 insertions(+), 14 deletions(-) create mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/DotNetWatcherTests.cs create mode 100755 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj create mode 100755 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/Program.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs index f303e8fe53..592c657675 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs @@ -63,20 +63,25 @@ namespace Microsoft.DotNet.Watcher.Internal private Process CreateProcess(ProcessSpec processSpec) { - var startInfo = new ProcessStartInfo - { - FileName = processSpec.Executable, - Arguments = ArgumentEscaper.EscapeAndConcatenate(processSpec.Arguments), - UseShellExecute = false, - WorkingDirectory = processSpec.WorkingDirectory, - RedirectStandardOutput = processSpec.IsOutputCaptured, - RedirectStandardError = processSpec.IsOutputCaptured, - }; var process = new Process { - StartInfo = startInfo, - EnableRaisingEvents = true + EnableRaisingEvents = true, + StartInfo = + { + FileName = processSpec.Executable, + Arguments = ArgumentEscaper.EscapeAndConcatenate(processSpec.Arguments), + UseShellExecute = false, + WorkingDirectory = processSpec.WorkingDirectory, + RedirectStandardOutput = processSpec.IsOutputCaptured, + RedirectStandardError = processSpec.IsOutputCaptured, + } }; + + foreach (var env in processSpec.EnvironmentVariables) + { + process.StartInfo.Environment.Add(env.Key, env.Value); + } + return process; } @@ -131,4 +136,4 @@ namespace Microsoft.DotNet.Watcher.Internal } } } -} \ No newline at end of file +} diff --git a/src/Microsoft.DotNet.Watcher.Tools/ProcessSpec.cs b/src/Microsoft.DotNet.Watcher.Tools/ProcessSpec.cs index 4b1508e5e2..ad5eb262b3 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/ProcessSpec.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/ProcessSpec.cs @@ -11,6 +11,7 @@ namespace Microsoft.DotNet.Watcher { public string Executable { get; set; } public string WorkingDirectory { get; set; } + public IDictionary EnvironmentVariables { get; } = new Dictionary(); public IEnumerable Arguments { get; set; } public OutputCapture OutputCapture { get; set; } diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index 261a92f31d..2f60889657 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -133,7 +133,11 @@ namespace Microsoft.DotNet.Watcher { Executable = DotNetMuxer.MuxerPathOrDefault(), WorkingDirectory = Path.GetDirectoryName(projectFile), - Arguments = args + Arguments = args, + EnvironmentVariables = + { + ["DOTNET_WATCH"] = "1" + }, }; await new DotNetWatcher(reporter) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/DotNetWatcherTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/DotNetWatcherTests.cs new file mode 100644 index 0000000000..f9d16972ee --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/DotNetWatcherTests.cs @@ -0,0 +1,46 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Threading.Tasks; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests +{ + public class DotNetWatcherTests : IDisposable + { + private readonly KitchenSinkApp _app; + + public DotNetWatcherTests(ITestOutputHelper logger) + { + _app = new KitchenSinkApp(logger); + _app.Prepare(); + } + + [Fact] + public async Task RunsWithDotnetWatchEnvVariable() + { + Assert.True(string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DOTNET_WATCH")), "DOTNET_WATCH cannot be set already when this test is running"); + + await _app.StartWatcherAsync().OrTimeout(); + const string messagePrefix = "DOTNET_WATCH = "; + var message = await _app.Process.GetOutputLineAsync(m => m.StartsWith(messagePrefix)); + var envValue = message.Substring(messagePrefix.Length); + Assert.Equal("1", envValue); + } + + public void Dispose() + { + _app.Dispose(); + } + + private class KitchenSinkApp : WatchableApp + { + public KitchenSinkApp(ITestOutputHelper logger) + : base("KitchenSink", logger) + { + } + } + } +} diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs index 6e4d6cc883..271a2832e4 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs @@ -93,7 +93,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public virtual void Dispose() { - Process.Dispose(); + Process?.Dispose(); Scenario.Dispose(); } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj new file mode 100755 index 0000000000..abb9969a56 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj @@ -0,0 +1,8 @@ + + + + Exe + netcoreapp1.1 + + + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/Program.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/Program.cs new file mode 100755 index 0000000000..5251cdc1e0 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/Program.cs @@ -0,0 +1,18 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; + +namespace KitchenSink +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Started"); + Console.WriteLine("PID = " + Process.GetCurrentProcess().Id); + Console.WriteLine("DOTNET_WATCH = " + Environment.GetEnvironmentVariable("DOTNET_WATCH")); + } + } +} From 8c327312824457b4dd1fccd814380894edf36eab Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 14 Mar 2017 12:22:25 -0700 Subject: [PATCH 0432/1029] Update dependencies and build version to 1.2.0 Unify dependencies Remove duplcated code from CommandLineUtils Update appveyor image --- .travis.yml | 11 +- appveyor.yml | 2 +- build/dependencies.props | 5 +- shared/CommandLine/AnsiConsole.cs | 143 ----- shared/CommandLine/CommandArgument.cs | 29 - shared/CommandLine/CommandLineApplication.cs | 555 ------------------ shared/CommandLine/CommandOption.cs | 108 ---- shared/CommandLine/CommandOptionType.cs | 13 - shared/CommandLine/CommandParsingException.cs | 18 - shared/{Reporting => }/ConsoleReporter.cs | 0 shared/{Reporting => }/IReporter.cs | 0 .../Microsoft.DotNet.Watcher.Tools.csproj | 3 +- ....Extensions.Caching.SqlConfig.Tools.csproj | 3 +- ...soft.Extensions.SecretManager.Tools.csproj | 3 +- ...otNet.Watcher.Tools.FunctionalTests.csproj | 8 +- ...icrosoft.DotNet.Watcher.Tools.Tests.csproj | 6 +- ...xtensions.SecretManager.Tools.Tests.csproj | 6 +- .../Microsoft.Extensions.Tools.Tests.csproj | 7 +- version.props | 4 +- 19 files changed, 28 insertions(+), 896 deletions(-) delete mode 100644 shared/CommandLine/AnsiConsole.cs delete mode 100644 shared/CommandLine/CommandArgument.cs delete mode 100644 shared/CommandLine/CommandLineApplication.cs delete mode 100644 shared/CommandLine/CommandOption.cs delete mode 100644 shared/CommandLine/CommandOptionType.cs delete mode 100644 shared/CommandLine/CommandParsingException.cs rename shared/{Reporting => }/ConsoleReporter.cs (100%) rename shared/{Reporting => }/IReporter.cs (100%) diff --git a/.travis.yml b/.travis.yml index 058b4421ec..e4c69a2a09 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,26 +14,17 @@ env: global: - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - DOTNET_CLI_TELEMETRY_OPTOUT: 1 -mono: - - 4.0.5 +mono: none os: - linux - osx -osx_image: xcode7.3 branches: only: - master - release - dev - /^(.*\/)?ci-.*$/ - - /^feature\// before_install: - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; fi script: - ./build.sh -notifications: - webhooks: - secure: "dhjfYLtihxx3zDdj0TLMJjiN4YJ37Qu0L9ySx7ek+YsfOAqKPHUsI6JNDtChauQxUB2NoL/i80+47oHhMelPyXniu1xA0MWaHV8bddZHzNQs1N8vGjjPmtbC5DQ7jmy+p7Xa5+ZscZ9NWEvJRqBInNdqugDAstDEIWbC35bq8H9t+6tZYu1sJctp1zF/k/w4OjJUoI1ZNLuusYIB1E+G/irvVT2x4GOC2QY3wXM4lJ2ORcZE9NgUBLNx/Hy5Rst5i4zO/mrFkYM/wOY6bAM6/gjjanK+d1wQnD9HuZH1ZVQqJRH3lveurYq9ih4zxV8MbW3FdLL1cXswEZbUBeqHlxVE32KwWF18nFUwdmrNQebnYnrZ/VWsa4pl+bOFNy2nomI3ibJ4F4+RwqTPXXE13qCr0CsC5RKu5bVQTpi0t4CKlUMsVlevN2jJcmAA641bnETNTDwk5WdT7Mjf9Pnn+krLZ7im9li3Plc/d8ynR1oiRzwFdp3u/9m3Oc8K+zMsNO5IOxHul9WsWbIkh3sNecqKHPSyVHB4FgdUoQ65xpc0887YKorbuBTOnlZugP8M/FmowkcwLo5xDD7kchkxyq9X8dPjej+tzpTsNVJjrOg4LP+nKxmOa+qc1r62eF0GdnIjwU30y6NdfvBCXoQJE1y063/zyGPIxSfCRmVzq4A=" - on_success: always - on_failure: always - on_start: always diff --git a/appveyor.yml b/appveyor.yml index 3f828ce38e..1041615c68 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,4 +11,4 @@ build_script: clone_depth: 1 test: off deploy: off -os: Visual Studio 2017 RC +os: Visual Studio 2017 diff --git a/build/dependencies.props b/build/dependencies.props index e704edaec0..5a4c06ce33 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,6 +1,9 @@ - 1.6.1 + 1.2.0-* 4.3.0 + 1.6.1 + 15.0.0 + 2.2.0 diff --git a/shared/CommandLine/AnsiConsole.cs b/shared/CommandLine/AnsiConsole.cs deleted file mode 100644 index 79d705f25e..0000000000 --- a/shared/CommandLine/AnsiConsole.cs +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; - -namespace Microsoft.Extensions.CommandLineUtils -{ - public class AnsiConsole - { - private AnsiConsole(TextWriter writer, bool useConsoleColor) - { - Writer = writer; - - _useConsoleColor = useConsoleColor; - if (_useConsoleColor) - { - OriginalForegroundColor = Console.ForegroundColor; - } - } - - private int _boldRecursion; - private bool _useConsoleColor; - - public static AnsiConsole GetOutput(bool useConsoleColor) - { - return new AnsiConsole(Console.Out, useConsoleColor); - } - - public static AnsiConsole GetError(bool useConsoleColor) - { - return new AnsiConsole(Console.Error, useConsoleColor); - } - - public TextWriter Writer { get; } - - public ConsoleColor OriginalForegroundColor { get; } - - private void SetColor(ConsoleColor color) - { - Console.ForegroundColor = (ConsoleColor)(((int)Console.ForegroundColor & 0x08) | ((int)color & 0x07)); - } - - private void SetBold(bool bold) - { - _boldRecursion += bold ? 1 : -1; - if (_boldRecursion > 1 || (_boldRecursion == 1 && !bold)) - { - return; - } - - Console.ForegroundColor = (ConsoleColor)((int)Console.ForegroundColor ^ 0x08); - } - - public void WriteLine(string message) - { - if (!_useConsoleColor) - { - Writer.WriteLine(message); - return; - } - - var escapeScan = 0; - for (; ;) - { - var escapeIndex = message.IndexOf("\x1b[", escapeScan); - if (escapeIndex == -1) - { - var text = message.Substring(escapeScan); - Writer.Write(text); - break; - } - else - { - var startIndex = escapeIndex + 2; - var endIndex = startIndex; - while (endIndex != message.Length && - message[endIndex] >= 0x20 && - message[endIndex] <= 0x3f) - { - endIndex += 1; - } - - var text = message.Substring(escapeScan, escapeIndex - escapeScan); - Writer.Write(text); - if (endIndex == message.Length) - { - break; - } - - switch (message[endIndex]) - { - case 'm': - int value; - if (int.TryParse(message.Substring(startIndex, endIndex - startIndex), out value)) - { - switch (value) - { - case 1: - SetBold(true); - break; - case 22: - SetBold(false); - break; - case 30: - SetColor(ConsoleColor.Black); - break; - case 31: - SetColor(ConsoleColor.Red); - break; - case 32: - SetColor(ConsoleColor.Green); - break; - case 33: - SetColor(ConsoleColor.Yellow); - break; - case 34: - SetColor(ConsoleColor.Blue); - break; - case 35: - SetColor(ConsoleColor.Magenta); - break; - case 36: - SetColor(ConsoleColor.Cyan); - break; - case 37: - SetColor(ConsoleColor.Gray); - break; - case 39: - SetColor(OriginalForegroundColor); - break; - } - } - break; - } - - escapeScan = endIndex + 1; - } - } - Writer.WriteLine(); - } - } -} diff --git a/shared/CommandLine/CommandArgument.cs b/shared/CommandLine/CommandArgument.cs deleted file mode 100644 index c687485e33..0000000000 --- a/shared/CommandLine/CommandArgument.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using System.Linq; - -namespace Microsoft.Extensions.CommandLineUtils -{ - public class CommandArgument - { - public CommandArgument() - { - Values = new List(); - } - - public string Name { get; set; } - public bool ShowInHelpText { get; set; } = true; - public string Description { get; set; } - public List Values { get; private set; } - public bool MultipleValues { get; set; } - public string Value - { - get - { - return Values.FirstOrDefault(); - } - } - } -} diff --git a/shared/CommandLine/CommandLineApplication.cs b/shared/CommandLine/CommandLineApplication.cs deleted file mode 100644 index 0623e5104e..0000000000 --- a/shared/CommandLine/CommandLineApplication.cs +++ /dev/null @@ -1,555 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Microsoft.Extensions.CommandLineUtils -{ - public class CommandLineApplication - { - // Indicates whether the parser should throw an exception when it runs into an unexpected argument. - // If this field is set to false, the parser will stop parsing when it sees an unexpected argument, and all - // remaining arguments, including the first unexpected argument, will be stored in RemainingArguments property. - private readonly bool _throwOnUnexpectedArg; - - public CommandLineApplication(bool throwOnUnexpectedArg = true) - { - _throwOnUnexpectedArg = throwOnUnexpectedArg; - Options = new List(); - Arguments = new List(); - Commands = new List(); - RemainingArguments = new List(); - Invoke = () => 0; - } - - public CommandLineApplication Parent { get; set; } - public string Name { get; set; } - public string FullName { get; set; } - public string Syntax { get; set; } - public string Description { get; set; } - public bool ShowInHelpText { get; set; } = true; - public string ExtendedHelpText { get; set; } - public readonly List Options; - public CommandOption OptionHelp { get; private set; } - public CommandOption OptionVersion { get; private set; } - public readonly List Arguments; - public readonly List RemainingArguments; - public bool IsShowingInformation { get; protected set; } // Is showing help or version? - public Func Invoke { get; set; } - public Func LongVersionGetter { get; set; } - public Func ShortVersionGetter { get; set; } - public readonly List Commands; - public bool AllowArgumentSeparator { get; set; } - public TextWriter Out { get; set; } = Console.Out; - public TextWriter Error { get; set; } = Console.Error; - - public IEnumerable GetOptions() - { - var expr = Options.AsEnumerable(); - var rootNode = this; - while (rootNode.Parent != null) - { - rootNode = rootNode.Parent; - expr = expr.Concat(rootNode.Options.Where(o => o.Inherited)); - } - - return expr; - } - - public CommandLineApplication Command(string name, Action configuration, - bool throwOnUnexpectedArg = true) - { - var command = new CommandLineApplication(throwOnUnexpectedArg) { Name = name, Parent = this }; - Commands.Add(command); - configuration(command); - return command; - } - - public CommandOption Option(string template, string description, CommandOptionType optionType) - => Option(template, description, optionType, _ => { }, inherited: false); - - public CommandOption Option(string template, string description, CommandOptionType optionType, bool inherited) - => Option(template, description, optionType, _ => { }, inherited); - - public CommandOption Option(string template, string description, CommandOptionType optionType, Action configuration) - => Option(template, description, optionType, configuration, inherited: false); - - public CommandOption Option(string template, string description, CommandOptionType optionType, Action configuration, bool inherited) - { - var option = new CommandOption(template, optionType) - { - Description = description, - Inherited = inherited - }; - Options.Add(option); - configuration(option); - return option; - } - - public CommandArgument Argument(string name, string description, bool multipleValues = false) - { - return Argument(name, description, _ => { }, multipleValues); - } - - public CommandArgument Argument(string name, string description, Action configuration, bool multipleValues = false) - { - var lastArg = Arguments.LastOrDefault(); - if (lastArg != null && lastArg.MultipleValues) - { - var message = string.Format("The last argument '{0}' accepts multiple values. No more argument can be added.", - lastArg.Name); - throw new InvalidOperationException(message); - } - - var argument = new CommandArgument { Name = name, Description = description, MultipleValues = multipleValues }; - Arguments.Add(argument); - configuration(argument); - return argument; - } - - public void OnExecute(Func invoke) - { - Invoke = invoke; - } - - public void OnExecute(Func> invoke) - { - Invoke = () => invoke().Result; - } - public int Execute(params string[] args) - { - CommandLineApplication command = this; - CommandOption option = null; - IEnumerator arguments = null; - - for (var index = 0; index < args.Length; index++) - { - var arg = args[index]; - var processed = false; - if (!processed && option == null) - { - string[] longOption = null; - string[] shortOption = null; - - if (arg.StartsWith("--")) - { - longOption = arg.Substring(2).Split(new[] { ':', '=' }, 2); - } - else if (arg.StartsWith("-")) - { - shortOption = arg.Substring(1).Split(new[] { ':', '=' }, 2); - } - if (longOption != null) - { - processed = true; - var longOptionName = longOption[0]; - option = command.GetOptions().SingleOrDefault(opt => string.Equals(opt.LongName, longOptionName, StringComparison.Ordinal)); - - if (option == null) - { - if (string.IsNullOrEmpty(longOptionName) && !command._throwOnUnexpectedArg && AllowArgumentSeparator) - { - // skip over the '--' argument separator - index++; - } - - HandleUnexpectedArg(command, args, index, argTypeName: "option"); - break; - } - - // If we find a help/version option, show information and stop parsing - if (command.OptionHelp == option) - { - command.ShowHelp(); - return 0; - } - else if (command.OptionVersion == option) - { - command.ShowVersion(); - return 0; - } - - if (longOption.Length == 2) - { - if (!option.TryParse(longOption[1])) - { - command.ShowHint(); - throw new CommandParsingException(command, $"Unexpected value '{longOption[1]}' for option '{option.LongName}'"); - } - option = null; - } - else if (option.OptionType == CommandOptionType.NoValue) - { - // No value is needed for this option - option.TryParse(null); - option = null; - } - } - if (shortOption != null) - { - processed = true; - option = command.GetOptions().SingleOrDefault(opt => string.Equals(opt.ShortName, shortOption[0], StringComparison.Ordinal)); - - // If not a short option, try symbol option - if (option == null) - { - option = command.GetOptions().SingleOrDefault(opt => string.Equals(opt.SymbolName, shortOption[0], StringComparison.Ordinal)); - } - - if (option == null) - { - HandleUnexpectedArg(command, args, index, argTypeName: "option"); - break; - } - - // If we find a help/version option, show information and stop parsing - if (command.OptionHelp == option) - { - command.ShowHelp(); - return 0; - } - else if (command.OptionVersion == option) - { - command.ShowVersion(); - return 0; - } - - if (shortOption.Length == 2) - { - if (!option.TryParse(shortOption[1])) - { - command.ShowHint(); - throw new CommandParsingException(command, $"Unexpected value '{shortOption[1]}' for option '{option.LongName}'"); - } - option = null; - } - else if (option.OptionType == CommandOptionType.NoValue) - { - // No value is needed for this option - option.TryParse(null); - option = null; - } - } - } - - if (!processed && option != null) - { - processed = true; - if (!option.TryParse(arg)) - { - command.ShowHint(); - throw new CommandParsingException(command, $"Unexpected value '{arg}' for option '{option.LongName}'"); - } - option = null; - } - - if (!processed && arguments == null) - { - var currentCommand = command; - foreach (var subcommand in command.Commands) - { - if (string.Equals(subcommand.Name, arg, StringComparison.OrdinalIgnoreCase)) - { - processed = true; - command = subcommand; - break; - } - } - - // If we detect a subcommand - if (command != currentCommand) - { - processed = true; - } - } - if (!processed) - { - if (arguments == null) - { - arguments = new CommandArgumentEnumerator(command.Arguments.GetEnumerator()); - } - if (arguments.MoveNext()) - { - processed = true; - arguments.Current.Values.Add(arg); - } - } - if (!processed) - { - HandleUnexpectedArg(command, args, index, argTypeName: "command or argument"); - break; - } - } - - if (option != null) - { - command.ShowHint(); - throw new CommandParsingException(command, $"Missing value for option '{option.LongName}'"); - } - - return command.Invoke(); - } - - // Helper method that adds a help option - public CommandOption HelpOption(string template) - { - // Help option is special because we stop parsing once we see it - // So we store it separately for further use - OptionHelp = Option(template, "Show help information", CommandOptionType.NoValue); - - return OptionHelp; - } - - public CommandOption VersionOption(string template, - string shortFormVersion, - string longFormVersion = null) - { - if (longFormVersion == null) - { - return VersionOption(template, () => shortFormVersion); - } - else - { - return VersionOption(template, () => shortFormVersion, () => longFormVersion); - } - } - - // Helper method that adds a version option - public CommandOption VersionOption(string template, - Func shortFormVersionGetter, - Func longFormVersionGetter = null) - { - // Version option is special because we stop parsing once we see it - // So we store it separately for further use - OptionVersion = Option(template, "Show version information", CommandOptionType.NoValue); - ShortVersionGetter = shortFormVersionGetter; - LongVersionGetter = longFormVersionGetter ?? shortFormVersionGetter; - - return OptionVersion; - } - - // Show short hint that reminds users to use help option - public void ShowHint() - { - if (OptionHelp != null) - { - Out.WriteLine(string.Format("Specify --{0} for a list of available options and commands.", OptionHelp.LongName)); - } - } - - // Show full help - public void ShowHelp(string commandName = null) - { - for (var cmd = this; cmd != null; cmd = cmd.Parent) - { - cmd.IsShowingInformation = true; - } - - Out.WriteLine(GetHelpText(commandName)); - } - - public virtual string GetHelpText(string commandName = null) - { - var headerBuilder = new StringBuilder("Usage:"); - for (var cmd = this; cmd != null; cmd = cmd.Parent) - { - headerBuilder.Insert(6, string.Format(" {0}", cmd.Name)); - } - - CommandLineApplication target; - - if (commandName == null || string.Equals(Name, commandName, StringComparison.OrdinalIgnoreCase)) - { - target = this; - } - else - { - target = Commands.SingleOrDefault(cmd => string.Equals(cmd.Name, commandName, StringComparison.OrdinalIgnoreCase)); - - if (target != null) - { - headerBuilder.AppendFormat(" {0}", commandName); - } - else - { - // The command name is invalid so don't try to show help for something that doesn't exist - target = this; - } - - } - - var optionsBuilder = new StringBuilder(); - var commandsBuilder = new StringBuilder(); - var argumentsBuilder = new StringBuilder(); - - var arguments = target.Arguments.Where(a => a.ShowInHelpText).ToList(); - if (arguments.Any()) - { - headerBuilder.Append(" [arguments]"); - - argumentsBuilder.AppendLine(); - argumentsBuilder.AppendLine("Arguments:"); - var maxArgLen = arguments.Max(a => a.Name.Length); - var outputFormat = string.Format(" {{0, -{0}}}{{1}}", maxArgLen + 2); - foreach (var arg in arguments) - { - argumentsBuilder.AppendFormat(outputFormat, arg.Name, arg.Description); - argumentsBuilder.AppendLine(); - } - } - - var options = target.GetOptions().Where(o => o.ShowInHelpText).ToList(); - if (options.Any()) - { - headerBuilder.Append(" [options]"); - - optionsBuilder.AppendLine(); - optionsBuilder.AppendLine("Options:"); - var maxOptLen = options.Max(o => o.Template.Length); - var outputFormat = string.Format(" {{0, -{0}}}{{1}}", maxOptLen + 2); - foreach (var opt in options) - { - optionsBuilder.AppendFormat(outputFormat, opt.Template, opt.Description); - optionsBuilder.AppendLine(); - } - } - - var commands = target.Commands.Where(c => c.ShowInHelpText).ToList(); - if (commands.Any()) - { - headerBuilder.Append(" [command]"); - - commandsBuilder.AppendLine(); - commandsBuilder.AppendLine("Commands:"); - var maxCmdLen = commands.Max(c => c.Name.Length); - var outputFormat = string.Format(" {{0, -{0}}}{{1}}", maxCmdLen + 2); - foreach (var cmd in commands.OrderBy(c => c.Name)) - { - commandsBuilder.AppendFormat(outputFormat, cmd.Name, cmd.Description); - commandsBuilder.AppendLine(); - } - - if (OptionHelp != null) - { - commandsBuilder.AppendLine(); - commandsBuilder.AppendFormat($"Use \"{target.Name} [command] --{OptionHelp.LongName}\" for more information about a command."); - commandsBuilder.AppendLine(); - } - } - - if (target.AllowArgumentSeparator) - { - headerBuilder.Append(" [[--] ...]"); - } - - headerBuilder.AppendLine(); - - var nameAndVersion = new StringBuilder(); - nameAndVersion.AppendLine(GetFullNameAndVersion()); - nameAndVersion.AppendLine(); - - return nameAndVersion.ToString() - + headerBuilder.ToString() - + argumentsBuilder.ToString() - + optionsBuilder.ToString() - + commandsBuilder.ToString() - + target.ExtendedHelpText; - } - - public void ShowVersion() - { - for (var cmd = this; cmd != null; cmd = cmd.Parent) - { - cmd.IsShowingInformation = true; - } - - Out.WriteLine(FullName); - Out.WriteLine(LongVersionGetter()); - } - - public string GetFullNameAndVersion() - { - return ShortVersionGetter == null ? FullName : string.Format("{0} {1}", FullName, ShortVersionGetter()); - } - - public void ShowRootCommandFullNameAndVersion() - { - var rootCmd = this; - while (rootCmd.Parent != null) - { - rootCmd = rootCmd.Parent; - } - - Out.WriteLine(rootCmd.GetFullNameAndVersion()); - Out.WriteLine(); - } - - private void HandleUnexpectedArg(CommandLineApplication command, string[] args, int index, string argTypeName) - { - if (command._throwOnUnexpectedArg) - { - command.ShowHint(); - throw new CommandParsingException(command, $"Unrecognized {argTypeName} '{args[index]}'"); - } - else - { - // All remaining arguments are stored for further use - command.RemainingArguments.AddRange(new ArraySegment(args, index, args.Length - index)); - } - } - - private class CommandArgumentEnumerator : IEnumerator - { - private readonly IEnumerator _enumerator; - - public CommandArgumentEnumerator(IEnumerator enumerator) - { - _enumerator = enumerator; - } - - public CommandArgument Current - { - get - { - return _enumerator.Current; - } - } - - object IEnumerator.Current - { - get - { - return Current; - } - } - - public void Dispose() - { - _enumerator.Dispose(); - } - - public bool MoveNext() - { - if (Current == null || !Current.MultipleValues) - { - return _enumerator.MoveNext(); - } - - // If current argument allows multiple values, we don't move forward and - // all later values will be added to current CommandArgument.Values - return true; - } - - public void Reset() - { - _enumerator.Reset(); - } - } - } -} diff --git a/shared/CommandLine/CommandOption.cs b/shared/CommandLine/CommandOption.cs deleted file mode 100644 index 8f6d6af4ad..0000000000 --- a/shared/CommandLine/CommandOption.cs +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Microsoft.Extensions.CommandLineUtils -{ - public class CommandOption - { - public CommandOption(string template, CommandOptionType optionType) - { - Template = template; - OptionType = optionType; - Values = new List(); - - foreach (var part in Template.Split(new[] { ' ', '|' }, StringSplitOptions.RemoveEmptyEntries)) - { - if (part.StartsWith("--")) - { - LongName = part.Substring(2); - } - else if (part.StartsWith("-")) - { - var optName = part.Substring(1); - - // If there is only one char and it is not an English letter, it is a symbol option (e.g. "-?") - if (optName.Length == 1 && !IsEnglishLetter(optName[0])) - { - SymbolName = optName; - } - else - { - ShortName = optName; - } - } - else if (part.StartsWith("<") && part.EndsWith(">")) - { - ValueName = part.Substring(1, part.Length - 2); - } - else - { - throw new ArgumentException($"Invalid template pattern '{template}'", nameof(template)); - } - } - - if (string.IsNullOrEmpty(LongName) && string.IsNullOrEmpty(ShortName) && string.IsNullOrEmpty(SymbolName)) - { - throw new ArgumentException($"Invalid template pattern '{template}'", nameof(template)); - } - } - - public string Template { get; set; } - public string ShortName { get; set; } - public string LongName { get; set; } - public string SymbolName { get; set; } - public string ValueName { get; set; } - public string Description { get; set; } - public List Values { get; private set; } - public CommandOptionType OptionType { get; private set; } - public bool ShowInHelpText { get; set; } = true; - public bool Inherited { get; set; } - - public bool TryParse(string value) - { - switch (OptionType) - { - case CommandOptionType.MultipleValue: - Values.Add(value); - break; - case CommandOptionType.SingleValue: - if (Values.Any()) - { - return false; - } - Values.Add(value); - break; - case CommandOptionType.NoValue: - if (value != null) - { - return false; - } - // Add a value to indicate that this option was specified - Values.Add("on"); - break; - default: - break; - } - return true; - } - - public bool HasValue() - { - return Values.Any(); - } - - public string Value() - { - return HasValue() ? Values[0] : null; - } - - private bool IsEnglishLetter(char c) - { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); - } - } -} \ No newline at end of file diff --git a/shared/CommandLine/CommandOptionType.cs b/shared/CommandLine/CommandOptionType.cs deleted file mode 100644 index 759182ca91..0000000000 --- a/shared/CommandLine/CommandOptionType.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - - -namespace Microsoft.Extensions.CommandLineUtils -{ - public enum CommandOptionType - { - MultipleValue, - SingleValue, - NoValue - } -} diff --git a/shared/CommandLine/CommandParsingException.cs b/shared/CommandLine/CommandParsingException.cs deleted file mode 100644 index b5151c2301..0000000000 --- a/shared/CommandLine/CommandParsingException.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; - -namespace Microsoft.Extensions.CommandLineUtils -{ - public class CommandParsingException : Exception - { - public CommandParsingException(CommandLineApplication command, string message) - : base(message) - { - Command = command; - } - - public CommandLineApplication Command { get; } - } -} diff --git a/shared/Reporting/ConsoleReporter.cs b/shared/ConsoleReporter.cs similarity index 100% rename from shared/Reporting/ConsoleReporter.cs rename to shared/ConsoleReporter.cs diff --git a/shared/Reporting/IReporter.cs b/shared/IReporter.cs similarity index 100% rename from shared/Reporting/IReporter.cs rename to shared/IReporter.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj index 547e8fcf6d..5a3606864d 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj @@ -20,7 +20,8 @@ - + + diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj index d3a16d3946..51d558612d 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj @@ -18,7 +18,8 @@ - + + diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj index 921fa53a34..f51bb14cf0 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj @@ -20,7 +20,8 @@ - + + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj index 19088145f1..4141169368 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj @@ -21,10 +21,10 @@ - - - - + + + + diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj index 285d18f0cf..dfa053ce59 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj @@ -15,9 +15,9 @@ - - - + + + diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj index 9a9dc14b24..85ca0d7e69 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj @@ -12,9 +12,9 @@ - - - + + + diff --git a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj index 0c151d0a68..6112fdd935 100644 --- a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj @@ -11,9 +11,10 @@ - - - + + + + diff --git a/version.props b/version.props index e143c25f8e..29f91e170d 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ - 1.0.1 - alpha + 1.2.0 + preview1 From ba0926736b86703c64044983f6e74a10c640ead9 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 14 Mar 2017 13:40:24 -0700 Subject: [PATCH 0433/1029] Update appveyor and travis settings --- .travis.yml | 1 - appveyor.yml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4f28213da4..56f3837d7e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,6 @@ mono: none os: - linux - osx -osx_image: xcode7.3 branches: only: - master diff --git a/appveyor.yml b/appveyor.yml index 3f828ce38e..1041615c68 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,4 +11,4 @@ build_script: clone_depth: 1 test: off deploy: off -os: Visual Studio 2017 RC +os: Visual Studio 2017 From d01f81eeb84d5edbcf6d52de4863e2eceaf8d8ab Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 14 Mar 2017 13:40:42 -0700 Subject: [PATCH 0434/1029] Update appveyor and travis settings --- .travis.yml | 1 - appveyor.yml | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index b8f60ce2e5..e4c69a2a09 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,6 @@ mono: none os: - linux - osx -osx_image: xcode7.3 branches: only: - master diff --git a/appveyor.yml b/appveyor.yml index 944c23c8ba..1041615c68 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,5 +11,4 @@ build_script: clone_depth: 1 test: off deploy: off -# Required for dotnet-test to work -os: Visual Studio 2015 +os: Visual Studio 2017 From d1d656d5b895690ad5b9c5aaeaa21c02d88f7285 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 15 Mar 2017 09:29:05 -0700 Subject: [PATCH 0435/1029] Add samples and update READMEs (#275) --- .../LaunchAnyCommand/LaunchAnyCommand.csproj | 15 ++++++++++ .../dotnet-watch/LaunchAnyCommand/README.md | 18 ++++++++++++ .../LaunchAnyCommand/package.json | 8 ++++++ .../LaunchAnyCommand/say-hello.js | 1 + samples/dotnet-watch/README.md | 5 ++++ .../WatchJavascriptFiles/Program.cs | 28 +++++++++++++++++++ .../WatchJavascriptFiles/README.md | 17 +++++++++++ .../WatchJavascriptFiles.csproj | 17 +++++++++++ .../WatchJavascriptFiles/wwwroot/app.js | 1 + .../WatchMultipleProjects/README.md | 19 +++++++++++++ .../WatchMultipleProjects/Test/Test.csproj | 13 +++++++++ .../WatchMultipleProjects/Test/UnitTest1.cs | 17 +++++++++++ .../WatchMultipleProjects/Web/Program.cs | 28 +++++++++++++++++++ .../WatchMultipleProjects/Web/Web.csproj | 15 ++++++++++ .../WatchMultipleProjects/watch.proj | 19 +++++++++++++ src/Microsoft.DotNet.Watcher.Tools/README.md | 6 ++-- .../README.md | 4 +-- .../README.md | 4 +-- 18 files changed, 228 insertions(+), 7 deletions(-) create mode 100644 samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj create mode 100644 samples/dotnet-watch/LaunchAnyCommand/README.md create mode 100644 samples/dotnet-watch/LaunchAnyCommand/package.json create mode 100644 samples/dotnet-watch/LaunchAnyCommand/say-hello.js create mode 100644 samples/dotnet-watch/README.md create mode 100755 samples/dotnet-watch/WatchJavascriptFiles/Program.cs create mode 100644 samples/dotnet-watch/WatchJavascriptFiles/README.md create mode 100755 samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj create mode 100644 samples/dotnet-watch/WatchJavascriptFiles/wwwroot/app.js create mode 100644 samples/dotnet-watch/WatchMultipleProjects/README.md create mode 100755 samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj create mode 100755 samples/dotnet-watch/WatchMultipleProjects/Test/UnitTest1.cs create mode 100755 samples/dotnet-watch/WatchMultipleProjects/Web/Program.cs create mode 100755 samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj create mode 100644 samples/dotnet-watch/WatchMultipleProjects/watch.proj diff --git a/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj b/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj new file mode 100644 index 0000000000..80e25acb9c --- /dev/null +++ b/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj @@ -0,0 +1,15 @@ + + + netcoreapp1.1 + + + + + + + + + + + + diff --git a/samples/dotnet-watch/LaunchAnyCommand/README.md b/samples/dotnet-watch/LaunchAnyCommand/README.md new file mode 100644 index 0000000000..698d69225d --- /dev/null +++ b/samples/dotnet-watch/LaunchAnyCommand/README.md @@ -0,0 +1,18 @@ +Launch any command with dotnet-watch +==================================== + +## Prerequisites + +1. Install .NET Core command line. +2. Install NodeJS. + +## Usage + +Open a terminal to the directory containing this project. + +``` +dotnet restore +dotnet watch msbuild /t:RunMyNpmCommand +``` + +Changing the .csproj file, or the say-hello.js file will cause dotnet-watch to re-run the 'RunMyNpmCommand' target in MyApp.csproj. diff --git a/samples/dotnet-watch/LaunchAnyCommand/package.json b/samples/dotnet-watch/LaunchAnyCommand/package.json new file mode 100644 index 0000000000..61e25fb082 --- /dev/null +++ b/samples/dotnet-watch/LaunchAnyCommand/package.json @@ -0,0 +1,8 @@ +{ + "name": "any-command", + "version": "0.0.0", + "private": true, + "scripts": { + "custom": "node say-hello.js" + } +} diff --git a/samples/dotnet-watch/LaunchAnyCommand/say-hello.js b/samples/dotnet-watch/LaunchAnyCommand/say-hello.js new file mode 100644 index 0000000000..c35728f5a1 --- /dev/null +++ b/samples/dotnet-watch/LaunchAnyCommand/say-hello.js @@ -0,0 +1 @@ +console.log("Hello from Javascript"); diff --git a/samples/dotnet-watch/README.md b/samples/dotnet-watch/README.md new file mode 100644 index 0000000000..467a552f7e --- /dev/null +++ b/samples/dotnet-watch/README.md @@ -0,0 +1,5 @@ +dotnet-watch samples +==================== + +The samples in this folder show some ways to customize dotnet-watch. For full details on +available settings and configuration, see the [README for the Microsoft.DotNet.Watcher.Tools](../../src/Microsoft.DotNet.Watcher.Tools/README.md) project. diff --git a/samples/dotnet-watch/WatchJavascriptFiles/Program.cs b/samples/dotnet-watch/WatchJavascriptFiles/Program.cs new file mode 100755 index 0000000000..f71a9e073d --- /dev/null +++ b/samples/dotnet-watch/WatchJavascriptFiles/Program.cs @@ -0,0 +1,28 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; + +namespace WatchJavascriptFiles +{ + public class Program + { + public static void Main(string[] args) + { + var host = new WebHostBuilder() + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .Configure(app => + app.Run(async (context) => + { + await context.Response.WriteAsync("Hello World!"); + })) + .Build(); + + host.Run(); + } + } +} diff --git a/samples/dotnet-watch/WatchJavascriptFiles/README.md b/samples/dotnet-watch/WatchJavascriptFiles/README.md new file mode 100644 index 0000000000..dc98940cd7 --- /dev/null +++ b/samples/dotnet-watch/WatchJavascriptFiles/README.md @@ -0,0 +1,17 @@ +Watch JavaScript files with dotnet-watch +======================================== + +## Prerequisites + +Install .NET Core command line. + +## Usage + +Open a terminal to the directory containing this project. + +``` +dotnet restore +dotnet watch run +``` + +Changing the .csproj file, or \*.js file in wwwroot, or any \*.cs file will cause dotnet-watch to restart the website. diff --git a/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj b/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj new file mode 100755 index 0000000000..4ff79540da --- /dev/null +++ b/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj @@ -0,0 +1,17 @@ + + + + netcoreapp1.1 + + + + + + + + + + + + + diff --git a/samples/dotnet-watch/WatchJavascriptFiles/wwwroot/app.js b/samples/dotnet-watch/WatchJavascriptFiles/wwwroot/app.js new file mode 100644 index 0000000000..a94cbdc370 --- /dev/null +++ b/samples/dotnet-watch/WatchJavascriptFiles/wwwroot/app.js @@ -0,0 +1 @@ +document.title = "My awesome website"; diff --git a/samples/dotnet-watch/WatchMultipleProjects/README.md b/samples/dotnet-watch/WatchMultipleProjects/README.md new file mode 100644 index 0000000000..2c01233d36 --- /dev/null +++ b/samples/dotnet-watch/WatchMultipleProjects/README.md @@ -0,0 +1,19 @@ +Watch multiple projects with dotnet-watch +========================================= + +## Prerequisites + +Install .NET Core command line. + +## Usage + +Open a terminal to the directory containing this project. + +``` +dotnet restore watch.proj +dotnet watch msbuild watch.proj /t:TestAndRun +``` + +The "TestAndRun" target in watch.proj will execute "dotnet test" on Test.csproj and then launch the website by calling "dotnet run" on Web.csproj. + +Changing any \*.cs file in Test/ or Web/, any \*.csproj file, or watch.proj, will cause dotnet-watch to relaunch the "TestAndRun" target from watch.proj. diff --git a/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj b/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj new file mode 100755 index 0000000000..7c8da8f68a --- /dev/null +++ b/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj @@ -0,0 +1,13 @@ + + + + netcoreapp1.1 + + + + + + + + + diff --git a/samples/dotnet-watch/WatchMultipleProjects/Test/UnitTest1.cs b/samples/dotnet-watch/WatchMultipleProjects/Test/UnitTest1.cs new file mode 100755 index 0000000000..0da9a7f234 --- /dev/null +++ b/samples/dotnet-watch/WatchMultipleProjects/Test/UnitTest1.cs @@ -0,0 +1,17 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Xunit; + +namespace Test +{ + public class UnitTest1 + { + [Fact] + public void Test1() + { + Assert.True(true); + } + } +} diff --git a/samples/dotnet-watch/WatchMultipleProjects/Web/Program.cs b/samples/dotnet-watch/WatchMultipleProjects/Web/Program.cs new file mode 100755 index 0000000000..6a02b1f332 --- /dev/null +++ b/samples/dotnet-watch/WatchMultipleProjects/Web/Program.cs @@ -0,0 +1,28 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; + +namespace Web +{ + public class Program + { + public static void Main(string[] args) + { + var host = new WebHostBuilder() + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .Configure(app => + app.Run(async (context) => + { + await context.Response.WriteAsync("Hello World!"); + })) + .Build(); + + host.Run(); + } + } +} diff --git a/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj b/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj new file mode 100755 index 0000000000..4b6806ff93 --- /dev/null +++ b/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj @@ -0,0 +1,15 @@ + + + + netcoreapp1.1 + + + + + + + + + + + diff --git a/samples/dotnet-watch/WatchMultipleProjects/watch.proj b/samples/dotnet-watch/WatchMultipleProjects/watch.proj new file mode 100644 index 0000000000..fd05a8a4e9 --- /dev/null +++ b/samples/dotnet-watch/WatchMultipleProjects/watch.proj @@ -0,0 +1,19 @@ + + + netcoreapp1.1 + + + + + + + + + + + + + + + + diff --git a/src/Microsoft.DotNet.Watcher.Tools/README.md b/src/Microsoft.DotNet.Watcher.Tools/README.md index 894ef42864..32ecfdcc2a 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/README.md +++ b/src/Microsoft.DotNet.Watcher.Tools/README.md @@ -8,7 +8,7 @@ Install `Microsoft.DotNet.Watcher.Tools` as a `DotNetCliToolReference` to your p ```xml - + ``` @@ -65,9 +65,9 @@ Example: ```xml - + - + ``` diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/README.md b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/README.md index 0d989a980d..ec0c35973a 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/README.md +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/README.md @@ -9,10 +9,10 @@ Install `Microsoft.Extensions.Caching.SqlConfig.Tools` as a `DotNetCliToolRefere ```xml - + ``` ### How To Use -Run `dotnet sql-cache --help` for more information about usage. \ No newline at end of file +Run `dotnet sql-cache --help` for more information about usage. diff --git a/src/Microsoft.Extensions.SecretManager.Tools/README.md b/src/Microsoft.Extensions.SecretManager.Tools/README.md index b930f9dd71..a933ba8c30 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/README.md +++ b/src/Microsoft.Extensions.SecretManager.Tools/README.md @@ -9,10 +9,10 @@ Install `Microsoft.Extensions.SecretManager.Tools` as a `DotNetCliToolReference` ```xml - + ``` ### How To Use -Run `dotnet user-secrets --help` for more information about usage. \ No newline at end of file +Run `dotnet user-secrets --help` for more information about usage. From e3ca1d1a2cd8d1471f5d82103c7bddf95b71a8b8 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 15 Mar 2017 13:47:45 -0700 Subject: [PATCH 0436/1029] Unify dependency versions to one file and remove workarounds --- build/dependencies.props | 5 ++++- .../Microsoft.Extensions.WebEncoders.csproj | 4 ++-- ...icrosoft.AspNetCore.Html.Abstractions.Test.csproj | 11 +++++++---- .../Microsoft.Extensions.WebEncoders.Tests.csproj | 12 +++++++----- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index e704edaec0..5a4c06ce33 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,6 +1,9 @@ - 1.6.1 + 1.2.0-* 4.3.0 + 1.6.1 + 15.0.0 + 2.2.0 diff --git a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj index 70766d649f..d80a4bbcc6 100755 --- a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj +++ b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj @@ -13,8 +13,8 @@ - - + + diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj index 1fe9581c45..8f5f62fd36 100755 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj @@ -10,10 +10,13 @@ - - - - + + + + + + + diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj index 77b807e9dd..f090acc59c 100755 --- a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj +++ b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj @@ -5,15 +5,17 @@ netcoreapp1.1;net452 netcoreapp1.1 - $(PackageTargetFallback);dnxcore50;portable-net451+win8 - - - - + + + + + + + From 832cbdcee8df72ba74d6892542e16312c5d0ef38 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 15 Mar 2017 15:11:25 -0700 Subject: [PATCH 0437/1029] Unify dependency versions to one file --- build/common.props | 1 - build/dependencies.props | 7 ++++++- .../Microsoft.AspNetCore.JsonPatch.csproj | 4 ++-- ...Microsoft.AspNetCore.JsonPatch.Test.csproj | 19 +++++++++++++----- tools/Key.snk | Bin 596 -> 0 bytes 5 files changed, 22 insertions(+), 9 deletions(-) delete mode 100644 tools/Key.snk diff --git a/build/common.props b/build/common.props index 17a0ccb4d8..1d3e64007b 100644 --- a/build/common.props +++ b/build/common.props @@ -1,5 +1,4 @@ - diff --git a/build/dependencies.props b/build/dependencies.props index e704edaec0..4fe028e673 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,6 +1,11 @@ - 1.6.1 + 1.2.0-* 4.3.0 + 9.0.1 + 4.7.1 + 1.6.1 + 15.0.0 + 2.2.0 diff --git a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj index d3d5b01a89..f68aae1aaa 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj +++ b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj @@ -10,8 +10,8 @@ - - + + diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj index e939e5d62c..6f5575c5ee 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj @@ -1,22 +1,31 @@  + + netcoreapp1.1;net452 netcoreapp1.1 + - - - - - + + + + + + + + + + + diff --git a/tools/Key.snk b/tools/Key.snk deleted file mode 100644 index e10e4889c125d3120cd9e81582243d70f7cbb806..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098=Iw=HCsnz~#iVhm& zj%TU(_THUee?3yHBjk$37ysB?i5#7WD$={H zV4B!OxRPrb|8)HPg~A}8P>^=#y<)56#=E&NzcjOtPK~<4n6GHt=K$ro*T(lhby_@U zEk(hLzk1H)0yXj{A_5>fk-TgNoP|q6(tP2xo8zt8i%212CWM#AeCd?`hS|4~L({h~Moo(~vy&3Z z1uI}`fd^*>o=rwbAGymj6RM^pZm(*Kfhs+Y1#`-2JPWZMK8@;ZWCk2+9bX4YP);~fj-BU*R zQPvWv$89!{Rl9wM+zR>_TSkn^voYxA?2G iKnV#iZ6Ah`K>b=@=IjYJXrxL124zR(38)nxe+&q_$QXwJ From 616f7dcfe74d809543125558af6dc984dfb1315c Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 21 Mar 2017 11:46:29 -0700 Subject: [PATCH 0438/1029] Update Travis to macOS Sierra [skip appveyor] --- .travis.yml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index e4c69a2a09..2a46104677 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,6 @@ language: csharp -sudo: required +sudo: false dist: trusty -addons: - apt: - packages: - - gettext - - libcurl4-openssl-dev - - libicu-dev - - libssl-dev - - libunwind8 - - zlib1g env: global: - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true @@ -18,6 +9,7 @@ mono: none os: - linux - osx +osx_image: xcode8.2 branches: only: - master From cac669df3d627831611b698fb9f7ca54f0b7107e Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 21 Mar 2017 12:07:05 -0700 Subject: [PATCH 0439/1029] Update Travis to macOS Sierra [skip appveyor] --- .travis.yml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index e4c69a2a09..2a46104677 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,6 @@ language: csharp -sudo: required +sudo: false dist: trusty -addons: - apt: - packages: - - gettext - - libcurl4-openssl-dev - - libicu-dev - - libssl-dev - - libunwind8 - - zlib1g env: global: - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true @@ -18,6 +9,7 @@ mono: none os: - linux - osx +osx_image: xcode8.2 branches: only: - master From ebd8f61dcbe5909926162d06033a48fae3463123 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 21 Mar 2017 12:14:12 -0700 Subject: [PATCH 0440/1029] Update Travis to macOS Sierra [skip appveyor] --- .travis.yml | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/.travis.yml b/.travis.yml index 56f3837d7e..2a46104677 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,6 @@ language: csharp -sudo: required +sudo: false dist: trusty -addons: - apt: - packages: - - gettext - - libcurl4-openssl-dev - - libicu-dev - - libssl-dev - - libunwind8 - - zlib1g env: global: - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true @@ -18,6 +9,7 @@ mono: none os: - linux - osx +osx_image: xcode8.2 branches: only: - master @@ -28,9 +20,3 @@ before_install: - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; fi script: - ./build.sh -notifications: - webhooks: - secure: "d87o+y2WUx204s8TfSaEuekYudnSyyPaFEXkuzgs3uAyzkKAm/Hx0xcMSuKDqWhYmKaxL7VtgEd2z7mltr2cHZ4oyCrsf6V5v4iI48ojaGykqFXfv8ld6khmLwtdkC32lF2YyuDNL8kUvKNdP9jkrWlpoO/WC6QEqAUxdOuuLo/wLyfrPLbzIvbojwveXbmcwvsfDizLdZdVd88FZSV41h+yBKLnyhpeqRvHG85BTgT/GmVB7Vyjs3yChiS639Aq5DoOP8jBaRdB8Bqs09KibFXzJwDBlKvALIqiwzog3hpd5SVxrgOTCkWbOwqq4TSkahDE425W3vFbmLDANgdfsyAkqgt8daE2BkFTojEHQED+u9CEd8oJVX6FoGnYpuDzge4FVh9iG3HSuKwoVdlONzzew4oJ75iQ+0f67ZNV9oDuScdva/SGb2gYgVUkeJIjDoMxKuaZyhbBT9jRXRBI+LsIjziEhLU/649FjTSmQx0HLpcT7+kaeSmhqT9JffVLidMdvZwhPZsLxPSG9UVBH9G8rdyHXP2e0ZlicHNjjNV6kbDqfDPhHx2/MfZGugsJXjOONKu/5LZduQzmAOysqdLKqkBVkMq2xl7aGV+yVZAtTmZB3nqOWGyKlFC9kLGO+qlJ4tBac26lHCZWTK+4VOAtN5Dag0DkDikgGdZaq78=" - on_success: always - on_failure: always - on_start: always From 1f8e8fae5defe460a6322783e8059c5f7671ddb6 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 21 Mar 2017 15:48:04 -0700 Subject: [PATCH 0441/1029] React to aspnet/Common#205 --- .../Microsoft.DotNet.Watcher.Tools.csproj | 2 +- .../Microsoft.Extensions.Caching.SqlConfig.Tools.csproj | 2 +- .../Microsoft.Extensions.SecretManager.Tools.csproj | 2 +- .../Microsoft.Extensions.Tools.Tests.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj index 5a3606864d..a010d061c6 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj @@ -20,7 +20,7 @@ - + diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj index 51d558612d..ce971c28dd 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj @@ -18,7 +18,7 @@ - + diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj index f51bb14cf0..a9fb82f62c 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj @@ -20,7 +20,7 @@ - + diff --git a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj index 6112fdd935..8d6d2ad328 100644 --- a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj @@ -11,7 +11,7 @@ - + From 849319bcffdf1195fb4057b132b20a43ff235c09 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 21 Mar 2017 16:31:29 -0700 Subject: [PATCH 0442/1029] React to changes in command line utils --- shared/CommandLineApplicationExtensions.cs | 4 ++-- .../Internal/ClearCommand.cs | 4 ++-- .../Internal/ListCommand.cs | 4 ++-- .../Internal/RemoveCommand.cs | 5 ++--- .../Internal/SetCommand.cs | 4 ++-- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/shared/CommandLineApplicationExtensions.cs b/shared/CommandLineApplicationExtensions.cs index b268cea062..6206c861c0 100644 --- a/shared/CommandLineApplicationExtensions.cs +++ b/shared/CommandLineApplicationExtensions.cs @@ -6,7 +6,7 @@ using System.Reflection; namespace Microsoft.Extensions.CommandLineUtils { - public static class CommandLineApplicationExtensions + internal static class CommandLineApplicationExtensions { public static CommandOption HelpOption(this CommandLineApplication app) => app.HelpOption("-?|-h|--help"); @@ -35,4 +35,4 @@ namespace Microsoft.Extensions.CommandLineUtils return versionAttribute; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ClearCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ClearCommand.cs index 2569b6eaf4..108fd542d7 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ClearCommand.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ClearCommand.cs @@ -5,7 +5,7 @@ using Microsoft.Extensions.CommandLineUtils; namespace Microsoft.Extensions.SecretManager.Tools.Internal { - public class ClearCommand : ICommand + internal class ClearCommand : ICommand { public static void Configure(CommandLineApplication command, CommandLineOptions options) { @@ -24,4 +24,4 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal context.SecretStore.Save(); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ListCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ListCommand.cs index 5bfd07db44..bbefab2a13 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ListCommand.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ListCommand.cs @@ -7,7 +7,7 @@ using Newtonsoft.Json.Linq; namespace Microsoft.Extensions.SecretManager.Tools.Internal { - public class ListCommand : ICommand + internal class ListCommand : ICommand { private readonly bool _jsonOutput; @@ -64,4 +64,4 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal context.Reporter.Output("//END"); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs index 60a337ea10..3bc594b149 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs @@ -2,11 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.Extensions.CommandLineUtils; -using Microsoft.Extensions.Tools.Internal; namespace Microsoft.Extensions.SecretManager.Tools.Internal { - public class RemoveCommand : ICommand + internal class RemoveCommand : ICommand { private readonly string _keyName; @@ -46,4 +45,4 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal } } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs index 5c393f3223..5ffc7876eb 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs @@ -9,7 +9,7 @@ using Microsoft.Extensions.Tools.Internal; namespace Microsoft.Extensions.SecretManager.Tools.Internal { - public class SetCommand + internal class SetCommand { public static void Configure(CommandLineApplication command, CommandLineOptions options, IConsole console) { @@ -102,4 +102,4 @@ Examples: } } } -} \ No newline at end of file +} From bac161fdd6f193c5a63584db5a2a5bc8c4729135 Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Tue, 21 Mar 2017 15:41:08 -0700 Subject: [PATCH 0443/1029] Converted test projects to run on netcoreapp2.0 --- build/dependencies.props | 1 + .../Microsoft.AspNetCore.Html.Abstractions.Test.csproj | 4 ++-- .../Microsoft.Extensions.WebEncoders.Tests.csproj | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 5a4c06ce33..12a50aa67f 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,6 +3,7 @@ 1.2.0-* 4.3.0 1.6.1 + 2.0.0-* 15.0.0 2.2.0 diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj index 8f5f62fd36..3e6fcd27cb 100755 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj @@ -3,8 +3,8 @@ - netcoreapp1.1;net452 - netcoreapp1.1 + netcoreapp2.0;net452 + netcoreapp2.0 diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj index f090acc59c..35a8477927 100755 --- a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj +++ b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj @@ -3,8 +3,8 @@ - netcoreapp1.1;net452 - netcoreapp1.1 + netcoreapp2.0;net452 + netcoreapp2.0 From 13219fafa9b669f5b1fd83e8bcd45e39dcd13c7f Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 21 Mar 2017 16:55:42 -0700 Subject: [PATCH 0444/1029] Remove code that moved into CommandLineUtils --- DotNetTools.sln | 7 -- shared/ArgumentEscaper.cs | 107 ------------------ shared/DotNetMuxer.cs | 56 --------- .../DotNetWatcher.cs | 3 +- .../Internal/MsBuildFileSetFactory.cs | 3 +- .../Internal/ProcessRunner.cs | 1 + .../Internal/ProjectIdResolver.cs | 2 +- .../AwaitableProcess.cs | 4 +- ...otNet.Watcher.Tools.FunctionalTests.csproj | 1 + .../Scenario/ProjectToolScenario.cs | 2 +- .../Scenario/WatchableApp.cs | 2 +- .../ConsoleReporterTests.cs | 0 .../ArgumentEscaperTests.cs | 23 ---- .../Microsoft.Extensions.Tools.Tests.csproj | 20 ---- 14 files changed, 11 insertions(+), 220 deletions(-) delete mode 100644 shared/ArgumentEscaper.cs delete mode 100644 shared/DotNetMuxer.cs rename test/{Microsoft.Extensions.Tools.Tests => Microsoft.DotNet.Watcher.Tools.Tests}/ConsoleReporterTests.cs (100%) delete mode 100644 test/Microsoft.Extensions.Tools.Tests/ArgumentEscaperTests.cs delete mode 100644 test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj diff --git a/DotNetTools.sln b/DotNetTools.sln index 8b681184c6..e788eb2226 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -24,8 +24,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Watcher.To EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Caching.SqlConfig.Tools", "src\Microsoft.Extensions.Caching.SqlConfig.Tools\Microsoft.Extensions.Caching.SqlConfig.Tools.csproj", "{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Tools.Tests", "test\Microsoft.Extensions.Tools.Tests\Microsoft.Extensions.Tools.Tests.csproj", "{9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -56,10 +54,6 @@ Global {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.Build.0 = Debug|Any CPU {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.ActiveCfg = Release|Any CPU {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.Build.0 = Release|Any CPU - {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -71,6 +65,5 @@ Global {7B331122-83B1-4F08-A119-DC846959844C} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {8A2E6961-6B12-4A8E-8215-3E7301D52EAC} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {53F3B53D-303A-4DAA-9C38-4F55195FA5B9} = {66517987-2A5A-4330-B130-207039378FD4} - {9295E811-FF0F-E40A-2F9A-0B2C4EBC22AD} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} EndGlobalSection EndGlobal diff --git a/shared/ArgumentEscaper.cs b/shared/ArgumentEscaper.cs deleted file mode 100644 index 91d8ef3086..0000000000 --- a/shared/ArgumentEscaper.cs +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Microsoft.Extensions.Tools.Internal -{ - public static class ArgumentEscaper - { - /// - /// Undo the processing which took place to create string[] args in Main, so that the next process will - /// receive the same string[] args. - /// - /// - /// See https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/ - /// - /// - /// - public static string EscapeAndConcatenate(IEnumerable args) - => string.Join(" ", args.Select(EscapeSingleArg)); - - private static string EscapeSingleArg(string arg) - { - var sb = new StringBuilder(); - - var needsQuotes = ShouldSurroundWithQuotes(arg); - var isQuoted = needsQuotes || IsSurroundedWithQuotes(arg); - - if (needsQuotes) - { - sb.Append('"'); - } - - for (int i = 0; i < arg.Length; ++i) - { - var backslashes = 0; - - // Consume all backslashes - while (i < arg.Length && arg[i] == '\\') - { - backslashes++; - i++; - } - - if (i == arg.Length && isQuoted) - { - // Escape any backslashes at the end of the arg when the argument is also quoted. - // This ensures the outside quote is interpreted as an argument delimiter - sb.Append('\\', 2 * backslashes); - } - else if (i == arg.Length) - { - // At then end of the arg, which isn't quoted, - // just add the backslashes, no need to escape - sb.Append('\\', backslashes); - } - else if (arg[i] == '"') - { - // Escape any preceding backslashes and the quote - sb.Append('\\', (2 * backslashes) + 1); - sb.Append('"'); - } - else - { - // Output any consumed backslashes and the character - sb.Append('\\', backslashes); - sb.Append(arg[i]); - } - } - - if (needsQuotes) - { - sb.Append('"'); - } - - return sb.ToString(); - } - - private static bool ShouldSurroundWithQuotes(string argument) - { - // Don't quote already quoted strings - if (IsSurroundedWithQuotes(argument)) - { - return false; - } - - // Only quote if whitespace exists in the string - return ContainsWhitespace(argument); - } - - private static bool IsSurroundedWithQuotes(string argument) - { - if (argument.Length <= 1) - { - return false; - } - - return argument[0] == '"' && argument[argument.Length - 1] == '"'; - } - - private static bool ContainsWhitespace(string argument) - => argument.IndexOfAny(new [] { ' ', '\t', '\n' }) >= 0; - } -} \ No newline at end of file diff --git a/shared/DotNetMuxer.cs b/shared/DotNetMuxer.cs deleted file mode 100644 index 56e627f192..0000000000 --- a/shared/DotNetMuxer.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Runtime.InteropServices; - -namespace Microsoft.Extensions.Tools.Internal -{ - public static class DotNetMuxer - { - private const string MuxerName = "dotnet"; - - static DotNetMuxer() - { - MuxerPath = TryFindMuxerPath(); - } - - public static string MuxerPath { get; } - - public static string MuxerPathOrDefault() - => MuxerPath ?? MuxerName; - - private static string TryFindMuxerPath() - { - var fileName = MuxerName; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - fileName += ".exe"; - } - - var fxDepsFile = AppContext.GetData("FX_DEPS_FILE") as string; - - if (string.IsNullOrEmpty(fxDepsFile)) - { - return null; - } - - var muxerDir = new FileInfo(fxDepsFile) // Microsoft.NETCore.App.deps.json - .Directory? // (version) - .Parent? // Microsoft.NETCore.App - .Parent? // shared - .Parent; // DOTNET_HOME - - if (muxerDir == null) - { - return null; - } - - var muxer = Path.Combine(muxerDir.FullName, fileName); - return File.Exists(muxer) - ? muxer - : null; - } - } -} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs index fb324de797..66a213a043 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs @@ -1,10 +1,11 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Threading; using System.Threading.Tasks; using Microsoft.DotNet.Watcher.Internal; +using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Tools.Internal; namespace Microsoft.DotNet.Watcher diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs index 1a7e900845..a9fd44cece 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -9,6 +9,7 @@ using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Tools.Internal; namespace Microsoft.DotNet.Watcher.Internal diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs index 592c657675..c866b6db14 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.IO; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Internal; using Microsoft.Extensions.Tools.Internal; diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs index afea6d7a58..83fdde4463 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs @@ -2,10 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; +using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Tools.Internal; namespace Microsoft.Extensions.SecretManager.Tools.Internal diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs index 11583832d0..4834125ebe 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -10,7 +10,7 @@ using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; using Microsoft.Extensions.Internal; -using Microsoft.Extensions.Tools.Internal; +using Microsoft.Extensions.CommandLineUtils; using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj index 4141169368..7e562aba0d 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj @@ -22,6 +22,7 @@ + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs index 1b0f62c7de..5c96f03bfb 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -1,13 +1,13 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Microsoft.Extensions.Tools.Internal; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Threading; +using Microsoft.Extensions.CommandLineUtils; using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs index 271a2832e4..3fdb1872e3 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs @@ -7,7 +7,7 @@ using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; -using Microsoft.Extensions.Tools.Internal; +using Microsoft.Extensions.CommandLineUtils; using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests diff --git a/test/Microsoft.Extensions.Tools.Tests/ConsoleReporterTests.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/ConsoleReporterTests.cs similarity index 100% rename from test/Microsoft.Extensions.Tools.Tests/ConsoleReporterTests.cs rename to test/Microsoft.DotNet.Watcher.Tools.Tests/ConsoleReporterTests.cs diff --git a/test/Microsoft.Extensions.Tools.Tests/ArgumentEscaperTests.cs b/test/Microsoft.Extensions.Tools.Tests/ArgumentEscaperTests.cs deleted file mode 100644 index 78119021d9..0000000000 --- a/test/Microsoft.Extensions.Tools.Tests/ArgumentEscaperTests.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.Extensions.Tools.Internal; -using Xunit; - -namespace Microsoft.Extensions.Tools.Tests -{ - public class ArgumentEscaperTests - { - [Theory] - [InlineData(new[] { "one", "two", "three" }, "one two three")] - [InlineData(new[] { "line1\nline2", "word1\tword2" }, "\"line1\nline2\" \"word1\tword2\"")] - [InlineData(new[] { "with spaces" }, "\"with spaces\"")] - [InlineData(new[] { @"with\backslash" }, @"with\backslash")] - [InlineData(new[] { @"""quotedwith\backslash""" }, @"\""quotedwith\backslash\""")] - [InlineData(new[] { @"C:\Users\" }, @"C:\Users\")] - [InlineData(new[] { @"C:\Program Files\dotnet\" }, @"""C:\Program Files\dotnet\\""")] - [InlineData(new[] { @"backslash\""preceedingquote" }, @"backslash\\\""preceedingquote")] - public void EscapesArguments(string[] args, string expected) - => Assert.Equal(expected, ArgumentEscaper.EscapeAndConcatenate(args)); - } -} \ No newline at end of file diff --git a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj deleted file mode 100644 index 8d6d2ad328..0000000000 --- a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - netcoreapp1.1 - - - - - - - - - - - - - - From f246dd3502b1e2aa976e8b8d668f1d5c5e79f96b Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 16 Mar 2017 12:12:57 -0700 Subject: [PATCH 0445/1029] Upgrade test projects to .NET Core 2.0 --- build/dependencies.props | 2 +- .../Microsoft.DotNet.Watcher.Tools.csproj | 1 + .../Microsoft.Extensions.Caching.SqlConfig.Tools.csproj | 1 + .../Microsoft.Extensions.SecretManager.Tools.csproj | 1 + .../Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj | 2 +- .../TestProjects/AppWithDeps/AppWithDeps.csproj | 4 ++-- .../TestProjects/KitchenSink/KitchenSink.csproj | 3 ++- .../Microsoft.DotNet.Watcher.Tools.Tests.csproj | 2 +- .../Microsoft.Extensions.SecretManager.Tools.Tests.csproj | 2 +- 9 files changed, 11 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 5a4c06ce33..49b3a12446 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -2,7 +2,7 @@ 1.2.0-* 4.3.0 - 1.6.1 + 2.0.0-* 15.0.0 2.2.0 diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj index a010d061c6..3bfe8623a0 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj @@ -4,6 +4,7 @@ netcoreapp1.0 + 1.0.4 dotnet-watch exe Command line tool to watch for source file changes during development and restart the dotnet command. diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj index ce971c28dd..59161d136e 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj @@ -4,6 +4,7 @@ netcoreapp1.0 + 1.0.4 dotnet-sql-cache exe Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching. diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj index a9fb82f62c..baf540b976 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj @@ -4,6 +4,7 @@ netcoreapp1.0 + 1.0.4 dotnet-user-secrets exe Command line tool to manage user secrets for Microsoft.Extensions.Configuration. diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj index 7e562aba0d..05ec2a8723 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj @@ -3,7 +3,7 @@ - netcoreapp1.1 + netcoreapp2.0 $(DefaultItemExcludes);TestProjects\**\* diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj index 8afd97e37b..eced22cfbb 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj @@ -1,7 +1,7 @@ - netcoreapp1.0 + netcoreapp1.1 exe @@ -9,4 +9,4 @@ - \ No newline at end of file + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj index abb9969a56..ab06b4ee0d 100755 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj @@ -2,7 +2,8 @@ Exe - netcoreapp1.1 + netcoreapp2.0 + 2.0.0-* diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj index dfa053ce59..bcb78e5e3b 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj @@ -3,7 +3,7 @@ - netcoreapp1.1 + netcoreapp2.0 diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj index 85ca0d7e69..4f3a3bb12a 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj @@ -3,7 +3,7 @@ - netcoreapp1.1 + netcoreapp2.0 From d2be921ca461505e93a5bae957ea345d1b1b1379 Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Mon, 13 Mar 2017 17:20:01 -0700 Subject: [PATCH 0446/1029] Converted test project to run on netcoreapp2.0 --- build/dependencies.props | 1 + .../Microsoft.AspNetCore.JsonPatch.Test.csproj | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 4fe028e673..b810d63d6e 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -5,6 +5,7 @@ 9.0.1 4.7.1 1.6.1 + 2.0.0-* 15.0.0 2.2.0 diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj index 6f5575c5ee..bb67d98fb1 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj @@ -3,8 +3,8 @@ - netcoreapp1.1;net452 - netcoreapp1.1 + netcoreapp2.0;net452 + netcoreapp2.0 From 9a7abcd902358017bdcfafa4cc5371360758551c Mon Sep 17 00:00:00 2001 From: Pranav K Date: Sun, 12 Mar 2017 15:02:51 -0700 Subject: [PATCH 0447/1029] Remove net451 as a cross-compile target --- .gitignore | 3 ++- .../Microsoft.AspNetCore.Html.Abstractions.Test.csproj | 2 +- .../Microsoft.Extensions.WebEncoders.Tests.csproj | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 980ee002d9..6da3c6a3e9 100644 --- a/.gitignore +++ b/.gitignore @@ -36,4 +36,5 @@ node_modules **/[Cc]ompiler/[Rr]esources/**/*.js *launchSettings.json .build/ -.testPublish/ \ No newline at end of file +.testPublish/ +global.json diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj index 3e6fcd27cb..ac305ecf01 100755 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj @@ -3,7 +3,7 @@ - netcoreapp2.0;net452 + netcoreapp2.0;net46 netcoreapp2.0 diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj index 35a8477927..94bc15926e 100755 --- a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj +++ b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj @@ -3,7 +3,7 @@ - netcoreapp2.0;net452 + netcoreapp2.0;net46 netcoreapp2.0 From f66753cc3c0ec85ea806970a50271acba16b982f Mon Sep 17 00:00:00 2001 From: Pranav K Date: Sun, 12 Mar 2017 15:50:01 -0700 Subject: [PATCH 0448/1029] Remove net451 as a cross-compile target --- .gitignore | 3 ++- .../Microsoft.AspNetCore.JsonPatch.csproj | 7 ++----- .../Microsoft.AspNetCore.JsonPatch.Test.csproj | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 06cfaa0cbe..2e8ec28064 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,5 @@ nuget.exe *.sln.ide node_modules *launchSettings.json -*.orig \ No newline at end of file +*.orig +global.json diff --git a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj index f68aae1aaa..073f7f170f 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj +++ b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj @@ -3,7 +3,7 @@ ASP.NET Core support for JSON PATCH. - net451;netstandard1.3 + netstandard1.3 $(NoWarn);CS1591 true aspnetcore;json;jsonpatch @@ -11,11 +11,8 @@ - - - - + diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj index bb67d98fb1..d8ef8158e3 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj @@ -3,7 +3,7 @@ - netcoreapp2.0;net452 + netcoreapp2.0;net46 netcoreapp2.0 From 0e8b790a0876a183304b6406b38ccee39f6d3745 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Sat, 25 Mar 2017 15:30:49 -0700 Subject: [PATCH 0449/1029] Disable API Check for these command-line tools --- build/common.props | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build/common.props b/build/common.props index 506f240784..26a28ce97a 100644 --- a/build/common.props +++ b/build/common.props @@ -10,6 +10,9 @@ true true $(VersionSuffix)-$(BuildNumber) + + + false From ab6e74f4b4eb19c02156ed85934a29000b4d008f Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Mon, 27 Mar 2017 18:14:22 -0700 Subject: [PATCH 0450/1029] Upgraded Json.NET version to 10.0.1 --- build/dependencies.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/dependencies.props b/build/dependencies.props index b810d63d6e..8aa0110742 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -2,7 +2,7 @@ 1.2.0-* 4.3.0 - 9.0.1 + 10.0.1 4.7.1 1.6.1 2.0.0-* From e4e62b31561536519ba8489f8fa568f76e50567a Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 29 Mar 2017 11:30:32 -0700 Subject: [PATCH 0451/1029] Updating to 2.0.0 Internal.AspNetCore.Sdk --- build/common.props | 2 +- build/dependencies.props | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/build/common.props b/build/common.props index 26a28ce97a..73ecc03dbf 100644 --- a/build/common.props +++ b/build/common.props @@ -16,7 +16,7 @@ - + diff --git a/build/dependencies.props b/build/dependencies.props index 49b3a12446..a7462bdaec 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -2,8 +2,9 @@ 1.2.0-* 4.3.0 + 2.0.0-* 2.0.0-* 15.0.0 2.2.0 - + \ No newline at end of file From 2e3c35b863ab242a2c948911225537965483740c Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 29 Mar 2017 11:30:33 -0700 Subject: [PATCH 0452/1029] Updating to 2.0.0 Internal.AspNetCore.Sdk --- build/common.props | 2 +- build/dependencies.props | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/build/common.props b/build/common.props index de08271afe..647ef2d1e9 100644 --- a/build/common.props +++ b/build/common.props @@ -12,7 +12,7 @@ - + diff --git a/build/dependencies.props b/build/dependencies.props index 12a50aa67f..8c81df7f34 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -2,9 +2,10 @@ 1.2.0-* 4.3.0 + 2.0.0-* 1.6.1 2.0.0-* 15.0.0 2.2.0 - + \ No newline at end of file From 99ff496e7128b3b51968c0971459143df1321205 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 29 Mar 2017 11:30:34 -0700 Subject: [PATCH 0453/1029] Updating to 2.0.0 Internal.AspNetCore.Sdk --- build/common.props | 2 +- build/dependencies.props | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/build/common.props b/build/common.props index 1d3e64007b..ffe4d99846 100644 --- a/build/common.props +++ b/build/common.props @@ -13,7 +13,7 @@ - + diff --git a/build/dependencies.props b/build/dependencies.props index 8aa0110742..72d6874ffd 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -2,6 +2,7 @@ 1.2.0-* 4.3.0 + 2.0.0-* 10.0.1 4.7.1 1.6.1 @@ -9,4 +10,4 @@ 15.0.0 2.2.0 - + \ No newline at end of file From 0e6db5af0f82d85273b800660045d2696e6302e1 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Wed, 29 Mar 2017 14:32:35 -0700 Subject: [PATCH 0454/1029] Bump to netstandard1.1 for options --- .../Microsoft.Extensions.WebEncoders.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj index d80a4bbcc6..773011fef5 100755 --- a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj +++ b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj @@ -5,7 +5,7 @@ Microsoft .NET Extensions Contains registration and configuration APIs to add the core framework encoders to a dependency injection container. - netstandard1.0 + netstandard1.1 $(NoWarn);CS1591 true true From 023b1d7db86356237744a5f7b5ab86c72d2f45f6 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 3 Apr 2017 21:41:09 -0700 Subject: [PATCH 0455/1029] Updating versions to 2.0.0-preview1 --- build/dependencies.props | 2 +- version.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index a7462bdaec..904c96d3c1 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,6 +1,6 @@ - 1.2.0-* + 2.0.0-* 4.3.0 2.0.0-* 2.0.0-* diff --git a/version.props b/version.props index 29f91e170d..e5b7eb2dbe 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ - 1.2.0 + 2.0.0 preview1 From ebc2c99aaf71e820d3acef6f89986b2e854279d1 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 3 Apr 2017 21:41:10 -0700 Subject: [PATCH 0456/1029] Updating versions to 2.0.0-preview1 --- build/dependencies.props | 2 +- version.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 8c81df7f34..1973fc186f 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,6 +1,6 @@ - 1.2.0-* + 2.0.0-* 4.3.0 2.0.0-* 1.6.1 diff --git a/version.props b/version.props index 17fd5ac36d..c7150e64f4 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ - 1.2.0 + 2.0.0 preview1 From 290fd0a28da2b4edebb74709fed71517cfcc6778 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 3 Apr 2017 21:41:10 -0700 Subject: [PATCH 0457/1029] Updating versions to 2.0.0-preview1 --- build/dependencies.props | 2 +- version.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 72d6874ffd..5f6c92189c 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,6 +1,6 @@ - 1.2.0-* + 2.0.0-* 4.3.0 2.0.0-* 10.0.1 diff --git a/version.props b/version.props index e77c8d9c38..44cb2290b9 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ - 1.2.0 + 2.0.0 preview1 \ No newline at end of file From cd5fa7ec1f809f6d68c28dd407b105cc83264bc0 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 11 Apr 2017 14:27:56 -0700 Subject: [PATCH 0458/1029] Update package verion to 1.0.1 rtm and pin build dependencies and tools --- build.ps1 | 2 +- build.sh | 2 +- build/common.props | 2 +- global.json | 5 +++++ .../Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj | 6 +++--- .../Microsoft.DotNet.Watcher.Tools.Tests.csproj | 6 +++--- .../Microsoft.Extensions.SecretManager.Tools.Tests.csproj | 6 +++--- .../Microsoft.Extensions.Tools.Tests.csproj | 6 +++--- version.props | 3 ++- 9 files changed, 22 insertions(+), 16 deletions(-) create mode 100644 global.json diff --git a/build.ps1 b/build.ps1 index 5bf0e2c113..557a79ebc6 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.0.1-msbuild-tools.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index b0bcadb579..e22a9d1681 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/1.0.1-msbuild-tools.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi diff --git a/build/common.props b/build/common.props index 506f240784..14cf5b7835 100644 --- a/build/common.props +++ b/build/common.props @@ -13,7 +13,7 @@ - + diff --git a/global.json b/global.json new file mode 100644 index 0000000000..68d693de30 --- /dev/null +++ b/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "version": "1.0.1" + } +} diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj index 19088145f1..b9cbaa07b0 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj @@ -22,9 +22,9 @@ - - - + + + diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj index 285d18f0cf..4e593b0c3f 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj @@ -15,9 +15,9 @@ - - - + + + diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj index 9a9dc14b24..6e03aa2b6c 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj @@ -12,9 +12,9 @@ - - - + + + diff --git a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj index 0c151d0a68..03dfc1f9b4 100644 --- a/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.Tools.Tests/Microsoft.Extensions.Tools.Tests.csproj @@ -11,9 +11,9 @@ - - - + + + diff --git a/version.props b/version.props index e143c25f8e..5726661ca3 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,8 @@ + 1.0.1 1.0.1 - alpha + rtm From 734c735fb5559ee49850cde3e40e03e9d9164cdf Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 10 Mar 2017 09:18:38 -0800 Subject: [PATCH 0459/1029] Simplify console output and fix color output on CMD --- appveyor.yml | 2 +- shared/IConsole.cs | 2 + shared/PhysicalConsole.cs | 7 ++ shared/Reporting/ColorFormatter.cs | 57 --------------- shared/Reporting/CompositeFormatter.cs | 26 ------- shared/Reporting/ConditionalFormatter.cs | 24 ------- shared/Reporting/ConsoleReporter.cs | 72 +++++++++++++++++++ shared/Reporting/DefaultFormatter.cs | 14 ---- shared/Reporting/FormatterBuilder.cs | 46 ------------ shared/Reporting/FormattingReporter.cs | 62 ---------------- shared/Reporting/IFormatter.cs | 10 --- shared/Reporting/PrefixFormatter.cs | 20 ------ shared/Reporting/ReporterBuilder.cs | 65 ----------------- .../PrefixConsoleReporter.cs | 32 +++++++++ src/Microsoft.DotNet.Watcher.Tools/Program.cs | 47 +----------- .../Program.cs | 31 +------- .../Program.cs | 30 +------- ...porterTests.cs => ConsoleReporterTests.cs} | 36 +++------- test/Shared/TestConsole.cs | 5 ++ 19 files changed, 132 insertions(+), 456 deletions(-) delete mode 100644 shared/Reporting/ColorFormatter.cs delete mode 100644 shared/Reporting/CompositeFormatter.cs delete mode 100644 shared/Reporting/ConditionalFormatter.cs create mode 100644 shared/Reporting/ConsoleReporter.cs delete mode 100644 shared/Reporting/DefaultFormatter.cs delete mode 100644 shared/Reporting/FormatterBuilder.cs delete mode 100644 shared/Reporting/FormattingReporter.cs delete mode 100644 shared/Reporting/IFormatter.cs delete mode 100644 shared/Reporting/PrefixFormatter.cs delete mode 100644 shared/Reporting/ReporterBuilder.cs create mode 100644 src/Microsoft.DotNet.Watcher.Tools/PrefixConsoleReporter.cs rename test/Microsoft.Extensions.Tools.Tests/{ReporterTests.cs => ConsoleReporterTests.cs} (68%) diff --git a/appveyor.yml b/appveyor.yml index 3f828ce38e..1041615c68 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,4 +11,4 @@ build_script: clone_depth: 1 test: off deploy: off -os: Visual Studio 2017 RC +os: Visual Studio 2017 diff --git a/shared/IConsole.cs b/shared/IConsole.cs index 20bb36e7f9..7216c267a0 100644 --- a/shared/IConsole.cs +++ b/shared/IConsole.cs @@ -15,5 +15,7 @@ namespace Microsoft.Extensions.Tools.Internal bool IsInputRedirected { get; } bool IsOutputRedirected { get; } bool IsErrorRedirected { get; } + ConsoleColor ForegroundColor { get; set; } + void ResetColor(); } } diff --git a/shared/PhysicalConsole.cs b/shared/PhysicalConsole.cs index bdfb60ac0e..9a93323d5c 100644 --- a/shared/PhysicalConsole.cs +++ b/shared/PhysicalConsole.cs @@ -25,5 +25,12 @@ namespace Microsoft.Extensions.Tools.Internal public bool IsInputRedirected => Console.IsInputRedirected; public bool IsOutputRedirected => Console.IsOutputRedirected; public bool IsErrorRedirected => Console.IsErrorRedirected; + public ConsoleColor ForegroundColor + { + get => Console.ForegroundColor; + set => Console.ForegroundColor = value; + } + + public void ResetColor() => Console.ResetColor(); } } diff --git a/shared/Reporting/ColorFormatter.cs b/shared/Reporting/ColorFormatter.cs deleted file mode 100644 index 5675d5b367..0000000000 --- a/shared/Reporting/ColorFormatter.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; - -namespace Microsoft.Extensions.Tools.Internal -{ - public class ColorFormatter : IFormatter - { - // resets foreground color only - private const string ResetColor = "\x1B[39m"; - - private static readonly IDictionary AnsiColorCodes - = new Dictionary - { - {ConsoleColor.Black, 30}, - {ConsoleColor.DarkRed, 31}, - {ConsoleColor.DarkGreen, 32}, - {ConsoleColor.DarkYellow, 33}, - {ConsoleColor.DarkBlue, 34}, - {ConsoleColor.DarkMagenta, 35}, - {ConsoleColor.DarkCyan, 36}, - {ConsoleColor.Gray, 37}, - {ConsoleColor.DarkGray, 90}, - {ConsoleColor.Red, 91}, - {ConsoleColor.Green, 92}, - {ConsoleColor.Yellow, 93}, - {ConsoleColor.Blue, 94}, - {ConsoleColor.Magenta, 95}, - {ConsoleColor.Cyan, 96}, - {ConsoleColor.White, 97}, - }; - - private readonly string _prefix; - - public ColorFormatter(ConsoleColor color) - { - _prefix = GetAnsiCode(color); - } - - public string Format(string text) - => text?.Length > 0 - ? $"{_prefix}{text}{ResetColor}" - : text; - - private static string GetAnsiCode(ConsoleColor color) - { - int code; - if (!AnsiColorCodes.TryGetValue(color, out code)) - { - throw new ArgumentOutOfRangeException(nameof(color), color, null); - } - return $"\x1B[{code}m"; - } - } -} \ No newline at end of file diff --git a/shared/Reporting/CompositeFormatter.cs b/shared/Reporting/CompositeFormatter.cs deleted file mode 100644 index 63aa074760..0000000000 --- a/shared/Reporting/CompositeFormatter.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.Extensions.Tools.Internal -{ - public class CompositeFormatter : IFormatter - { - private readonly IFormatter[] _formatters; - - public CompositeFormatter(IFormatter[] formatters) - { - Ensure.NotNull(formatters, nameof(formatters)); - _formatters = formatters; - } - - public string Format(string text) - { - foreach (var formatter in _formatters) - { - text = formatter.Format(text); - } - - return text; - } - } -} \ No newline at end of file diff --git a/shared/Reporting/ConditionalFormatter.cs b/shared/Reporting/ConditionalFormatter.cs deleted file mode 100644 index b0881f2bac..0000000000 --- a/shared/Reporting/ConditionalFormatter.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; - -namespace Microsoft.Extensions.Tools.Internal -{ - public class ConditionalFormatter : IFormatter - { - private readonly Func _predicate; - - public ConditionalFormatter(Func predicate) - { - Ensure.NotNull(predicate, nameof(predicate)); - - _predicate = predicate; - } - - public string Format(string text) - => _predicate() - ? text - : null; - } -} \ No newline at end of file diff --git a/shared/Reporting/ConsoleReporter.cs b/shared/Reporting/ConsoleReporter.cs new file mode 100644 index 0000000000..ffcd1e8705 --- /dev/null +++ b/shared/Reporting/ConsoleReporter.cs @@ -0,0 +1,72 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; + +namespace Microsoft.Extensions.Tools.Internal +{ + public class ConsoleReporter : IReporter + { + private object _writeLock = new object(); + + public ConsoleReporter(IConsole console) + : this(console, verbose: false, quiet: false) + { } + + public ConsoleReporter(IConsole console, bool verbose, bool quiet) + { + Ensure.NotNull(console, nameof(console)); + + Console = console; + IsVerbose = verbose; + IsQuiet = quiet; + } + + protected IConsole Console { get; } + public bool IsVerbose { get; set; } + public bool IsQuiet { get; set; } + + protected virtual void WriteLine(TextWriter writer, string message, ConsoleColor? color) + { + lock (_writeLock) + { + if (color.HasValue) + { + Console.ForegroundColor = color.Value; + } + + writer.WriteLine(message); + + if (color.HasValue) + { + Console.ResetColor(); + } + } + } + + public virtual void Error(string message) + => WriteLine(Console.Error, message, ConsoleColor.Red); + public virtual void Warn(string message) + => WriteLine(Console.Out, message, ConsoleColor.Yellow); + + public virtual void Output(string message) + { + if (IsQuiet) + { + return; + } + WriteLine(Console.Out, message, color: null); + } + + public virtual void Verbose(string message) + { + if (!IsVerbose) + { + return; + } + + WriteLine(Console.Out, message, ConsoleColor.DarkGray); + } + } +} diff --git a/shared/Reporting/DefaultFormatter.cs b/shared/Reporting/DefaultFormatter.cs deleted file mode 100644 index 4d4348b000..0000000000 --- a/shared/Reporting/DefaultFormatter.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.Extensions.Tools.Internal -{ - public class DefaultFormatter : IFormatter - { - public static readonly IFormatter Instance = new DefaultFormatter(); - - private DefaultFormatter() {} - public string Format(string text) - => text; - } -} \ No newline at end of file diff --git a/shared/Reporting/FormatterBuilder.cs b/shared/Reporting/FormatterBuilder.cs deleted file mode 100644 index 3d3491487c..0000000000 --- a/shared/Reporting/FormatterBuilder.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; - -namespace Microsoft.Extensions.Tools.Internal -{ - public class FormatterBuilder - { - private readonly List _formatters = new List(); - - public FormatterBuilder WithColor(ConsoleColor color) - { - _formatters.Add(new ColorFormatter(color)); - return this; - } - - public FormatterBuilder WithPrefix(string prefix) - { - _formatters.Add(new PrefixFormatter(prefix)); - return this; - } - - public FormatterBuilder When(Func predicate) - { - _formatters.Add(new ConditionalFormatter(predicate)); - return this; - } - - public IFormatter Build() - { - if (_formatters.Count == 0) - { - return DefaultFormatter.Instance; - } - - if (_formatters.Count == 1) - { - return _formatters[0]; - } - - return new CompositeFormatter(_formatters.ToArray()); - } - } -} \ No newline at end of file diff --git a/shared/Reporting/FormattingReporter.cs b/shared/Reporting/FormattingReporter.cs deleted file mode 100644 index 0c49c0d817..0000000000 --- a/shared/Reporting/FormattingReporter.cs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.IO; - -namespace Microsoft.Extensions.Tools.Internal -{ - public class FormattingReporter : IReporter - { - private readonly object _writelock = new object(); - private readonly IConsole _console; - private readonly IFormatter _verbose; - private readonly IFormatter _warn; - private readonly IFormatter _output; - private readonly IFormatter _error; - - public FormattingReporter(IConsole console, - IFormatter verbose, - IFormatter output, - IFormatter warn, - IFormatter error) - { - Ensure.NotNull(console, nameof(console)); - Ensure.NotNull(verbose, nameof(verbose)); - Ensure.NotNull(output, nameof(output)); - Ensure.NotNull(warn, nameof(warn)); - Ensure.NotNull(error, nameof(error)); - - _console = console; - _verbose = verbose; - _output = output; - _warn = warn; - _error = error; - } - - - public void Verbose(string message) - => Write(_console.Out, _verbose.Format(message)); - - public void Output(string message) - => Write(_console.Out, _output.Format(message)); - - public void Warn(string message) - => Write(_console.Out, _warn.Format(message)); - - public void Error(string message) - => Write(_console.Error, _error.Format(message)); - - private void Write(TextWriter writer, string message) - { - if (message == null) - { - return; - } - - lock (_writelock) - { - writer.WriteLine(message); - } - } - } -} \ No newline at end of file diff --git a/shared/Reporting/IFormatter.cs b/shared/Reporting/IFormatter.cs deleted file mode 100644 index 9094728632..0000000000 --- a/shared/Reporting/IFormatter.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.Extensions.Tools.Internal -{ - public interface IFormatter - { - string Format(string text); - } -} \ No newline at end of file diff --git a/shared/Reporting/PrefixFormatter.cs b/shared/Reporting/PrefixFormatter.cs deleted file mode 100644 index b9602c41ca..0000000000 --- a/shared/Reporting/PrefixFormatter.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.Extensions.Tools.Internal -{ - public class PrefixFormatter : IFormatter - { - private readonly string _prefix; - - public PrefixFormatter(string prefix) - { - Ensure.NotNullOrEmpty(prefix, nameof(prefix)); - - _prefix = prefix; - } - - public string Format(string text) - => _prefix + text; - } -} \ No newline at end of file diff --git a/shared/Reporting/ReporterBuilder.cs b/shared/Reporting/ReporterBuilder.cs deleted file mode 100644 index 9283642041..0000000000 --- a/shared/Reporting/ReporterBuilder.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; - -namespace Microsoft.Extensions.Tools.Internal -{ - public class ReporterBuilder - { - private readonly FormatterBuilder _verbose = new FormatterBuilder(); - private readonly FormatterBuilder _output = new FormatterBuilder(); - private readonly FormatterBuilder _warn = new FormatterBuilder(); - private readonly FormatterBuilder _error = new FormatterBuilder(); - private IConsole _console; - - public ReporterBuilder WithConsole(IConsole console) - { - _console = console; - return this; - } - - public FormatterBuilder Verbose() => _verbose; - public FormatterBuilder Output() => _output; - public FormatterBuilder Warn() => _warn; - public FormatterBuilder Error() => _error; - - public ReporterBuilder Verbose(Action configure) - { - configure(_verbose); - return this; - } - - public ReporterBuilder Output(Action configure) - { - configure(_output); - return this; - } - - public ReporterBuilder Warn(Action configure) - { - configure(_warn); - return this; - } - - public ReporterBuilder Error(Action configure) - { - configure(_error); - return this; - } - - public IReporter Build() - { - if (_console == null) - { - throw new InvalidOperationException($"Cannot build without first calling {nameof(WithConsole)}"); - } - - return new FormattingReporter(_console, - _verbose.Build(), - _output.Build(), - _warn.Build(), - _error.Build()); - } - } -} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/PrefixConsoleReporter.cs b/src/Microsoft.DotNet.Watcher.Tools/PrefixConsoleReporter.cs new file mode 100644 index 0000000000..b2453276ef --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/PrefixConsoleReporter.cs @@ -0,0 +1,32 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using Microsoft.Extensions.Tools.Internal; + +namespace Microsoft.DotNet.Watcher +{ + public class PrefixConsoleReporter : ConsoleReporter + { + private object _lock = new object(); + + public PrefixConsoleReporter(IConsole console, bool verbose, bool quiet) + : base(console, verbose, quiet) + { } + + protected override void WriteLine(TextWriter writer, string message, ConsoleColor? color) + { + const string prefix = "watch : "; + + lock (_lock) + { + Console.ForegroundColor = ConsoleColor.DarkGray; + writer.Write(prefix); + Console.ResetColor(); + + base.WriteLine(writer, message, color); + } + } + } +} diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index 9d18757d3c..261a92f31d 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -176,51 +176,6 @@ namespace Microsoft.DotNet.Watcher } private static IReporter CreateReporter(bool verbose, bool quiet, IConsole console) - { - const string prefix = "watch : "; - var colorPrefix = new ColorFormatter(ConsoleColor.DarkGray).Format(prefix); - - return new ReporterBuilder() - .WithConsole(console) - .Verbose(f => - { - if (console.IsOutputRedirected) - { - f.WithPrefix(prefix); - } - else - { - f.WithColor(ConsoleColor.DarkGray).WithPrefix(colorPrefix); - } - - f.When(() => verbose || CliContext.IsGlobalVerbose()); - }) - .Output(f => f - .WithPrefix(console.IsOutputRedirected ? prefix : colorPrefix) - .When(() => !quiet)) - .Warn(f => - { - if (console.IsOutputRedirected) - { - f.WithPrefix(prefix); - } - else - { - f.WithColor(ConsoleColor.Yellow).WithPrefix(colorPrefix); - } - }) - .Error(f => - { - if (console.IsOutputRedirected) - { - f.WithPrefix(prefix); - } - else - { - f.WithColor(ConsoleColor.Red).WithPrefix(colorPrefix); - } - }) - .Build(); - } + => new PrefixConsoleReporter(console, verbose || CliContext.IsGlobalVerbose(), quiet); } } diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs index 190335aded..874244f603 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs @@ -99,34 +99,7 @@ namespace Microsoft.Extensions.Caching.SqlConfig.Tools } private IReporter CreateReporter(bool verbose) - { - return new ReporterBuilder() - .WithConsole(_console) - .Verbose(f => - { - f.When(() => verbose); - if (!_console.IsOutputRedirected) - { - f.WithColor(ConsoleColor.DarkGray); - } - }) - .Warn(f => - { - if (!_console.IsOutputRedirected) - { - f.WithColor(ConsoleColor.Yellow); - } - }) - .Error(f => - { - if (!_console.IsErrorRedirected) - { - f.WithColor(ConsoleColor.Red); - } - }) - .Build(); - } - + => new ConsoleReporter(_console, verbose, quiet: false); private int CreateTableAndIndexes(IReporter reporter) { ValidateConnectionString(); @@ -197,4 +170,4 @@ namespace Microsoft.Extensions.Caching.SqlConfig.Tools } } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs index 667c16b27f..187e40128f 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Program.cs @@ -89,33 +89,7 @@ namespace Microsoft.Extensions.SecretManager.Tools } private IReporter CreateReporter(bool verbose) - { - return new ReporterBuilder() - .WithConsole(_console) - .Verbose(f => - { - f.When(() => verbose); - if (!_console.IsOutputRedirected) - { - f.WithColor(ConsoleColor.DarkGray); - } - }) - .Warn(f => - { - if (!_console.IsOutputRedirected) - { - f.WithColor(ConsoleColor.Yellow); - } - }) - .Error(f => - { - if (!_console.IsErrorRedirected) - { - f.WithColor(ConsoleColor.Red); - } - }) - .Build(); - } + => new ConsoleReporter(_console, verbose, quiet: false); internal string ResolveId(CommandLineOptions options, IReporter reporter) { @@ -128,4 +102,4 @@ namespace Microsoft.Extensions.SecretManager.Tools return resolver.Resolve(options.Project, options.Configuration); } } -} \ No newline at end of file +} diff --git a/test/Microsoft.Extensions.Tools.Tests/ReporterTests.cs b/test/Microsoft.Extensions.Tools.Tests/ConsoleReporterTests.cs similarity index 68% rename from test/Microsoft.Extensions.Tools.Tests/ReporterTests.cs rename to test/Microsoft.Extensions.Tools.Tests/ConsoleReporterTests.cs index 5c6cde5109..34cfd42850 100644 --- a/test/Microsoft.Extensions.Tools.Tests/ReporterTests.cs +++ b/test/Microsoft.Extensions.Tools.Tests/ConsoleReporterTests.cs @@ -13,30 +13,11 @@ namespace Microsoft.Extensions.Tools.Tests { private static readonly string EOL = Environment.NewLine; - [Theory] - [InlineData(ConsoleColor.DarkGray, "\x1B[90m")] - [InlineData(ConsoleColor.Red, "\x1B[91m")] - [InlineData(ConsoleColor.Yellow, "\x1B[93m")] - public void WrapsWithAnsiColorCode(ConsoleColor color, string code) - { - Assert.Equal($"{code}sample\x1B[39m", new ColorFormatter(color).Format("sample")); - } - - [Fact] - public void SkipsColorCodesForEmptyOrNullInput() - { - var formatter = new ColorFormatter(ConsoleColor.Blue); - Assert.Empty(formatter.Format(string.Empty)); - Assert.Null(formatter.Format(null)); - } - [Fact] public void WritesToStandardStreams() { var testConsole = new TestConsole(); - var reporter = new FormattingReporter(testConsole, - DefaultFormatter.Instance, DefaultFormatter.Instance, - DefaultFormatter.Instance, DefaultFormatter.Instance); + var reporter = new ConsoleReporter(testConsole, verbose: true, quiet: false); // stdout reporter.Verbose("verbose"); @@ -57,13 +38,6 @@ namespace Microsoft.Extensions.Tools.Tests testConsole.Clear(); } - [Fact] - public void FailsToBuildWithoutConsole() - { - Assert.Throws( - () => new ReporterBuilder().Build()); - } - private class TestConsole : IConsole { private readonly StringBuilder _out; @@ -92,12 +66,18 @@ namespace Microsoft.Extensions.Tools.Tests _error.Clear(); } + public void ResetColor() + { + ForegroundColor = default(ConsoleColor); + } + public TextWriter Out { get; } public TextWriter Error { get; } public TextReader In { get; } public bool IsInputRedirected { get; } public bool IsOutputRedirected { get; } public bool IsErrorRedirected { get; } + public ConsoleColor ForegroundColor { get; set; } } } -} \ No newline at end of file +} diff --git a/test/Shared/TestConsole.cs b/test/Shared/TestConsole.cs index fd98ff529b..6804c0265e 100644 --- a/test/Shared/TestConsole.cs +++ b/test/Shared/TestConsole.cs @@ -27,6 +27,7 @@ namespace Microsoft.Extensions.Tools.Internal public bool IsInputRedirected { get; set; } = false; public bool IsOutputRedirected { get; } = false; public bool IsErrorRedirected { get; } = false; + public ConsoleColor ForegroundColor { get; set; } public ConsoleCancelEventArgs ConsoleCancelKey() { @@ -39,6 +40,10 @@ namespace Microsoft.Extensions.Tools.Internal return args; } + public void ResetColor() + { + } + private class TestOutputWriter : TextWriter { private readonly ITestOutputHelper _output; From e0e972e98ca04adaf94d1889c9b262eede80fe81 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 11 Apr 2017 14:52:39 -0700 Subject: [PATCH 0460/1029] Update travis and appveyor build settings to include rel branches --- .travis.yml | 24 ++++-------------------- appveyor.yml | 1 + 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/.travis.yml b/.travis.yml index 058b4421ec..abf89971b2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,39 +1,23 @@ language: csharp -sudo: required +sudo: false dist: trusty -addons: - apt: - packages: - - gettext - - libcurl4-openssl-dev - - libicu-dev - - libssl-dev - - libunwind8 - - zlib1g env: global: - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - DOTNET_CLI_TELEMETRY_OPTOUT: 1 -mono: - - 4.0.5 +mono: none os: - linux - osx -osx_image: xcode7.3 +osx_image: xcode8.2 branches: only: - master - release - dev + - /^rel\// - /^(.*\/)?ci-.*$/ - - /^feature\// before_install: - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; fi script: - ./build.sh -notifications: - webhooks: - secure: "dhjfYLtihxx3zDdj0TLMJjiN4YJ37Qu0L9ySx7ek+YsfOAqKPHUsI6JNDtChauQxUB2NoL/i80+47oHhMelPyXniu1xA0MWaHV8bddZHzNQs1N8vGjjPmtbC5DQ7jmy+p7Xa5+ZscZ9NWEvJRqBInNdqugDAstDEIWbC35bq8H9t+6tZYu1sJctp1zF/k/w4OjJUoI1ZNLuusYIB1E+G/irvVT2x4GOC2QY3wXM4lJ2ORcZE9NgUBLNx/Hy5Rst5i4zO/mrFkYM/wOY6bAM6/gjjanK+d1wQnD9HuZH1ZVQqJRH3lveurYq9ih4zxV8MbW3FdLL1cXswEZbUBeqHlxVE32KwWF18nFUwdmrNQebnYnrZ/VWsa4pl+bOFNy2nomI3ibJ4F4+RwqTPXXE13qCr0CsC5RKu5bVQTpi0t4CKlUMsVlevN2jJcmAA641bnETNTDwk5WdT7Mjf9Pnn+krLZ7im9li3Plc/d8ynR1oiRzwFdp3u/9m3Oc8K+zMsNO5IOxHul9WsWbIkh3sNecqKHPSyVHB4FgdUoQ65xpc0887YKorbuBTOnlZugP8M/FmowkcwLo5xDD7kchkxyq9X8dPjej+tzpTsNVJjrOg4LP+nKxmOa+qc1r62eF0GdnIjwU30y6NdfvBCXoQJE1y063/zyGPIxSfCRmVzq4A=" - on_success: always - on_failure: always - on_start: always diff --git a/appveyor.yml b/appveyor.yml index 1041615c68..778c4c4e0d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,6 +4,7 @@ branches: only: - master - release + - /^rel\/.*/ - dev - /^(.*\/)?ci-.*$/ build_script: From 1e61428f8e679a050b57932bfecc46fdbac75021 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 24 Apr 2017 10:39:27 -0700 Subject: [PATCH 0461/1029] Lift packages to target .NET Core 2.0 --- .../Microsoft.DotNet.Watcher.Tools.csproj | 3 +-- .../Microsoft.Extensions.Caching.SqlConfig.Tools.csproj | 3 +-- .../Microsoft.Extensions.SecretManager.Tools.csproj | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj index 3bfe8623a0..f124d96c03 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj @@ -3,8 +3,7 @@ - netcoreapp1.0 - 1.0.4 + netcoreapp2.0 dotnet-watch exe Command line tool to watch for source file changes during development and restart the dotnet command. diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj index 59161d136e..2d9e0cfb74 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj @@ -3,8 +3,7 @@ - netcoreapp1.0 - 1.0.4 + netcoreapp2.0 dotnet-sql-cache exe Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching. diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj index baf540b976..b73f1f8838 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj @@ -3,8 +3,7 @@ - netcoreapp1.0 - 1.0.4 + netcoreapp2.0 dotnet-user-secrets exe Command line tool to manage user secrets for Microsoft.Extensions.Configuration. From 2c2992b465fbd929891086bf1614139e4f5c438e Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 25 Apr 2017 11:04:08 -0700 Subject: [PATCH 0462/1029] Use Bundled NETStandard.Library \ NETCoreApp versions instead of explicitly specifying one --- build/dependencies.props | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 1973fc186f..01387147a4 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,9 +3,7 @@ 2.0.0-* 4.3.0 2.0.0-* - 1.6.1 - 2.0.0-* 15.0.0 2.2.0 - \ No newline at end of file + From e61f7a591ce3d5c05ef3246dfd2ea45662dbb277 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 25 Apr 2017 11:04:08 -0700 Subject: [PATCH 0463/1029] Use Bundled NETStandard.Library \ NETCoreApp versions instead of explicitly specifying one --- build/common.props | 2 +- build/dependencies.props | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/build/common.props b/build/common.props index ffe4d99846..a2698f3553 100644 --- a/build/common.props +++ b/build/common.props @@ -17,7 +17,7 @@ - + diff --git a/build/dependencies.props b/build/dependencies.props index 5f6c92189c..ac44ce3323 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -5,9 +5,7 @@ 2.0.0-* 10.0.1 4.7.1 - 1.6.1 - 2.0.0-* 15.0.0 2.2.0 - \ No newline at end of file + From d3d88481e2cc74ca01d1060ed041448d661fe3a9 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 25 Apr 2017 11:04:07 -0700 Subject: [PATCH 0464/1029] Use Bundled NETStandard.Library \ NETCoreApp versions instead of explicitly specifying one --- build/dependencies.props | 3 +-- .../TestProjects/KitchenSink/KitchenSink.csproj | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 904c96d3c1..01387147a4 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,8 +3,7 @@ 2.0.0-* 4.3.0 2.0.0-* - 2.0.0-* 15.0.0 2.2.0 - \ No newline at end of file + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj index ab06b4ee0d..ce1697ae88 100755 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj @@ -3,7 +3,6 @@ Exe netcoreapp2.0 - 2.0.0-* From 08799573e063e53e444c2f909164fc497f9a0b55 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 25 Apr 2017 22:01:50 -0700 Subject: [PATCH 0465/1029] Branching for 2.0.0-preview1 --- NuGet.config | 4 ++-- build.ps1 | 2 +- build.sh | 2 +- build/dependencies.props | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/NuGet.config b/NuGet.config index 93f1ac47df..fa4304af9c 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + - + diff --git a/build.ps1 b/build.ps1 index 5bf0e2c113..225b1fe450 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/2.0.0-preview1.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index b0bcadb579..702b25c636 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/2.0.0-preview1.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi diff --git a/build/dependencies.props b/build/dependencies.props index 01387147a4..c7741b724b 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,6 +1,6 @@ - 2.0.0-* + 2.0.0-preview1-* 4.3.0 2.0.0-* 15.0.0 From 755bba2c623035bc9bf1b55ebb05c1756834b5d2 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 25 Apr 2017 22:02:36 -0700 Subject: [PATCH 0466/1029] Branching for 2.0.0-preview1 --- NuGet.config | 2 +- build.ps1 | 2 +- build.sh | 2 +- build/dependencies.props | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/NuGet.config b/NuGet.config index 8e65695611..fa4304af9c 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + diff --git a/build.ps1 b/build.ps1 index 5bf0e2c113..225b1fe450 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/2.0.0-preview1.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index b0bcadb579..702b25c636 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/2.0.0-preview1.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi diff --git a/build/dependencies.props b/build/dependencies.props index 01387147a4..c7741b724b 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,6 +1,6 @@ - 2.0.0-* + 2.0.0-preview1-* 4.3.0 2.0.0-* 15.0.0 From c4dbc8d31592bb3ca191e77a6aeecffbbeb964df Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 25 Apr 2017 22:03:21 -0700 Subject: [PATCH 0467/1029] Branching for 2.0.0-preview1 --- NuGet.config | 4 ++-- build.ps1 | 2 +- build.sh | 2 +- build/dependencies.props | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/NuGet.config b/NuGet.config index 93f1ac47df..fa4304af9c 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ - + - + diff --git a/build.ps1 b/build.ps1 index 5bf0e2c113..225b1fe450 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/2.0.0-preview1.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index b0bcadb579..702b25c636 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/2.0.0-preview1.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi diff --git a/build/dependencies.props b/build/dependencies.props index ac44ce3323..dddf01f9f0 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,6 +1,6 @@ - 2.0.0-* + 2.0.0-preview1-* 4.3.0 2.0.0-* 10.0.1 From f86cd6b9b4ed1fe5fab1368e199ec8f0bc8adc9b Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 26 Apr 2017 07:12:47 -0700 Subject: [PATCH 0468/1029] Updating package version to preview2 --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index e5b7eb2dbe..f29a32b5bf 100644 --- a/version.props +++ b/version.props @@ -2,6 +2,6 @@ 2.0.0 - preview1 + preview2 From 36a11404acfa0991ece671128da4cc26a720fe0d Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 26 Apr 2017 07:12:58 -0700 Subject: [PATCH 0469/1029] Updating package version to preview2 --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index c7150e64f4..6af4f81de2 100644 --- a/version.props +++ b/version.props @@ -2,6 +2,6 @@ 2.0.0 - preview1 + preview2 From d0e7b6b7cdd23c352cb06b721707fb10de605524 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 26 Apr 2017 07:13:08 -0700 Subject: [PATCH 0470/1029] Updating package version to preview2 --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 44cb2290b9..0b2b8e0010 100644 --- a/version.props +++ b/version.props @@ -2,6 +2,6 @@ 2.0.0 - preview1 + preview2 \ No newline at end of file From 3a248e22c80d0742abc4cddc4aba694fd29bfe50 Mon Sep 17 00:00:00 2001 From: Mike Harder Date: Thu, 27 Apr 2017 13:37:20 -0700 Subject: [PATCH 0471/1029] Upgrade System.Data.SqlClient to 4.4.0-* (#287) - Addresses "SqlClient fails with netcoreapp2.0 on Win7/Server2008" (https://github.com/dotnet/corefx/issues/18406) - Revert if and when $(CoreFxVersion) is upgraded to 4.4.0-* --- .../Microsoft.Extensions.Caching.SqlConfig.Tools.csproj | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj index 2d9e0cfb74..fc1b331e7d 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj @@ -19,7 +19,13 @@ - + + + From add3d931010f8dc1a08ae80bdf0c1aaed4a95431 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 27 Apr 2017 14:52:32 -0700 Subject: [PATCH 0472/1029] :arrow_up: RuntimeFrameworkVersion to 1.0.5 --- build/dependencies.props | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/dependencies.props b/build/dependencies.props index e704edaec0..b8c12b4814 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -2,5 +2,7 @@ 1.6.1 4.3.0 + + 1.0.5 From 88f43ffc1a43b42fb3b360d45841896334747182 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 27 Apr 2017 17:01:55 -0700 Subject: [PATCH 0473/1029] Fix race conditions between CTRL+C and RunAsync in dotnet-watch Increase timeouts in testing dotnet-run and improve verbosity of test logging --- .../CommandLineOptions.cs | 3 + src/Microsoft.DotNet.Watcher.Tools/Program.cs | 112 ++++++++++-------- .../AppWithDepsTests.cs | 5 +- .../DotNetWatcherTests.cs | 2 +- .../GlobbingAppTests.cs | 41 ++++--- .../NoDepsAppTests.cs | 23 ++-- .../Scenario/WatchableApp.cs | 15 ++- ...icrosoft.DotNet.Watcher.Tools.Tests.csproj | 4 + .../ProgramTests.cs | 9 +- .../Utilities/TaskExtensions.cs | 25 ---- test/Shared/TestConsole.cs | 18 ++- 11 files changed, 143 insertions(+), 114 deletions(-) delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TaskExtensions.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs index 8056dff67e..e6a6b90fba 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs @@ -38,6 +38,9 @@ Environment variables: changes. This is required for some file systems, such as network shares, Docker mounted volumes, and other virtual file systems. + DOTNET_WATCH + dotnet-watch sets this variable to '1' on all child processes launched. + Remarks: The special option '--' is used to delimit the end of the options and the beginning of arguments that will be passed to the child dotnet process. diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index 2f60889657..3b287ed30f 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -12,10 +12,12 @@ using Microsoft.Extensions.Tools.Internal; namespace Microsoft.DotNet.Watcher { - public class Program + public class Program : IDisposable { private readonly IConsole _console; private readonly string _workingDir; + private readonly CancellationTokenSource _cts; + private IReporter _reporter; public Program(IConsole console, string workingDir) { @@ -24,15 +26,21 @@ namespace Microsoft.DotNet.Watcher _console = console; _workingDir = workingDir; + _cts = new CancellationTokenSource(); + _console.CancelKeyPress += OnCancelKeyPress; + _reporter = CreateReporter(verbose: true, quiet: false, console: _console); } public static int Main(string[] args) { DebugHelper.HandleDebugSwitch(ref args); - return new Program(PhysicalConsole.Singleton, Directory.GetCurrentDirectory()) - .RunAsync(args) - .GetAwaiter() - .GetResult(); + using (var program = new Program(PhysicalConsole.Singleton, Directory.GetCurrentDirectory())) + { + return program + .RunAsync(args) + .GetAwaiter() + .GetResult(); + } } public async Task RunAsync(string[] args) @@ -44,8 +52,7 @@ namespace Microsoft.DotNet.Watcher } catch (CommandParsingException ex) { - CreateReporter(verbose: true, quiet: false, console: _console) - .Error(ex.Message); + _reporter.Error(ex.Message); return 1; } @@ -60,54 +67,55 @@ namespace Microsoft.DotNet.Watcher return 2; } - var reporter = CreateReporter(options.IsVerbose, options.IsQuiet, _console); + // update reporter as configured by options + _reporter = CreateReporter(options.IsVerbose, options.IsQuiet, _console); - using (CancellationTokenSource ctrlCTokenSource = new CancellationTokenSource()) + try { - _console.CancelKeyPress += (sender, ev) => + if (_cts.IsCancellationRequested) { - if (!ctrlCTokenSource.IsCancellationRequested) - { - reporter.Output("Shutdown requested. Press Ctrl+C again to force exit."); - ev.Cancel = true; - } - else - { - ev.Cancel = false; - } - ctrlCTokenSource.Cancel(); - }; - - try - { - if (options.ListFiles) - { - return await ListFilesAsync(reporter, - options.Project, - ctrlCTokenSource.Token); - } - else - { - - return await MainInternalAsync(reporter, - options.Project, - options.RemainingArguments, - ctrlCTokenSource.Token); - } - } - catch (Exception ex) - { - if (ex is TaskCanceledException || ex is OperationCanceledException) - { - // swallow when only exception is the CTRL+C forced an exit - return 0; - } - - reporter.Error(ex.ToString()); - reporter.Error("An unexpected error occurred"); return 1; } + + if (options.ListFiles) + { + return await ListFilesAsync(_reporter, + options.Project, + _cts.Token); + } + else + { + return await MainInternalAsync(_reporter, + options.Project, + options.RemainingArguments, + _cts.Token); + } } + catch (Exception ex) + { + if (ex is TaskCanceledException || ex is OperationCanceledException) + { + // swallow when only exception is the CTRL+C forced an exit + return 0; + } + + _reporter.Error(ex.ToString()); + _reporter.Error("An unexpected error occurred"); + return 1; + } + } + + private void OnCancelKeyPress(object sender, ConsoleCancelEventArgs args) + { + // suppress CTRL+C on the first press + args.Cancel = !_cts.IsCancellationRequested; + + if (args.Cancel) + { + _reporter.Output("Shutdown requested. Press Ctrl+C again to force exit."); + } + + _cts.Cancel(); } private async Task MainInternalAsync( @@ -181,5 +189,11 @@ namespace Microsoft.DotNet.Watcher private static IReporter CreateReporter(bool verbose, bool quiet, IConsole console) => new PrefixConsoleReporter(console, verbose || CliContext.IsGlobalVerbose(), quiet); + + public void Dispose() + { + _console.CancelKeyPress -= OnCancelKeyPress; + _cts.Dispose(); + } } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs index 37bfd618d1..3cbef02868 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs @@ -4,6 +4,7 @@ using System; using System.IO; using System.Threading.Tasks; +using Microsoft.AspNetCore.Testing; using Xunit; using Xunit.Abstractions; @@ -22,13 +23,13 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [Fact] public async Task ChangeFileInDependency() { - await _app.StartWatcherAsync().OrTimeout(); + await _app.StartWatcherAsync(); var fileToChange = Path.Combine(_app.DependencyFolder, "Foo.cs"); var programCs = File.ReadAllText(fileToChange); File.WriteAllText(fileToChange, programCs); - await _app.HasRestarted().OrTimeout(); + await _app.HasRestarted(); } public void Dispose() diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/DotNetWatcherTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/DotNetWatcherTests.cs index f9d16972ee..950f765135 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/DotNetWatcherTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/DotNetWatcherTests.cs @@ -23,7 +23,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { Assert.True(string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DOTNET_WATCH")), "DOTNET_WATCH cannot be set already when this test is running"); - await _app.StartWatcherAsync().OrTimeout(); + await _app.StartWatcherAsync(); const string messagePrefix = "DOTNET_WATCH = "; var message = await _app.Process.GetOutputLineAsync(m => m.StartsWith(messagePrefix)); var envValue = message.Substring(messagePrefix.Length); diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs index f2c37077d5..011d64805a 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Testing; using Microsoft.DotNet.Watcher.Tools.Tests; using Xunit; using Xunit.Abstractions; @@ -13,6 +14,8 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { public class GlobbingAppTests : IDisposable { + private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(30); + private GlobbingApp _app; public GlobbingAppTests(ITestOutputHelper logger) { @@ -25,84 +28,84 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [InlineData(false)] public async Task ChangeCompiledFile(bool usePollingWatcher) { - await _app.StartWatcherAsync().OrTimeout(); + await _app.StartWatcherAsync(); - var types = await _app.GetCompiledAppDefinedTypes().OrTimeout(); + var types = await _app.GetCompiledAppDefinedTypes().TimeoutAfter(DefaultTimeout); Assert.Equal(2, types); var fileToChange = Path.Combine(_app.SourceDirectory, "include", "Foo.cs"); var programCs = File.ReadAllText(fileToChange); File.WriteAllText(fileToChange, programCs); - await _app.HasRestarted().OrTimeout(); - types = await _app.GetCompiledAppDefinedTypes().OrTimeout(); + await _app.HasRestarted(); + types = await _app.GetCompiledAppDefinedTypes().TimeoutAfter(DefaultTimeout); Assert.Equal(2, types); } [Fact(Skip = "Broken. See https://github.com/aspnet/DotNetTools/issues/212")] public async Task AddCompiledFile() { - await _app.StartWatcherAsync().OrTimeout(); + await _app.StartWatcherAsync(); - var types = await _app.GetCompiledAppDefinedTypes().OrTimeout(); + var types = await _app.GetCompiledAppDefinedTypes().TimeoutAfter(DefaultTimeout); Assert.Equal(2, types); var fileToChange = Path.Combine(_app.SourceDirectory, "include", "Bar.cs"); File.WriteAllText(fileToChange, "public class Bar {}"); - await _app.HasRestarted().OrTimeout(); - types = await _app.GetCompiledAppDefinedTypes().OrTimeout(); + await _app.HasRestarted(); + types = await _app.GetCompiledAppDefinedTypes().TimeoutAfter(DefaultTimeout); Assert.Equal(3, types); } [Fact] public async Task DeleteCompiledFile() { - await _app.StartWatcherAsync().OrTimeout(); + await _app.StartWatcherAsync(); - var types = await _app.GetCompiledAppDefinedTypes().OrTimeout(); + var types = await _app.GetCompiledAppDefinedTypes().TimeoutAfter(DefaultTimeout); Assert.Equal(2, types); var fileToChange = Path.Combine(_app.SourceDirectory, "include", "Foo.cs"); File.Delete(fileToChange); - await _app.HasRestarted().OrTimeout(); - types = await _app.GetCompiledAppDefinedTypes().OrTimeout(); + await _app.HasRestarted(); + types = await _app.GetCompiledAppDefinedTypes().TimeoutAfter(DefaultTimeout); Assert.Equal(1, types); } [Fact] public async Task DeleteSourceFolder() { - await _app.StartWatcherAsync().OrTimeout(); + await _app.StartWatcherAsync(); - var types = await _app.GetCompiledAppDefinedTypes().OrTimeout(); + var types = await _app.GetCompiledAppDefinedTypes().TimeoutAfter(DefaultTimeout); Assert.Equal(2, types); var folderToDelete = Path.Combine(_app.SourceDirectory, "include"); Directory.Delete(folderToDelete, recursive: true); - await _app.HasRestarted().OrTimeout(); - types = await _app.GetCompiledAppDefinedTypes().OrTimeout(); + await _app.HasRestarted(); + types = await _app.GetCompiledAppDefinedTypes().TimeoutAfter(DefaultTimeout); Assert.Equal(1, types); } [Fact] public async Task RenameCompiledFile() { - await _app.StartWatcherAsync().OrTimeout(); + await _app.StartWatcherAsync(); var oldFile = Path.Combine(_app.SourceDirectory, "include", "Foo.cs"); var newFile = Path.Combine(_app.SourceDirectory, "include", "Foo_new.cs"); File.Move(oldFile, newFile); - await _app.HasRestarted().OrTimeout(); + await _app.HasRestarted(); } [Fact] public async Task ChangeExcludedFile() { - await _app.StartWatcherAsync().OrTimeout(); + await _app.StartWatcherAsync(); var changedFile = Path.Combine(_app.SourceDirectory, "exclude", "Baz.cs"); File.WriteAllText(changedFile, ""); diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs index 6e22a55436..633766d96a 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs @@ -5,6 +5,7 @@ using System; using System.Diagnostics; using System.IO; using System.Threading.Tasks; +using Microsoft.AspNetCore.Testing; using Xunit; using Xunit.Abstractions; @@ -12,6 +13,8 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { public class NoDepsAppTests : IDisposable { + private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(30); + private readonly WatchableApp _app; public NoDepsAppTests(ITestOutputHelper logger) @@ -23,16 +26,16 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [Fact] public async Task RestartProcessOnFileChange() { - await _app.StartWatcherAsync(new[] { "--no-exit" }).OrTimeout(); - var pid = await _app.GetProcessId().OrTimeout(); + await _app.StartWatcherAsync(new[] { "--no-exit" }); + var pid = await _app.GetProcessId().TimeoutAfter(DefaultTimeout); // Then wait for it to restart when we change a file var fileToChange = Path.Combine(_app.SourceDirectory, "Program.cs"); var programCs = File.ReadAllText(fileToChange); File.WriteAllText(fileToChange, programCs); - await _app.HasRestarted().OrTimeout(); - var pid2 = await _app.GetProcessId().OrTimeout(); + await _app.HasRestarted(); + var pid2 = await _app.GetProcessId().TimeoutAfter(DefaultTimeout); Assert.NotEqual(pid, pid2); // first app should have shut down @@ -42,18 +45,18 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [Fact] public async Task RestartProcessThatTerminatesAfterFileChange() { - await _app.StartWatcherAsync().OrTimeout(); - var pid = await _app.GetProcessId().OrTimeout(); - await _app.HasExited().OrTimeout(); // process should exit after run + await _app.StartWatcherAsync(); + var pid = await _app.GetProcessId().TimeoutAfter(DefaultTimeout); + await _app.HasExited().TimeoutAfter(DefaultTimeout); // process should exit after run var fileToChange = Path.Combine(_app.SourceDirectory, "Program.cs"); var programCs = File.ReadAllText(fileToChange); File.WriteAllText(fileToChange, programCs); - await _app.HasRestarted().OrTimeout(); - var pid2 = await _app.GetProcessId().OrTimeout(); + await _app.HasRestarted(); + var pid2 = await _app.GetProcessId().TimeoutAfter(DefaultTimeout); Assert.NotEqual(pid, pid2); - await _app.HasExited().OrTimeout(); // process should exit after run + await _app.HasExited().TimeoutAfter(DefaultTimeout); // process should exit after run } public void Dispose() diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs index 3fdb1872e3..7be9e65c7c 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; +using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.CommandLineUtils; using Xunit.Abstractions; @@ -38,7 +39,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public string SourceDirectory { get; } public Task HasRestarted() - => Process.GetOutputLineAsync(StartedMessage); + => Process.GetOutputLineAsync(StartedMessage).TimeoutAfter(TimeSpan.FromMinutes(2)); public Task HasExited() => Process.GetOutputLineAsync(ExitingMessage); @@ -74,7 +75,11 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { Executable = DotNetMuxer.MuxerPathOrDefault(), Arguments = args, - WorkingDirectory = SourceDirectory + WorkingDirectory = SourceDirectory, + EnvironmentVariables = + { + ["DOTNET_CLI_CONTEXT_VERBOSE"] = bool.TrueString + }, }; Process = new AwaitableProcess(spec, _logger); @@ -88,11 +93,15 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { var args = new[] { "run", "--" }.Concat(arguments); Start(args, name); - await Process.GetOutputLineAsync(StartedMessage); + + // Make this timeout long because it depends much on the MSBuild compilation speed. + // Slow machines may take a bit to compile and boot test apps + await Process.GetOutputLineAsync(StartedMessage).TimeoutAfter(TimeSpan.FromMinutes(2)); } public virtual void Dispose() { + _logger?.WriteLine("Disposing WatchableApp"); Process?.Dispose(); Scenario.Dispose(); } diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj index bcb78e5e3b..55bc572749 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj @@ -15,6 +15,10 @@ + + + + diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/ProgramTests.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/ProgramTests.cs index e00099acfb..8c116b5595 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/ProgramTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/ProgramTests.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Text; using System.Threading.Tasks; +using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.Tools.Internal; using Xunit; using Xunit.Abstractions; @@ -35,18 +36,20 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests var stdout = new StringBuilder(); _console.Out = new StringWriter(stdout); var program = new Program(_console, _tempDir.Root) - .RunAsync(new [] { "run" }); + .RunAsync(new[] { "run" }); + await _console.CancelKeyPressSubscribed.TimeoutAfter(TimeSpan.FromSeconds(30)); _console.ConsoleCancelKey(); - var exitCode = await program.OrTimeout(); + var exitCode = await program.TimeoutAfter(TimeSpan.FromSeconds(30)); Assert.Contains("Shutdown requested. Press Ctrl+C again to force exit.", stdout.ToString()); Assert.Equal(0, exitCode); } + public void Dispose() { _tempDir.Dispose(); } } -} \ No newline at end of file +} diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TaskExtensions.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TaskExtensions.cs deleted file mode 100644 index daaa77918e..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TaskExtensions.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Runtime.CompilerServices; - -namespace System.Threading.Tasks -{ - public static class TaskExtensions - { - public static async Task OrTimeout(this Task task, int timeout = 30, [CallerFilePath] string file = null, [CallerLineNumber] int line = 0) - { - await OrTimeout((Task)task, timeout, file, line); - return task.Result; - } - - public static async Task OrTimeout(this Task task, int timeout = 30, [CallerFilePath] string file = null, [CallerLineNumber] int line = 0) - { - var finished = await Task.WhenAny(task, Task.Delay(TimeSpan.FromSeconds(timeout))); - if (!ReferenceEquals(finished, task)) - { - throw new TimeoutException($"Task exceeded max running time of {timeout}s at {file}:{line}"); - } - } - } -} \ No newline at end of file diff --git a/test/Shared/TestConsole.cs b/test/Shared/TestConsole.cs index 6804c0265e..b8198238f3 100644 --- a/test/Shared/TestConsole.cs +++ b/test/Shared/TestConsole.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Linq; using System.Reflection; +using System.Threading.Tasks; using System.Text; using Xunit.Abstractions; @@ -12,6 +13,9 @@ namespace Microsoft.Extensions.Tools.Internal { public class TestConsole : IConsole { + private event ConsoleCancelEventHandler _cancelKeyPress; + private readonly TaskCompletionSource _cancelKeySubscribed = new TaskCompletionSource(); + public TestConsole(ITestOutputHelper output) { var writer = new TestOutputWriter(output); @@ -19,7 +23,17 @@ namespace Microsoft.Extensions.Tools.Internal Out = writer; } - public event ConsoleCancelEventHandler CancelKeyPress; + public event ConsoleCancelEventHandler CancelKeyPress + { + add + { + _cancelKeyPress += value; + _cancelKeySubscribed.TrySetResult(true); + } + remove => _cancelKeyPress -= value; + } + + public Task CancelKeyPressSubscribed => _cancelKeySubscribed.Task; public TextWriter Error { get; set; } public TextWriter Out { get; set; } @@ -36,7 +50,7 @@ namespace Microsoft.Extensions.Tools.Internal .DeclaredConstructors .Single(c => c.GetParameters().First().ParameterType == typeof(ConsoleSpecialKey)); var args = (ConsoleCancelEventArgs)ctor.Invoke(new object[] { ConsoleSpecialKey.ControlC }); - CancelKeyPress?.Invoke(this, args); + _cancelKeyPress.Invoke(this, args); return args; } From f23ba913db86eab154b27afff602e3573f8ff6d1 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 28 Apr 2017 14:03:27 -0700 Subject: [PATCH 0474/1029] Skip dotnet-watch functional tests while we investigate CI hangs --- build/repo.props | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 build/repo.props diff --git a/build/repo.props b/build/repo.props new file mode 100644 index 0000000000..1d120e0973 --- /dev/null +++ b/build/repo.props @@ -0,0 +1,5 @@ + + + + + From d277144cb393bf48e458eb12f5a66b5e803778fb Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 1 May 2017 12:39:14 -0700 Subject: [PATCH 0475/1029] Use the bundled NETStandard.Library package in netstandard targeting libraries --- build/dependencies.props | 1 + 1 file changed, 1 insertion(+) diff --git a/build/dependencies.props b/build/dependencies.props index c7741b724b..3db1eba0a2 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,6 +3,7 @@ 2.0.0-preview1-* 4.3.0 2.0.0-* + $(BundledNETStandardPackageVersion) 15.0.0 2.2.0 From aa4bef0f546c1c8544bd09af1e86e0ad6ea8f0b2 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 1 May 2017 12:39:26 -0700 Subject: [PATCH 0476/1029] Use the bundled NETStandard.Library package in netstandard targeting libraries --- build/dependencies.props | 1 + 1 file changed, 1 insertion(+) diff --git a/build/dependencies.props b/build/dependencies.props index c7741b724b..3db1eba0a2 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,6 +3,7 @@ 2.0.0-preview1-* 4.3.0 2.0.0-* + $(BundledNETStandardPackageVersion) 15.0.0 2.2.0 From 4628a2ff4e3097dd7e3c14e5e0d74d9c3d50371c Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 1 May 2017 12:39:39 -0700 Subject: [PATCH 0477/1029] Use the bundled NETStandard.Library package in netstandard targeting libraries --- build/dependencies.props | 1 + 1 file changed, 1 insertion(+) diff --git a/build/dependencies.props b/build/dependencies.props index dddf01f9f0..8dce2099b3 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -5,6 +5,7 @@ 2.0.0-* 10.0.1 4.7.1 + $(BundledNETStandardPackageVersion) 15.0.0 2.2.0 From ed07fbe94a33c3238dc0ec2f7abb5de9ede78a68 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 28 Apr 2017 16:57:16 -0700 Subject: [PATCH 0478/1029] Remove blocking call to stream reader and fix bug in task chaining --- build/repo.props | 5 -- .../AppWithDepsTests.cs | 3 +- .../AwaitableProcess.cs | 79 ++++++++++------- .../GlobbingAppTests.cs | 4 +- .../NoDepsAppTests.cs | 1 - .../Scenario/ProjectToolScenario.cs | 88 +++++++++++++------ .../Scenario/WatchableApp.cs | 19 ++-- .../AssertEx.cs | 4 +- .../Utilities/TaskExtensions.cs | 11 ++- 9 files changed, 132 insertions(+), 82 deletions(-) delete mode 100644 build/repo.props diff --git a/build/repo.props b/build/repo.props deleted file mode 100644 index 1d120e0973..0000000000 --- a/build/repo.props +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs index 37bfd618d1..93c563eb50 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -16,7 +16,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public AppWithDepsTests(ITestOutputHelper logger) { _app = new AppWithDeps(logger); - _app.Prepare(); } [Fact] diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs index 11583832d0..c16f33c0b6 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs @@ -4,9 +4,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.IO; -using System.Text; -using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; using Microsoft.Extensions.Internal; @@ -21,12 +18,12 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests private readonly ProcessSpec _spec; private BufferBlock _source; private ITestOutputHelper _logger; - private int _reading; public AwaitableProcess(ProcessSpec spec, ITestOutputHelper logger) { _spec = spec; _logger = logger; + _source = new BufferBlock(); } public void Start() @@ -36,19 +33,32 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests throw new InvalidOperationException("Already started"); } - var psi = new ProcessStartInfo + _process = new Process { - UseShellExecute = false, - FileName = _spec.Executable, - WorkingDirectory = _spec.WorkingDirectory, - Arguments = ArgumentEscaper.EscapeAndConcatenate(_spec.Arguments), - RedirectStandardOutput = true, - RedirectStandardError = true + EnableRaisingEvents = true, + StartInfo = new ProcessStartInfo + { + UseShellExecute = false, + FileName = _spec.Executable, + WorkingDirectory = _spec.WorkingDirectory, + Arguments = ArgumentEscaper.EscapeAndConcatenate(_spec.Arguments), + RedirectStandardOutput = true, + RedirectStandardError = true, + Environment = + { + ["DOTNET_SKIP_FIRST_TIME_EXPERIENCE"] = "true" + } + } }; - _process = Process.Start(psi); - _logger.WriteLine($"{DateTime.Now}: process start: '{psi.FileName} {psi.Arguments}'"); - StartProcessingOutput(_process.StandardOutput); - StartProcessingOutput(_process.StandardError);; + + _process.OutputDataReceived += OnData; + _process.ErrorDataReceived += OnData; + _process.Exited += OnExit; + + _process.Start(); + _process.BeginErrorReadLine(); + _process.BeginOutputReadLine(); + _logger.WriteLine($"{DateTime.Now}: process start: '{_process.StartInfo.FileName} {_process.StartInfo.Arguments}'"); } public Task GetOutputLineAsync(string message) @@ -87,32 +97,33 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests return lines; } - private void StartProcessingOutput(StreamReader streamReader) + private void OnData(object sender, DataReceivedEventArgs args) { - _source = _source ?? new BufferBlock(); - Interlocked.Increment(ref _reading); - Task.Run(() => - { - string line; - while ((line = streamReader.ReadLine()) != null) - { - _logger.WriteLine($"{DateTime.Now}: post: '{line}'"); - _source.Post(line); - } + var line = args.Data ?? string.Empty; + _logger.WriteLine($"{DateTime.Now}: post: '{line}'"); + _source.Post(line); + } - if (Interlocked.Decrement(ref _reading) <= 0) - { - _source.Complete(); - } - }).ConfigureAwait(false); + private void OnExit(object sender, EventArgs args) + { + _source.Complete(); } public void Dispose() { - if (_process != null && !_process.HasExited) + _source.Complete(); + + if (_process != null) { - _process.KillTree(); + if (!_process.HasExited) + { + _process.KillTree(); + } + + _process.ErrorDataReceived -= OnData; + _process.OutputDataReceived -= OnData; + _process.Exited -= OnExit; } } } -} \ No newline at end of file +} diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs index f2c37077d5..d04929e693 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -17,7 +17,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public GlobbingAppTests(ITestOutputHelper logger) { _app = new GlobbingApp(logger); - _app.Prepare(); } [Theory] @@ -115,6 +114,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [Fact] public async Task ListsFiles() { + await _app.PrepareAsync(); _app.Start(new [] { "--list" }); var lines = await _app.Process.GetAllOutputLines(); diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs index 6e22a55436..8d190bfe42 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs @@ -17,7 +17,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public NoDepsAppTests(ITestOutputHelper logger) { _app = new WatchableApp("NoDepsApp", logger); - _app.Prepare(); } [Fact] diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs index 1b0f62c7de..b16a9f508e 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -1,13 +1,15 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Microsoft.Extensions.Tools.Internal; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Internal; +using Microsoft.Extensions.Tools.Internal; using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests @@ -55,50 +57,84 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } } - public void Restore(string project) + public Task RestoreAsync(string project) { _logger?.WriteLine($"Restoring msbuild project in {project}"); - ExecuteCommand(project, "restore"); + return ExecuteCommandAsync(project, TimeSpan.FromSeconds(120), "restore"); } - public void Build(string project) + public Task BuildAsync(string project) { _logger?.WriteLine($"Building {project}"); - ExecuteCommand(project, "build"); + return ExecuteCommandAsync(project, TimeSpan.FromSeconds(60), "build"); } - private void ExecuteCommand(string project, params string[] arguments) + private async Task ExecuteCommandAsync(string project, TimeSpan timeout, params string[] arguments) { + var tcs = new TaskCompletionSource(); project = Path.Combine(WorkFolder, project); - var psi = new ProcessStartInfo + _logger?.WriteLine($"Project directory: '{project}'"); + + var process = new Process { - FileName = DotNetMuxer.MuxerPathOrDefault(), - Arguments = ArgumentEscaper.EscapeAndConcatenate(arguments), - WorkingDirectory = project, - RedirectStandardOutput = true, - RedirectStandardError = true + EnableRaisingEvents = true, + StartInfo = new ProcessStartInfo + { + FileName = DotNetMuxer.MuxerPathOrDefault(), + Arguments = ArgumentEscaper.EscapeAndConcatenate(arguments), + WorkingDirectory = project, + RedirectStandardOutput = true, + RedirectStandardError = true, + Environment = + { + ["DOTNET_SKIP_FIRST_TIME_EXPERIENCE"] = "true" + } + }, }; - var process = new Process() + void OnData(object sender, DataReceivedEventArgs args) + => _logger?.WriteLine(args.Data ?? string.Empty); + + void OnExit(object sender, EventArgs args) { - StartInfo = psi, - EnableRaisingEvents = true - }; + _logger?.WriteLine($"Process exited {process.Id}"); + tcs.TrySetResult(null); + } - void WriteLine(object sender, DataReceivedEventArgs args) - => _logger.WriteLine(args.Data); - - process.ErrorDataReceived += WriteLine; - process.OutputDataReceived += WriteLine; + process.ErrorDataReceived += OnData; + process.OutputDataReceived += OnData; + process.Exited += OnExit; process.Start(); - process.WaitForExit(); - process.ErrorDataReceived -= WriteLine; - process.OutputDataReceived -= WriteLine; + process.BeginErrorReadLine(); + process.BeginOutputReadLine(); + _logger?.WriteLine($"Started process {process.Id}: {process.StartInfo.FileName} {process.StartInfo.Arguments}"); + + var done = await Task.WhenAny(tcs.Task, Task.Delay(timeout)); + process.CancelErrorRead(); + process.CancelOutputRead(); + + process.ErrorDataReceived -= OnData; + process.OutputDataReceived -= OnData; + process.Exited -= OnExit; + + if (!ReferenceEquals(done, tcs.Task)) + { + if (!process.HasExited) + { + _logger?.WriteLine($"Killing process {process.Id}"); + process.KillTree(); + } + + throw new TimeoutException($"Process timed out after {timeout.TotalSeconds} seconds"); + } + + _logger?.WriteLine($"Process exited {process.Id} with code {process.ExitCode}"); if (process.ExitCode != 0) { + throw new InvalidOperationException($"Exit code {process.ExitCode}"); } } @@ -179,4 +215,4 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } } } -} \ No newline at end of file +} diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs index 6e4d6cc883..4199f3ba88 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -52,10 +52,10 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests return int.Parse(pid); } - public void Prepare() + public async Task PrepareAsync() { - Scenario.Restore(_appName); - Scenario.Build(_appName); + await Scenario.RestoreAsync(_appName); + await Scenario.BuildAsync(_appName); _prepared = true; } @@ -63,7 +63,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { if (!_prepared) { - throw new InvalidOperationException("Call .Prepare() first"); + throw new InvalidOperationException($"Call {nameof(PrepareAsync)} first"); } var args = Scenario @@ -86,6 +86,11 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public async Task StartWatcherAsync(string[] arguments, [CallerMemberName] string name = null) { + if (!_prepared) + { + await PrepareAsync(); + } + var args = new[] { "run", "--" }.Concat(arguments); Start(args, name); await Process.GetOutputLineAsync(StartedMessage); @@ -93,8 +98,8 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public virtual void Dispose() { - Process.Dispose(); - Scenario.Dispose(); + Process?.Dispose(); + Scenario?.Dispose(); } } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs index aa4f94b3fa..58e0f06ebd 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs @@ -21,7 +21,7 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests { Func normalize = p => p.Replace('\\', '/'); var expected = new HashSet(expectedFiles.Select(normalize)); - Assert.True(expected.SetEquals(actualFiles.Select(normalize)), "File sets should be equal"); + Assert.True(expected.SetEquals(actualFiles.Where(p => !string.IsNullOrEmpty(p)).Select(normalize)), "File sets should be equal"); } } -} \ No newline at end of file +} diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TaskExtensions.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TaskExtensions.cs index daaa77918e..3302d44b7f 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TaskExtensions.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TaskExtensions.cs @@ -9,8 +9,12 @@ namespace System.Threading.Tasks { public static async Task OrTimeout(this Task task, int timeout = 30, [CallerFilePath] string file = null, [CallerLineNumber] int line = 0) { - await OrTimeout((Task)task, timeout, file, line); - return task.Result; + var finished = await Task.WhenAny(task, Task.Delay(TimeSpan.FromSeconds(timeout))); + if (!ReferenceEquals(finished, task)) + { + throw new TimeoutException($"Task exceeded max running time of {timeout}s at {file}:{line}"); + } + return await task; } public static async Task OrTimeout(this Task task, int timeout = 30, [CallerFilePath] string file = null, [CallerLineNumber] int line = 0) @@ -20,6 +24,7 @@ namespace System.Threading.Tasks { throw new TimeoutException($"Task exceeded max running time of {timeout}s at {file}:{line}"); } + await task; } } -} \ No newline at end of file +} From db517803c8ef05b3961c7a976ae52c1b0c292ec5 Mon Sep 17 00:00:00 2001 From: Mike Harder Date: Wed, 3 May 2017 11:30:51 -0700 Subject: [PATCH 0479/1029] Move System.Data.SqlClient version from csproj to dependencies.props (#293) --- build/dependencies.props | 8 ++++++++ .../Microsoft.Extensions.Caching.SqlConfig.Tools.csproj | 6 +++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 3db1eba0a2..cf961b6939 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,6 +1,14 @@ 2.0.0-preview1-* + + + 4.4.0-* + 4.3.0 2.0.0-* $(BundledNETStandardPackageVersion) diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj index fc1b331e7d..8fed872aac 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj @@ -21,11 +21,11 @@ - + From a23a255e2e25478474172920dd695a23175e8bb6 Mon Sep 17 00:00:00 2001 From: Mike Harder Date: Wed, 3 May 2017 11:43:39 -0700 Subject: [PATCH 0480/1029] Fix whitespace. --- build/dependencies.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/dependencies.props b/build/dependencies.props index 6e80e57101..c436976da7 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,6 +1,6 @@ - 2.0.0-* + 2.0.0-* + + <_SSLCertificateGenerationTaskAssembly>$(MSBuildThisFileDirectory)..\tools\netcoreapp2.0\Microsoft.AspNetCore.CertificateGeneration.Task.dll + + + + + + + + diff --git a/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/GenerateSSLCertificateTaskTest.cs b/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/GenerateSSLCertificateTaskTest.cs new file mode 100644 index 0000000000..245333a84e --- /dev/null +++ b/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/GenerateSSLCertificateTaskTest.cs @@ -0,0 +1,227 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using Xunit; + +namespace Microsoft.AspNetCore.CertificateGeneration.Task +{ + public class GenerateSSLCertificateTaskTest : IDisposable + { + private const string TestSubject = "CN=test.ssl.localhost"; + + [Fact] + public void GenerateSSLCertificateTaskTest_CreatesCertificate_IfNoCertificateIsFound() + { + // Arrange + EnsureCleanUp(); + var task = new TestGenerateSSLCertificateTask(); + + // Act + var result = task.Execute(); + + // Assert + Assert.True(result); + var certificates = GetTestCertificates(); + Assert.Equal(1, certificates.Count); + Assert.Equal(1, task.Messages.Count); + Assert.StartsWith($"Generated certificate {TestSubject}", task.Messages[0]); + } + + [Fact] + public void GenerateSSLCertificateTaskTest_CreatesCertificate_IfFoundCertificateHasExpired() + { + // Arrange + EnsureCleanUp(); + CreateCertificate(notBefore: DateTimeOffset.UtcNow.AddYears(-2), expires: DateTimeOffset.UtcNow.AddYears(-1)); + + var task = new TestGenerateSSLCertificateTask(); + + // Act + var result = task.Execute(); + + // Assert + Assert.True(result); + var certificates = GetTestCertificates(); + Assert.Equal(2, certificates.Count); + Assert.Equal(1, task.Messages.Count); + Assert.StartsWith($"Generated certificate {TestSubject}", task.Messages[0]); + } + + [Fact] + public void GenerateSSLCertificateTaskTest_CreatesCertificate_IfFoundCertificateIsNotYetValid() + { + // Arrange + EnsureCleanUp(); + CreateCertificate(notBefore: DateTimeOffset.UtcNow.AddYears(1), expires: DateTimeOffset.UtcNow.AddYears(2)); + + var task = new TestGenerateSSLCertificateTask(); + + // Act + var result = task.Execute(); + + // Assert + Assert.True(result); + var certificates = GetTestCertificates(); + Assert.Equal(2, certificates.Count); + Assert.Equal(1, task.Messages.Count); + Assert.StartsWith($"Generated certificate {TestSubject}", task.Messages[0]); + } + + [Fact] + public void GenerateSSLCertificateTaskTest_CreatesCertificate_IfFoundCertificateDoesNotHavePrivateKeys() + { + // Arrange + EnsureCleanUp(); + CreateCertificate(savePrivateKey: false); + var task = new TestGenerateSSLCertificateTask(); + + // Act + var result = task.Execute(); + + // Assert + Assert.True(result); + var certificates = GetTestCertificates(); + Assert.Equal(2, certificates.Count); + Assert.Equal(1, task.Messages.Count); + Assert.StartsWith($"Generated certificate {TestSubject}", task.Messages[0]); + } + + [Fact] + public void GenerateSSLCertificateTaskTest_DoesNothing_IfValidCertificateIsFound() + { + // Arrange + EnsureCleanUp(); + CreateCertificate(); + var task = new TestGenerateSSLCertificateTask(); + + // Act + var result = task.Execute(); + + // Assert + Assert.True(result); + var certificates = GetTestCertificates(); + Assert.Equal(1, certificates.Count); + Assert.Equal(1, task.Messages.Count); + Assert.Equal($"A certificate with subject name '{TestSubject}' already exists. Skipping certificate generation.", task.Messages[0]); + } + + [Fact] + public void GenerateSSLCertificateTaskTest_CreatesACertificateWhenThereIsAlreadyAValidCertificate_IfForceIsSpecified() + { + // Arrange + EnsureCleanUp(); + CreateCertificate(); + var task = new TestGenerateSSLCertificateTask() { Force = true }; + + // Act + var result = task.Execute(); + + // Assert + Assert.True(result); + var certificates = GetTestCertificates(); + Assert.Equal(2, certificates.Count); + Assert.Equal(1, task.Messages.Count); + Assert.StartsWith($"Generated certificate {TestSubject}", task.Messages[0]); + } + + public X509CertificateCollection GetTestCertificates() + { + using (var store = new X509Store(StoreName.My, StoreLocation.CurrentUser)) + { + store.Open(OpenFlags.ReadWrite); + var certificates = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName, TestSubject, validOnly: false); + store.Close(); + + return certificates; + } + } + + private void EnsureCleanUp() + { + using (var store = new X509Store(StoreName.My, StoreLocation.CurrentUser)) + { + store.Open(OpenFlags.ReadWrite); + var certificates = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName, TestSubject, validOnly: false); + store.RemoveRange(certificates); + store.Close(); + } + } + + public void Dispose() + { + EnsureCleanUp(); + } + + private void CreateCertificate( + DateTimeOffset notBefore = default(DateTimeOffset), + DateTimeOffset expires = default(DateTimeOffset), + bool savePrivateKey = true) + { + using (var rsa = RSA.Create(2048)) + { + var signingRequest = new CertificateRequest( + new X500DistinguishedName(TestSubject), rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); + + var enhancedKeyUsage = new OidCollection(); + enhancedKeyUsage.Add(new Oid("1.3.6.1.5.5.7.3.1", "Server Authentication")); + signingRequest.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(enhancedKeyUsage, critical: true)); + signingRequest.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.KeyEncipherment, critical: true)); + signingRequest.CertificateExtensions.Add( + new X509BasicConstraintsExtension( + certificateAuthority: false, + hasPathLengthConstraint: false, + pathLengthConstraint: 0, + critical: true)); + + var sanBuilder = new SubjectAlternativeNameBuilder(); + sanBuilder.AddDnsName(TestSubject.Replace("CN=", "")); + signingRequest.CertificateExtensions.Add(sanBuilder.Build()); + + var certificate = signingRequest.CreateSelfSigned( + notBefore == default(DateTimeOffset) ? DateTimeOffset.Now : notBefore, + expires == default(DateTimeOffset) ? DateTimeOffset.Now.AddYears(1) : expires); + + + var imported = certificate; + if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && savePrivateKey) + { + var export = certificate.Export(X509ContentType.Pkcs12, ""); + + imported = new X509Certificate2(export, "", X509KeyStorageFlags.PersistKeySet); + Array.Clear(export, 0, export.Length); + } + else if (!savePrivateKey) + { + var export = certificate.Export(X509ContentType.Cert, ""); + + imported = new X509Certificate2(export, "", X509KeyStorageFlags.PersistKeySet); + Array.Clear(export, 0, export.Length); + } + + using (var store = new X509Store(StoreName.My, StoreLocation.CurrentUser)) + { + store.Open(OpenFlags.ReadWrite); + store.Add(imported); + store.Close(); + }; + } + } + + private class TestGenerateSSLCertificateTask : GenerateSSLCertificateTask + { + public TestGenerateSSLCertificateTask() + { + Subject = TestSubject; + } + + public IList Messages { get; set; } = new List(); + + protected override void LogMessage(string message) => Messages.Add(message); + } + } +} diff --git a/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj b/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj new file mode 100644 index 0000000000..6e956b40f5 --- /dev/null +++ b/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj @@ -0,0 +1,21 @@ + + + + + + netcoreapp2.0 + + + + + + + + + + + + + + + From 85d712251d9d24477d20c07fd385a3e60c4bdc81 Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Fri, 26 May 2017 12:39:37 -0700 Subject: [PATCH 0492/1029] Updated to use the latest shared runtime --- build/dependencies.props | 1 + 1 file changed, 1 insertion(+) diff --git a/build/dependencies.props b/build/dependencies.props index a6c3217f9f..b38ceacda4 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -13,6 +13,7 @@ 2.1.0-* 15.1.1012 $(BundledNETStandardPackageVersion) + 2.0.0-* 15.3.0-* 2.3.0-beta2-* From 46dd25fcac69c32ddce56931ebc082b5dc0a7897 Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Fri, 26 May 2017 12:40:38 -0700 Subject: [PATCH 0493/1029] Updated to use the latest shared runtime --- build/dependencies.props | 1 + 1 file changed, 1 insertion(+) diff --git a/build/dependencies.props b/build/dependencies.props index ed2c89867f..e9ed2ba5bf 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,6 +4,7 @@ 4.3.0 2.1.0-* $(BundledNETStandardPackageVersion) + 2.0.0-* 15.3.0-* 2.3.0-beta2-* From 758006d17f7d6accea730627d451a8d0c6b731cf Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Fri, 26 May 2017 12:41:43 -0700 Subject: [PATCH 0494/1029] Updated to use the latest shared runtime --- build/dependencies.props | 1 + 1 file changed, 1 insertion(+) diff --git a/build/dependencies.props b/build/dependencies.props index 0011678b86..55f77f78f3 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -6,6 +6,7 @@ 10.0.1 4.7.1 $(BundledNETStandardPackageVersion) + 2.0.0-* 15.3.0-* 2.3.0-beta2-* From eb4be67863c3f907847c266c35f24176b1169e4d Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Tue, 30 May 2017 09:52:51 -0700 Subject: [PATCH 0495/1029] Add temporary NPV exception --- NuGetPackageVerifier.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index 214ca77a9c..34870e0f87 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -23,6 +23,9 @@ "exclusions":{ "BUILD_ITEMS_FRAMEWORK": { "*": "This is an MSBuild task intended to run through dotnet msbuild /t:Target independently of whether your project targets full framework or .net core." + }, + "THIRDPARTY_DEPENDENCY_NOT_REGISTERED": { + "*": "Temporary exception while waiting for Coherence-Signed to get a new version of NugetPackageVerifier." } } } From f4f0af98cdc37b42ca4f6bc680d8a333e6ea7f60 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 31 May 2017 19:36:23 -0700 Subject: [PATCH 0496/1029] Branching for rel/2.0.0-preview2 --- NuGet.config | 5 +++-- build/dependencies.props | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/NuGet.config b/NuGet.config index 93f1ac47df..c4bc056c4d 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,8 +1,9 @@  - + + - + \ No newline at end of file diff --git a/build/dependencies.props b/build/dependencies.props index b38ceacda4..98f289b4c2 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,6 +1,6 @@ - 2.0.0-* + 2.0.0-preview2-* - 4.4.0-* - - 4.3.0 + 4.4.0-* 2.1.0-* 15.1.1012 $(BundledNETStandardPackageVersion) diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj index 8fed872aac..2d9e0cfb74 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj @@ -19,13 +19,7 @@ - - - + From cfb7ae413f811e54ade3db99fb468b8629676a81 Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Thu, 15 Jun 2017 05:07:52 -0700 Subject: [PATCH 0511/1029] Updated NETStandardImplicitPackageVersion to 2.0.0-* from BundledNETStandardPackageVersion --- NuGet.config | 1 + build/common.props | 2 +- build/dependencies.props | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/NuGet.config b/NuGet.config index 4e8a1f6de1..42f3f72326 100644 --- a/NuGet.config +++ b/NuGet.config @@ -3,6 +3,7 @@ + diff --git a/build/common.props b/build/common.props index a2698f3553..9f0faa97ad 100644 --- a/build/common.props +++ b/build/common.props @@ -17,7 +17,7 @@ - + diff --git a/build/dependencies.props b/build/dependencies.props index 5e815355d7..33e05e9df0 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -6,7 +6,7 @@ 10.0.1 4.7.1 2.0.0-* - $(BundledNETStandardPackageVersion) + 2.0.0-* 2.0.0-* 15.3.0-* 2.3.0-beta2-* From 483d06734a2839cc7a99ea90a235511e6bc2cee7 Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Thu, 15 Jun 2017 05:28:10 -0700 Subject: [PATCH 0512/1029] Fixed version of netstandard.library --- build/dependencies.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/dependencies.props b/build/dependencies.props index ec8387f1bd..7abf7b8e28 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,7 +4,7 @@ 4.4.0-* 2.1.0-* 15.1.1012 - $(BundledNETStandardPackageVersion) + 2.0.0-* 2.0.0-* 15.3.0-* 2.3.0-beta2-* From a8b6fa757a3ae49bfe02e0c75bb30006eb404d10 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 16 Jun 2017 08:19:31 -0700 Subject: [PATCH 0513/1029] Remove dotnet-core feed from NuGet.config --- NuGet.config | 1 - 1 file changed, 1 deletion(-) diff --git a/NuGet.config b/NuGet.config index 42f3f72326..4e8a1f6de1 100644 --- a/NuGet.config +++ b/NuGet.config @@ -3,7 +3,6 @@ - From 0742f56dbda0abbbd5e7c5f1e0e5c5458cb9b813 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Sat, 17 Jun 2017 13:45:20 -0700 Subject: [PATCH 0514/1029] Fix minor formatting error in help text for user-secrets --- .../Internal/SetCommand.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs index 5ffc7876eb..fa389ca242 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs @@ -19,7 +19,8 @@ Additional Info: This command will also handle piped input. Piped input is expected to be a valid JSON format. Examples: - dotnet user-secrets set ConnStr ""User ID=bob;Password=***"""; + dotnet user-secrets set ConnStr ""User ID=bob;Password=***"" +"; var catCmd = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? @"type .\secrets.json" From 0dfb8e474a6ca7a43eff5f12d1bc5e44daee90e0 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 19 Jun 2017 15:10:21 -0700 Subject: [PATCH 0515/1029] Remove named constraint from SqlCache tool (#310) --- src/Microsoft.Extensions.Caching.SqlConfig.Tools/SqlQueries.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/SqlQueries.cs b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/SqlQueries.cs index 110ee13caf..c8ae6f8284 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/SqlQueries.cs +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/SqlQueries.cs @@ -16,7 +16,7 @@ namespace Microsoft.Extensions.Caching.SqlConfig.Tools "ExpiresAtTime datetimeoffset NOT NULL, " + "SlidingExpirationInSeconds bigint NULL," + "AbsoluteExpiration datetimeoffset NULL, " + - "CONSTRAINT pk_Id PRIMARY KEY (Id))"; + "PRIMARY KEY (Id))"; private const string CreateNonClusteredIndexOnExpirationTimeFormat = "CREATE NONCLUSTERED INDEX Index_ExpiresAtTime ON {0}(ExpiresAtTime)"; From c816bce13a1f6eb0fc529a56dd1801d3221faafb Mon Sep 17 00:00:00 2001 From: Jass Bagga Date: Wed, 21 Jun 2017 12:35:31 -0700 Subject: [PATCH 0516/1029] Refactor invalid operation exception handling (#87) Addresses part of #80 --- .../Operations/OperationBase.cs | 31 +++++++++----- .../Operations/OperationOfT.cs | 3 ++ .../Operations/OperationType.cs | 3 +- .../OperationBaseTests.cs | 41 +++++++++++++++++++ 4 files changed, 67 insertions(+), 11 deletions(-) create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/OperationBaseTests.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationBase.cs b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationBase.cs index eb35fa7e9d..e629e2308d 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationBase.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationBase.cs @@ -2,26 +2,21 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.AspNetCore.JsonPatch.Exceptions; using Newtonsoft.Json; namespace Microsoft.AspNetCore.JsonPatch.Operations { public class OperationBase { + private string _op; + private OperationType _operationType; + [JsonIgnore] public OperationType OperationType { get { - OperationType result; - if (!Enum.TryParse(op, ignoreCase: true, result: out result)) - { - throw new JsonPatchException( - Resources.FormatInvalidJsonPatchOperation(op), - innerException: null); - } - return result; + return _operationType; } } @@ -29,7 +24,23 @@ namespace Microsoft.AspNetCore.JsonPatch.Operations public string path { get; set; } [JsonProperty("op")] - public string op { get; set; } + public string op + { + get + { + return _op; + } + set + { + OperationType result; + if (!Enum.TryParse(value, ignoreCase: true, result: out result)) + { + result = OperationType.Invalid; + } + _operationType = result; + _op = value; + } + } [JsonProperty("from")] public string from { get; set; } diff --git a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationOfT.cs b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationOfT.cs index 5af4f5d3f9..7189cf8210 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationOfT.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationOfT.cs @@ -75,6 +75,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Operations break; case OperationType.Test: throw new JsonPatchException(new JsonPatchError(objectToApplyTo, this, Resources.TestOperationNotSupported)); + case OperationType.Invalid: + throw new JsonPatchException( + Resources.FormatInvalidJsonPatchOperation(op), innerException: null); default: break; } diff --git a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationType.cs b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationType.cs index 846b07019f..725646df3a 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationType.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationType.cs @@ -10,6 +10,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Operations Replace, Move, Copy, - Test + Test, + Invalid } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/OperationBaseTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/OperationBaseTests.cs new file mode 100644 index 0000000000..955344404f --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/OperationBaseTests.cs @@ -0,0 +1,41 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch.Operations +{ + public class OperationBaseTests + { + [Theory] + [InlineData("ADd", OperationType.Add)] + [InlineData("Copy", OperationType.Copy)] + [InlineData("mOVE", OperationType.Move)] + [InlineData("REMOVE", OperationType.Remove)] + [InlineData("replace", OperationType.Replace)] + [InlineData("TeSt", OperationType.Test)] + public void SetValidOperationType(string op, OperationType operationType) + { + // Arrange + var operationBase = new OperationBase(); + operationBase.op = op; + + // Act & Assert + Assert.Equal(operationType, operationBase.OperationType); + } + + [Theory] + [InlineData("invalid", OperationType.Invalid)] + [InlineData("coppy", OperationType.Invalid)] + [InlineData("notvalid", OperationType.Invalid)] + public void InvalidOperationType_SetsOperationTypeInvalid(string op, OperationType operationType) + { + // Arrange + var operationBase = new OperationBase(); + operationBase.op = op; + + // Act & Assert + Assert.Equal(operationType, operationBase.OperationType); + } + } +} From b5ccc996f087f487d6f04c56bedb7f879d545fad Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 26 Jun 2017 09:36:15 -0700 Subject: [PATCH 0517/1029] Adding libunwind8 to .travis.yml [skip appveyor] --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index dfa226a245..fb3f3a84c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,10 @@ os: - linux - osx osx_image: xcode8.2 +addons: + apt: + packages: + - libunwind8 branches: only: - master From 16b9c59ac364950cb74a9bb49b14d25aa5126fb2 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 26 Jun 2017 09:37:33 -0700 Subject: [PATCH 0518/1029] Adding libunwind8 to .travis.yml [skip appveyor] --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 2a46104677..b10be14215 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,10 @@ os: - linux - osx osx_image: xcode8.2 +addons: + apt: + packages: + - libunwind8 branches: only: - master From 877e458da066c42ab84f067de49e9fbddd849238 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 26 Jun 2017 09:38:31 -0700 Subject: [PATCH 0519/1029] Adding libunwind8 to .travis.yml [skip appveyor] --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 2a46104677..b10be14215 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,10 @@ os: - linux - osx osx_image: xcode8.2 +addons: + apt: + packages: + - libunwind8 branches: only: - master From 61505b88a558be83bd2112f4a97954cbb1d1ce7f Mon Sep 17 00:00:00 2001 From: Jass Bagga Date: Wed, 28 Jun 2017 12:11:17 -0700 Subject: [PATCH 0520/1029] Remove use of GetTempFileName (#313) --- .../Internal/MsBuildFileSetFactory.cs | 4 ++-- .../Internal/ProjectIdResolver.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs index 1c778101db..01b8f4a996 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -71,7 +71,7 @@ namespace Microsoft.DotNet.Watcher.Internal { EnsureInitialized(); - var watchList = Path.GetTempFileName(); + var watchList = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); try { var projectDir = Path.GetDirectoryName(_projectFile); diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs index 83fdde4463..cf3105cea2 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -34,7 +34,7 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal ? configuration : DefaultConfig; - var outputFile = Path.GetTempFileName(); + var outputFile = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); try { var args = new[] From d7bdf1d4e4f2415c9ea3f50c06679b35522d4bf4 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 29 Jun 2017 08:18:18 -0700 Subject: [PATCH 0521/1029] Update dependencies.props * Update Moq to 4.7.49. * Add NETStandardImplicitPackageVersion --- build/dependencies.props | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 33e05e9df0..22b77634a0 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,10 +1,11 @@ - + 2.0.0-* 4.4.0-* 2.1.0-* 10.0.1 - 4.7.1 + 4.7.49 + 2.0.0-* 2.0.0-* 2.0.0-* 2.0.0-* From 4ce09ef0bd0a39bb8e6e7c737e3d0b1be3f9db7c Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 3 Jul 2017 14:05:27 -0700 Subject: [PATCH 0522/1029] Update LICENSE.txt text --- LICENSE.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 0bdc1962b6..7b2956ecee 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,10 +1,12 @@ -Copyright (c) .NET Foundation. All rights reserved. +Copyright (c) .NET Foundation and Contributors + +All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use -these files except in compliance with the License. You may obtain a copy of the +this file except in compliance with the License. You may obtain a copy of the License at -http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR From 0704198e554cb0b4407063a1c4c578b48ba32c71 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 3 Jul 2017 14:05:58 -0700 Subject: [PATCH 0523/1029] Update LICENSE.txt text --- LICENSE.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 0bdc1962b6..7b2956ecee 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,10 +1,12 @@ -Copyright (c) .NET Foundation. All rights reserved. +Copyright (c) .NET Foundation and Contributors + +All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use -these files except in compliance with the License. You may obtain a copy of the +this file except in compliance with the License. You may obtain a copy of the License at -http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR From fbfdbf4fe905898d18d119b2729bb5f25d8788b8 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 3 Jul 2017 14:06:32 -0700 Subject: [PATCH 0524/1029] Update LICENSE.txt text --- LICENSE.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 0bdc1962b6..7b2956ecee 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,10 +1,12 @@ -Copyright (c) .NET Foundation. All rights reserved. +Copyright (c) .NET Foundation and Contributors + +All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use -these files except in compliance with the License. You may obtain a copy of the +this file except in compliance with the License. You may obtain a copy of the License at -http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR From 83f315865388d2b09bcec7f9fcbe19b6159e50c5 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 6 Jul 2017 10:37:07 -0700 Subject: [PATCH 0525/1029] React to aspnet/BuildTools#293 [ci skip] --- build/dependencies.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/dependencies.props b/build/dependencies.props index 7abf7b8e28..70bf81b26f 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -2,7 +2,7 @@ 2.0.0-* 4.4.0-* - 2.1.0-* + 2.0.1-* 15.1.1012 2.0.0-* 2.0.0-* From 6849a49905ce6febe8699f831514e926a88c11d9 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 6 Jul 2017 10:37:33 -0700 Subject: [PATCH 0526/1029] React to aspnet/BuildTools#293 [ci skip] --- build/dependencies.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/dependencies.props b/build/dependencies.props index c81696f7f4..b4bc781894 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -2,7 +2,7 @@ 2.0.0-* 4.4.0-* - 2.1.0-* + 2.0.1-* 2.0.0-* 2.0.0-* 2.0.0-* From 4d87a52f6e6b7d360e1fa4fd950a8bc127e59cff Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 6 Jul 2017 10:38:05 -0700 Subject: [PATCH 0527/1029] React to aspnet/BuildTools#293 [ci skip] --- build/dependencies.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/dependencies.props b/build/dependencies.props index 22b77634a0..624ea78685 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -2,7 +2,7 @@ 2.0.0-* 4.4.0-* - 2.1.0-* + 2.0.1-* 10.0.1 4.7.49 2.0.0-* From 7bbcd150a2750b2615de0dedf87932bbb60551db Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Thu, 6 Jul 2017 12:07:31 -0700 Subject: [PATCH 0528/1029] Set "TreatWarningsAsErrors" before NuGet restore * Ensures our build stays clean of NuGet warnings --- build/common.props | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/common.props b/build/common.props index 73ecc03dbf..b463ac3b10 100644 --- a/build/common.props +++ b/build/common.props @@ -10,7 +10,8 @@ true true $(VersionSuffix)-$(BuildNumber) - + true + false From bcbfe745f4c649f1a7b3cda62eb0d75dec661ca6 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Thu, 6 Jul 2017 12:12:21 -0700 Subject: [PATCH 0529/1029] Set "TreatWarningsAsErrors" before NuGet restore * Ensures our build stays clean of NuGet warnings --- build/common.props | 1 + 1 file changed, 1 insertion(+) diff --git a/build/common.props b/build/common.props index da05c181bb..7abb374f12 100644 --- a/build/common.props +++ b/build/common.props @@ -9,6 +9,7 @@ true true $(VersionSuffix)-$(BuildNumber) + true From 2a2326dec94d569e27c839de7a79e3d2a1412714 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Thu, 6 Jul 2017 12:16:57 -0700 Subject: [PATCH 0530/1029] Set "TreatWarningsAsErrors" before NuGet restore * Ensures our build stays clean of NuGet warnings --- build/common.props | 1 + 1 file changed, 1 insertion(+) diff --git a/build/common.props b/build/common.props index 9f0faa97ad..c00767473e 100644 --- a/build/common.props +++ b/build/common.props @@ -10,6 +10,7 @@ true true $(VersionSuffix)-$(BuildNumber) + true From c2d4d223e7827d9dd0d0ce18d3515367c4a46cfc Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 6 Jul 2017 15:08:09 -0700 Subject: [PATCH 0531/1029] Update version suffix for 2.0.0 RTM release --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 11ac1d7f41..e55a656d79 100644 --- a/version.props +++ b/version.props @@ -2,6 +2,6 @@ 2.0.0 - preview3 + rtm From 3d92b581e710b61c2d95c0826eb0f1a0090b1ccf Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 6 Jul 2017 15:08:18 -0700 Subject: [PATCH 0532/1029] Update version suffix for 2.0.0 RTM release --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 193a5999d8..eba6b16756 100644 --- a/version.props +++ b/version.props @@ -2,6 +2,6 @@ 2.0.0 - preview3 + rtm From bd90271c85460f93fb3a067cd1c55315fc71618b Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 6 Jul 2017 15:08:27 -0700 Subject: [PATCH 0533/1029] Update version suffix for 2.0.0 RTM release --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 90a2f5b5cc..b94223e008 100644 --- a/version.props +++ b/version.props @@ -2,6 +2,6 @@ 2.0.0 - preview3 + rtm \ No newline at end of file From e4f3b9d624d8cf3fff8edd281defdb610a33b7f2 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Thu, 6 Jul 2017 15:28:29 -0700 Subject: [PATCH 0534/1029] Remove NETSTandard.Library.NETFramework --- .../Microsoft.AspNetCore.JsonPatch.Test.csproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj index d5bb8d950f..f5b8c8268a 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj @@ -7,10 +7,6 @@ netcoreapp2.0 - - - - From 615f9d1743db0839ae027047efbcdeef438f0445 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Thu, 6 Jul 2017 15:51:42 -0700 Subject: [PATCH 0535/1029] Remove NETStandard.Library.NETFramework --- build/common.props | 4 ---- 1 file changed, 4 deletions(-) diff --git a/build/common.props b/build/common.props index 7abb374f12..83647293aa 100644 --- a/build/common.props +++ b/build/common.props @@ -16,8 +16,4 @@ - - - - From 78ee75c32f42ca5d5159fe017b0b1ff1fc6b1ce4 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 10 Jul 2017 11:42:05 -0700 Subject: [PATCH 0536/1029] Branching for 2.0.0 rtm --- NuGet.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NuGet.config b/NuGet.config index 4e8a1f6de1..37f0d27ea0 100644 --- a/NuGet.config +++ b/NuGet.config @@ -2,7 +2,7 @@ - + From b4afc95b281d8f2bee775ee58bf4b028e9a0c009 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 10 Jul 2017 11:42:52 -0700 Subject: [PATCH 0537/1029] Branching for 2.0.0 rtm --- NuGet.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NuGet.config b/NuGet.config index 4e8a1f6de1..37f0d27ea0 100644 --- a/NuGet.config +++ b/NuGet.config @@ -2,7 +2,7 @@ - + From 28801a17e7786daabd31cd27665cb988495a772d Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 10 Jul 2017 11:43:45 -0700 Subject: [PATCH 0538/1029] Branching for 2.0.0 rtm --- NuGet.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NuGet.config b/NuGet.config index 4e8a1f6de1..37f0d27ea0 100644 --- a/NuGet.config +++ b/NuGet.config @@ -2,7 +2,7 @@ - + From 15f1240ff814d152a5cb64f82016bc8eb86be94e Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 10 Jul 2017 11:57:55 -0700 Subject: [PATCH 0539/1029] Updating KoreBuild branch --- build.ps1 | 2 +- build.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.ps1 b/build.ps1 index 5bf0e2c113..1785334385 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/2.0.0.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index b0bcadb579..5e27ed8efb 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/2.0.0.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi From 1fbbf5e72ff21df8418224b2d4ecd07ff3fcbefd Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 10 Jul 2017 11:57:57 -0700 Subject: [PATCH 0540/1029] Updating KoreBuild branch --- build.ps1 | 2 +- build.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.ps1 b/build.ps1 index 5bf0e2c113..1785334385 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/2.0.0.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index b0bcadb579..5e27ed8efb 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/2.0.0.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi From 1481037d6ec436fd6d290bef5deeb115099d96e1 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 10 Jul 2017 11:57:58 -0700 Subject: [PATCH 0541/1029] Updating KoreBuild branch --- build.ps1 | 2 +- build.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.ps1 b/build.ps1 index 5bf0e2c113..1785334385 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ cd $PSScriptRoot $repoFolder = $PSScriptRoot $env:REPO_FOLDER = $repoFolder -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/2.0.0.zip" if ($env:KOREBUILD_ZIP) { $koreBuildZip=$env:KOREBUILD_ZIP diff --git a/build.sh b/build.sh index b0bcadb579..5e27ed8efb 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/2.0.0.zip" if [ ! -z $KOREBUILD_ZIP ]; then koreBuildZip=$KOREBUILD_ZIP fi From 8f13caf33f263f76f72d2ab0f356e9c30bc09905 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Fri, 7 Jul 2017 14:56:16 -0700 Subject: [PATCH 0542/1029] Skip first time experience on Appveyor --- appveyor.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 1041615c68..31efd8196f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -init: +init: - git config --global core.autocrlf true branches: only: @@ -9,6 +9,10 @@ branches: build_script: - ps: .\build.ps1 clone_depth: 1 +environment: + global: + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + DOTNET_CLI_TELEMETRY_OPTOUT: 1 test: off deploy: off os: Visual Studio 2017 From e9d7403c6f8f5d1cb3172d5ebcbc0eb498cdae65 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Fri, 7 Jul 2017 14:55:40 -0700 Subject: [PATCH 0543/1029] Skip first time experience on Appveyor --- appveyor.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 1041615c68..31efd8196f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -init: +init: - git config --global core.autocrlf true branches: only: @@ -9,6 +9,10 @@ branches: build_script: - ps: .\build.ps1 clone_depth: 1 +environment: + global: + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + DOTNET_CLI_TELEMETRY_OPTOUT: 1 test: off deploy: off os: Visual Studio 2017 From 3c50592c9b3608d662294208b33b007596664939 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Fri, 7 Jul 2017 14:55:05 -0700 Subject: [PATCH 0544/1029] Skip first time experience on Appveyor --- appveyor.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 778c4c4e0d..8a514a70a3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -init: +init: - git config --global core.autocrlf true branches: only: @@ -10,6 +10,10 @@ branches: build_script: - ps: .\build.ps1 clone_depth: 1 +environment: + global: + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + DOTNET_CLI_TELEMETRY_OPTOUT: 1 test: off deploy: off os: Visual Studio 2017 From 5618fa52d822a5787b0287de80b7ad042e03cece Mon Sep 17 00:00:00 2001 From: Mike Harder Date: Tue, 11 Jul 2017 17:47:28 -0700 Subject: [PATCH 0545/1029] Update MSBuild to 15.3.0-* (#320) - Matches version shipping with Visual Studio 15.3 --- build/dependencies.props | 2 +- .../Microsoft.AspNetCore.CertificateGeneration.Task.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 70bf81b26f..c537163d57 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,7 +3,7 @@ 2.0.0-* 4.4.0-* 2.0.1-* - 15.1.1012 + 15.3.0-* 2.0.0-* 2.0.0-* 15.3.0-* diff --git a/src/Microsoft.AspNetCore.CertificateGeneration.Task/Microsoft.AspNetCore.CertificateGeneration.Task.csproj b/src/Microsoft.AspNetCore.CertificateGeneration.Task/Microsoft.AspNetCore.CertificateGeneration.Task.csproj index 59e932ab97..e4ff13938a 100644 --- a/src/Microsoft.AspNetCore.CertificateGeneration.Task/Microsoft.AspNetCore.CertificateGeneration.Task.csproj +++ b/src/Microsoft.AspNetCore.CertificateGeneration.Task/Microsoft.AspNetCore.CertificateGeneration.Task.csproj @@ -14,7 +14,7 @@ - + From 5ce07b212344b0708f6b54b7518df7a5c1ddbb87 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Wed, 12 Jul 2017 16:20:12 -0700 Subject: [PATCH 0546/1029] Update MSBuild version --- build/dependencies.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/dependencies.props b/build/dependencies.props index c537163d57..8d815ea49c 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,7 +3,7 @@ 2.0.0-* 4.4.0-* 2.0.1-* - 15.3.0-* + 15.3.406 2.0.0-* 2.0.0-* 15.3.0-* From 76aa9b26fc97ffe7148a44d29b623dc888cf0ca0 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 13 Jul 2017 11:53:52 -0700 Subject: [PATCH 0547/1029] Use async main in dotnet-watch --- .../Microsoft.DotNet.Watcher.Tools.csproj | 1 + src/Microsoft.DotNet.Watcher.Tools/Program.cs | 21 ++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj index f124d96c03..ee16dd6429 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj @@ -3,6 +3,7 @@ + 7.1 netcoreapp2.0 dotnet-watch exe diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index 1aea715ddf..c8832649fb 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -31,15 +31,21 @@ namespace Microsoft.DotNet.Watcher _reporter = CreateReporter(verbose: true, quiet: false, console: _console); } - public static int Main(string[] args) + public static async Task Main(string[] args) { - DebugHelper.HandleDebugSwitch(ref args); - using (var program = new Program(PhysicalConsole.Singleton, Directory.GetCurrentDirectory())) + try { - return program - .RunAsync(args) - .GetAwaiter() - .GetResult(); + DebugHelper.HandleDebugSwitch(ref args); + using (var program = new Program(PhysicalConsole.Singleton, Directory.GetCurrentDirectory())) + { + return await program.RunAsync(args); + } + } + catch (Exception ex) + { + Console.Error.WriteLine("Unexpected error:"); + Console.Error.WriteLine(ex.ToString()); + return 1; } } @@ -200,7 +206,6 @@ namespace Microsoft.DotNet.Watcher private static IReporter CreateReporter(bool verbose, bool quiet, IConsole console) => new PrefixConsoleReporter(console, verbose || CliContext.IsGlobalVerbose(), quiet); - private string NormalizePath(string path) { if (path == null || Path.IsPathRooted(path)) From bc3f2cbcab433000116e9636b46a60149b6dcfb5 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Tue, 18 Jul 2017 10:59:11 -0700 Subject: [PATCH 0548/1029] Update MSBuild version --- build/dependencies.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/dependencies.props b/build/dependencies.props index 8d815ea49c..923dcc6cbd 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,7 +3,7 @@ 2.0.0-* 4.4.0-* 2.0.1-* - 15.3.406 + 15.3.407 2.0.0-* 2.0.0-* 15.3.0-* From 465f09b3364a551771b6a3d5a22c344ec650dd0e Mon Sep 17 00:00:00 2001 From: Mike Harder Date: Wed, 19 Jul 2017 09:38:17 -0700 Subject: [PATCH 0549/1029] Remove duplicate NETStandardImplicitPackageVersion (#95) --- build/dependencies.props | 1 - 1 file changed, 1 deletion(-) diff --git a/build/dependencies.props b/build/dependencies.props index 624ea78685..f04855911e 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -7,7 +7,6 @@ 4.7.49 2.0.0-* 2.0.0-* - 2.0.0-* 2.0.0-* 15.3.0-* 2.3.0-beta2-* From 08c6291db29791729e35d36484c26c2a4cb32698 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Thu, 20 Jul 2017 14:23:02 -0700 Subject: [PATCH 0550/1029] Update MSBuild version --- build/dependencies.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/dependencies.props b/build/dependencies.props index 923dcc6cbd..24a58e6f62 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,7 +3,7 @@ 2.0.0-* 4.4.0-* 2.0.1-* - 15.3.407 + 15.3.409 2.0.0-* 2.0.0-* 15.3.0-* From 443df66f3b3caf1df982a8246d7db87aee36fe08 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Fri, 21 Jul 2017 12:58:22 -0700 Subject: [PATCH 0551/1029] 2.0.0-rtm to 2.1.0-preview1 --- version.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.props b/version.props index e55a656d79..5a5f18889b 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ - 2.0.0 - rtm + 2.1.0 + preview1 From de5d7de12469c312992cf2e9867314ee91a2622e Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Fri, 21 Jul 2017 12:59:18 -0700 Subject: [PATCH 0552/1029] 2.0.0-rtm to 2.1.0-preview1 --- version.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.props b/version.props index eba6b16756..1ea46af42a 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ - 2.0.0 - rtm + 2.1.0 + preview1 From 7f2a1def984a685f1ed39a70cf47c6cc868f0914 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Fri, 21 Jul 2017 13:00:17 -0700 Subject: [PATCH 0553/1029] 2.0.0-rtm to 2.1.0-preview1 --- version.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.props b/version.props index b94223e008..cb77b43933 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ - 2.0.0 - rtm + 2.1.0 + preview1 \ No newline at end of file From 44607ecf18c3858f585002b700443dc504217cae Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Mon, 24 Jul 2017 17:55:29 -0700 Subject: [PATCH 0554/1029] Set AspNetCoreVersion --- build/dependencies.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/dependencies.props b/build/dependencies.props index 24a58e6f62..7e2e1c2271 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,6 +1,6 @@ - 2.0.0-* + 2.1.0-* 4.4.0-* 2.0.1-* 15.3.409 From 2ac5f3617e9bd157e08d701429abb8b5943fe720 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Mon, 24 Jul 2017 17:56:12 -0700 Subject: [PATCH 0555/1029] Set AspNetCoreVersion --- build/dependencies.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/dependencies.props b/build/dependencies.props index b4bc781894..833d909a0d 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,6 +1,6 @@ - 2.0.0-* + 2.1.0-* 4.4.0-* 2.0.1-* 2.0.0-* From db9eee83b78e20d32232e60c382cea006265aa9c Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Mon, 24 Jul 2017 17:56:54 -0700 Subject: [PATCH 0556/1029] Set AspNetCoreVersion --- build/dependencies.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index f04855911e..0071bd6d24 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,6 +1,6 @@ - + - 2.0.0-* + 2.1.0-* 4.4.0-* 2.0.1-* 10.0.1 From 3cdc49764270fec53e80644f87fc216c9871d4d3 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 25 Jul 2017 15:12:54 -0700 Subject: [PATCH 0557/1029] Updating to InternalAspNetCoreSdkVersion 2.1.1-* --- build/dependencies.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/dependencies.props b/build/dependencies.props index 7e2e1c2271..2734d91184 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -2,7 +2,7 @@ 2.1.0-* 4.4.0-* - 2.0.1-* + 2.1.1-* 15.3.409 2.0.0-* 2.0.0-* From 7d5f3511d1e837a8760a5916c3ce657964cd9e53 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 25 Jul 2017 15:13:18 -0700 Subject: [PATCH 0558/1029] Updating to InternalAspNetCoreSdkVersion 2.1.1-* --- build/dependencies.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/dependencies.props b/build/dependencies.props index 833d909a0d..3c71bd378d 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -2,7 +2,7 @@ 2.1.0-* 4.4.0-* - 2.0.1-* + 2.1.1-* 2.0.0-* 2.0.0-* 2.0.0-* From eaefe914eace7fa16e8deb497f07d313fbc0b366 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 25 Jul 2017 15:13:44 -0700 Subject: [PATCH 0559/1029] Updating to InternalAspNetCoreSdkVersion 2.1.1-* --- build/dependencies.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/dependencies.props b/build/dependencies.props index 0071bd6d24..f2fb071ace 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -2,7 +2,7 @@ 2.1.0-* 4.4.0-* - 2.0.1-* + 2.1.1-* 10.0.1 4.7.49 2.0.0-* From 04b98cf1b091d8a7fa27d3bfd8330b16114c7a0f Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 25 Jul 2017 16:31:31 -0700 Subject: [PATCH 0560/1029] Update bootstrappers to use the compiled version of KoreBuild [ci skip] --- .gitignore | 2 + build.cmd | 2 +- build.ps1 | 218 ++++++++++++++++++++++++++++++++----------- build.sh | 224 +++++++++++++++++++++++++++++++++++++-------- build/common.props | 2 +- version.props | 7 -- version.xml | 8 ++ 7 files changed, 363 insertions(+), 100 deletions(-) delete mode 100644 version.props create mode 100644 version.xml diff --git a/.gitignore b/.gitignore index c595526f32..44848d7813 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,5 @@ testWorkDir/ *.nuget.targets .idea/ .dotnet/ +global.json +korebuild-lock.txt diff --git a/build.cmd b/build.cmd index 7d4894cb4a..b6c8d24864 100644 --- a/build.cmd +++ b/build.cmd @@ -1,2 +1,2 @@ @ECHO OFF -PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*; exit $LASTEXITCODE" \ No newline at end of file +PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*; exit $LASTEXITCODE" diff --git a/build.ps1 b/build.ps1 index 5bf0e2c113..d5eb4d5cf2 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,67 +1,177 @@ -$ErrorActionPreference = "Stop" +#!/usr/bin/env powershell +#requires -version 4 -function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $retries) -{ - while($true) - { - try - { - Invoke-WebRequest $url -OutFile $downloadLocation - break - } - catch - { - $exceptionMessage = $_.Exception.Message - Write-Host "Failed to download '$url': $exceptionMessage" - if ($retries -gt 0) { - $retries-- - Write-Host "Waiting 10 seconds before retrying. Retries left: $retries" - Start-Sleep -Seconds 10 +<# +.SYNOPSIS +Build this repository +.DESCRIPTION +Downloads korebuild if required. Then builds the repository. + +.PARAMETER Path +The folder to build. Defaults to the folder containing this script. + +.PARAMETER Channel +The channel of KoreBuild to download. Overrides the value from the config file. + +.PARAMETER DotNetHome +The directory where .NET Core tools will be stored. + +.PARAMETER ToolsSource +The base url where build tools can be downloaded. Overrides the value from the config file. + +.PARAMETER Update +Updates KoreBuild to the latest version even if a lock file is present. + +.PARAMETER ConfigFile +The path to the configuration file that stores values. Defaults to version.xml. + +.PARAMETER MSBuildArgs +Arguments to be passed to MSBuild + +.NOTES +This function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be. +When the lockfile is not present, KoreBuild will create one using latest available version from $Channel. + +The $ConfigFile is expected to be an XML file. It is optional, and the configuration values in it are optional as well. + +.EXAMPLE +Example config file: +```xml + + + + dev + https://aspnetcore.blob.core.windows.net/buildtools + + +``` +#> +[CmdletBinding(PositionalBinding = $false)] +param( + [string]$Path = $PSScriptRoot, + [Alias('c')] + [string]$Channel, + [Alias('d')] + [string]$DotNetHome, + [Alias('s')] + [string]$ToolsSource, + [Alias('u')] + [switch]$Update, + [string]$ConfigFile = (Join-Path $PSScriptRoot 'version.xml'), + [Parameter(ValueFromRemainingArguments = $true)] + [string[]]$MSBuildArgs +) + +Set-StrictMode -Version 2 +$ErrorActionPreference = 'Stop' + +# +# Functions +# + +function Get-KoreBuild { + + $lockFile = Join-Path $Path 'korebuild-lock.txt' + + if (!(Test-Path $lockFile) -or $Update) { + Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile + } + + $version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1 + if (!$version) { + Write-Error "Failed to parse version from $lockFile. Expected a line that begins with 'version:'" + } + $version = $version.TrimStart('version:').Trim() + $korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version) + + if (!(Test-Path $korebuildPath)) { + Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version" + New-Item -ItemType Directory -Path $korebuildPath | Out-Null + $remotePath = "$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip" + + try { + $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip" + Get-RemoteFile $remotePath $tmpfile + if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) { + # Use built-in commands where possible as they are cross-plat compatible + Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath } - else - { - $exception = $_.Exception - throw $exception + else { + # Fallback to old approach for old installations of PowerShell + Add-Type -AssemblyName System.IO.Compression.FileSystem + [System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath) } } + catch { + Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore + throw + } + finally { + Remove-Item $tmpfile -ErrorAction Ignore + } } + + return $korebuildPath } -cd $PSScriptRoot - -$repoFolder = $PSScriptRoot -$env:REPO_FOLDER = $repoFolder - -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" -if ($env:KOREBUILD_ZIP) -{ - $koreBuildZip=$env:KOREBUILD_ZIP +function Join-Paths([string]$path, [string[]]$childPaths) { + $childPaths | ForEach-Object { $path = Join-Path $path $_ } + return $path } -$buildFolder = ".build" -$buildFile="$buildFolder\KoreBuild.ps1" - -if (!(Test-Path $buildFolder)) { - Write-Host "Downloading KoreBuild from $koreBuildZip" - - $tempFolder=$env:TEMP + "\KoreBuild-" + [guid]::NewGuid() - New-Item -Path "$tempFolder" -Type directory | Out-Null - - $localZipFile="$tempFolder\korebuild.zip" - - DownloadWithRetry -url $koreBuildZip -downloadLocation $localZipFile -retries 6 - - Add-Type -AssemblyName System.IO.Compression.FileSystem - [System.IO.Compression.ZipFile]::ExtractToDirectory($localZipFile, $tempFolder) - - New-Item -Path "$buildFolder" -Type directory | Out-Null - copy-item "$tempFolder\**\build\*" $buildFolder -Recurse - - # Cleanup - if (Test-Path $tempFolder) { - Remove-Item -Recurse -Force $tempFolder +function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) { + if ($RemotePath -notlike 'http*') { + Copy-Item $RemotePath $LocalPath + return } + + $retries = 10 + while ($retries -gt 0) { + $retries -= 1 + try { + Invoke-WebRequest -UseBasicParsing -Uri $RemotePath -OutFile $LocalPath + return + } + catch { + Write-Verbose "Request failed. $retries retries remaining" + } + } + + Write-Error "Download failed: '$RemotePath'." } -&"$buildFile" @args +# +# Main +# + +# Load configuration or set defaults + +if (Test-Path $ConfigFile) { + [xml] $config = Get-Content $ConfigFile + if (!($Channel)) { [string] $Channel = Select-Xml -Xml $config -XPath '/Project/PropertyGroup/KoreBuildChannel' } + if (!($ToolsSource)) { [string] $ToolsSource = Select-Xml -Xml $config -XPath '/Project/PropertyGroup/KoreBuildToolsSource' } +} + +if (!$DotNetHome) { + $DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } ` + elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} ` + elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}` + else { Join-Path $PSScriptRoot '.dotnet'} +} + +if (!$Channel) { $Channel = 'dev' } +if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } + +# Execute + +$korebuildPath = Get-KoreBuild +Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1') + +try { + Install-Tools $ToolsSource $DotNetHome + Invoke-RepositoryBuild $Path @MSBuildArgs +} +finally { + Remove-Module 'KoreBuild' -ErrorAction Ignore +} diff --git a/build.sh b/build.sh index b0bcadb579..ab590e62f1 100755 --- a/build.sh +++ b/build.sh @@ -1,46 +1,196 @@ #!/usr/bin/env bash -repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" -if [ ! -z $KOREBUILD_ZIP ]; then - koreBuildZip=$KOREBUILD_ZIP -fi +set -euo pipefail -buildFolder=".build" -buildFile="$buildFolder/KoreBuild.sh" +# +# variables +# -if test ! -d $buildFolder; then - echo "Downloading KoreBuild from $koreBuildZip" +RESET="\033[0m" +RED="\033[0;31m" +MAGENTA="\033[0;95m" +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +[ -z "${DOTNET_HOME:-}"] && DOTNET_HOME="$HOME/.dotnet" +config_file="$DIR/version.xml" +verbose=false +update=false +repo_path="$DIR" +channel='' +tools_source='' - tempFolder="/tmp/KoreBuild-$(uuidgen)" - mkdir $tempFolder +# +# Functions +# +__usage() { + echo "Usage: $(basename ${BASH_SOURCE[0]}) [options] [[--] ...]" + echo "" + echo "Arguments:" + echo " ... Arguments passed to MSBuild. Variable number of arguments allowed." + echo "" + echo "Options:" + echo " --verbose Show verbose output." + echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." + echo " --config-file TThe path to the configuration file that stores values. Defaults to version.xml." + echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." + echo " --path The directory to build. Defaults to the directory containing the script." + echo " -s|--tools-source The base url where build tools can be downloaded. Overrides the value from the config file." + echo " -u|--update Update to the latest KoreBuild even if the lock file is present." + echo "" + echo "Description:" + echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." + echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel." - localZipFile="$tempFolder/korebuild.zip" - - retries=6 - until (wget -O $localZipFile $koreBuildZip 2>/dev/null || curl -o $localZipFile --location $koreBuildZip 2>/dev/null) - do - echo "Failed to download '$koreBuildZip'" - if [ "$retries" -le 0 ]; then - exit 1 - fi - retries=$((retries - 1)) - echo "Waiting 10 seconds before retrying. Retries left: $retries" - sleep 10s - done - - unzip -q -d $tempFolder $localZipFile - - mkdir $buildFolder - cp -r $tempFolder/**/build/** $buildFolder - - chmod +x $buildFile - - # Cleanup - if test -d $tempFolder; then - rm -rf $tempFolder + if [[ "${1:-}" != '--no-exit' ]]; then + exit 2 fi +} + +get_korebuild() { + local lock_file="$repo_path/korebuild-lock.txt" + if [ ! -f $lock_file ] || [ "$update" = true ]; then + __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" $lock_file + fi + local version="$(grep 'version:*' -m 1 $lock_file)" + if [[ "$version" == '' ]]; then + __error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'" + return 1 + fi + version="$(echo ${version#version:} | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" + + { + if [ ! -d "$korebuild_path" ]; then + mkdir -p "$korebuild_path" + local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" + tmpfile="$(mktemp)" + echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" + if __get_remote_file $remote_path $tmpfile; then + unzip -q -d "$korebuild_path" $tmpfile + fi + rm $tmpfile || true + fi + + source "$korebuild_path/KoreBuild.sh" + } || { + if [ -d "$korebuild_path" ]; then + echo "Cleaning up after failed installation" + rm -rf "$korebuild_path" || true + fi + return 1 + } +} + +__error() { + echo -e "${RED}$@${RESET}" 1>&2 +} + +__machine_has() { + hash "$1" > /dev/null 2>&1 + return $? +} + +__get_remote_file() { + local remote_path=$1 + local local_path=$2 + + if [[ "$remote_path" != 'http'* ]]; then + cp $remote_path $local_path + return 0 + fi + + failed=false + if __machine_has wget; then + wget --tries 10 --quiet -O $local_path $remote_path || failed=true + fi + + if [ "$failed" = true ] && __machine_has curl; then + failed=false + curl --retry 10 -sSL -f --create-dirs -o $local_path $remote_path || failed=true + fi + + if [ "$failed" = true ]; then + __error "Download failed: $remote_path" 1>&2 + return 1 + fi +} + +__read_dom () { local IFS=\> ; read -d \< ENTITY CONTENT ;} + +# +# main +# + +while [[ $# > 0 ]]; do + case $1 in + -\?|-h|--help) + __usage --no-exit + exit 0 + ;; + -c|--channel|-Channel) + shift + channel=${1:-} + [ -z "$channel" ] && __usage + ;; + --config-file|-ConfigFile) + shift + config_file="${1:-}" + [ -z "$config_file" ] && __usage + ;; + -d|--dotnet-home|-DotNetHome) + shift + DOTNET_HOME=${1:-} + [ -z "$DOTNET_HOME" ] && __usage + ;; + --path|-Path) + shift + repo_path="${1:-}" + [ -z "$repo_path" ] && __usage + ;; + -s|--tools-source|-ToolsSource) + shift + tools_source="${1:-}" + [ -z "$tools_source" ] && __usage + ;; + -u|--update|-Update) + update=true + ;; + --verbose|-Verbose) + verbose=true + ;; + --) + shift + break + ;; + *) + break + ;; + esac + shift +done + +if ! __machine_has unzip; then + __error 'Missing required command: unzip' + exit 1 fi -$buildFile -r $repoFolder "$@" +if ! __machine_has curl && ! __machine_has wget; then + __error 'Missing required command. Either wget or curl is required.' + exit 1 +fi + +if [ -f $config_file ]; then + comment=false + while __read_dom; do + if [ "$comment" = true ]; then [[ $CONTENT == *'-->'* ]] && comment=false ; continue; fi + if [[ $ENTITY == '!--'* ]]; then comment=true; continue; fi + if [ -z "$channel" ] && [[ $ENTITY == "KoreBuildChannel" ]]; then channel=$CONTENT; fi + if [ -z "$tools_source" ] && [[ $ENTITY == "KoreBuildToolsSource" ]]; then tools_source=$CONTENT; fi + done < $config_file +fi + +[ -z "$channel" ] && channel='dev' +[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' + +get_korebuild +install_tools "$tools_source" "$DOTNET_HOME" +invoke_repository_build "$repo_path" $@ diff --git a/build/common.props b/build/common.props index b463ac3b10..2d638b0045 100644 --- a/build/common.props +++ b/build/common.props @@ -1,6 +1,6 @@ - + Microsoft .NET diff --git a/version.props b/version.props deleted file mode 100644 index 5a5f18889b..0000000000 --- a/version.props +++ /dev/null @@ -1,7 +0,0 @@ - - - - 2.1.0 - preview1 - - diff --git a/version.xml b/version.xml new file mode 100644 index 0000000000..3c05022b7d --- /dev/null +++ b/version.xml @@ -0,0 +1,8 @@ + + + + dev + 2.1.0 + preview1 + + From 4b747a75bded9ef1e8648f98f640d0096b631044 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 25 Jul 2017 16:32:07 -0700 Subject: [PATCH 0561/1029] Update bootstrappers to use the compiled version of KoreBuild [ci skip] --- .gitignore | 1 + build.cmd | 2 +- build.ps1 | 218 +++++++++++++++++++++++++--------- build.sh | 224 +++++++++++++++++++++++++++++------ build/common.props | 2 +- version.props => version.xml | 3 +- 6 files changed, 356 insertions(+), 94 deletions(-) rename version.props => version.xml (55%) diff --git a/.gitignore b/.gitignore index 6da3c6a3e9..a7fdfd773b 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,4 @@ node_modules .build/ .testPublish/ global.json +korebuild-lock.txt diff --git a/build.cmd b/build.cmd index 7d4894cb4a..b6c8d24864 100644 --- a/build.cmd +++ b/build.cmd @@ -1,2 +1,2 @@ @ECHO OFF -PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*; exit $LASTEXITCODE" \ No newline at end of file +PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*; exit $LASTEXITCODE" diff --git a/build.ps1 b/build.ps1 index 5bf0e2c113..d5eb4d5cf2 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,67 +1,177 @@ -$ErrorActionPreference = "Stop" +#!/usr/bin/env powershell +#requires -version 4 -function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $retries) -{ - while($true) - { - try - { - Invoke-WebRequest $url -OutFile $downloadLocation - break - } - catch - { - $exceptionMessage = $_.Exception.Message - Write-Host "Failed to download '$url': $exceptionMessage" - if ($retries -gt 0) { - $retries-- - Write-Host "Waiting 10 seconds before retrying. Retries left: $retries" - Start-Sleep -Seconds 10 +<# +.SYNOPSIS +Build this repository +.DESCRIPTION +Downloads korebuild if required. Then builds the repository. + +.PARAMETER Path +The folder to build. Defaults to the folder containing this script. + +.PARAMETER Channel +The channel of KoreBuild to download. Overrides the value from the config file. + +.PARAMETER DotNetHome +The directory where .NET Core tools will be stored. + +.PARAMETER ToolsSource +The base url where build tools can be downloaded. Overrides the value from the config file. + +.PARAMETER Update +Updates KoreBuild to the latest version even if a lock file is present. + +.PARAMETER ConfigFile +The path to the configuration file that stores values. Defaults to version.xml. + +.PARAMETER MSBuildArgs +Arguments to be passed to MSBuild + +.NOTES +This function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be. +When the lockfile is not present, KoreBuild will create one using latest available version from $Channel. + +The $ConfigFile is expected to be an XML file. It is optional, and the configuration values in it are optional as well. + +.EXAMPLE +Example config file: +```xml + + + + dev + https://aspnetcore.blob.core.windows.net/buildtools + + +``` +#> +[CmdletBinding(PositionalBinding = $false)] +param( + [string]$Path = $PSScriptRoot, + [Alias('c')] + [string]$Channel, + [Alias('d')] + [string]$DotNetHome, + [Alias('s')] + [string]$ToolsSource, + [Alias('u')] + [switch]$Update, + [string]$ConfigFile = (Join-Path $PSScriptRoot 'version.xml'), + [Parameter(ValueFromRemainingArguments = $true)] + [string[]]$MSBuildArgs +) + +Set-StrictMode -Version 2 +$ErrorActionPreference = 'Stop' + +# +# Functions +# + +function Get-KoreBuild { + + $lockFile = Join-Path $Path 'korebuild-lock.txt' + + if (!(Test-Path $lockFile) -or $Update) { + Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile + } + + $version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1 + if (!$version) { + Write-Error "Failed to parse version from $lockFile. Expected a line that begins with 'version:'" + } + $version = $version.TrimStart('version:').Trim() + $korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version) + + if (!(Test-Path $korebuildPath)) { + Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version" + New-Item -ItemType Directory -Path $korebuildPath | Out-Null + $remotePath = "$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip" + + try { + $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip" + Get-RemoteFile $remotePath $tmpfile + if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) { + # Use built-in commands where possible as they are cross-plat compatible + Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath } - else - { - $exception = $_.Exception - throw $exception + else { + # Fallback to old approach for old installations of PowerShell + Add-Type -AssemblyName System.IO.Compression.FileSystem + [System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath) } } + catch { + Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore + throw + } + finally { + Remove-Item $tmpfile -ErrorAction Ignore + } } + + return $korebuildPath } -cd $PSScriptRoot - -$repoFolder = $PSScriptRoot -$env:REPO_FOLDER = $repoFolder - -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" -if ($env:KOREBUILD_ZIP) -{ - $koreBuildZip=$env:KOREBUILD_ZIP +function Join-Paths([string]$path, [string[]]$childPaths) { + $childPaths | ForEach-Object { $path = Join-Path $path $_ } + return $path } -$buildFolder = ".build" -$buildFile="$buildFolder\KoreBuild.ps1" - -if (!(Test-Path $buildFolder)) { - Write-Host "Downloading KoreBuild from $koreBuildZip" - - $tempFolder=$env:TEMP + "\KoreBuild-" + [guid]::NewGuid() - New-Item -Path "$tempFolder" -Type directory | Out-Null - - $localZipFile="$tempFolder\korebuild.zip" - - DownloadWithRetry -url $koreBuildZip -downloadLocation $localZipFile -retries 6 - - Add-Type -AssemblyName System.IO.Compression.FileSystem - [System.IO.Compression.ZipFile]::ExtractToDirectory($localZipFile, $tempFolder) - - New-Item -Path "$buildFolder" -Type directory | Out-Null - copy-item "$tempFolder\**\build\*" $buildFolder -Recurse - - # Cleanup - if (Test-Path $tempFolder) { - Remove-Item -Recurse -Force $tempFolder +function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) { + if ($RemotePath -notlike 'http*') { + Copy-Item $RemotePath $LocalPath + return } + + $retries = 10 + while ($retries -gt 0) { + $retries -= 1 + try { + Invoke-WebRequest -UseBasicParsing -Uri $RemotePath -OutFile $LocalPath + return + } + catch { + Write-Verbose "Request failed. $retries retries remaining" + } + } + + Write-Error "Download failed: '$RemotePath'." } -&"$buildFile" @args +# +# Main +# + +# Load configuration or set defaults + +if (Test-Path $ConfigFile) { + [xml] $config = Get-Content $ConfigFile + if (!($Channel)) { [string] $Channel = Select-Xml -Xml $config -XPath '/Project/PropertyGroup/KoreBuildChannel' } + if (!($ToolsSource)) { [string] $ToolsSource = Select-Xml -Xml $config -XPath '/Project/PropertyGroup/KoreBuildToolsSource' } +} + +if (!$DotNetHome) { + $DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } ` + elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} ` + elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}` + else { Join-Path $PSScriptRoot '.dotnet'} +} + +if (!$Channel) { $Channel = 'dev' } +if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } + +# Execute + +$korebuildPath = Get-KoreBuild +Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1') + +try { + Install-Tools $ToolsSource $DotNetHome + Invoke-RepositoryBuild $Path @MSBuildArgs +} +finally { + Remove-Module 'KoreBuild' -ErrorAction Ignore +} diff --git a/build.sh b/build.sh index b0bcadb579..ab590e62f1 100755 --- a/build.sh +++ b/build.sh @@ -1,46 +1,196 @@ #!/usr/bin/env bash -repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" -if [ ! -z $KOREBUILD_ZIP ]; then - koreBuildZip=$KOREBUILD_ZIP -fi +set -euo pipefail -buildFolder=".build" -buildFile="$buildFolder/KoreBuild.sh" +# +# variables +# -if test ! -d $buildFolder; then - echo "Downloading KoreBuild from $koreBuildZip" +RESET="\033[0m" +RED="\033[0;31m" +MAGENTA="\033[0;95m" +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +[ -z "${DOTNET_HOME:-}"] && DOTNET_HOME="$HOME/.dotnet" +config_file="$DIR/version.xml" +verbose=false +update=false +repo_path="$DIR" +channel='' +tools_source='' - tempFolder="/tmp/KoreBuild-$(uuidgen)" - mkdir $tempFolder +# +# Functions +# +__usage() { + echo "Usage: $(basename ${BASH_SOURCE[0]}) [options] [[--] ...]" + echo "" + echo "Arguments:" + echo " ... Arguments passed to MSBuild. Variable number of arguments allowed." + echo "" + echo "Options:" + echo " --verbose Show verbose output." + echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." + echo " --config-file TThe path to the configuration file that stores values. Defaults to version.xml." + echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." + echo " --path The directory to build. Defaults to the directory containing the script." + echo " -s|--tools-source The base url where build tools can be downloaded. Overrides the value from the config file." + echo " -u|--update Update to the latest KoreBuild even if the lock file is present." + echo "" + echo "Description:" + echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." + echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel." - localZipFile="$tempFolder/korebuild.zip" - - retries=6 - until (wget -O $localZipFile $koreBuildZip 2>/dev/null || curl -o $localZipFile --location $koreBuildZip 2>/dev/null) - do - echo "Failed to download '$koreBuildZip'" - if [ "$retries" -le 0 ]; then - exit 1 - fi - retries=$((retries - 1)) - echo "Waiting 10 seconds before retrying. Retries left: $retries" - sleep 10s - done - - unzip -q -d $tempFolder $localZipFile - - mkdir $buildFolder - cp -r $tempFolder/**/build/** $buildFolder - - chmod +x $buildFile - - # Cleanup - if test -d $tempFolder; then - rm -rf $tempFolder + if [[ "${1:-}" != '--no-exit' ]]; then + exit 2 fi +} + +get_korebuild() { + local lock_file="$repo_path/korebuild-lock.txt" + if [ ! -f $lock_file ] || [ "$update" = true ]; then + __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" $lock_file + fi + local version="$(grep 'version:*' -m 1 $lock_file)" + if [[ "$version" == '' ]]; then + __error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'" + return 1 + fi + version="$(echo ${version#version:} | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" + + { + if [ ! -d "$korebuild_path" ]; then + mkdir -p "$korebuild_path" + local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" + tmpfile="$(mktemp)" + echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" + if __get_remote_file $remote_path $tmpfile; then + unzip -q -d "$korebuild_path" $tmpfile + fi + rm $tmpfile || true + fi + + source "$korebuild_path/KoreBuild.sh" + } || { + if [ -d "$korebuild_path" ]; then + echo "Cleaning up after failed installation" + rm -rf "$korebuild_path" || true + fi + return 1 + } +} + +__error() { + echo -e "${RED}$@${RESET}" 1>&2 +} + +__machine_has() { + hash "$1" > /dev/null 2>&1 + return $? +} + +__get_remote_file() { + local remote_path=$1 + local local_path=$2 + + if [[ "$remote_path" != 'http'* ]]; then + cp $remote_path $local_path + return 0 + fi + + failed=false + if __machine_has wget; then + wget --tries 10 --quiet -O $local_path $remote_path || failed=true + fi + + if [ "$failed" = true ] && __machine_has curl; then + failed=false + curl --retry 10 -sSL -f --create-dirs -o $local_path $remote_path || failed=true + fi + + if [ "$failed" = true ]; then + __error "Download failed: $remote_path" 1>&2 + return 1 + fi +} + +__read_dom () { local IFS=\> ; read -d \< ENTITY CONTENT ;} + +# +# main +# + +while [[ $# > 0 ]]; do + case $1 in + -\?|-h|--help) + __usage --no-exit + exit 0 + ;; + -c|--channel|-Channel) + shift + channel=${1:-} + [ -z "$channel" ] && __usage + ;; + --config-file|-ConfigFile) + shift + config_file="${1:-}" + [ -z "$config_file" ] && __usage + ;; + -d|--dotnet-home|-DotNetHome) + shift + DOTNET_HOME=${1:-} + [ -z "$DOTNET_HOME" ] && __usage + ;; + --path|-Path) + shift + repo_path="${1:-}" + [ -z "$repo_path" ] && __usage + ;; + -s|--tools-source|-ToolsSource) + shift + tools_source="${1:-}" + [ -z "$tools_source" ] && __usage + ;; + -u|--update|-Update) + update=true + ;; + --verbose|-Verbose) + verbose=true + ;; + --) + shift + break + ;; + *) + break + ;; + esac + shift +done + +if ! __machine_has unzip; then + __error 'Missing required command: unzip' + exit 1 fi -$buildFile -r $repoFolder "$@" +if ! __machine_has curl && ! __machine_has wget; then + __error 'Missing required command. Either wget or curl is required.' + exit 1 +fi + +if [ -f $config_file ]; then + comment=false + while __read_dom; do + if [ "$comment" = true ]; then [[ $CONTENT == *'-->'* ]] && comment=false ; continue; fi + if [[ $ENTITY == '!--'* ]]; then comment=true; continue; fi + if [ -z "$channel" ] && [[ $ENTITY == "KoreBuildChannel" ]]; then channel=$CONTENT; fi + if [ -z "$tools_source" ] && [[ $ENTITY == "KoreBuildToolsSource" ]]; then tools_source=$CONTENT; fi + done < $config_file +fi + +[ -z "$channel" ] && channel='dev' +[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' + +get_korebuild +install_tools "$tools_source" "$DOTNET_HOME" +invoke_repository_build "$repo_path" $@ diff --git a/build/common.props b/build/common.props index 83647293aa..c03e5c1314 100644 --- a/build/common.props +++ b/build/common.props @@ -1,6 +1,6 @@ - + https://github.com/aspnet/HtmlAbstractions diff --git a/version.props b/version.xml similarity index 55% rename from version.props rename to version.xml index 1ea46af42a..3c05022b7d 100644 --- a/version.props +++ b/version.xml @@ -1,6 +1,7 @@ - + + dev 2.1.0 preview1 From b52b1d700ecd22b3437411e6e29d2cba9cca611f Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 25 Jul 2017 16:32:53 -0700 Subject: [PATCH 0562/1029] Update bootstrappers to use the compiled version of KoreBuild [ci skip] --- .gitignore | 1 + build.cmd | 2 +- build.ps1 | 218 ++++++++++++++++++++++++++++++++----------- build.sh | 224 +++++++++++++++++++++++++++++++++++++-------- build/common.props | 2 +- version.props | 7 -- version.xml | 8 ++ 7 files changed, 362 insertions(+), 100 deletions(-) delete mode 100644 version.props create mode 100644 version.xml diff --git a/.gitignore b/.gitignore index 2e8ec28064..24d990294f 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,4 @@ node_modules *launchSettings.json *.orig global.json +korebuild-lock.txt diff --git a/build.cmd b/build.cmd index 7d4894cb4a..b6c8d24864 100644 --- a/build.cmd +++ b/build.cmd @@ -1,2 +1,2 @@ @ECHO OFF -PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*; exit $LASTEXITCODE" \ No newline at end of file +PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*; exit $LASTEXITCODE" diff --git a/build.ps1 b/build.ps1 index 5bf0e2c113..d5eb4d5cf2 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,67 +1,177 @@ -$ErrorActionPreference = "Stop" +#!/usr/bin/env powershell +#requires -version 4 -function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $retries) -{ - while($true) - { - try - { - Invoke-WebRequest $url -OutFile $downloadLocation - break - } - catch - { - $exceptionMessage = $_.Exception.Message - Write-Host "Failed to download '$url': $exceptionMessage" - if ($retries -gt 0) { - $retries-- - Write-Host "Waiting 10 seconds before retrying. Retries left: $retries" - Start-Sleep -Seconds 10 +<# +.SYNOPSIS +Build this repository +.DESCRIPTION +Downloads korebuild if required. Then builds the repository. + +.PARAMETER Path +The folder to build. Defaults to the folder containing this script. + +.PARAMETER Channel +The channel of KoreBuild to download. Overrides the value from the config file. + +.PARAMETER DotNetHome +The directory where .NET Core tools will be stored. + +.PARAMETER ToolsSource +The base url where build tools can be downloaded. Overrides the value from the config file. + +.PARAMETER Update +Updates KoreBuild to the latest version even if a lock file is present. + +.PARAMETER ConfigFile +The path to the configuration file that stores values. Defaults to version.xml. + +.PARAMETER MSBuildArgs +Arguments to be passed to MSBuild + +.NOTES +This function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be. +When the lockfile is not present, KoreBuild will create one using latest available version from $Channel. + +The $ConfigFile is expected to be an XML file. It is optional, and the configuration values in it are optional as well. + +.EXAMPLE +Example config file: +```xml + + + + dev + https://aspnetcore.blob.core.windows.net/buildtools + + +``` +#> +[CmdletBinding(PositionalBinding = $false)] +param( + [string]$Path = $PSScriptRoot, + [Alias('c')] + [string]$Channel, + [Alias('d')] + [string]$DotNetHome, + [Alias('s')] + [string]$ToolsSource, + [Alias('u')] + [switch]$Update, + [string]$ConfigFile = (Join-Path $PSScriptRoot 'version.xml'), + [Parameter(ValueFromRemainingArguments = $true)] + [string[]]$MSBuildArgs +) + +Set-StrictMode -Version 2 +$ErrorActionPreference = 'Stop' + +# +# Functions +# + +function Get-KoreBuild { + + $lockFile = Join-Path $Path 'korebuild-lock.txt' + + if (!(Test-Path $lockFile) -or $Update) { + Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile + } + + $version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1 + if (!$version) { + Write-Error "Failed to parse version from $lockFile. Expected a line that begins with 'version:'" + } + $version = $version.TrimStart('version:').Trim() + $korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version) + + if (!(Test-Path $korebuildPath)) { + Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version" + New-Item -ItemType Directory -Path $korebuildPath | Out-Null + $remotePath = "$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip" + + try { + $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip" + Get-RemoteFile $remotePath $tmpfile + if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) { + # Use built-in commands where possible as they are cross-plat compatible + Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath } - else - { - $exception = $_.Exception - throw $exception + else { + # Fallback to old approach for old installations of PowerShell + Add-Type -AssemblyName System.IO.Compression.FileSystem + [System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath) } } + catch { + Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore + throw + } + finally { + Remove-Item $tmpfile -ErrorAction Ignore + } } + + return $korebuildPath } -cd $PSScriptRoot - -$repoFolder = $PSScriptRoot -$env:REPO_FOLDER = $repoFolder - -$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" -if ($env:KOREBUILD_ZIP) -{ - $koreBuildZip=$env:KOREBUILD_ZIP +function Join-Paths([string]$path, [string[]]$childPaths) { + $childPaths | ForEach-Object { $path = Join-Path $path $_ } + return $path } -$buildFolder = ".build" -$buildFile="$buildFolder\KoreBuild.ps1" - -if (!(Test-Path $buildFolder)) { - Write-Host "Downloading KoreBuild from $koreBuildZip" - - $tempFolder=$env:TEMP + "\KoreBuild-" + [guid]::NewGuid() - New-Item -Path "$tempFolder" -Type directory | Out-Null - - $localZipFile="$tempFolder\korebuild.zip" - - DownloadWithRetry -url $koreBuildZip -downloadLocation $localZipFile -retries 6 - - Add-Type -AssemblyName System.IO.Compression.FileSystem - [System.IO.Compression.ZipFile]::ExtractToDirectory($localZipFile, $tempFolder) - - New-Item -Path "$buildFolder" -Type directory | Out-Null - copy-item "$tempFolder\**\build\*" $buildFolder -Recurse - - # Cleanup - if (Test-Path $tempFolder) { - Remove-Item -Recurse -Force $tempFolder +function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) { + if ($RemotePath -notlike 'http*') { + Copy-Item $RemotePath $LocalPath + return } + + $retries = 10 + while ($retries -gt 0) { + $retries -= 1 + try { + Invoke-WebRequest -UseBasicParsing -Uri $RemotePath -OutFile $LocalPath + return + } + catch { + Write-Verbose "Request failed. $retries retries remaining" + } + } + + Write-Error "Download failed: '$RemotePath'." } -&"$buildFile" @args +# +# Main +# + +# Load configuration or set defaults + +if (Test-Path $ConfigFile) { + [xml] $config = Get-Content $ConfigFile + if (!($Channel)) { [string] $Channel = Select-Xml -Xml $config -XPath '/Project/PropertyGroup/KoreBuildChannel' } + if (!($ToolsSource)) { [string] $ToolsSource = Select-Xml -Xml $config -XPath '/Project/PropertyGroup/KoreBuildToolsSource' } +} + +if (!$DotNetHome) { + $DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } ` + elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} ` + elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}` + else { Join-Path $PSScriptRoot '.dotnet'} +} + +if (!$Channel) { $Channel = 'dev' } +if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } + +# Execute + +$korebuildPath = Get-KoreBuild +Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1') + +try { + Install-Tools $ToolsSource $DotNetHome + Invoke-RepositoryBuild $Path @MSBuildArgs +} +finally { + Remove-Module 'KoreBuild' -ErrorAction Ignore +} diff --git a/build.sh b/build.sh index b0bcadb579..ab590e62f1 100755 --- a/build.sh +++ b/build.sh @@ -1,46 +1,196 @@ #!/usr/bin/env bash -repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -cd $repoFolder -koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" -if [ ! -z $KOREBUILD_ZIP ]; then - koreBuildZip=$KOREBUILD_ZIP -fi +set -euo pipefail -buildFolder=".build" -buildFile="$buildFolder/KoreBuild.sh" +# +# variables +# -if test ! -d $buildFolder; then - echo "Downloading KoreBuild from $koreBuildZip" +RESET="\033[0m" +RED="\033[0;31m" +MAGENTA="\033[0;95m" +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +[ -z "${DOTNET_HOME:-}"] && DOTNET_HOME="$HOME/.dotnet" +config_file="$DIR/version.xml" +verbose=false +update=false +repo_path="$DIR" +channel='' +tools_source='' - tempFolder="/tmp/KoreBuild-$(uuidgen)" - mkdir $tempFolder +# +# Functions +# +__usage() { + echo "Usage: $(basename ${BASH_SOURCE[0]}) [options] [[--] ...]" + echo "" + echo "Arguments:" + echo " ... Arguments passed to MSBuild. Variable number of arguments allowed." + echo "" + echo "Options:" + echo " --verbose Show verbose output." + echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." + echo " --config-file TThe path to the configuration file that stores values. Defaults to version.xml." + echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." + echo " --path The directory to build. Defaults to the directory containing the script." + echo " -s|--tools-source The base url where build tools can be downloaded. Overrides the value from the config file." + echo " -u|--update Update to the latest KoreBuild even if the lock file is present." + echo "" + echo "Description:" + echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." + echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel." - localZipFile="$tempFolder/korebuild.zip" - - retries=6 - until (wget -O $localZipFile $koreBuildZip 2>/dev/null || curl -o $localZipFile --location $koreBuildZip 2>/dev/null) - do - echo "Failed to download '$koreBuildZip'" - if [ "$retries" -le 0 ]; then - exit 1 - fi - retries=$((retries - 1)) - echo "Waiting 10 seconds before retrying. Retries left: $retries" - sleep 10s - done - - unzip -q -d $tempFolder $localZipFile - - mkdir $buildFolder - cp -r $tempFolder/**/build/** $buildFolder - - chmod +x $buildFile - - # Cleanup - if test -d $tempFolder; then - rm -rf $tempFolder + if [[ "${1:-}" != '--no-exit' ]]; then + exit 2 fi +} + +get_korebuild() { + local lock_file="$repo_path/korebuild-lock.txt" + if [ ! -f $lock_file ] || [ "$update" = true ]; then + __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" $lock_file + fi + local version="$(grep 'version:*' -m 1 $lock_file)" + if [[ "$version" == '' ]]; then + __error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'" + return 1 + fi + version="$(echo ${version#version:} | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" + + { + if [ ! -d "$korebuild_path" ]; then + mkdir -p "$korebuild_path" + local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" + tmpfile="$(mktemp)" + echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" + if __get_remote_file $remote_path $tmpfile; then + unzip -q -d "$korebuild_path" $tmpfile + fi + rm $tmpfile || true + fi + + source "$korebuild_path/KoreBuild.sh" + } || { + if [ -d "$korebuild_path" ]; then + echo "Cleaning up after failed installation" + rm -rf "$korebuild_path" || true + fi + return 1 + } +} + +__error() { + echo -e "${RED}$@${RESET}" 1>&2 +} + +__machine_has() { + hash "$1" > /dev/null 2>&1 + return $? +} + +__get_remote_file() { + local remote_path=$1 + local local_path=$2 + + if [[ "$remote_path" != 'http'* ]]; then + cp $remote_path $local_path + return 0 + fi + + failed=false + if __machine_has wget; then + wget --tries 10 --quiet -O $local_path $remote_path || failed=true + fi + + if [ "$failed" = true ] && __machine_has curl; then + failed=false + curl --retry 10 -sSL -f --create-dirs -o $local_path $remote_path || failed=true + fi + + if [ "$failed" = true ]; then + __error "Download failed: $remote_path" 1>&2 + return 1 + fi +} + +__read_dom () { local IFS=\> ; read -d \< ENTITY CONTENT ;} + +# +# main +# + +while [[ $# > 0 ]]; do + case $1 in + -\?|-h|--help) + __usage --no-exit + exit 0 + ;; + -c|--channel|-Channel) + shift + channel=${1:-} + [ -z "$channel" ] && __usage + ;; + --config-file|-ConfigFile) + shift + config_file="${1:-}" + [ -z "$config_file" ] && __usage + ;; + -d|--dotnet-home|-DotNetHome) + shift + DOTNET_HOME=${1:-} + [ -z "$DOTNET_HOME" ] && __usage + ;; + --path|-Path) + shift + repo_path="${1:-}" + [ -z "$repo_path" ] && __usage + ;; + -s|--tools-source|-ToolsSource) + shift + tools_source="${1:-}" + [ -z "$tools_source" ] && __usage + ;; + -u|--update|-Update) + update=true + ;; + --verbose|-Verbose) + verbose=true + ;; + --) + shift + break + ;; + *) + break + ;; + esac + shift +done + +if ! __machine_has unzip; then + __error 'Missing required command: unzip' + exit 1 fi -$buildFile -r $repoFolder "$@" +if ! __machine_has curl && ! __machine_has wget; then + __error 'Missing required command. Either wget or curl is required.' + exit 1 +fi + +if [ -f $config_file ]; then + comment=false + while __read_dom; do + if [ "$comment" = true ]; then [[ $CONTENT == *'-->'* ]] && comment=false ; continue; fi + if [[ $ENTITY == '!--'* ]]; then comment=true; continue; fi + if [ -z "$channel" ] && [[ $ENTITY == "KoreBuildChannel" ]]; then channel=$CONTENT; fi + if [ -z "$tools_source" ] && [[ $ENTITY == "KoreBuildToolsSource" ]]; then tools_source=$CONTENT; fi + done < $config_file +fi + +[ -z "$channel" ] && channel='dev' +[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' + +get_korebuild +install_tools "$tools_source" "$DOTNET_HOME" +invoke_repository_build "$repo_path" $@ diff --git a/build/common.props b/build/common.props index c00767473e..b749c350f1 100644 --- a/build/common.props +++ b/build/common.props @@ -1,6 +1,6 @@ - + Microsoft ASP.NET Core diff --git a/version.props b/version.props deleted file mode 100644 index cb77b43933..0000000000 --- a/version.props +++ /dev/null @@ -1,7 +0,0 @@ - - - - 2.1.0 - preview1 - - \ No newline at end of file diff --git a/version.xml b/version.xml new file mode 100644 index 0000000000..3c05022b7d --- /dev/null +++ b/version.xml @@ -0,0 +1,8 @@ + + + + dev + 2.1.0 + preview1 + + From 4cfeca184c7be130a67912f58f70bb036306b8b3 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 26 Jul 2017 10:27:09 -0700 Subject: [PATCH 0563/1029] Fix syntax warning when running build.sh on older versions of bash [ci skip] --- build.sh | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/build.sh b/build.sh index ab590e62f1..5568c6182a 100755 --- a/build.sh +++ b/build.sh @@ -10,7 +10,7 @@ RESET="\033[0m" RED="\033[0;31m" MAGENTA="\033[0;95m" DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -[ -z "${DOTNET_HOME:-}"] && DOTNET_HOME="$HOME/.dotnet" +[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" config_file="$DIR/version.xml" verbose=false update=false @@ -22,7 +22,7 @@ tools_source='' # Functions # __usage() { - echo "Usage: $(basename ${BASH_SOURCE[0]}) [options] [[--] ...]" + echo "Usage: $(basename "${BASH_SOURCE[0]}") [options] [[--] ...]" echo "" echo "Arguments:" echo " ... Arguments passed to MSBuild. Variable number of arguments allowed." @@ -46,16 +46,17 @@ __usage() { } get_korebuild() { + local version local lock_file="$repo_path/korebuild-lock.txt" - if [ ! -f $lock_file ] || [ "$update" = true ]; then - __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" $lock_file + if [ ! -f "$lock_file" ] || [ "$update" = true ]; then + __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" fi - local version="$(grep 'version:*' -m 1 $lock_file)" + version="$(grep 'version:*' -m 1 "$lock_file")" if [[ "$version" == '' ]]; then __error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'" return 1 fi - version="$(echo ${version#version:} | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" { @@ -64,10 +65,10 @@ get_korebuild() { local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" tmpfile="$(mktemp)" echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" - if __get_remote_file $remote_path $tmpfile; then - unzip -q -d "$korebuild_path" $tmpfile + if __get_remote_file "$remote_path" "$tmpfile"; then + unzip -q -d "$korebuild_path" "$tmpfile" fi - rm $tmpfile || true + rm "$tmpfile" || true fi source "$korebuild_path/KoreBuild.sh" @@ -81,7 +82,7 @@ get_korebuild() { } __error() { - echo -e "${RED}$@${RESET}" 1>&2 + echo -e "${RED}$*${RESET}" 1>&2 } __machine_has() { @@ -94,18 +95,18 @@ __get_remote_file() { local local_path=$2 if [[ "$remote_path" != 'http'* ]]; then - cp $remote_path $local_path + cp "$remote_path" "$local_path" return 0 fi failed=false if __machine_has wget; then - wget --tries 10 --quiet -O $local_path $remote_path || failed=true + wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true fi if [ "$failed" = true ] && __machine_has curl; then failed=false - curl --retry 10 -sSL -f --create-dirs -o $local_path $remote_path || failed=true + curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true fi if [ "$failed" = true ]; then @@ -114,13 +115,13 @@ __get_remote_file() { fi } -__read_dom () { local IFS=\> ; read -d \< ENTITY CONTENT ;} +__read_dom () { local IFS=\> ; read -r -d \< ENTITY CONTENT ;} # # main # -while [[ $# > 0 ]]; do +while [[ $# -gt 0 ]]; do case $1 in -\?|-h|--help) __usage --no-exit @@ -128,7 +129,7 @@ while [[ $# > 0 ]]; do ;; -c|--channel|-Channel) shift - channel=${1:-} + channel="${1:-}" [ -z "$channel" ] && __usage ;; --config-file|-ConfigFile) @@ -138,7 +139,7 @@ while [[ $# > 0 ]]; do ;; -d|--dotnet-home|-DotNetHome) shift - DOTNET_HOME=${1:-} + DOTNET_HOME="${1:-}" [ -z "$DOTNET_HOME" ] && __usage ;; --path|-Path) @@ -178,14 +179,14 @@ if ! __machine_has curl && ! __machine_has wget; then exit 1 fi -if [ -f $config_file ]; then +if [ -f "$config_file" ]; then comment=false while __read_dom; do if [ "$comment" = true ]; then [[ $CONTENT == *'-->'* ]] && comment=false ; continue; fi if [[ $ENTITY == '!--'* ]]; then comment=true; continue; fi if [ -z "$channel" ] && [[ $ENTITY == "KoreBuildChannel" ]]; then channel=$CONTENT; fi if [ -z "$tools_source" ] && [[ $ENTITY == "KoreBuildToolsSource" ]]; then tools_source=$CONTENT; fi - done < $config_file + done < "$config_file" fi [ -z "$channel" ] && channel='dev' @@ -193,4 +194,4 @@ fi get_korebuild install_tools "$tools_source" "$DOTNET_HOME" -invoke_repository_build "$repo_path" $@ +invoke_repository_build "$repo_path" "$@" From 9c3d4543f550e9ca985887f72627a2b0d021fe12 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 26 Jul 2017 10:27:33 -0700 Subject: [PATCH 0564/1029] Fix syntax warning when running build.sh on older versions of bash [ci skip] --- build.sh | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/build.sh b/build.sh index ab590e62f1..5568c6182a 100755 --- a/build.sh +++ b/build.sh @@ -10,7 +10,7 @@ RESET="\033[0m" RED="\033[0;31m" MAGENTA="\033[0;95m" DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -[ -z "${DOTNET_HOME:-}"] && DOTNET_HOME="$HOME/.dotnet" +[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" config_file="$DIR/version.xml" verbose=false update=false @@ -22,7 +22,7 @@ tools_source='' # Functions # __usage() { - echo "Usage: $(basename ${BASH_SOURCE[0]}) [options] [[--] ...]" + echo "Usage: $(basename "${BASH_SOURCE[0]}") [options] [[--] ...]" echo "" echo "Arguments:" echo " ... Arguments passed to MSBuild. Variable number of arguments allowed." @@ -46,16 +46,17 @@ __usage() { } get_korebuild() { + local version local lock_file="$repo_path/korebuild-lock.txt" - if [ ! -f $lock_file ] || [ "$update" = true ]; then - __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" $lock_file + if [ ! -f "$lock_file" ] || [ "$update" = true ]; then + __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" fi - local version="$(grep 'version:*' -m 1 $lock_file)" + version="$(grep 'version:*' -m 1 "$lock_file")" if [[ "$version" == '' ]]; then __error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'" return 1 fi - version="$(echo ${version#version:} | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" { @@ -64,10 +65,10 @@ get_korebuild() { local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" tmpfile="$(mktemp)" echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" - if __get_remote_file $remote_path $tmpfile; then - unzip -q -d "$korebuild_path" $tmpfile + if __get_remote_file "$remote_path" "$tmpfile"; then + unzip -q -d "$korebuild_path" "$tmpfile" fi - rm $tmpfile || true + rm "$tmpfile" || true fi source "$korebuild_path/KoreBuild.sh" @@ -81,7 +82,7 @@ get_korebuild() { } __error() { - echo -e "${RED}$@${RESET}" 1>&2 + echo -e "${RED}$*${RESET}" 1>&2 } __machine_has() { @@ -94,18 +95,18 @@ __get_remote_file() { local local_path=$2 if [[ "$remote_path" != 'http'* ]]; then - cp $remote_path $local_path + cp "$remote_path" "$local_path" return 0 fi failed=false if __machine_has wget; then - wget --tries 10 --quiet -O $local_path $remote_path || failed=true + wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true fi if [ "$failed" = true ] && __machine_has curl; then failed=false - curl --retry 10 -sSL -f --create-dirs -o $local_path $remote_path || failed=true + curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true fi if [ "$failed" = true ]; then @@ -114,13 +115,13 @@ __get_remote_file() { fi } -__read_dom () { local IFS=\> ; read -d \< ENTITY CONTENT ;} +__read_dom () { local IFS=\> ; read -r -d \< ENTITY CONTENT ;} # # main # -while [[ $# > 0 ]]; do +while [[ $# -gt 0 ]]; do case $1 in -\?|-h|--help) __usage --no-exit @@ -128,7 +129,7 @@ while [[ $# > 0 ]]; do ;; -c|--channel|-Channel) shift - channel=${1:-} + channel="${1:-}" [ -z "$channel" ] && __usage ;; --config-file|-ConfigFile) @@ -138,7 +139,7 @@ while [[ $# > 0 ]]; do ;; -d|--dotnet-home|-DotNetHome) shift - DOTNET_HOME=${1:-} + DOTNET_HOME="${1:-}" [ -z "$DOTNET_HOME" ] && __usage ;; --path|-Path) @@ -178,14 +179,14 @@ if ! __machine_has curl && ! __machine_has wget; then exit 1 fi -if [ -f $config_file ]; then +if [ -f "$config_file" ]; then comment=false while __read_dom; do if [ "$comment" = true ]; then [[ $CONTENT == *'-->'* ]] && comment=false ; continue; fi if [[ $ENTITY == '!--'* ]]; then comment=true; continue; fi if [ -z "$channel" ] && [[ $ENTITY == "KoreBuildChannel" ]]; then channel=$CONTENT; fi if [ -z "$tools_source" ] && [[ $ENTITY == "KoreBuildToolsSource" ]]; then tools_source=$CONTENT; fi - done < $config_file + done < "$config_file" fi [ -z "$channel" ] && channel='dev' @@ -193,4 +194,4 @@ fi get_korebuild install_tools "$tools_source" "$DOTNET_HOME" -invoke_repository_build "$repo_path" $@ +invoke_repository_build "$repo_path" "$@" From 6a20337254dc0fcc5227e2243fdc3f52c88e58da Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 26 Jul 2017 10:27:59 -0700 Subject: [PATCH 0565/1029] Fix syntax warning when running build.sh on older versions of bash [ci skip] --- build.sh | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/build.sh b/build.sh index ab590e62f1..5568c6182a 100755 --- a/build.sh +++ b/build.sh @@ -10,7 +10,7 @@ RESET="\033[0m" RED="\033[0;31m" MAGENTA="\033[0;95m" DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -[ -z "${DOTNET_HOME:-}"] && DOTNET_HOME="$HOME/.dotnet" +[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" config_file="$DIR/version.xml" verbose=false update=false @@ -22,7 +22,7 @@ tools_source='' # Functions # __usage() { - echo "Usage: $(basename ${BASH_SOURCE[0]}) [options] [[--] ...]" + echo "Usage: $(basename "${BASH_SOURCE[0]}") [options] [[--] ...]" echo "" echo "Arguments:" echo " ... Arguments passed to MSBuild. Variable number of arguments allowed." @@ -46,16 +46,17 @@ __usage() { } get_korebuild() { + local version local lock_file="$repo_path/korebuild-lock.txt" - if [ ! -f $lock_file ] || [ "$update" = true ]; then - __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" $lock_file + if [ ! -f "$lock_file" ] || [ "$update" = true ]; then + __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" fi - local version="$(grep 'version:*' -m 1 $lock_file)" + version="$(grep 'version:*' -m 1 "$lock_file")" if [[ "$version" == '' ]]; then __error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'" return 1 fi - version="$(echo ${version#version:} | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" { @@ -64,10 +65,10 @@ get_korebuild() { local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" tmpfile="$(mktemp)" echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" - if __get_remote_file $remote_path $tmpfile; then - unzip -q -d "$korebuild_path" $tmpfile + if __get_remote_file "$remote_path" "$tmpfile"; then + unzip -q -d "$korebuild_path" "$tmpfile" fi - rm $tmpfile || true + rm "$tmpfile" || true fi source "$korebuild_path/KoreBuild.sh" @@ -81,7 +82,7 @@ get_korebuild() { } __error() { - echo -e "${RED}$@${RESET}" 1>&2 + echo -e "${RED}$*${RESET}" 1>&2 } __machine_has() { @@ -94,18 +95,18 @@ __get_remote_file() { local local_path=$2 if [[ "$remote_path" != 'http'* ]]; then - cp $remote_path $local_path + cp "$remote_path" "$local_path" return 0 fi failed=false if __machine_has wget; then - wget --tries 10 --quiet -O $local_path $remote_path || failed=true + wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true fi if [ "$failed" = true ] && __machine_has curl; then failed=false - curl --retry 10 -sSL -f --create-dirs -o $local_path $remote_path || failed=true + curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true fi if [ "$failed" = true ]; then @@ -114,13 +115,13 @@ __get_remote_file() { fi } -__read_dom () { local IFS=\> ; read -d \< ENTITY CONTENT ;} +__read_dom () { local IFS=\> ; read -r -d \< ENTITY CONTENT ;} # # main # -while [[ $# > 0 ]]; do +while [[ $# -gt 0 ]]; do case $1 in -\?|-h|--help) __usage --no-exit @@ -128,7 +129,7 @@ while [[ $# > 0 ]]; do ;; -c|--channel|-Channel) shift - channel=${1:-} + channel="${1:-}" [ -z "$channel" ] && __usage ;; --config-file|-ConfigFile) @@ -138,7 +139,7 @@ while [[ $# > 0 ]]; do ;; -d|--dotnet-home|-DotNetHome) shift - DOTNET_HOME=${1:-} + DOTNET_HOME="${1:-}" [ -z "$DOTNET_HOME" ] && __usage ;; --path|-Path) @@ -178,14 +179,14 @@ if ! __machine_has curl && ! __machine_has wget; then exit 1 fi -if [ -f $config_file ]; then +if [ -f "$config_file" ]; then comment=false while __read_dom; do if [ "$comment" = true ]; then [[ $CONTENT == *'-->'* ]] && comment=false ; continue; fi if [[ $ENTITY == '!--'* ]]; then comment=true; continue; fi if [ -z "$channel" ] && [[ $ENTITY == "KoreBuildChannel" ]]; then channel=$CONTENT; fi if [ -z "$tools_source" ] && [[ $ENTITY == "KoreBuildToolsSource" ]]; then tools_source=$CONTENT; fi - done < $config_file + done < "$config_file" fi [ -z "$channel" ] && channel='dev' @@ -193,4 +194,4 @@ fi get_korebuild install_tools "$tools_source" "$DOTNET_HOME" -invoke_repository_build "$repo_path" $@ +invoke_repository_build "$repo_path" "$@" From d058fe5a3971479d4e3e4778ea8667036832f40a Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 14 Jul 2017 11:27:01 -0700 Subject: [PATCH 0566/1029] Fix StackOverflowException caused when creating the watcher on directories from a network share --- shared/NullReporter.cs | 25 +++++++++++++++++ .../CommandLineOptions.cs | 12 ++++++++ .../DotNetWatcher.cs | 2 +- .../Internal/FileSetWatcher.cs | 5 ++-- .../Internal/FileWatcher.cs | 28 ++++++++++++++++++- .../Internal/FileWatcher/DotnetFileWatcher.cs | 28 +++++++++++++------ .../FileWatcher/FileWatcherFactory.cs | 10 +------ .../FileWatcher/IFileSystemWatcher.cs | 4 ++- .../FileWatcher/PollingFileWatcher.cs | 14 +++++----- .../Internal/MsBuildFileSetFactory.cs | 2 +- src/Microsoft.DotNet.Watcher.Tools/Program.cs | 5 ++++ 11 files changed, 104 insertions(+), 31 deletions(-) create mode 100644 shared/NullReporter.cs diff --git a/shared/NullReporter.cs b/shared/NullReporter.cs new file mode 100644 index 0000000000..5d80aeac91 --- /dev/null +++ b/shared/NullReporter.cs @@ -0,0 +1,25 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Extensions.Tools.Internal +{ + public class NullReporter : IReporter + { + private NullReporter() + { } + + public static IReporter Singleton { get; } = new NullReporter(); + + public void Verbose(string message) + { } + + public void Output(string message) + { } + + public void Warn(string message) + { } + + public void Error(string message) + { } + } +} diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs index af158d0e53..22705c9265 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Reflection; using Microsoft.DotNet.Watcher.Tools; @@ -19,6 +20,17 @@ namespace Microsoft.DotNet.Watcher public IList RemainingArguments { get; private set; } public bool ListFiles { get; private set; } + public static bool IsPollingEnabled + { + get + { + var envVar = Environment.GetEnvironmentVariable("DOTNET_USE_POLLING_FILE_WATCHER"); + return envVar != null && + (envVar.Equals("1", StringComparison.OrdinalIgnoreCase) || + envVar.Equals("true", StringComparison.OrdinalIgnoreCase)); + } + } + public static CommandLineOptions Parse(string[] args, IConsole console) { Ensure.NotNull(args, nameof(args)); diff --git a/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs index 66a213a043..258ba0ab1e 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs @@ -51,7 +51,7 @@ namespace Microsoft.DotNet.Watcher using (var combinedCancellationSource = CancellationTokenSource.CreateLinkedTokenSource( cancellationToken, currentRunCancellationSource.Token)) - using (var fileSetWatcher = new FileSetWatcher(fileSet)) + using (var fileSetWatcher = new FileSetWatcher(fileSet, _reporter)) { var fileSetTask = fileSetWatcher.GetChangedFileAsync(combinedCancellationSource.Token); var processTask = _processRunner.RunAsync(processSpec, combinedCancellationSource.Token); diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSetWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSetWatcher.cs index 597d13cdd1..3dc56cc452 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSetWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSetWatcher.cs @@ -11,14 +11,15 @@ namespace Microsoft.DotNet.Watcher.Internal { public class FileSetWatcher : IDisposable { - private readonly FileWatcher _fileWatcher = new FileWatcher(); + private readonly FileWatcher _fileWatcher; private readonly IFileSet _fileSet; - public FileSetWatcher(IFileSet fileSet) + public FileSetWatcher(IFileSet fileSet, IReporter reporter) { Ensure.NotNull(fileSet, nameof(fileSet)); _fileSet = fileSet; + _fileWatcher = new FileWatcher(reporter); } public async Task GetChangedFileAsync(CancellationToken cancellationToken) diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher.cs index 20840f40b9..65c2ff9285 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using Microsoft.Extensions.Tools.Internal; namespace Microsoft.DotNet.Watcher.Internal { @@ -12,7 +13,18 @@ namespace Microsoft.DotNet.Watcher.Internal { private bool _disposed; - private readonly IDictionary _watchers = new Dictionary(); + private readonly IDictionary _watchers; + private readonly IReporter _reporter; + + public FileWatcher() + : this(NullReporter.Singleton) + { } + + public FileWatcher(IReporter reporter) + { + _reporter = reporter ?? throw new ArgumentNullException(nameof(reporter)); + _watchers = new Dictionary(); + } public event Action OnFileChange; @@ -33,8 +45,11 @@ namespace Microsoft.DotNet.Watcher.Internal foreach (var watcher in _watchers) { + watcher.Value.OnFileChange -= WatcherChangedHandler; + watcher.Value.OnError -= WatcherErrorHandler; watcher.Value.Dispose(); } + _watchers.Clear(); } @@ -66,11 +81,20 @@ namespace Microsoft.DotNet.Watcher.Internal var newWatcher = FileWatcherFactory.CreateWatcher(directory); newWatcher.OnFileChange += WatcherChangedHandler; + newWatcher.OnError += WatcherErrorHandler; newWatcher.EnableRaisingEvents = true; _watchers.Add(directory, newWatcher); } + private void WatcherErrorHandler(object sender, Exception error) + { + if (sender is IFileSystemWatcher watcher) + { + _reporter.Warn($"The file watcher observing '{watcher.BasePath}' encountered an error: {error.Message}"); + } + } + private void WatcherChangedHandler(object sender, string changedPath) { NotifyChange(changedPath); @@ -90,7 +114,9 @@ namespace Microsoft.DotNet.Watcher.Internal _watchers.Remove(directory); watcher.EnableRaisingEvents = false; + watcher.OnFileChange -= WatcherChangedHandler; + watcher.OnError -= WatcherErrorHandler; watcher.Dispose(); } diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/DotnetFileWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/DotnetFileWatcher.cs index 5064239746..d1103c41e6 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/DotnetFileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/DotnetFileWatcher.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.ComponentModel; using System.IO; using Microsoft.Extensions.Tools.Internal; @@ -10,7 +11,6 @@ namespace Microsoft.DotNet.Watcher.Internal internal class DotnetFileWatcher : IFileSystemWatcher { private readonly Func _watcherFactory; - private readonly string _watchedDirectory; private FileSystemWatcher _fileSystemWatcher; @@ -26,14 +26,16 @@ namespace Microsoft.DotNet.Watcher.Internal Ensure.NotNull(fileSystemWatcherFactory, nameof(fileSystemWatcherFactory)); Ensure.NotNullOrEmpty(watchedDirectory, nameof(watchedDirectory)); - _watchedDirectory = watchedDirectory; + BasePath = watchedDirectory; _watcherFactory = fileSystemWatcherFactory; CreateFileSystemWatcher(); } public event EventHandler OnFileChange; - public event EventHandler OnError; + public event EventHandler OnError; + + public string BasePath { get; } private static FileSystemWatcher DefaultWatcherFactory(string watchedDirectory) { @@ -44,10 +46,18 @@ namespace Microsoft.DotNet.Watcher.Internal private void WatcherErrorHandler(object sender, ErrorEventArgs e) { - // Recreate the watcher - CreateFileSystemWatcher(); + var exception = e.GetException(); - OnError?.Invoke(this, null); + // Win32Exception may be triggered when setting EnableRaisingEvents on a file system type + // that is not supported, such as a network share. Don't attempt to recreate the watcher + // in this case as it will cause a StackOverflowException + if (!(exception is Win32Exception)) + { + // Recreate the watcher if it is a recoverable error. + CreateFileSystemWatcher(); + } + + OnError?.Invoke(this, exception); } private void WatcherRenameHandler(object sender, RenamedEventArgs e) @@ -99,7 +109,7 @@ namespace Microsoft.DotNet.Watcher.Internal _fileSystemWatcher.Dispose(); } - _fileSystemWatcher = _watcherFactory(_watchedDirectory); + _fileSystemWatcher = _watcherFactory(BasePath); _fileSystemWatcher.IncludeSubdirectories = true; _fileSystemWatcher.Created += WatcherChangeHandler; @@ -114,8 +124,8 @@ namespace Microsoft.DotNet.Watcher.Internal public bool EnableRaisingEvents { - get { return _fileSystemWatcher.EnableRaisingEvents; } - set { _fileSystemWatcher.EnableRaisingEvents = value; } + get => _fileSystemWatcher.EnableRaisingEvents; + set => _fileSystemWatcher.EnableRaisingEvents = value; } public void Dispose() diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/FileWatcherFactory.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/FileWatcherFactory.cs index 248342571f..cbb1c12a74 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/FileWatcherFactory.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/FileWatcherFactory.cs @@ -8,15 +8,7 @@ namespace Microsoft.DotNet.Watcher.Internal public static class FileWatcherFactory { public static IFileSystemWatcher CreateWatcher(string watchedDirectory) - { - var envVar = Environment.GetEnvironmentVariable("DOTNET_USE_POLLING_FILE_WATCHER"); - var usePollingWatcher = - envVar != null && - (envVar.Equals("1", StringComparison.OrdinalIgnoreCase) || - envVar.Equals("true", StringComparison.OrdinalIgnoreCase)); - - return CreateWatcher(watchedDirectory, usePollingWatcher); - } + => CreateWatcher(watchedDirectory, CommandLineOptions.IsPollingEnabled); public static IFileSystemWatcher CreateWatcher(string watchedDirectory, bool usePollingWatcher) { diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/IFileSystemWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/IFileSystemWatcher.cs index 4bfc6bac6d..aaf5773449 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/IFileSystemWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/IFileSystemWatcher.cs @@ -9,7 +9,9 @@ namespace Microsoft.DotNet.Watcher.Internal { event EventHandler OnFileChange; - event EventHandler OnError; + event EventHandler OnError; + + string BasePath { get; } bool EnableRaisingEvents { get; set; } } diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs index 25e4f6f76f..1b503af774 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs @@ -31,6 +31,7 @@ namespace Microsoft.DotNet.Watcher.Internal Ensure.NotNullOrEmpty(watchedDirectory, nameof(watchedDirectory)); _watchedDirectory = new DirectoryInfo(watchedDirectory); + BasePath = _watchedDirectory.FullName; _pollingThread = new Thread(new ThreadStart(PollingLoop)); _pollingThread.IsBackground = true; @@ -44,15 +45,14 @@ namespace Microsoft.DotNet.Watcher.Internal public event EventHandler OnFileChange; #pragma warning disable CS0067 // not used - public event EventHandler OnError; + public event EventHandler OnError; #pragma warning restore + public string BasePath { get; } + public bool EnableRaisingEvents { - get - { - return _raiseEvents; - } + get => _raiseEvents; set { EnsureNotDisposed(); @@ -125,7 +125,7 @@ namespace Microsoft.DotNet.Watcher.Internal _knownEntities[fullFilePath] = new FileMeta(fileMeta.FileInfo, true); } - catch(FileNotFoundException) + catch (FileNotFoundException) { _knownEntities[fullFilePath] = new FileMeta(fileMeta.FileInfo, false); } @@ -187,7 +187,7 @@ namespace Microsoft.DotNet.Watcher.Internal { return; } - + var entities = dirInfo.EnumerateFileSystemInfos("*.*"); foreach (var entity in entities) { diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs index 01b8f4a996..0190b089ca 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs @@ -144,7 +144,7 @@ namespace Microsoft.DotNet.Watcher.Internal var fileSet = new FileSet(new[] { _projectFile }); - using (var watcher = new FileSetWatcher(fileSet)) + using (var watcher = new FileSetWatcher(fileSet, _reporter)) { await watcher.GetChangedFileAsync(cancellationToken); diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index c8832649fb..019c95a329 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -160,6 +160,11 @@ namespace Microsoft.DotNet.Watcher }, }; + if (CommandLineOptions.IsPollingEnabled) + { + _reporter.Output("Polling file watcher is enabled"); + } + await new DotNetWatcher(reporter) .WatchAsync(processInfo, fileSetFactory, cancellationToken); From 04505ea5f665d967e859e87f475d62ca12803267 Mon Sep 17 00:00:00 2001 From: John Luo Date: Wed, 2 Aug 2017 12:44:44 -0700 Subject: [PATCH 0567/1029] Update __get_remote_file logic --- build.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/build.sh b/build.sh index 5568c6182a..8eace4c20d 100755 --- a/build.sh +++ b/build.sh @@ -99,17 +99,16 @@ __get_remote_file() { return 0 fi - failed=false + local succeeded=false if __machine_has wget; then - wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true + wget --tries 10 --quiet -O "$local_path" "$remote_path" && succeeded=true fi - if [ "$failed" = true ] && __machine_has curl; then - failed=false - curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true + if [ "$succeeded" = false ] && __machine_has curl; then + curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" && succeeded=true fi - if [ "$failed" = true ]; then + if [ "$succeeded" = false ]; then __error "Download failed: $remote_path" 1>&2 return 1 fi From dce16d26ecc51fc89912b86eb7c2199679bcb87b Mon Sep 17 00:00:00 2001 From: John Luo Date: Wed, 2 Aug 2017 12:44:45 -0700 Subject: [PATCH 0568/1029] Update __get_remote_file logic --- build.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/build.sh b/build.sh index 5568c6182a..8eace4c20d 100755 --- a/build.sh +++ b/build.sh @@ -99,17 +99,16 @@ __get_remote_file() { return 0 fi - failed=false + local succeeded=false if __machine_has wget; then - wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true + wget --tries 10 --quiet -O "$local_path" "$remote_path" && succeeded=true fi - if [ "$failed" = true ] && __machine_has curl; then - failed=false - curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true + if [ "$succeeded" = false ] && __machine_has curl; then + curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" && succeeded=true fi - if [ "$failed" = true ]; then + if [ "$succeeded" = false ]; then __error "Download failed: $remote_path" 1>&2 return 1 fi From 90d9b8d5131bffe2e16a19aeb964066b59b0aca1 Mon Sep 17 00:00:00 2001 From: John Luo Date: Wed, 2 Aug 2017 12:44:46 -0700 Subject: [PATCH 0569/1029] Update __get_remote_file logic --- build.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/build.sh b/build.sh index 5568c6182a..8eace4c20d 100755 --- a/build.sh +++ b/build.sh @@ -99,17 +99,16 @@ __get_remote_file() { return 0 fi - failed=false + local succeeded=false if __machine_has wget; then - wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true + wget --tries 10 --quiet -O "$local_path" "$remote_path" && succeeded=true fi - if [ "$failed" = true ] && __machine_has curl; then - failed=false - curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true + if [ "$succeeded" = false ] && __machine_has curl; then + curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" && succeeded=true fi - if [ "$failed" = true ]; then + if [ "$succeeded" = false ]; then __error "Download failed: $remote_path" 1>&2 return 1 fi From 531da3c774d3041706fb459b10cdee72111f15d4 Mon Sep 17 00:00:00 2001 From: John Luo Date: Wed, 2 Aug 2017 14:31:25 -0700 Subject: [PATCH 0570/1029] Ensure fallback to curl after failed wget --- build.sh | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/build.sh b/build.sh index 8eace4c20d..11cdbe5504 100755 --- a/build.sh +++ b/build.sh @@ -99,16 +99,19 @@ __get_remote_file() { return 0 fi - local succeeded=false + local failed=false if __machine_has wget; then - wget --tries 10 --quiet -O "$local_path" "$remote_path" && succeeded=true + wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true + else + failed=true fi - if [ "$succeeded" = false ] && __machine_has curl; then - curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" && succeeded=true + if [ "$failed" = true ] && __machine_has curl; then + failed=false + curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true fi - if [ "$succeeded" = false ]; then + if [ "$failed" = true ]; then __error "Download failed: $remote_path" 1>&2 return 1 fi From aa2c30688236abf8037b4dd9e47971eddae858e2 Mon Sep 17 00:00:00 2001 From: John Luo Date: Wed, 2 Aug 2017 14:31:53 -0700 Subject: [PATCH 0571/1029] Ensure fallback to curl after failed wget --- build.sh | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/build.sh b/build.sh index 8eace4c20d..11cdbe5504 100755 --- a/build.sh +++ b/build.sh @@ -99,16 +99,19 @@ __get_remote_file() { return 0 fi - local succeeded=false + local failed=false if __machine_has wget; then - wget --tries 10 --quiet -O "$local_path" "$remote_path" && succeeded=true + wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true + else + failed=true fi - if [ "$succeeded" = false ] && __machine_has curl; then - curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" && succeeded=true + if [ "$failed" = true ] && __machine_has curl; then + failed=false + curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true fi - if [ "$succeeded" = false ]; then + if [ "$failed" = true ]; then __error "Download failed: $remote_path" 1>&2 return 1 fi From 13754ed0c7dc7db53fa1ee6d79b714d0882a8ac5 Mon Sep 17 00:00:00 2001 From: John Luo Date: Wed, 2 Aug 2017 14:32:27 -0700 Subject: [PATCH 0572/1029] Ensure fallback to curl after failed wget --- build.sh | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/build.sh b/build.sh index 8eace4c20d..11cdbe5504 100755 --- a/build.sh +++ b/build.sh @@ -99,16 +99,19 @@ __get_remote_file() { return 0 fi - local succeeded=false + local failed=false if __machine_has wget; then - wget --tries 10 --quiet -O "$local_path" "$remote_path" && succeeded=true + wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true + else + failed=true fi - if [ "$succeeded" = false ] && __machine_has curl; then - curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" && succeeded=true + if [ "$failed" = true ] && __machine_has curl; then + failed=false + curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true fi - if [ "$succeeded" = false ]; then + if [ "$failed" = true ]; then __error "Download failed: $remote_path" 1>&2 return 1 fi From 14dcbdb9dd37f3a3d91649c3deb685b77e481709 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 7 Aug 2017 10:05:30 -0700 Subject: [PATCH 0573/1029] Remove duplicate PackageReference [ci skip] --- .../Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj b/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj index 6e956b40f5..d7920e7b39 100644 --- a/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj +++ b/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj @@ -11,7 +11,6 @@ - From a2c0410e39a05bf646d1a042ec2284af37847b1b Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 17 Aug 2017 16:15:42 -0700 Subject: [PATCH 0574/1029] Use PackageLineup to manage package versions --- appveyor.yml => .appveyor.yml | 0 Directory.Build.props | 14 +++++++++++ Directory.Build.targets | 14 +++++++++++ JsonPatch.sln | 25 ++++++++++++++++++- build/common.props | 24 ------------------ build/dependencies.props | 14 ----------- build/repo.props | 6 +++++ src/Directory.Build.props | 7 ++++++ .../Microsoft.AspNetCore.JsonPatch.csproj | 7 +++--- test/Directory.Build.props | 11 ++++++++ .../DictionaryAdapterTest.cs | 14 +++++------ ...Microsoft.AspNetCore.JsonPatch.Test.csproj | 9 ++----- .../ObjectAdapterTests.cs | 8 +++--- 13 files changed, 92 insertions(+), 61 deletions(-) rename appveyor.yml => .appveyor.yml (100%) create mode 100644 Directory.Build.props create mode 100644 Directory.Build.targets delete mode 100644 build/common.props delete mode 100644 build/dependencies.props create mode 100644 build/repo.props create mode 100644 src/Directory.Build.props create mode 100644 test/Directory.Build.props diff --git a/appveyor.yml b/.appveyor.yml similarity index 100% rename from appveyor.yml rename to .appveyor.yml diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000000..57d9ef7e6a --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,14 @@ + + + + + Microsoft ASP.NET Core + https://github.com/aspnet/JsonPatch + git + $(MSBuildThisFileDirectory)build\Key.snk + true + true + $(VersionSuffix)-$(BuildNumber) + true + + diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 0000000000..9989b1046b --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,14 @@ + + + + <_BootstrapperFile Condition=" $([MSBuild]::IsOSUnixLike()) ">build.sh + <_BootstrapperFile Condition="! $([MSBuild]::IsOSUnixLike()) ">build.cmd + <_BootstrapperError> + Package references have not been pinned. Run './$(_BootstrapperFile) /t:Pin'. + Also, you can run './$(_BootstrapperFile) /t:Restore' which will pin *and* restore packages. '$(_BootstrapperFile)' can be found in '$(MSBuildThisFileDirectory)'. + + + + + + diff --git a/JsonPatch.sln b/JsonPatch.sln index b75721a487..87b48a8ea1 100644 --- a/JsonPatch.sln +++ b/JsonPatch.sln @@ -1,10 +1,16 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26222.1 +VisualStudioVersion = 15.0.26815.3 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{430B59ED-F960-4D3A-8FFE-3370008E168D}" + ProjectSection(SolutionItems) = preProject + src\Directory.Build.props = src\Directory.Build.props + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{36CD6341-AB44-44EB-B3AA-BF98C89FECDD}" + ProjectSection(SolutionItems) = preProject + test\Directory.Build.props = test\Directory.Build.props + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.JsonPatch", "src\Microsoft.AspNetCore.JsonPatch\Microsoft.AspNetCore.JsonPatch.csproj", "{4D55F4D8-633B-462F-A5B1-FEB84BD2D534}" EndProject @@ -12,7 +18,21 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.JsonPa EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C430C499-382D-47BD-B351-CF8F89C08CD2}" ProjectSection(SolutionItems) = preProject + .appveyor.yml = .appveyor.yml + .gitattributes = .gitattributes + .gitignore = .gitignore + .travis.yml = .travis.yml + build.cmd = build.cmd + build.ps1 = build.ps1 + build.sh = build.sh + CONTRIBUTING.md = CONTRIBUTING.md + Directory.Build.props = Directory.Build.props + Directory.Build.targets = Directory.Build.targets + LICENSE.txt = LICENSE.txt NuGet.config = NuGet.config + NuGetPackageVerifier.json = NuGetPackageVerifier.json + README.md = README.md + version.xml = version.xml EndProjectSection EndProject Global @@ -37,4 +57,7 @@ Global {4D55F4D8-633B-462F-A5B1-FEB84BD2D534} = {430B59ED-F960-4D3A-8FFE-3370008E168D} {81C20848-E063-4E12-AC40-0B55A532C16C} = {36CD6341-AB44-44EB-B3AA-BF98C89FECDD} EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {9FFA3EB9-8740-4434-BC8C-F3D595161B59} + EndGlobalSection EndGlobal diff --git a/build/common.props b/build/common.props deleted file mode 100644 index b749c350f1..0000000000 --- a/build/common.props +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - Microsoft ASP.NET Core - https://github.com/aspnet/JsonPatch - git - $(MSBuildThisFileDirectory)Key.snk - true - true - $(VersionSuffix)-$(BuildNumber) - true - - - - - - - - - - - diff --git a/build/dependencies.props b/build/dependencies.props deleted file mode 100644 index f2fb071ace..0000000000 --- a/build/dependencies.props +++ /dev/null @@ -1,14 +0,0 @@ - - - 2.1.0-* - 4.4.0-* - 2.1.1-* - 10.0.1 - 4.7.49 - 2.0.0-* - 2.0.0-* - 2.0.0-* - 15.3.0-* - 2.3.0-beta2-* - - diff --git a/build/repo.props b/build/repo.props new file mode 100644 index 0000000000..c5d91e8a2c --- /dev/null +++ b/build/repo.props @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 0000000000..5236edee58 --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj index e9732e8621..a364de22ef 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj +++ b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj @@ -1,5 +1,4 @@ - ASP.NET Core support for JSON PATCH. @@ -10,9 +9,9 @@ - - - + + + diff --git a/test/Directory.Build.props b/test/Directory.Build.props new file mode 100644 index 0000000000..31ed7dd07c --- /dev/null +++ b/test/Directory.Build.props @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs index 6a88bd6cc7..bc50b872a2 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs @@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.True(addStatus); Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Equal(1, dictionary.Count); + Assert.Single(dictionary); Assert.Equal("James", dictionary[nameKey]); } @@ -48,7 +48,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.True(addStatus); Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Equal(1, dictionary.Count); + Assert.Single(dictionary); Assert.Equal("James", dictionary[nameKey]); // Act @@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.True(addStatus); Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Equal(1, dictionary.Count); + Assert.Single(dictionary); Assert.Equal("James", dictionary[nameKey]); // Act @@ -107,7 +107,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.True(replaceStatus); Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Equal(1, dictionary.Count); + Assert.Single(dictionary); Assert.Equal("James", dictionary[nameKey]); } @@ -129,7 +129,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.Equal( string.Format("The target location specified by path segment '{0}' was not found.", nameKey), message); - Assert.Equal(0, dictionary.Count); + Assert.Empty(dictionary); } [Fact] @@ -150,7 +150,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.Equal( string.Format("The target location specified by path segment '{0}' was not found.", nameKey), message); - Assert.Equal(0, dictionary.Count); + Assert.Empty(dictionary); } [Fact] @@ -170,7 +170,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal //Assert Assert.True(removeStatus); Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Equal(0, dictionary.Count); + Assert.Empty(dictionary); } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj index f5b8c8268a..2e4f68b538 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj @@ -1,7 +1,5 @@  - - netcoreapp2.0;net461 netcoreapp2.0 @@ -12,11 +10,8 @@ - - - - - + + diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs index 56b25d22be..34a8c97b67 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs @@ -720,8 +720,8 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters var serialized = JsonConvert.SerializeObject(patchDoc); // Assert - Assert.False(serialized.Contains("operations")); - Assert.False(serialized.Contains("Operations")); + Assert.DoesNotContain("operations", serialized); + Assert.DoesNotContain("Operations", serialized); } [Fact] @@ -2061,7 +2061,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters patchDoc.ApplyTo(model); // Assert - Assert.Equal(1, model.Count); + Assert.Single(model); Assert.Equal(expected, model["WA"]); } @@ -2080,7 +2080,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters deserialized.ApplyTo(model); // Assert - Assert.Equal(1, model.Count); + Assert.Single(model); Assert.Equal(expected, model["WA"]); } From a4320ccbda79d587e931c21bb2df8adf55d6399d Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 18 Aug 2017 09:55:10 -0700 Subject: [PATCH 0575/1029] Upgrade to xunit 2.3.0-beta4 --- appveyor.yml => .appveyor.yml | 0 build/common.props => Directory.Build.props | 12 +++------ Directory.Build.targets | 2 ++ DotNetTools.sln | 27 +++++++++++++++++-- build/dependencies.props | 5 ++-- src/Directory.Build.props | 7 +++++ ...pNetCore.CertificateGeneration.Task.csproj | 4 +-- .../Microsoft.DotNet.Watcher.Tools.csproj | 4 +-- ....Extensions.Caching.SqlConfig.Tools.csproj | 2 -- ...soft.Extensions.SecretManager.Tools.csproj | 2 -- test/Directory.Build.props | 11 ++++++++ .../GenerateSSLCertificateTaskTest.cs | 20 +++++++------- ...re.CertificateGeneration.Task.Tests.csproj | 9 ------- .../FileWatcherTests.cs | 18 ++++++------- .../GlobbingAppTests.cs | 3 ++- ...otNet.Watcher.Tools.FunctionalTests.csproj | 5 ---- .../Scenario/WatchableApp.cs | 5 ++-- ...icrosoft.DotNet.Watcher.Tools.Tests.csproj | 5 ---- ...xtensions.SecretManager.Tools.Tests.csproj | 5 ---- 19 files changed, 79 insertions(+), 67 deletions(-) rename appveyor.yml => .appveyor.yml (100%) rename build/common.props => Directory.Build.props (65%) create mode 100644 Directory.Build.targets create mode 100644 src/Directory.Build.props create mode 100644 test/Directory.Build.props diff --git a/appveyor.yml b/.appveyor.yml similarity index 100% rename from appveyor.yml rename to .appveyor.yml diff --git a/build/common.props b/Directory.Build.props similarity index 65% rename from build/common.props rename to Directory.Build.props index 2d638b0045..267a97877a 100644 --- a/build/common.props +++ b/Directory.Build.props @@ -1,23 +1,19 @@ - - + + Microsoft .NET https://github.com/aspnet/DotNetTools git - $(MSBuildThisFileDirectory)Key.snk + $(MSBuildThisFileDirectory)build\Key.snk true true $(VersionSuffix)-$(BuildNumber) true - + false - - - - diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 0000000000..8c119d5413 --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,2 @@ + + diff --git a/DotNetTools.sln b/DotNetTools.sln index 8af718e399..caea9174df 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -1,18 +1,38 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26510.0 +VisualStudioVersion = 15.0.26815.3 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66517987-2A5A-4330-B130-207039378FD4}" + ProjectSection(SolutionItems) = preProject + src\Directory.Build.props = src\Directory.Build.props + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Watcher.Tools", "src\Microsoft.DotNet.Watcher.Tools\Microsoft.DotNet.Watcher.Tools.csproj", "{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8321E0D1-9A47-4D2F-AED8-3AE636D44E35}" ProjectSection(SolutionItems) = preProject + .appveyor.yml = .appveyor.yml .editorconfig = .editorconfig - NuGet.Config = NuGet.Config + .gitattributes = .gitattributes + .gitignore = .gitignore + .travis.yml = .travis.yml + build.cmd = build.cmd + build.ps1 = build.ps1 + build.sh = build.sh + CONTRIBUTING.md = CONTRIBUTING.md + Directory.Build.props = Directory.Build.props + Directory.Build.targets = Directory.Build.targets + LICENSE.txt = LICENSE.txt + NuGet.config = NuGet.config + NuGetPackageVerifier.json = NuGetPackageVerifier.json + README.md = README.md + version.xml = version.xml EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F5B382BC-258F-46E1-AC3D-10E5CCD55134}" + ProjectSection(SolutionItems) = preProject + test\Directory.Build.props = test\Directory.Build.props + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Watcher.Tools.FunctionalTests", "test\Microsoft.DotNet.Watcher.Tools.FunctionalTests\Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj", "{16BADE2F-1184-4518-8A70-B68A19D0805B}" EndProject @@ -80,4 +100,7 @@ Global {7B293291-26F4-47F0-9C2F-E396F35A4280} = {66517987-2A5A-4330-B130-207039378FD4} {3A7EF01A-073B-4123-850D-DFA4701EBE5B} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {57C07F14-2EAC-44FF-A277-B9221B4B2BF7} + EndGlobalSection EndGlobal diff --git a/build/dependencies.props b/build/dependencies.props index 2734d91184..9946d7ccab 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -6,7 +6,8 @@ 15.3.409 2.0.0-* 2.0.0-* - 15.3.0-* - 2.3.0-beta2-* + 15.3.0 + 2.3.0-beta4-build3742 + 0.6.1 diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 0000000000..e150035ea9 --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/Microsoft.AspNetCore.CertificateGeneration.Task/Microsoft.AspNetCore.CertificateGeneration.Task.csproj b/src/Microsoft.AspNetCore.CertificateGeneration.Task/Microsoft.AspNetCore.CertificateGeneration.Task.csproj index e4ff13938a..33922b9ab1 100644 --- a/src/Microsoft.AspNetCore.CertificateGeneration.Task/Microsoft.AspNetCore.CertificateGeneration.Task.csproj +++ b/src/Microsoft.AspNetCore.CertificateGeneration.Task/Microsoft.AspNetCore.CertificateGeneration.Task.csproj @@ -1,7 +1,5 @@  - - netcoreapp2.0 MSBuild target for generating HTTPS certificates for development cross-platform. @@ -16,5 +14,5 @@ - + diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj index ee16dd6429..f8860e118f 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj @@ -1,9 +1,7 @@  - - - 7.1 + latest netcoreapp2.0 dotnet-watch exe diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj index 2d9e0cfb74..62243363fa 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj @@ -1,7 +1,5 @@  - - netcoreapp2.0 dotnet-sql-cache diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj index b73f1f8838..3dc5343a79 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj @@ -1,7 +1,5 @@  - - netcoreapp2.0 dotnet-user-secrets diff --git a/test/Directory.Build.props b/test/Directory.Build.props new file mode 100644 index 0000000000..607b54f498 --- /dev/null +++ b/test/Directory.Build.props @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/GenerateSSLCertificateTaskTest.cs b/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/GenerateSSLCertificateTaskTest.cs index 245333a84e..3ed7ef69db 100644 --- a/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/GenerateSSLCertificateTaskTest.cs +++ b/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/GenerateSSLCertificateTaskTest.cs @@ -27,8 +27,8 @@ namespace Microsoft.AspNetCore.CertificateGeneration.Task // Assert Assert.True(result); var certificates = GetTestCertificates(); - Assert.Equal(1, certificates.Count); - Assert.Equal(1, task.Messages.Count); + Assert.Single(certificates); + Assert.Single(task.Messages); Assert.StartsWith($"Generated certificate {TestSubject}", task.Messages[0]); } @@ -48,7 +48,7 @@ namespace Microsoft.AspNetCore.CertificateGeneration.Task Assert.True(result); var certificates = GetTestCertificates(); Assert.Equal(2, certificates.Count); - Assert.Equal(1, task.Messages.Count); + Assert.Single(task.Messages); Assert.StartsWith($"Generated certificate {TestSubject}", task.Messages[0]); } @@ -87,7 +87,7 @@ namespace Microsoft.AspNetCore.CertificateGeneration.Task Assert.True(result); var certificates = GetTestCertificates(); Assert.Equal(2, certificates.Count); - Assert.Equal(1, task.Messages.Count); + Assert.Single(task.Messages); Assert.StartsWith($"Generated certificate {TestSubject}", task.Messages[0]); } @@ -105,8 +105,8 @@ namespace Microsoft.AspNetCore.CertificateGeneration.Task // Assert Assert.True(result); var certificates = GetTestCertificates(); - Assert.Equal(1, certificates.Count); - Assert.Equal(1, task.Messages.Count); + Assert.Single(certificates); + Assert.Single(task.Messages); Assert.Equal($"A certificate with subject name '{TestSubject}' already exists. Skipping certificate generation.", task.Messages[0]); } @@ -125,7 +125,7 @@ namespace Microsoft.AspNetCore.CertificateGeneration.Task Assert.True(result); var certificates = GetTestCertificates(); Assert.Equal(2, certificates.Count); - Assert.Equal(1, task.Messages.Count); + Assert.Single(task.Messages); Assert.StartsWith($"Generated certificate {TestSubject}", task.Messages[0]); } @@ -167,8 +167,10 @@ namespace Microsoft.AspNetCore.CertificateGeneration.Task var signingRequest = new CertificateRequest( new X500DistinguishedName(TestSubject), rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); - var enhancedKeyUsage = new OidCollection(); - enhancedKeyUsage.Add(new Oid("1.3.6.1.5.5.7.3.1", "Server Authentication")); + var enhancedKeyUsage = new OidCollection + { + new Oid("1.3.6.1.5.5.7.3.1", "Server Authentication") + }; signingRequest.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(enhancedKeyUsage, critical: true)); signingRequest.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.KeyEncipherment, critical: true)); signingRequest.CertificateExtensions.Add( diff --git a/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj b/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj index d7920e7b39..41303778f3 100644 --- a/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj +++ b/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj @@ -1,7 +1,5 @@ - - netcoreapp2.0 @@ -10,11 +8,4 @@ - - - - - - - diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs index f627a5bd0d..4df16166a0 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -120,8 +120,8 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests File.Move(srcFile, dstFile); Assert.True(changedEv.WaitOne(DefaultTimeout)); - Assert.True(filesChanged.Contains(srcFile)); - Assert.True(filesChanged.Contains(dstFile)); + Assert.Contains(srcFile, filesChanged); + Assert.Contains(dstFile, filesChanged); } }); } @@ -165,8 +165,8 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests File.WriteAllText(testFileFullPath, string.Empty); Assert.True(changedEv.WaitOne(DefaultTimeout)); - Assert.True(filesChanged.Contains(subdir)); - Assert.True(filesChanged.Contains(testFileFullPath)); + Assert.Contains(subdir, filesChanged); + Assert.Contains(testFileFullPath, filesChanged); } }); } @@ -399,10 +399,10 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests Assert.True(changedEv.WaitOne(DefaultTimeout)); - Assert.True(filesChanged.Contains(f1)); - Assert.True(filesChanged.Contains(f2)); - Assert.True(filesChanged.Contains(f3)); - Assert.True(filesChanged.Contains(subdir)); + Assert.Contains(f1, filesChanged); + Assert.Contains(f2, filesChanged); + Assert.Contains(f3, filesChanged); + Assert.Contains(subdir, filesChanged); } }); } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs index be3bcef66a..e5b83b1112 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -27,6 +27,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [InlineData(false)] public async Task ChangeCompiledFile(bool usePollingWatcher) { + _app.UsePollingWatcher = usePollingWatcher; await _app.StartWatcherAsync(); var types = await _app.GetCompiledAppDefinedTypes().TimeoutAfter(DefaultTimeout); diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj index 05ec2a8723..c00a30bc00 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj @@ -1,7 +1,5 @@  - - netcoreapp2.0 $(DefaultItemExcludes);TestProjects\**\* @@ -23,9 +21,6 @@ - - - diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs index 2b60ef9a17..8fad2e5486 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -78,7 +78,8 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests WorkingDirectory = SourceDirectory, EnvironmentVariables = { - ["DOTNET_CLI_CONTEXT_VERBOSE"] = bool.TrueString + ["DOTNET_CLI_CONTEXT_VERBOSE"] = bool.TrueString, + ["DOTNET_USE_POLLING_FILE_WATCHER"] = UsePollingWatcher.ToString(), }, }; diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj index 55bc572749..14920c0f1e 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj @@ -1,7 +1,5 @@  - - netcoreapp2.0 @@ -19,9 +17,6 @@ - - - diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj index 4f3a3bb12a..5ac356aa2e 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj @@ -1,7 +1,5 @@  - - netcoreapp2.0 @@ -12,9 +10,6 @@ - - - From 01bf47170fdb848f4ced623b1fad7450c8848d64 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 18 Aug 2017 10:43:19 -0700 Subject: [PATCH 0576/1029] Revert lineups change until we work out issues with PackageLineup This reverts commit a2c0410e39a05bf646d1a042ec2284af37847b1b. --- Directory.Build.props | 14 ----------- Directory.Build.targets | 14 ----------- JsonPatch.sln | 25 +------------------ .appveyor.yml => appveyor.yml | 0 build/common.props | 24 ++++++++++++++++++ build/dependencies.props | 14 +++++++++++ build/repo.props | 6 ----- src/Directory.Build.props | 7 ------ .../Microsoft.AspNetCore.JsonPatch.csproj | 7 +++--- test/Directory.Build.props | 11 -------- .../DictionaryAdapterTest.cs | 14 +++++------ ...Microsoft.AspNetCore.JsonPatch.Test.csproj | 9 +++++-- .../ObjectAdapterTests.cs | 8 +++--- 13 files changed, 61 insertions(+), 92 deletions(-) delete mode 100644 Directory.Build.props delete mode 100644 Directory.Build.targets rename .appveyor.yml => appveyor.yml (100%) create mode 100644 build/common.props create mode 100644 build/dependencies.props delete mode 100644 build/repo.props delete mode 100644 src/Directory.Build.props delete mode 100644 test/Directory.Build.props diff --git a/Directory.Build.props b/Directory.Build.props deleted file mode 100644 index 57d9ef7e6a..0000000000 --- a/Directory.Build.props +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Microsoft ASP.NET Core - https://github.com/aspnet/JsonPatch - git - $(MSBuildThisFileDirectory)build\Key.snk - true - true - $(VersionSuffix)-$(BuildNumber) - true - - diff --git a/Directory.Build.targets b/Directory.Build.targets deleted file mode 100644 index 9989b1046b..0000000000 --- a/Directory.Build.targets +++ /dev/null @@ -1,14 +0,0 @@ - - - - <_BootstrapperFile Condition=" $([MSBuild]::IsOSUnixLike()) ">build.sh - <_BootstrapperFile Condition="! $([MSBuild]::IsOSUnixLike()) ">build.cmd - <_BootstrapperError> - Package references have not been pinned. Run './$(_BootstrapperFile) /t:Pin'. - Also, you can run './$(_BootstrapperFile) /t:Restore' which will pin *and* restore packages. '$(_BootstrapperFile)' can be found in '$(MSBuildThisFileDirectory)'. - - - - - - diff --git a/JsonPatch.sln b/JsonPatch.sln index 87b48a8ea1..b75721a487 100644 --- a/JsonPatch.sln +++ b/JsonPatch.sln @@ -1,16 +1,10 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26815.3 +VisualStudioVersion = 15.0.26222.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{430B59ED-F960-4D3A-8FFE-3370008E168D}" - ProjectSection(SolutionItems) = preProject - src\Directory.Build.props = src\Directory.Build.props - EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{36CD6341-AB44-44EB-B3AA-BF98C89FECDD}" - ProjectSection(SolutionItems) = preProject - test\Directory.Build.props = test\Directory.Build.props - EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.JsonPatch", "src\Microsoft.AspNetCore.JsonPatch\Microsoft.AspNetCore.JsonPatch.csproj", "{4D55F4D8-633B-462F-A5B1-FEB84BD2D534}" EndProject @@ -18,21 +12,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.JsonPa EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C430C499-382D-47BD-B351-CF8F89C08CD2}" ProjectSection(SolutionItems) = preProject - .appveyor.yml = .appveyor.yml - .gitattributes = .gitattributes - .gitignore = .gitignore - .travis.yml = .travis.yml - build.cmd = build.cmd - build.ps1 = build.ps1 - build.sh = build.sh - CONTRIBUTING.md = CONTRIBUTING.md - Directory.Build.props = Directory.Build.props - Directory.Build.targets = Directory.Build.targets - LICENSE.txt = LICENSE.txt NuGet.config = NuGet.config - NuGetPackageVerifier.json = NuGetPackageVerifier.json - README.md = README.md - version.xml = version.xml EndProjectSection EndProject Global @@ -57,7 +37,4 @@ Global {4D55F4D8-633B-462F-A5B1-FEB84BD2D534} = {430B59ED-F960-4D3A-8FFE-3370008E168D} {81C20848-E063-4E12-AC40-0B55A532C16C} = {36CD6341-AB44-44EB-B3AA-BF98C89FECDD} EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {9FFA3EB9-8740-4434-BC8C-F3D595161B59} - EndGlobalSection EndGlobal diff --git a/.appveyor.yml b/appveyor.yml similarity index 100% rename from .appveyor.yml rename to appveyor.yml diff --git a/build/common.props b/build/common.props new file mode 100644 index 0000000000..b749c350f1 --- /dev/null +++ b/build/common.props @@ -0,0 +1,24 @@ + + + + + + Microsoft ASP.NET Core + https://github.com/aspnet/JsonPatch + git + $(MSBuildThisFileDirectory)Key.snk + true + true + $(VersionSuffix)-$(BuildNumber) + true + + + + + + + + + + + diff --git a/build/dependencies.props b/build/dependencies.props new file mode 100644 index 0000000000..f2fb071ace --- /dev/null +++ b/build/dependencies.props @@ -0,0 +1,14 @@ + + + 2.1.0-* + 4.4.0-* + 2.1.1-* + 10.0.1 + 4.7.49 + 2.0.0-* + 2.0.0-* + 2.0.0-* + 15.3.0-* + 2.3.0-beta2-* + + diff --git a/build/repo.props b/build/repo.props deleted file mode 100644 index c5d91e8a2c..0000000000 --- a/build/repo.props +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/src/Directory.Build.props b/src/Directory.Build.props deleted file mode 100644 index 5236edee58..0000000000 --- a/src/Directory.Build.props +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj index a364de22ef..e9732e8621 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj +++ b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj @@ -1,4 +1,5 @@ + ASP.NET Core support for JSON PATCH. @@ -9,9 +10,9 @@ - - - + + + diff --git a/test/Directory.Build.props b/test/Directory.Build.props deleted file mode 100644 index 31ed7dd07c..0000000000 --- a/test/Directory.Build.props +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs index bc50b872a2..6a88bd6cc7 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs @@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.True(addStatus); Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Single(dictionary); + Assert.Equal(1, dictionary.Count); Assert.Equal("James", dictionary[nameKey]); } @@ -48,7 +48,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.True(addStatus); Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Single(dictionary); + Assert.Equal(1, dictionary.Count); Assert.Equal("James", dictionary[nameKey]); // Act @@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.True(addStatus); Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Single(dictionary); + Assert.Equal(1, dictionary.Count); Assert.Equal("James", dictionary[nameKey]); // Act @@ -107,7 +107,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.True(replaceStatus); Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Single(dictionary); + Assert.Equal(1, dictionary.Count); Assert.Equal("James", dictionary[nameKey]); } @@ -129,7 +129,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.Equal( string.Format("The target location specified by path segment '{0}' was not found.", nameKey), message); - Assert.Empty(dictionary); + Assert.Equal(0, dictionary.Count); } [Fact] @@ -150,7 +150,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.Equal( string.Format("The target location specified by path segment '{0}' was not found.", nameKey), message); - Assert.Empty(dictionary); + Assert.Equal(0, dictionary.Count); } [Fact] @@ -170,7 +170,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal //Assert Assert.True(removeStatus); Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Empty(dictionary); + Assert.Equal(0, dictionary.Count); } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj index 2e4f68b538..f5b8c8268a 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj @@ -1,5 +1,7 @@  + + netcoreapp2.0;net461 netcoreapp2.0 @@ -10,8 +12,11 @@ - - + + + + + diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs index 34a8c97b67..56b25d22be 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs @@ -720,8 +720,8 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters var serialized = JsonConvert.SerializeObject(patchDoc); // Assert - Assert.DoesNotContain("operations", serialized); - Assert.DoesNotContain("Operations", serialized); + Assert.False(serialized.Contains("operations")); + Assert.False(serialized.Contains("Operations")); } [Fact] @@ -2061,7 +2061,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters patchDoc.ApplyTo(model); // Assert - Assert.Single(model); + Assert.Equal(1, model.Count); Assert.Equal(expected, model["WA"]); } @@ -2080,7 +2080,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters deserialized.ApplyTo(model); // Assert - Assert.Single(model); + Assert.Equal(1, model.Count); Assert.Equal(expected, model["WA"]); } From a993c2a5ff3d4f21a50c3a424cb42201944c4b19 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 18 Aug 2017 16:31:06 -0700 Subject: [PATCH 0577/1029] Use PackageLineup to manage versions (revert revert) We resolved the issues with PackageLineup and partial graph builds. This reverts commit 01bf47170fdb848f4ced623b1fad7450c8848d64. --- appveyor.yml => .appveyor.yml | 0 Directory.Build.props | 14 +++++++++++ Directory.Build.targets | 14 +++++++++++ JsonPatch.sln | 25 ++++++++++++++++++- build/common.props | 24 ------------------ build/dependencies.props | 14 ----------- build/repo.props | 6 +++++ src/Directory.Build.props | 7 ++++++ .../Microsoft.AspNetCore.JsonPatch.csproj | 7 +++--- test/Directory.Build.props | 11 ++++++++ .../DictionaryAdapterTest.cs | 14 +++++------ ...Microsoft.AspNetCore.JsonPatch.Test.csproj | 9 ++----- .../ObjectAdapterTests.cs | 8 +++--- 13 files changed, 92 insertions(+), 61 deletions(-) rename appveyor.yml => .appveyor.yml (100%) create mode 100644 Directory.Build.props create mode 100644 Directory.Build.targets delete mode 100644 build/common.props delete mode 100644 build/dependencies.props create mode 100644 build/repo.props create mode 100644 src/Directory.Build.props create mode 100644 test/Directory.Build.props diff --git a/appveyor.yml b/.appveyor.yml similarity index 100% rename from appveyor.yml rename to .appveyor.yml diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000000..57d9ef7e6a --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,14 @@ + + + + + Microsoft ASP.NET Core + https://github.com/aspnet/JsonPatch + git + $(MSBuildThisFileDirectory)build\Key.snk + true + true + $(VersionSuffix)-$(BuildNumber) + true + + diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 0000000000..9989b1046b --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,14 @@ + + + + <_BootstrapperFile Condition=" $([MSBuild]::IsOSUnixLike()) ">build.sh + <_BootstrapperFile Condition="! $([MSBuild]::IsOSUnixLike()) ">build.cmd + <_BootstrapperError> + Package references have not been pinned. Run './$(_BootstrapperFile) /t:Pin'. + Also, you can run './$(_BootstrapperFile) /t:Restore' which will pin *and* restore packages. '$(_BootstrapperFile)' can be found in '$(MSBuildThisFileDirectory)'. + + + + + + diff --git a/JsonPatch.sln b/JsonPatch.sln index b75721a487..87b48a8ea1 100644 --- a/JsonPatch.sln +++ b/JsonPatch.sln @@ -1,10 +1,16 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26222.1 +VisualStudioVersion = 15.0.26815.3 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{430B59ED-F960-4D3A-8FFE-3370008E168D}" + ProjectSection(SolutionItems) = preProject + src\Directory.Build.props = src\Directory.Build.props + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{36CD6341-AB44-44EB-B3AA-BF98C89FECDD}" + ProjectSection(SolutionItems) = preProject + test\Directory.Build.props = test\Directory.Build.props + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.JsonPatch", "src\Microsoft.AspNetCore.JsonPatch\Microsoft.AspNetCore.JsonPatch.csproj", "{4D55F4D8-633B-462F-A5B1-FEB84BD2D534}" EndProject @@ -12,7 +18,21 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.JsonPa EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C430C499-382D-47BD-B351-CF8F89C08CD2}" ProjectSection(SolutionItems) = preProject + .appveyor.yml = .appveyor.yml + .gitattributes = .gitattributes + .gitignore = .gitignore + .travis.yml = .travis.yml + build.cmd = build.cmd + build.ps1 = build.ps1 + build.sh = build.sh + CONTRIBUTING.md = CONTRIBUTING.md + Directory.Build.props = Directory.Build.props + Directory.Build.targets = Directory.Build.targets + LICENSE.txt = LICENSE.txt NuGet.config = NuGet.config + NuGetPackageVerifier.json = NuGetPackageVerifier.json + README.md = README.md + version.xml = version.xml EndProjectSection EndProject Global @@ -37,4 +57,7 @@ Global {4D55F4D8-633B-462F-A5B1-FEB84BD2D534} = {430B59ED-F960-4D3A-8FFE-3370008E168D} {81C20848-E063-4E12-AC40-0B55A532C16C} = {36CD6341-AB44-44EB-B3AA-BF98C89FECDD} EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {9FFA3EB9-8740-4434-BC8C-F3D595161B59} + EndGlobalSection EndGlobal diff --git a/build/common.props b/build/common.props deleted file mode 100644 index b749c350f1..0000000000 --- a/build/common.props +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - Microsoft ASP.NET Core - https://github.com/aspnet/JsonPatch - git - $(MSBuildThisFileDirectory)Key.snk - true - true - $(VersionSuffix)-$(BuildNumber) - true - - - - - - - - - - - diff --git a/build/dependencies.props b/build/dependencies.props deleted file mode 100644 index f2fb071ace..0000000000 --- a/build/dependencies.props +++ /dev/null @@ -1,14 +0,0 @@ - - - 2.1.0-* - 4.4.0-* - 2.1.1-* - 10.0.1 - 4.7.49 - 2.0.0-* - 2.0.0-* - 2.0.0-* - 15.3.0-* - 2.3.0-beta2-* - - diff --git a/build/repo.props b/build/repo.props new file mode 100644 index 0000000000..c5d91e8a2c --- /dev/null +++ b/build/repo.props @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 0000000000..5236edee58 --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj index e9732e8621..a364de22ef 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj +++ b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj @@ -1,5 +1,4 @@ - ASP.NET Core support for JSON PATCH. @@ -10,9 +9,9 @@ - - - + + + diff --git a/test/Directory.Build.props b/test/Directory.Build.props new file mode 100644 index 0000000000..31ed7dd07c --- /dev/null +++ b/test/Directory.Build.props @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs index 6a88bd6cc7..bc50b872a2 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs @@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.True(addStatus); Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Equal(1, dictionary.Count); + Assert.Single(dictionary); Assert.Equal("James", dictionary[nameKey]); } @@ -48,7 +48,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.True(addStatus); Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Equal(1, dictionary.Count); + Assert.Single(dictionary); Assert.Equal("James", dictionary[nameKey]); // Act @@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.True(addStatus); Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Equal(1, dictionary.Count); + Assert.Single(dictionary); Assert.Equal("James", dictionary[nameKey]); // Act @@ -107,7 +107,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.True(replaceStatus); Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Equal(1, dictionary.Count); + Assert.Single(dictionary); Assert.Equal("James", dictionary[nameKey]); } @@ -129,7 +129,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.Equal( string.Format("The target location specified by path segment '{0}' was not found.", nameKey), message); - Assert.Equal(0, dictionary.Count); + Assert.Empty(dictionary); } [Fact] @@ -150,7 +150,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.Equal( string.Format("The target location specified by path segment '{0}' was not found.", nameKey), message); - Assert.Equal(0, dictionary.Count); + Assert.Empty(dictionary); } [Fact] @@ -170,7 +170,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal //Assert Assert.True(removeStatus); Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); - Assert.Equal(0, dictionary.Count); + Assert.Empty(dictionary); } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj index f5b8c8268a..2e4f68b538 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj @@ -1,7 +1,5 @@  - - netcoreapp2.0;net461 netcoreapp2.0 @@ -12,11 +10,8 @@ - - - - - + + diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs index 56b25d22be..34a8c97b67 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs @@ -720,8 +720,8 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters var serialized = JsonConvert.SerializeObject(patchDoc); // Assert - Assert.False(serialized.Contains("operations")); - Assert.False(serialized.Contains("Operations")); + Assert.DoesNotContain("operations", serialized); + Assert.DoesNotContain("Operations", serialized); } [Fact] @@ -2061,7 +2061,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters patchDoc.ApplyTo(model); // Assert - Assert.Equal(1, model.Count); + Assert.Single(model); Assert.Equal(expected, model["WA"]); } @@ -2080,7 +2080,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters deserialized.ApplyTo(model); // Assert - Assert.Equal(1, model.Count); + Assert.Single(model); Assert.Equal(expected, model["WA"]); } From 68a6e8d367b27d00e00ae00b4bacd764dc6fb503 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 22 Aug 2017 15:19:42 -0700 Subject: [PATCH 0578/1029] Upgrade to xunit 2.3.0-beta4 --- build/dependencies.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 3c71bd378d..1235e00530 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -6,7 +6,7 @@ 2.0.0-* 2.0.0-* 2.0.0-* - 15.3.0-* - 2.3.0-beta2-* + 15.3.0 + 2.3.0-beta4-build3742 From d4b64af0e60a319d8240837d3174fac9b04e271b Mon Sep 17 00:00:00 2001 From: Jass Bagga Date: Wed, 23 Aug 2017 10:30:11 -0700 Subject: [PATCH 0579/1029] Use DictionaryKeyResolver for ExpandoObjectAdapter (#100) Addresses #102 --- .../Adapters/ObjectAdapter.cs | 31 +--- .../Internal/ExpandoObjectAdapter.cs | 22 +-- .../ExpandoObjectDictionaryExtensions.cs | 26 --- .../Internal/ListAdapter.cs | 34 ++-- .../Internal/PocoAdapter.cs | 24 +-- .../Dynamic/AddOperationTests.cs | 51 +++--- .../Dynamic/AddTypedOperationTests.cs | 8 +- .../Dynamic/CopyOperationTests.cs | 24 +-- .../Dynamic/CopyTypedOperationTests.cs | 24 +-- .../Dynamic/CustomNamingStrategyTests.cs | 154 ++++++++++++++++++ .../Dynamic/MoveOperationTests.cs | 45 +++-- .../Dynamic/MoveTypedOperationTests.cs | 12 +- .../Dynamic/PatchDocumentTests.cs | 12 +- .../Dynamic/RemoveOperationTests.cs | 80 ++++----- .../Dynamic/RemoveTypedOperationTests.cs | 20 +-- .../ObjectVisitorTest.cs | 4 - 16 files changed, 330 insertions(+), 241 deletions(-) delete mode 100644 src/Microsoft.AspNetCore.JsonPatch/Internal/ExpandoObjectDictionaryExtensions.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CustomNamingStrategyTests.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs index b1a487f088..a30343868a 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs @@ -2,8 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.AspNetCore.JsonPatch.Exceptions; -using Microsoft.AspNetCore.JsonPatch.Helpers; using Microsoft.AspNetCore.JsonPatch.Internal; using Microsoft.AspNetCore.JsonPatch.Operations; using Newtonsoft.Json.Serialization; @@ -22,12 +20,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters IContractResolver contractResolver, Action logErrorAction) { - if (contractResolver == null) - { - throw new ArgumentNullException(nameof(contractResolver)); - } - - ContractResolver = contractResolver; + ContractResolver = contractResolver ?? throw new ArgumentNullException(nameof(contractResolver)); LogErrorAction = logErrorAction; } @@ -144,10 +137,8 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters var parsedPath = new ParsedPath(path); var visitor = new ObjectVisitor(parsedPath, ContractResolver); - IAdapter adapter; var target = objectToApplyTo; - string errorMessage; - if (!visitor.TryVisit(ref target, out adapter, out errorMessage)) + if (!visitor.TryVisit(ref target, out var adapter, out var errorMessage)) { var error = CreatePathNotFoundError(objectToApplyTo, path, operation, errorMessage); ErrorReporter(error); @@ -197,9 +188,8 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters throw new ArgumentNullException(nameof(objectToApplyTo)); } - object propertyValue; // Get value at 'from' location and add that value to the 'path' location - if (TryGetValue(operation.from, objectToApplyTo, operation, out propertyValue)) + if (TryGetValue(operation.from, objectToApplyTo, operation, out var propertyValue)) { // remove that value Remove(operation.from, objectToApplyTo, operation); @@ -253,10 +243,8 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters var parsedPath = new ParsedPath(path); var visitor = new ObjectVisitor(parsedPath, ContractResolver); - IAdapter adapter; var target = objectToApplyTo; - string errorMessage; - if (!visitor.TryVisit(ref target, out adapter, out errorMessage)) + if (!visitor.TryVisit(ref target, out var adapter, out var errorMessage)) { var error = CreatePathNotFoundError(objectToApplyTo, path, operationToReport, errorMessage); ErrorReporter(error); @@ -306,10 +294,8 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters var parsedPath = new ParsedPath(operation.path); var visitor = new ObjectVisitor(parsedPath, ContractResolver); - IAdapter adapter; var target = objectToApplyTo; - string errorMessage; - if (!visitor.TryVisit(ref target, out adapter, out errorMessage)) + if (!visitor.TryVisit(ref target, out var adapter, out var errorMessage)) { var error = CreatePathNotFoundError(objectToApplyTo, operation.path, operation, errorMessage); ErrorReporter(error); @@ -358,9 +344,8 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters throw new ArgumentNullException(nameof(objectToApplyTo)); } - object propertyValue; // Get value at 'from' location and add that value to the 'path' location - if (TryGetValue(operation.from, objectToApplyTo, operation, out propertyValue)) + if (TryGetValue(operation.from, objectToApplyTo, operation, out var propertyValue)) { // Create deep copy var copyResult = ConversionResultProvider.CopyTo(propertyValue, propertyValue.GetType()); @@ -406,10 +391,8 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters var parsedPath = new ParsedPath(fromLocation); var visitor = new ObjectVisitor(parsedPath, ContractResolver); - IAdapter adapter; var target = objectToGetValueFrom; - string errorMessage; - if (!visitor.TryVisit(ref target, out adapter, out errorMessage)) + if (!visitor.TryVisit(ref target, out var adapter, out var errorMessage)) { var error = CreatePathNotFoundError(objectToGetValueFrom, fromLocation, operation, errorMessage); ErrorReporter(error); diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ExpandoObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ExpandoObjectAdapter.cs index 681b5309e6..c35d1b702c 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/ExpandoObjectAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ExpandoObjectAdapter.cs @@ -16,10 +16,10 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal object value, out string errorMessage) { + var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType()); + var key = contract.DictionaryKeyResolver(segment); var dictionary = (IDictionary)target; - var key = dictionary.GetKeyUsingCaseInsensitiveSearch(segment); - // As per JsonPatch spec, if a key already exists, adding should replace the existing value dictionary[key] = ConvertValue(dictionary, key, value); @@ -34,9 +34,10 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal out object value, out string errorMessage) { + var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType()); + var key = contract.DictionaryKeyResolver(segment); var dictionary = (IDictionary)target; - var key = dictionary.GetKeyUsingCaseInsensitiveSearch(segment); value = dictionary[key]; errorMessage = null; @@ -49,10 +50,10 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal IContractResolver contractResolver, out string errorMessage) { + var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType()); + var key = contract.DictionaryKeyResolver(segment); var dictionary = (IDictionary)target; - var key = dictionary.GetKeyUsingCaseInsensitiveSearch(segment); - // As per JsonPatch spec, the target location must exist for remove to be successful if (!dictionary.ContainsKey(key)) { @@ -73,10 +74,10 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal object value, out string errorMessage) { + var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType()); + var key = contract.DictionaryKeyResolver(segment); var dictionary = (IDictionary)target; - var key = dictionary.GetKeyUsingCaseInsensitiveSearch(segment); - // As per JsonPatch spec, the target location must exist for remove to be successful if (!dictionary.ContainsKey(key)) { @@ -105,10 +106,10 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return false; } + var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType()); + var key = contract.DictionaryKeyResolver(segment); var dictionary = (IDictionary)expandoObject; - var key = dictionary.GetKeyUsingCaseInsensitiveSearch(segment); - if (dictionary.ContainsKey(key)) { nextTarget = dictionary[key]; @@ -125,8 +126,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal private object ConvertValue(IDictionary dictionary, string key, object newValue) { - object existingValue = null; - if (dictionary.TryGetValue(key, out existingValue)) + if (dictionary.TryGetValue(key, out var existingValue)) { if (existingValue != null) { diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ExpandoObjectDictionaryExtensions.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ExpandoObjectDictionaryExtensions.cs deleted file mode 100644 index 8bb60dd2a7..0000000000 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/ExpandoObjectDictionaryExtensions.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; - -namespace Microsoft.AspNetCore.JsonPatch.Internal -{ - // Helper methods to allow case-insensitive key search - public static class ExpandoObjectDictionaryExtensions - { - internal static string GetKeyUsingCaseInsensitiveSearch( - this IDictionary propertyDictionary, - string key) - { - foreach (var keyInDictionary in propertyDictionary.Keys) - { - if (string.Equals(key, keyInDictionary, StringComparison.OrdinalIgnoreCase)) - { - return keyInDictionary; - } - } - return key; - } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs index 343712690a..a1c0498e47 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs @@ -20,20 +20,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { var list = (IList)target; - Type typeArgument = null; - if (!TryGetListTypeArgument(list, out typeArgument, out errorMessage)) + if (!TryGetListTypeArgument(list, out var typeArgument, out errorMessage)) { return false; } - PositionInfo positionInfo; - if (!TryGetPositionInfo(list, segment, OperationType.Add, out positionInfo, out errorMessage)) + if (!TryGetPositionInfo(list, segment, OperationType.Add, out var positionInfo, out errorMessage)) { return false; } - object convertedValue = null; - if (!TryConvertValue(value, typeArgument, segment, out convertedValue, out errorMessage)) + if (!TryConvertValue(value, typeArgument, segment, out var convertedValue, out errorMessage)) { return false; } @@ -60,15 +57,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { var list = (IList)target; - Type typeArgument = null; - if (!TryGetListTypeArgument(list, out typeArgument, out errorMessage)) + if (!TryGetListTypeArgument(list, out var typeArgument, out errorMessage)) { value = null; return false; } - PositionInfo positionInfo; - if (!TryGetPositionInfo(list, segment, OperationType.Get, out positionInfo, out errorMessage)) + if (!TryGetPositionInfo(list, segment, OperationType.Get, out var positionInfo, out errorMessage)) { value = null; return false; @@ -95,14 +90,12 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { var list = (IList)target; - Type typeArgument = null; - if (!TryGetListTypeArgument(list, out typeArgument, out errorMessage)) + if (!TryGetListTypeArgument(list, out var typeArgument, out errorMessage)) { return false; } - PositionInfo positionInfo; - if (!TryGetPositionInfo(list, segment, OperationType.Remove, out positionInfo, out errorMessage)) + if (!TryGetPositionInfo(list, segment, OperationType.Remove, out var positionInfo, out errorMessage)) { return false; } @@ -129,20 +122,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { var list = (IList)target; - Type typeArgument = null; - if (!TryGetListTypeArgument(list, out typeArgument, out errorMessage)) + if (!TryGetListTypeArgument(list, out var typeArgument, out errorMessage)) { return false; } - PositionInfo positionInfo; - if (!TryGetPositionInfo(list, segment, OperationType.Replace, out positionInfo, out errorMessage)) + if (!TryGetPositionInfo(list, segment, OperationType.Replace, out var positionInfo, out errorMessage)) { return false; } - object convertedValue = null; - if (!TryConvertValue(value, typeArgument, segment, out convertedValue, out errorMessage)) + if (!TryConvertValue(value, typeArgument, segment, out var convertedValue, out errorMessage)) { return false; } @@ -175,7 +165,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return false; } - int index = -1; + var index = -1; if (!int.TryParse(segment, out index)) { value = null; @@ -257,7 +247,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - int position = -1; + var position = -1; if (int.TryParse(segment, out position)) { if (position >= 0 && position < list.Count) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs index 0755e132e1..eab16a3035 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs @@ -17,8 +17,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal object value, out string errorMessage) { - JsonProperty jsonProperty = null; - if (!TryGetJsonProperty(target, contractResolver, segment, out jsonProperty)) + if (!TryGetJsonProperty(target, contractResolver, segment, out var jsonProperty)) { errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); return false; @@ -30,8 +29,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return false; } - object convertedValue = null; - if (!TryConvertValue(value, jsonProperty.PropertyType, out convertedValue)) + if (!TryConvertValue(value, jsonProperty.PropertyType, out var convertedValue)) { errorMessage = Resources.FormatInvalidValueForProperty(value); return false; @@ -50,8 +48,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal out object value, out string errorMessage) { - JsonProperty jsonProperty = null; - if (!TryGetJsonProperty(target, contractResolver, segment, out jsonProperty)) + if (!TryGetJsonProperty(target, contractResolver, segment, out var jsonProperty)) { errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); value = null; @@ -76,8 +73,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal IContractResolver contractResolver, out string errorMessage) { - JsonProperty jsonProperty = null; - if (!TryGetJsonProperty(target, contractResolver, segment, out jsonProperty)) + if (!TryGetJsonProperty(target, contractResolver, segment, out var jsonProperty)) { errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); return false; @@ -112,8 +108,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal object value, out string errorMessage) { - JsonProperty jsonProperty = null; - if (!TryGetJsonProperty(target, contractResolver, segment, out jsonProperty)) + if (!TryGetJsonProperty(target, contractResolver, segment, out var jsonProperty)) { errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); return false; @@ -125,8 +120,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return false; } - object convertedValue = null; - if (!TryConvertValue(value, jsonProperty.PropertyType, out convertedValue)) + if (!TryConvertValue(value, jsonProperty.PropertyType, out var convertedValue)) { errorMessage = Resources.FormatInvalidValueForProperty(value); return false; @@ -152,8 +146,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return false; } - JsonProperty jsonProperty = null; - if (TryGetJsonProperty(target, contractResolver, segment, out jsonProperty)) + if (TryGetJsonProperty(target, contractResolver, segment, out var jsonProperty)) { value = jsonProperty.ValueProvider.GetValue(target); errorMessage = null; @@ -171,8 +164,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal string segment, out JsonProperty jsonProperty) { - var jsonObjectContract = contractResolver.ResolveContract(target.GetType()) as JsonObjectContract; - if (jsonObjectContract != null) + if (contractResolver.ResolveContract(target.GetType()) is JsonObjectContract jsonObjectContract) { var pocoProperty = jsonObjectContract .Properties diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs index cbd44a7ef9..e1cdb21df2 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs @@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("NewInt", 1); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic obj.Test = 1; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("NewInt", 1); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -65,7 +65,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("Nested/NewInt", 1); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -90,7 +90,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("Nested/NewInt", 1); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -115,7 +115,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("Nested/StringProperty", "A"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -137,7 +137,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("Nested/NewInt", 1); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -158,7 +158,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("DynamicProperty/NewInt", 1); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -181,7 +181,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("DynamicProperty/StringProperty", "B"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -203,7 +203,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic dynamic valueToAdd = new { IntValue = 1, StringValue = "test", GuidValue = Guid.NewGuid() }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("ComplexProperty", valueToAdd); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -227,7 +227,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("StringProperty", "B"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -249,7 +249,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.StringProperty = "A"; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("StringProperty", "B"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -269,7 +269,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.InBetweenFirst.InBetweenSecond.StringProperty = "A"; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("/InBetweenFirst/InBetweenSecond/StringProperty", "B"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -291,7 +291,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond.StringProperty = "A"; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("/Nested/DynamicProperty/InBetweenFirst/InBetweenSecond/StringProperty", "B"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -325,7 +325,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("DynamicProperty/OtherProperty/IntProperty", 1); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -366,7 +366,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("baz/bat", "qux"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -382,13 +382,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic } [Fact] - public void ShouldReplacePropertyWithDifferentCase() + public void ShouldNotReplacePropertyWithDifferentCase() { dynamic doc = new ExpandoObject(); doc.StringProperty = "A"; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("stringproperty", "B"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -396,7 +396,8 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); - Assert.Equal("B", doc.StringProperty); + Assert.Equal("A", doc.StringProperty); + Assert.Equal("B", doc.stringproperty); } [Fact] @@ -408,7 +409,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("IntegerList/0", 4); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -426,7 +427,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.IntegerList = new List() { 1, 2, 3 }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("IntegerList/-1", 4); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -450,7 +451,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("integerlist/0", 4); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -470,7 +471,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("IntegerList/4", 4); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -494,7 +495,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("IntegerList/0", 4); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -514,7 +515,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("IntegerList/-1", 4); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -538,7 +539,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("IntegerList/-", 4); var serialized = JsonConvert.SerializeObject(patchDoc); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs index f28d877ea4..bbf5118962 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs @@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("IntegerList/-1", 4); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("ListOfSimpleDTO/0/IntegerList/0", 4); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -74,7 +74,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("ListOfSimpleDTO/-1/IntegerList/0", 4); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -103,7 +103,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic } }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add("ListOfSimpleDTO/20/IntegerList/0", 4); var serialized = JsonConvert.SerializeObject(patchDoc); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyOperationTests.cs index 87f221bc15..42dd0072c4 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyOperationTests.cs @@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.StringProperty = "A"; doc.AnotherStringProperty = "B"; - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("StringProperty", "AnotherStringProperty"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.IntegerList = new List() { 1, 2, 3 }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("IntegerList/0", "IntegerList/1"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.IntegerList = new List() { 1, 2, 3 }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("IntegerList/0", "IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -70,7 +70,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.IntegerList = new List() { 1, 2, 3 }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("IntegerList/0", "IntegerValue"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -89,7 +89,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.IntegerList = new List() { 1, 2, 3 }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("IntegerValue", "IntegerList/0"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -107,7 +107,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.IntegerList = new List() { 1, 2, 3 }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("IntegerValue", "IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -129,7 +129,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("SimpleDTO/StringProperty", "SimpleDTO/AnotherStringProperty"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -150,7 +150,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/1"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -170,7 +170,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -191,7 +191,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerValue"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -212,7 +212,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/0"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); @@ -232,7 +232,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs index 3a51556013..0ea602da03 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs @@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("StringProperty", "AnotherStringProperty"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -38,7 +38,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("IntegerList/0", "IntegerList/1"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -58,7 +58,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("IntegerList/0", "IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("IntegerList/0", "IntegerValue"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -98,7 +98,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("IntegerValue", "IntegerList/0"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -118,7 +118,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("IntegerValue", "IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -142,7 +142,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("SimpleDTO/StringProperty", "SimpleDTO/AnotherStringProperty"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -165,7 +165,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/1"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -187,7 +187,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -210,7 +210,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerValue"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -233,7 +233,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/0"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); @@ -255,7 +255,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CustomNamingStrategyTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CustomNamingStrategyTests.cs new file mode 100644 index 0000000000..b829b81902 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CustomNamingStrategyTests.cs @@ -0,0 +1,154 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Dynamic; +using Newtonsoft.Json.Serialization; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic +{ + public class CustomNamingStrategyTests + { + [Fact] + public void AddProperty_ToExpandoObject_WithCustomNamingStrategy() + { + // Arrange + var contractResolver = new DefaultContractResolver + { + NamingStrategy = new TestNamingStrategy() + }; + + dynamic obj = new ExpandoObject(); + obj.Test = 1; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Add("NewInt", 1); + patchDoc.ContractResolver = contractResolver; + + // Act + patchDoc.ApplyTo(obj); + + // Assert + Assert.Equal(1, obj.customNewInt); + Assert.Equal(1, obj.Test); + } + + [Fact] + public void CopyPropertyValue_ForExpandoObject_WithCustomNamingStrategy() + { + // Arrange + var contractResolver = new DefaultContractResolver + { + NamingStrategy = new TestNamingStrategy() + }; + + dynamic obj = new ExpandoObject(); + obj.customStringProperty = "A"; + obj.customAnotherStringProperty = "B"; + + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy("StringProperty", "AnotherStringProperty"); + patchDoc.ContractResolver = contractResolver; + + // Act + patchDoc.ApplyTo(obj); + + // Assert + Assert.Equal("A", obj.customAnotherStringProperty); + } + + [Fact] + public void MovePropertyValue_ForExpandoObject_WithCustomNamingStrategy() + { + // Arrange + var contractResolver = new DefaultContractResolver + { + NamingStrategy = new TestNamingStrategy() + }; + + dynamic obj = new ExpandoObject(); + obj.customStringProperty = "A"; + obj.customAnotherStringProperty = "B"; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Move("StringProperty", "AnotherStringProperty"); + patchDoc.ContractResolver = contractResolver; + + // Act + patchDoc.ApplyTo(obj); + var cont = obj as IDictionary; + cont.TryGetValue("customStringProperty", out var valueFromDictionary); + + // Assert + Assert.Equal("A", obj.customAnotherStringProperty); + Assert.Null(valueFromDictionary); + } + + [Fact] + public void RemoveProperty_FromExpandoObject_WithCustomNamingStrategy() + { + // Arrange + var contractResolver = new DefaultContractResolver + { + NamingStrategy = new TestNamingStrategy() + }; + + dynamic obj = new ExpandoObject(); + obj.customTest = 1; + + // create patch + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove("Test"); + patchDoc.ContractResolver = contractResolver; + + // Act + patchDoc.ApplyTo(obj); + var cont = obj as IDictionary; + cont.TryGetValue("customTest", out var valueFromDictionary); + + // Assert + Assert.Null(valueFromDictionary); + } + + [Fact] + public void ReplacePropertyValue_ForExpandoObject_WithCustomNamingStrategy() + { + // Arrange + var contractResolver = new DefaultContractResolver + { + NamingStrategy = new TestNamingStrategy() + }; + + dynamic obj = new ExpandoObject(); + obj.customTest = 1; + + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace("Test", 2); + patchDoc.ContractResolver = contractResolver; + + // Act + patchDoc.ApplyTo(obj); + + // Assert + Assert.Equal(2, obj.customTest); + } + + private class TestNamingStrategy : NamingStrategy + { + public new bool ProcessDictionaryKeys => true; + + public override string GetDictionaryKey(string key) + { + return "custom" + key; + } + + protected override string ResolvePropertyName(string name) + { + return name; + } + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveOperationTests.cs index 5e2f7ae814..0e3ea2cea0 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveOperationTests.cs @@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.AnotherStringProperty = "B"; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("StringProperty", "AnotherStringProperty"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -29,8 +29,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic Assert.Equal("A", doc.AnotherStringProperty); var cont = doc as IDictionary; - object valueFromDictionary; - cont.TryGetValue("StringProperty", out valueFromDictionary); + cont.TryGetValue("StringProperty", out var valueFromDictionary); Assert.Null(valueFromDictionary); } @@ -41,7 +40,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.StringProperty = "A"; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("StringProperty", "AnotherStringProperty"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -52,8 +51,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic Assert.Equal("A", doc.AnotherStringProperty); var cont = doc as IDictionary; - object valueFromDictionary; - cont.TryGetValue("StringProperty", out valueFromDictionary); + cont.TryGetValue("StringProperty", out var valueFromDictionary); Assert.Null(valueFromDictionary); } @@ -65,7 +63,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.SimpleDTO = new SimpleDTO() { AnotherStringProperty = "B" }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("StringProperty", "SimpleDTO/AnotherStringProperty"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -76,8 +74,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty); var cont = doc as IDictionary; - object valueFromDictionary; - cont.TryGetValue("StringProperty", out valueFromDictionary); + cont.TryGetValue("StringProperty", out var valueFromDictionary); Assert.Null(valueFromDictionary); } @@ -89,7 +86,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.SimpleDTO = new SimpleDTO() { AnotherStringProperty = "B" }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("SimpleDTO/AnotherStringProperty", "StringProperty"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -112,7 +109,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("Nested/StringProperty", "Nested/AnotherStringProperty"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -131,7 +128,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.IntegerList = new List() { 1, 2, 3 }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("IntegerList/0", "IntegerList/1"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -152,7 +149,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("Nested/IntegerList/0", "Nested/IntegerList/1"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -170,7 +167,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.IntegerList = new List() { 1, 2, 3 }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("IntegerList/0", "IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -190,7 +187,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("Nested/IntegerList/0", "Nested/IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -207,7 +204,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.IntegerList = new List() { 1, 2, 3 }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("IntegerList/0", "IntegerValue"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -229,7 +226,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("Nested/IntegerList/0", "Nested/IntegerValue"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -249,7 +246,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.IntegerList = new List() { 1, 2, 3 }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("IntegerValue", "IntegerList/0"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -258,8 +255,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); var cont = doc as IDictionary; - object valueFromDictionary; - cont.TryGetValue("IntegerValue", out valueFromDictionary); + cont.TryGetValue("IntegerValue", out var valueFromDictionary); Assert.Null(valueFromDictionary); Assert.Equal(new List() { 5, 1, 2, 3 }, doc.IntegerList); @@ -276,7 +272,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("Nested/IntegerValue", "Nested/IntegerList/0"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -296,7 +292,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.IntegerList = new List() { 1, 2, 3 }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("IntegerValue", "IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -305,8 +301,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); var cont = doc as IDictionary; - object valueFromDictionary; - cont.TryGetValue("IntegerValue", out valueFromDictionary); + cont.TryGetValue("IntegerValue", out var valueFromDictionary); Assert.Null(valueFromDictionary); Assert.Equal(new List() { 1, 2, 3, 5 }, doc.IntegerList); @@ -323,7 +318,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("Nested/IntegerValue", "Nested/IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs index f57ad3d11c..bfd79a0ea2 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs @@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("StringProperty", "AnotherStringProperty"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("IntegerList/0", "IntegerList/1"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -60,7 +60,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("IntegerList/0", "IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -79,7 +79,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("IntegerList/0", "IntegerValue"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -101,7 +101,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("IntegerValue", "IntegerList/0"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -123,7 +123,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move("IntegerValue", "IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/PatchDocumentTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/PatchDocumentTests.cs index e7e6f665a5..e86dc8acbd 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/PatchDocumentTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/PatchDocumentTests.cs @@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void InvalidPathAtBeginningShouldThrowException() { - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); var exception = Assert.Throws(() => { patchDoc.Add("//NewInt", 1); @@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void InvalidPathAtEndShouldThrowException() { - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); var exception = Assert.Throws(() => { patchDoc.Add("NewInt//", 1); @@ -38,7 +38,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void InvalidPathWithDotShouldThrowException() { - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); var exception = Assert.Throws(() => { patchDoc.Add("NewInt.Test", 1); @@ -57,7 +57,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic AnotherStringProperty = "B" }; - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy("StringProperty", "AnotherStringProperty"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -77,10 +77,10 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic AnotherStringProperty = "B" }; - JsonPatchDocument patchDocTyped = new JsonPatchDocument(); + var patchDocTyped = new JsonPatchDocument(); patchDocTyped.Copy(o => o.StringProperty, o => o.AnotherStringProperty); - JsonPatchDocument patchDocUntyped = new JsonPatchDocument(); + var patchDocUntyped = new JsonPatchDocument(); patchDocUntyped.Copy("StringProperty", "AnotherStringProperty"); var serializedTyped = JsonConvert.SerializeObject(patchDocTyped); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs index f0164765ee..c8985e3a86 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs @@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("Test"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.Test = 1; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("NonExisting"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic obj.Test = 1; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("Test"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -73,32 +73,31 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(obj); var cont = obj as IDictionary; - object valueFromDictionary; - - cont.TryGetValue("Test", out valueFromDictionary); + cont.TryGetValue("Test", out var valueFromDictionary); Assert.Null(valueFromDictionary); } [Fact] - public void RemovePropertyFromExpandoObjectMixedCase() + public void RemoveProperty_FromExpandoObject_MixedCase_ThrowsPathNotFoundException() { dynamic obj = new ExpandoObject(); obj.Test = 1; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("test"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(obj); - - var cont = obj as IDictionary; - object valueFromDictionary; - - cont.TryGetValue("Test", out valueFromDictionary); - Assert.Null(valueFromDictionary); + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(obj); + }); + Assert.Equal( + string.Format("The target location specified by path segment '{0}' was not found.", + "test"), + exception.Message); } [Fact] @@ -109,7 +108,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic obj.Test.AnotherTest = "A"; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("Test"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -118,32 +117,31 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(obj); var cont = obj as IDictionary; - object valueFromDictionary; - - cont.TryGetValue("Test", out valueFromDictionary); + cont.TryGetValue("Test", out var valueFromDictionary); Assert.Null(valueFromDictionary); } [Fact] - public void RemoveNestedPropertyFromExpandoObjectMixedCase() + public void RemoveNestedProperty_FromExpandoObject_MixedCase_ThrowsPathNotFoundException() { dynamic obj = new ExpandoObject(); obj.Test = new ExpandoObject(); obj.Test.AnotherTest = "A"; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("test"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(obj); - var cont = obj as IDictionary; - - object valueFromDictionary; - cont.TryGetValue("Test", out valueFromDictionary); - Assert.Null(valueFromDictionary); + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(obj); + }); + Assert.Equal( + string.Format("The target location specified by path segment '{0}' was not found.", "test"), + exception.Message); } [Fact] @@ -156,7 +154,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("SimpleDTO/StringProperty"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -167,7 +165,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic } [Fact] - public void NestedRemoveMixedCase() + public void NestedRemove_MixedCase_ThrowsPathNotFoundException() { dynamic doc = new ExpandoObject(); doc.SimpleDTO = new SimpleDTO() @@ -176,15 +174,21 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("Simpledto/stringProperty"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(doc); - - Assert.Null(doc.SimpleDTO.StringProperty); + var exception = Assert.Throws(() => + { + deserialized.ApplyTo(doc); + }); + Assert.Equal( + string.Format("For operation '{0}', the target location specified by path '{1}' was not found.", + "remove", + "/Simpledto/stringProperty"), + exception.Message); } [Fact] @@ -197,7 +201,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("SimpleDTO/IntegerList/2"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -218,7 +222,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("SimpleDTO/Integerlist/2"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -239,7 +243,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("SimpleDTO/IntegerList/3"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -264,7 +268,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("SimpleDTO/IntegerList/-1"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -289,7 +293,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("SimpleDTO/IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs index 50ae6e8d5d..f65b2e6342 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs @@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("StringProperty"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -39,7 +39,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("IntegerList/2"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("IntegerList/3"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("IntegerList/-1"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -107,7 +107,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -130,7 +130,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("SimpleDTO/StringProperty"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -153,7 +153,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("SimpleDTO/IntegerList/2"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -176,7 +176,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("SimpleDTO/IntegerList/3"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -203,7 +203,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("SimpleDTO/IntegerList/-1"); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -230,7 +230,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove("SimpleDTO/IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs index a03b830e02..391b5ebe2c 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs @@ -98,10 +98,6 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { get { - var model = new Class1(); - yield return new object[] { model, "/Items/Name", model.Items }; - yield return new object[] { model.Items, "/Name", model.Items }; - var nestedModel = new Class1Nested(); nestedModel.Customers.Add(new Class1()); yield return new object[] { nestedModel, "/Customers/0/Items/Name", nestedModel.Customers[0].Items }; From 3d6a8615de85a8d25f78db2abe2cc511be46592c Mon Sep 17 00:00:00 2001 From: Jass Bagga Date: Thu, 24 Aug 2017 15:11:01 -0700 Subject: [PATCH 0580/1029] Support DynamicObject types (#99) Addresses #38 --- .../Internal/DynamicObjectAdapter.cs | 211 ++++ .../Internal/ObjectVisitor.cs | 14 +- .../Properties/Resources.Designer.cs | 124 +- .../DictionaryAdapterTest.cs | 27 +- .../Dynamic/AddOperationTests.cs | 14 +- .../Dynamic/AddTypedOperationTests.cs | 30 +- .../Dynamic/CopyOperationTests.cs | 38 +- .../Dynamic/CopyTypedOperationTests.cs | 62 +- .../Dynamic/InheritedObject.cs | 10 + .../Dynamic/MoveOperationTests.cs | 24 +- .../Dynamic/MoveTypedOperationTests.cs | 14 +- .../Dynamic/{NestedDTO.cs => NestedObject.cs} | 4 +- .../Dynamic/PatchDocumentTests.cs | 12 +- .../Dynamic/RemoveOperationTests.cs | 43 +- .../Dynamic/RemoveTypedOperationTests.cs | 48 +- .../Dynamic/ReplaceOperationTests.cs | 38 +- .../Dynamic/ReplaceTypedOperationTests.cs | 54 +- .../Dynamic/SimpleDTOWithNestedDTO.cs | 22 - .../Dynamic/{SimpleDTO.cs => SimpleObject.cs} | 6 +- .../Dynamic/SimpleObjectWithNestedObject.cs | 22 + .../DynamicObjectAdapterTest.cs | 231 ++++ .../DynamicTestObject.cs | 87 ++ .../{InheritedDTO.cs => InheritedObject.cs} | 2 +- .../DynamicObjectIntegrationTests.cs | 263 +++++ ...nPatchDocumentJsonPropertyAttributeTest.cs | 38 +- ...TO.cs => JsonPropertyComplexNameObject.cs} | 4 +- ...onPropertyDTO.cs => JsonPropertyObject.cs} | 2 +- ...s => JsonPropertyWithAnotherNameObject.cs} | 2 +- .../JsonPropertyWithInheritanceDTO.cs | 19 - .../JsonPropertyWithInheritanceObject.cs | 15 + .../ListAdapterTest.cs | 86 +- .../{NestedDTO.cs => NestedObject.cs} | 2 +- .../NestedObjectTests.cs | 1030 ++++++++--------- .../ObjectAdapterTests.cs | 422 +++---- .../ObjectVisitorTest.cs | 44 +- .../SimpleDTOWithNestedDTO.cs | 30 - .../SimpleDTOWithNestedDTOWithNullCheck.cs | 15 - .../{SimpleDTO.cs => SimpleObject.cs} | 2 +- .../SimpleObjectWithNestedObject.cs | 30 + ...mpleObjectWithNestedObjectWithNullCheck.cs | 15 + ...lCheck.cs => SimpleObjectWithNullCheck.cs} | 2 +- 41 files changed, 1950 insertions(+), 1208 deletions(-) create mode 100644 src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/InheritedObject.cs rename test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/{NestedDTO.cs => NestedObject.cs} (78%) delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleDTOWithNestedDTO.cs rename test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/{SimpleDTO.cs => SimpleObject.cs} (81%) create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleObjectWithNestedObject.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/DynamicObjectAdapterTest.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/DynamicTestObject.cs rename test/Microsoft.AspNetCore.JsonPatch.Test/{InheritedDTO.cs => InheritedObject.cs} (85%) create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DynamicObjectIntegrationTests.cs rename test/Microsoft.AspNetCore.JsonPatch.Test/{JsonPropertyComplexNameDTO.cs => JsonPropertyComplexNameObject.cs} (78%) rename test/Microsoft.AspNetCore.JsonPatch.Test/{JsonPropertyDTO.cs => JsonPropertyObject.cs} (90%) rename test/Microsoft.AspNetCore.JsonPatch.Test/{JsonPropertyWithAnotherNameDTO.cs => JsonPropertyWithAnotherNameObject.cs} (84%) delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithInheritanceDTO.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithInheritanceObject.cs rename test/Microsoft.AspNetCore.JsonPatch.Test/{NestedDTO.cs => NestedObject.cs} (89%) delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTO.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTOWithNullCheck.cs rename test/Microsoft.AspNetCore.JsonPatch.Test/{SimpleDTO.cs => SimpleObject.cs} (95%) create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNestedObject.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNestedObjectWithNullCheck.cs rename test/Microsoft.AspNetCore.JsonPatch.Test/{SimpleDTOWithNullCheck.cs => SimpleObjectWithNullCheck.cs} (93%) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs new file mode 100644 index 0000000000..433326ce53 --- /dev/null +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs @@ -0,0 +1,211 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.CompilerServices; +using Microsoft.CSharp.RuntimeBinder; +using Newtonsoft.Json.Serialization; +using CSharpBinder = Microsoft.CSharp.RuntimeBinder; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + public class DynamicObjectAdapter : IAdapter + { + public bool TryAdd( + object target, + string segment, + IContractResolver contractResolver, + object value, + out string errorMessage) + { + if (!TrySetDynamicObjectProperty(target, contractResolver, segment, value, out errorMessage)) + { + return false; + } + + errorMessage = null; + return true; + } + + public bool TryGet( + object target, + string segment, + IContractResolver contractResolver, + out object value, + out string errorMessage) + { + if (!TryGetDynamicObjectProperty(target, contractResolver, segment, out value, out errorMessage)) + { + value = null; + return false; + } + + errorMessage = null; + return true; + } + + public bool TryRemove( + object target, + string segment, + IContractResolver contractResolver, + out string errorMessage) + { + if (!TryGetDynamicObjectProperty(target, contractResolver, segment, out var property, out errorMessage)) + { + return false; + } + + // Setting the value to "null" will use the default value in case of value types, and + // null in case of reference types + object value = null; + if (property.GetType().GetTypeInfo().IsValueType + && Nullable.GetUnderlyingType(property.GetType()) == null) + { + value = Activator.CreateInstance(property.GetType()); + } + + if (!TrySetDynamicObjectProperty(target, contractResolver, segment, value, out errorMessage)) + { + return false; + } + + errorMessage = null; + return true; + + } + + public bool TryReplace( + object target, + string segment, + IContractResolver contractResolver, + object value, + out string errorMessage) + { + if (!TryGetDynamicObjectProperty(target, contractResolver, segment, out var property, out errorMessage)) + { + return false; + } + + if (!TryConvertValue(value, property.GetType(), out var convertedValue)) + { + errorMessage = Resources.FormatInvalidValueForProperty(value); + return false; + } + + if (!TrySetDynamicObjectProperty(target, contractResolver, segment, convertedValue, out errorMessage)) + { + return false; + } + + errorMessage = null; + return true; + } + + public bool TryTraverse( + object target, + string segment, + IContractResolver contractResolver, + out object nextTarget, + out string errorMessage) + { + if (!TryGetDynamicObjectProperty(target, contractResolver, segment, out var property, out errorMessage)) + { + nextTarget = null; + return false; + } + else + { + nextTarget = property; + errorMessage = null; + return true; + } + } + + private bool TryGetDynamicObjectProperty( + object target, + IContractResolver contractResolver, + string segment, + out object value, + out string errorMessage) + { + var jsonDynamicContract = (JsonDynamicContract)contractResolver.ResolveContract(target.GetType()); + + var propertyName = jsonDynamicContract.PropertyNameResolver(segment); + + var binder = CSharpBinder.Binder.GetMember( + CSharpBinderFlags.None, + propertyName, + target.GetType(), + new List + { + CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) + }); + + var callsite = CallSite>.Create(binder); + + try + { + value = callsite.Target(callsite, target); + errorMessage = null; + return true; + } + catch (RuntimeBinderException) + { + value = null; + errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); + return false; + } + } + + private bool TrySetDynamicObjectProperty( + object target, + IContractResolver contractResolver, + string segment, + object value, + out string errorMessage) + { + var jsonDynamicContract = (JsonDynamicContract)contractResolver.ResolveContract(target.GetType()); + + var propertyName = jsonDynamicContract.PropertyNameResolver(segment); + + var binder = CSharpBinder.Binder.SetMember( + CSharpBinderFlags.None, + propertyName, + target.GetType(), + new List + { + CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), + CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) + }); + + var callsite = CallSite>.Create(binder); + + try + { + callsite.Target(callsite, target, value); + errorMessage = null; + return true; + } + catch (RuntimeBinderException) + { + errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); + return false; + } + } + + private bool TryConvertValue(object value, Type propertyType, out object convertedValue) + { + var conversionResult = ConversionResultProvider.ConvertTo(value, propertyType); + if (!conversionResult.CanBeConverted) + { + convertedValue = null; + return false; + } + + convertedValue = conversionResult.ConvertedInstance; + return true; + } + } +} diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs index b604f65a17..bbf6db4ff6 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs @@ -15,13 +15,8 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal public ObjectVisitor(ParsedPath path, IContractResolver contractResolver) { - if (contractResolver == null) - { - throw new ArgumentNullException(nameof(contractResolver)); - } - _path = path; - _contractResolver = contractResolver; + _contractResolver = contractResolver ?? throw new ArgumentNullException(nameof(contractResolver)); } public bool TryVisit(ref object target, out IAdapter adapter, out string errorMessage) @@ -38,8 +33,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Traverse until the penultimate segment to get the target object and adapter for (var i = 0; i < _path.Segments.Count - 1; i++) { - object next; - if (!adapter.TryTraverse(target, _path.Segments[i], _contractResolver, out next, out errorMessage)) + if (!adapter.TryTraverse(target, _path.Segments[i], _contractResolver, out var next, out errorMessage)) { adapter = null; return false; @@ -59,6 +53,10 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { return new ExpandoObjectAdapter(); } + else if (targetObject is IDynamicMetaObjectProvider) + { + return new DynamicObjectAdapter(); + } else if (targetObject is IDictionary) { return new DictionaryAdapter(); diff --git a/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs index 97c98c2b05..cd99292061 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs @@ -10,277 +10,243 @@ namespace Microsoft.AspNetCore.JsonPatch private static readonly ResourceManager _resourceManager = new ResourceManager("Microsoft.AspNetCore.JsonPatch.Resources", typeof(Resources).GetTypeInfo().Assembly); - /// - /// The type of the property at path '{0}' could not be determined. - /// - internal static string CannotDeterminePropertyType - { - get { return GetString("CannotDeterminePropertyType"); } - } - - /// - /// The type of the property at path '{0}' could not be determined. - /// - internal static string FormatCannotDeterminePropertyType(object p0) - { - return string.Format(CultureInfo.CurrentCulture, GetString("CannotDeterminePropertyType"), p0); - } - /// /// The property at '{0}' could not be copied. /// - internal static string CannotCannotCopyProperty + internal static string CannotCopyProperty { - get { return GetString("CannotCannotCopyProperty"); } + get => GetString("CannotCopyProperty"); } /// /// The property at '{0}' could not be copied. /// internal static string FormatCannotCopyProperty(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("CannotCopyProperty"), p0); + + /// + /// The type of the property at path '{0}' could not be determined. + /// + internal static string CannotDeterminePropertyType { - return string.Format(CultureInfo.CurrentCulture, GetString("CannotCannotCopyProperty"), p0); + get => GetString("CannotDeterminePropertyType"); } + /// + /// The type of the property at path '{0}' could not be determined. + /// + internal static string FormatCannotDeterminePropertyType(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("CannotDeterminePropertyType"), p0); + /// /// The '{0}' operation at path '{1}' could not be performed. /// internal static string CannotPerformOperation { - get { return GetString("CannotPerformOperation"); } + get => GetString("CannotPerformOperation"); } /// /// The '{0}' operation at path '{1}' could not be performed. /// internal static string FormatCannotPerformOperation(object p0, object p1) - { - return string.Format(CultureInfo.CurrentCulture, GetString("CannotPerformOperation"), p0, p1); - } + => string.Format(CultureInfo.CurrentCulture, GetString("CannotPerformOperation"), p0, p1); /// /// The property at '{0}' could not be read. /// internal static string CannotReadProperty { - get { return GetString("CannotReadProperty"); } + get => GetString("CannotReadProperty"); } /// /// The property at '{0}' could not be read. /// internal static string FormatCannotReadProperty(object p0) - { - return string.Format(CultureInfo.CurrentCulture, GetString("CannotReadProperty"), p0); - } + => string.Format(CultureInfo.CurrentCulture, GetString("CannotReadProperty"), p0); /// /// The property at path '{0}' could not be updated. /// internal static string CannotUpdateProperty { - get { return GetString("CannotUpdateProperty"); } + get => GetString("CannotUpdateProperty"); } /// /// The property at path '{0}' could not be updated. /// internal static string FormatCannotUpdateProperty(object p0) - { - return string.Format(CultureInfo.CurrentCulture, GetString("CannotUpdateProperty"), p0); - } + => string.Format(CultureInfo.CurrentCulture, GetString("CannotUpdateProperty"), p0); /// /// The index value provided by path segment '{0}' is out of bounds of the array size. /// internal static string IndexOutOfBounds { - get { return GetString("IndexOutOfBounds"); } + get => GetString("IndexOutOfBounds"); } /// /// The index value provided by path segment '{0}' is out of bounds of the array size. /// internal static string FormatIndexOutOfBounds(object p0) - { - return string.Format(CultureInfo.CurrentCulture, GetString("IndexOutOfBounds"), p0); - } + => string.Format(CultureInfo.CurrentCulture, GetString("IndexOutOfBounds"), p0); /// /// The path segment '{0}' is invalid for an array index. /// internal static string InvalidIndexValue { - get { return GetString("InvalidIndexValue"); } + get => GetString("InvalidIndexValue"); } /// /// The path segment '{0}' is invalid for an array index. /// internal static string FormatInvalidIndexValue(object p0) - { - return string.Format(CultureInfo.CurrentCulture, GetString("InvalidIndexValue"), p0); - } + => string.Format(CultureInfo.CurrentCulture, GetString("InvalidIndexValue"), p0); /// /// The type '{0}' was malformed and could not be parsed. /// internal static string InvalidJsonPatchDocument { - get { return GetString("InvalidJsonPatchDocument"); } + get => GetString("InvalidJsonPatchDocument"); } /// /// The type '{0}' was malformed and could not be parsed. /// internal static string FormatInvalidJsonPatchDocument(object p0) - { - return string.Format(CultureInfo.CurrentCulture, GetString("InvalidJsonPatchDocument"), p0); - } + => string.Format(CultureInfo.CurrentCulture, GetString("InvalidJsonPatchDocument"), p0); /// /// Invalid JsonPatch operation '{0}'. /// internal static string InvalidJsonPatchOperation { - get { return GetString("InvalidJsonPatchOperation"); } + get => GetString("InvalidJsonPatchOperation"); } /// /// Invalid JsonPatch operation '{0}'. /// internal static string FormatInvalidJsonPatchOperation(object p0) - { - return string.Format(CultureInfo.CurrentCulture, GetString("InvalidJsonPatchOperation"), p0); - } + => string.Format(CultureInfo.CurrentCulture, GetString("InvalidJsonPatchOperation"), p0); /// /// The provided string '{0}' is an invalid path. /// internal static string InvalidValueForPath { - get { return GetString("InvalidValueForPath"); } + get => GetString("InvalidValueForPath"); } /// /// The provided string '{0}' is an invalid path. /// internal static string FormatInvalidValueForPath(object p0) - { - return string.Format(CultureInfo.CurrentCulture, GetString("InvalidValueForPath"), p0); - } + => string.Format(CultureInfo.CurrentCulture, GetString("InvalidValueForPath"), p0); /// /// The value '{0}' is invalid for target location. /// internal static string InvalidValueForProperty { - get { return GetString("InvalidValueForProperty"); } + get => GetString("InvalidValueForProperty"); } /// /// The value '{0}' is invalid for target location. /// internal static string FormatInvalidValueForProperty(object p0) - { - return string.Format(CultureInfo.CurrentCulture, GetString("InvalidValueForProperty"), p0); - } + => string.Format(CultureInfo.CurrentCulture, GetString("InvalidValueForProperty"), p0); /// /// '{0}' must be of type '{1}'. /// internal static string ParameterMustMatchType { - get { return GetString("ParameterMustMatchType"); } + get => GetString("ParameterMustMatchType"); } /// /// '{0}' must be of type '{1}'. /// internal static string FormatParameterMustMatchType(object p0, object p1) - { - return string.Format(CultureInfo.CurrentCulture, GetString("ParameterMustMatchType"), p0, p1); - } + => string.Format(CultureInfo.CurrentCulture, GetString("ParameterMustMatchType"), p0, p1); /// /// The type '{0}' which is an array is not supported for json patch operations as it has a fixed size. /// internal static string PatchNotSupportedForArrays { - get { return GetString("PatchNotSupportedForArrays"); } + get => GetString("PatchNotSupportedForArrays"); } /// /// The type '{0}' which is an array is not supported for json patch operations as it has a fixed size. /// internal static string FormatPatchNotSupportedForArrays(object p0) - { - return string.Format(CultureInfo.CurrentCulture, GetString("PatchNotSupportedForArrays"), p0); - } + => string.Format(CultureInfo.CurrentCulture, GetString("PatchNotSupportedForArrays"), p0); /// /// The type '{0}' which is a non generic list is not supported for json patch operations. Only generic list types are supported. /// internal static string PatchNotSupportedForNonGenericLists { - get { return GetString("PatchNotSupportedForNonGenericLists"); } + get => GetString("PatchNotSupportedForNonGenericLists"); } /// /// The type '{0}' which is a non generic list is not supported for json patch operations. Only generic list types are supported. /// internal static string FormatPatchNotSupportedForNonGenericLists(object p0) - { - return string.Format(CultureInfo.CurrentCulture, GetString("PatchNotSupportedForNonGenericLists"), p0); - } + => string.Format(CultureInfo.CurrentCulture, GetString("PatchNotSupportedForNonGenericLists"), p0); /// /// The target location specified by path segment '{0}' was not found. /// internal static string TargetLocationAtPathSegmentNotFound { - get { return GetString("TargetLocationAtPathSegmentNotFound"); } + get => GetString("TargetLocationAtPathSegmentNotFound"); } /// /// The target location specified by path segment '{0}' was not found. /// internal static string FormatTargetLocationAtPathSegmentNotFound(object p0) - { - return string.Format(CultureInfo.CurrentCulture, GetString("TargetLocationAtPathSegmentNotFound"), p0); - } + => string.Format(CultureInfo.CurrentCulture, GetString("TargetLocationAtPathSegmentNotFound"), p0); /// /// For operation '{0}', the target location specified by path '{1}' was not found. /// internal static string TargetLocationNotFound { - get { return GetString("TargetLocationNotFound"); } + get => GetString("TargetLocationNotFound"); } /// /// For operation '{0}', the target location specified by path '{1}' was not found. /// internal static string FormatTargetLocationNotFound(object p0, object p1) - { - return string.Format(CultureInfo.CurrentCulture, GetString("TargetLocationNotFound"), p0, p1); - } + => string.Format(CultureInfo.CurrentCulture, GetString("TargetLocationNotFound"), p0, p1); /// /// The test operation is not supported. /// internal static string TestOperationNotSupported { - get { return GetString("TestOperationNotSupported"); } + get => GetString("TestOperationNotSupported"); } /// /// The test operation is not supported. /// internal static string FormatTestOperationNotSupported() - { - return GetString("TestOperationNotSupported"); - } + => GetString("TestOperationNotSupported"); private static string GetString(string name, params string[] formatterNames) { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs index bc50b872a2..084aa57379 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs @@ -20,10 +20,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal dictionary[nameKey] = "Mike"; var dictionaryAdapter = new DictionaryAdapter(); var resolver = new Mock(MockBehavior.Strict); - string message = null; // Act - var addStatus = dictionaryAdapter.TryAdd(dictionary, nameKey, resolver.Object, "James", out message); + var addStatus = dictionaryAdapter.TryAdd(dictionary, nameKey, resolver.Object, "James", out var message); // Assert Assert.True(addStatus); @@ -38,12 +37,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Arrange var dictionaryAdapter = new DictionaryAdapter(); var resolver = new Mock(MockBehavior.Strict); - string message = null; var nameKey = "Name"; var dictionary = new Dictionary(StringComparer.Ordinal); // Act - var addStatus = dictionaryAdapter.TryAdd(dictionary, nameKey, resolver.Object, "James", out message); + var addStatus = dictionaryAdapter.TryAdd(dictionary, nameKey, resolver.Object, "James", out var message); // Assert Assert.True(addStatus); @@ -52,8 +50,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.Equal("James", dictionary[nameKey]); // Act - object outValue = null; - addStatus = dictionaryAdapter.TryGet(dictionary, nameKey.ToUpper(), resolver.Object, out outValue, out message); + addStatus = dictionaryAdapter.TryGet(dictionary, nameKey.ToUpper(), resolver.Object, out var outValue, out message); // Assert Assert.True(addStatus); @@ -67,12 +64,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Arrange var dictionaryAdapter = new DictionaryAdapter(); var resolver = new Mock(MockBehavior.Strict); - string message = null; var nameKey = "Name"; var dictionary = new Dictionary(StringComparer.Ordinal); // Act - var addStatus = dictionaryAdapter.TryAdd(dictionary, nameKey, resolver.Object, "James", out message); + var addStatus = dictionaryAdapter.TryAdd(dictionary, nameKey, resolver.Object, "James", out var message); // Assert Assert.True(addStatus); @@ -81,8 +77,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.Equal("James", dictionary[nameKey]); // Act - object outValue = null; - addStatus = dictionaryAdapter.TryGet(dictionary, nameKey, resolver.Object, out outValue, out message); + addStatus = dictionaryAdapter.TryGet(dictionary, nameKey, resolver.Object, out var outValue, out message); // Assert Assert.True(addStatus); @@ -99,10 +94,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal dictionary.Add(nameKey, "Mike"); var dictionaryAdapter = new DictionaryAdapter(); var resolver = new Mock(MockBehavior.Strict); - string message = null; // Act - var replaceStatus = dictionaryAdapter.TryReplace(dictionary, nameKey, resolver.Object, "James", out message); + var replaceStatus = dictionaryAdapter.TryReplace(dictionary, nameKey, resolver.Object, "James", out var message); // Assert Assert.True(replaceStatus); @@ -119,10 +113,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var dictionary = new Dictionary(StringComparer.Ordinal); var dictionaryAdapter = new DictionaryAdapter(); var resolver = new Mock(MockBehavior.Strict); - string message = null; // Act - var replaceStatus = dictionaryAdapter.TryReplace(dictionary, nameKey, resolver.Object, "Mike", out message); + var replaceStatus = dictionaryAdapter.TryReplace(dictionary, nameKey, resolver.Object, "Mike", out var message); // Assert Assert.False(replaceStatus); @@ -140,10 +133,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var dictionary = new Dictionary(StringComparer.Ordinal); var dictionaryAdapter = new DictionaryAdapter(); var resolver = new Mock(MockBehavior.Strict); - string message = null; // Act - var removeStatus = dictionaryAdapter.TryRemove(dictionary, nameKey, resolver.Object, out message); + var removeStatus = dictionaryAdapter.TryRemove(dictionary, nameKey, resolver.Object, out var message); // Assert Assert.False(removeStatus); @@ -162,10 +154,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal dictionary[nameKey] = "James"; var dictionaryAdapter = new DictionaryAdapter(); var resolver = new Mock(MockBehavior.Strict); - string message = null; // Act - var removeStatus = dictionaryAdapter.TryRemove(dictionary, nameKey, resolver.Object, out message); + var removeStatus = dictionaryAdapter.TryRemove(dictionary, nameKey, resolver.Object, out var message); //Assert Assert.True(removeStatus); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs index e1cdb21df2..493444066b 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs @@ -8,7 +8,7 @@ using Microsoft.AspNetCore.JsonPatch.Exceptions; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Internal { public class AddOperationTests { @@ -86,7 +86,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic dynamic doc = new { Test = 1, - nested = new NestedDTO() + nested = new NestedObject() }; // create patch @@ -111,7 +111,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic dynamic doc = new { Test = 1, - nested = new NestedDTO() + nested = new NestedObject() }; // create patch @@ -152,7 +152,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void AddNewPropertyToExpandoOjectInTypedObject() { - var doc = new NestedDTO() + var doc = new NestedObject() { DynamicProperty = new ExpandoObject() }; @@ -175,7 +175,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic dynamic dynamicProperty = new ExpandoObject(); dynamicProperty.StringProperty = "A"; - var doc = new NestedDTO() + var doc = new NestedObject() { DynamicProperty = dynamicProperty }; @@ -284,7 +284,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic public void AddResultsShouldReplaceInNestedInDynamic() { dynamic doc = new ExpandoObject(); - doc.Nested = new NestedDTO(); + doc.Nested = new NestedObject(); doc.Nested.DynamicProperty = new ExpandoObject(); doc.Nested.DynamicProperty.InBetweenFirst = new ExpandoObject(); doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond = new ExpandoObject(); @@ -319,7 +319,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic // the root of the document, nor a member of an existing object, nor a // member of an existing array. - var doc = new NestedDTO() + var doc = new NestedObject() { DynamicProperty = new ExpandoObject() }; diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs index bbf5118962..b2eb4d3a3c 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs @@ -6,14 +6,14 @@ using Microsoft.AspNetCore.JsonPatch.Exceptions; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Internal { public class AddTypedOperationTests { [Fact] public void AddToListNegativePosition() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; @@ -37,11 +37,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void AddToListInList() { - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - ListOfSimpleDTO = new List() + ListOfSimpleObject = new List() { - new SimpleDTO() + new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } @@ -50,23 +50,23 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Add("ListOfSimpleDTO/0/IntegerList/0", 4); + patchDoc.Add("ListOfSimpleObject/0/IntegerList/0", 4); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); deserialized.ApplyTo(doc); - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.ListOfSimpleDTO[0].IntegerList); + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.ListOfSimpleObject[0].IntegerList); } [Fact] public void AddToListInListInvalidPositionTooSmall() { - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - ListOfSimpleDTO = new List() + ListOfSimpleObject = new List() { - new SimpleDTO() + new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } @@ -75,7 +75,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Add("ListOfSimpleDTO/-1/IntegerList/0", 4); + patchDoc.Add("ListOfSimpleObject/-1/IntegerList/0", 4); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); @@ -92,11 +92,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void AddToListInListInvalidPositionTooLarge() { - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - ListOfSimpleDTO = new List() + ListOfSimpleObject = new List() { - new SimpleDTO() + new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } @@ -104,7 +104,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic }; // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Add("ListOfSimpleDTO/20/IntegerList/0", 4); + patchDoc.Add("ListOfSimpleObject/20/IntegerList/0", 4); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyOperationTests.cs index 42dd0072c4..b2faff25a0 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyOperationTests.cs @@ -6,7 +6,7 @@ using System.Dynamic; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Internal { public class CopyOperationTests { @@ -122,7 +122,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic public void NestedCopy() { dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleDTO() + doc.SimpleObject = new SimpleObject() { StringProperty = "A", AnotherStringProperty = "B" @@ -130,82 +130,82 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleDTO/StringProperty", "SimpleDTO/AnotherStringProperty"); + patchDoc.Copy("SimpleObject/StringProperty", "SimpleObject/AnotherStringProperty"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); deserialized.ApplyTo(doc); - Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty); + Assert.Equal("A", doc.SimpleObject.AnotherStringProperty); } [Fact] public void NestedCopyInList() { dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleDTO() + doc.SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/1"); + patchDoc.Copy("SimpleObject/IntegerList/0", "SimpleObject/IntegerList/1"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); deserialized.ApplyTo(doc); - Assert.Equal(new List() { 1, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 1, 2, 3 }, doc.SimpleObject.IntegerList); } [Fact] public void NestedCopyFromListToEndOfList() { dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleDTO() + doc.SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/-"); + patchDoc.Copy("SimpleObject/IntegerList/0", "SimpleObject/IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); deserialized.ApplyTo(doc); - Assert.Equal(new List() { 1, 2, 3, 1 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 2, 3, 1 }, doc.SimpleObject.IntegerList); } [Fact] public void NestedCopyFromListToNonList() { dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleDTO() + doc.SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerValue"); + patchDoc.Copy("SimpleObject/IntegerList/0", "SimpleObject/IntegerValue"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); deserialized.ApplyTo(doc); - Assert.Equal(1, doc.SimpleDTO.IntegerValue); + Assert.Equal(1, doc.SimpleObject.IntegerValue); } [Fact] public void NestedCopyFromNonListToList() { dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleDTO() + doc.SimpleObject = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } @@ -213,19 +213,19 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/0"); + patchDoc.Copy("SimpleObject/IntegerValue", "SimpleObject/IntegerList/0"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); deserialized.ApplyTo(doc); - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleObject.IntegerList); } [Fact] public void NestedCopyToEndOfList() { dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleDTO() + doc.SimpleObject = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } @@ -233,13 +233,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/-"); + patchDoc.Copy("SimpleObject/IntegerValue", "SimpleObject/IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); deserialized.ApplyTo(doc); - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleObject.IntegerList); } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs index 0ea602da03..d0b0847c71 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs @@ -5,14 +5,14 @@ using System.Collections.Generic; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Internal { public class CopyTypedOperationTests { [Fact] public void Copy() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { StringProperty = "A", AnotherStringProperty = "B" @@ -32,7 +32,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void CopyInList() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; @@ -52,7 +52,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void CopyFromListToEndOfList() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; @@ -71,7 +71,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void CopyFromListToNonList() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; @@ -91,7 +91,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void CopyFromNonListToList() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } @@ -111,7 +111,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void CopyToEndOfList() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } @@ -132,9 +132,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void NestedCopy() { - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { StringProperty = "A", AnotherStringProperty = "B" @@ -143,22 +143,22 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleDTO/StringProperty", "SimpleDTO/AnotherStringProperty"); + patchDoc.Copy("SimpleObject/StringProperty", "SimpleObject/AnotherStringProperty"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); deserialized.ApplyTo(doc); - Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty); + Assert.Equal("A", doc.SimpleObject.AnotherStringProperty); } [Fact] public void NestedCopyInList() { - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } @@ -166,21 +166,21 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/1"); + patchDoc.Copy("SimpleObject/IntegerList/0", "SimpleObject/IntegerList/1"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); deserialized.ApplyTo(doc); - Assert.Equal(new List() { 1, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 1, 2, 3 }, doc.SimpleObject.IntegerList); } [Fact] public void NestedCopyFromListToEndOfList() { - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } @@ -188,22 +188,22 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerList/-"); + patchDoc.Copy("SimpleObject/IntegerList/0", "SimpleObject/IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); deserialized.ApplyTo(doc); - Assert.Equal(new List() { 1, 2, 3, 1 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 2, 3, 1 }, doc.SimpleObject.IntegerList); } [Fact] public void NestedCopyFromListToNonList() { - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } @@ -211,21 +211,21 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleDTO/IntegerList/0", "SimpleDTO/IntegerValue"); + patchDoc.Copy("SimpleObject/IntegerList/0", "SimpleObject/IntegerValue"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); deserialized.ApplyTo(doc); - Assert.Equal(1, doc.SimpleDTO.IntegerValue); + Assert.Equal(1, doc.SimpleObject.IntegerValue); } [Fact] public void NestedCopyFromNonListToList() { - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } @@ -234,20 +234,20 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/0"); + patchDoc.Copy("SimpleObject/IntegerValue", "SimpleObject/IntegerList/0"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); deserialized.ApplyTo(doc); - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleObject.IntegerList); } [Fact] public void NestedCopyToEndOfList() { - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } @@ -256,13 +256,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleDTO/IntegerValue", "SimpleDTO/IntegerList/-"); + patchDoc.Copy("SimpleObject/IntegerValue", "SimpleObject/IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); deserialized.ApplyTo(doc); - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleObject.IntegerList); } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/InheritedObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/InheritedObject.cs new file mode 100644 index 0000000000..29424d591e --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/InheritedObject.cs @@ -0,0 +1,10 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + public class InheritedObject : SimpleObject + { + public string AdditionalStringProperty { get; set; } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveOperationTests.cs index 0e3ea2cea0..31f58c4b82 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveOperationTests.cs @@ -6,7 +6,7 @@ using System.Dynamic; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Internal { public class MoveOperationTests { @@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic Assert.Equal("A", doc.AnotherStringProperty); var cont = doc as IDictionary; - cont.TryGetValue("StringProperty", out var valueFromDictionary); + cont.TryGetValue("StringProperty", out object valueFromDictionary); Assert.Null(valueFromDictionary); } @@ -60,7 +60,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic { dynamic doc = new ExpandoObject(); doc.StringProperty = "A"; - doc.SimpleDTO = new SimpleDTO() { AnotherStringProperty = "B" }; + doc.SimpleDTO = new SimpleObject() { AnotherStringProperty = "B" }; // create patch var patchDoc = new JsonPatchDocument(); @@ -74,7 +74,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty); var cont = doc as IDictionary; - cont.TryGetValue("StringProperty", out var valueFromDictionary); + cont.TryGetValue("StringProperty", out object valueFromDictionary); Assert.Null(valueFromDictionary); } @@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic { dynamic doc = new ExpandoObject(); doc.StringProperty = "A"; - doc.SimpleDTO = new SimpleDTO() { AnotherStringProperty = "B" }; + doc.SimpleDTO = new SimpleObject() { AnotherStringProperty = "B" }; // create patch var patchDoc = new JsonPatchDocument(); @@ -102,7 +102,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic public void NestedMove() { dynamic doc = new ExpandoObject(); - doc.Nested = new SimpleDTO() + doc.Nested = new SimpleObject() { StringProperty = "A", AnotherStringProperty = "B" @@ -143,7 +143,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic public void NestedMoveInList() { dynamic doc = new ExpandoObject(); - doc.Nested = new SimpleDTO() + doc.Nested = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; @@ -181,7 +181,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic public void NestedMoveFromListToEndOfList() { dynamic doc = new ExpandoObject(); - doc.Nested = new SimpleDTO() + doc.Nested = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; @@ -220,7 +220,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic public void NestedMoveFomListToNonList() { dynamic doc = new ExpandoObject(); - doc.Nested = new SimpleDTO() + doc.Nested = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; @@ -255,7 +255,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); var cont = doc as IDictionary; - cont.TryGetValue("IntegerValue", out var valueFromDictionary); + cont.TryGetValue("IntegerValue", out object valueFromDictionary); Assert.Null(valueFromDictionary); Assert.Equal(new List() { 5, 1, 2, 3 }, doc.IntegerList); @@ -265,7 +265,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic public void NestedMoveFromNonListToList() { dynamic doc = new ExpandoObject(); - doc.Nested = new SimpleDTO() + doc.Nested = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } @@ -311,7 +311,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic public void NestedMoveToEndOfList() { dynamic doc = new ExpandoObject(); - doc.Nested = new SimpleDTO() + doc.Nested = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs index bfd79a0ea2..4638718a59 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs @@ -5,14 +5,14 @@ using System.Collections.Generic; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Internal { public class MoveTypedOperationTests { [Fact] public void Move() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { StringProperty = "A", AnotherStringProperty = "B" @@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void MoveInList() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; @@ -54,7 +54,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void MoveFromListToEndOfList() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; @@ -73,7 +73,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void MoveFomListToNonList() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; @@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void MoveFromNonListToList() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } @@ -116,7 +116,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void MoveToEndOfList() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/NestedDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/NestedObject.cs similarity index 78% rename from test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/NestedDTO.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/NestedObject.cs index f94ad05d97..050ad3a3b4 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/NestedDTO.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/NestedObject.cs @@ -1,9 +1,9 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Internal { - public class NestedDTO + public class NestedObject { public string StringProperty { get; set; } public dynamic DynamicProperty { get; set; } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/PatchDocumentTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/PatchDocumentTests.cs index e86dc8acbd..403238bf99 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/PatchDocumentTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/PatchDocumentTests.cs @@ -5,7 +5,7 @@ using Microsoft.AspNetCore.JsonPatch.Exceptions; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Internal { public class PatchDocumentTests { @@ -51,7 +51,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void NonGenericPatchDocToGenericMustSerialize() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { StringProperty = "A", AnotherStringProperty = "B" @@ -61,7 +61,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic patchDoc.Copy("StringProperty", "AnotherStringProperty"); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); deserialized.ApplyTo(doc); @@ -71,14 +71,14 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void GenericPatchDocToNonGenericMustSerialize() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { StringProperty = "A", AnotherStringProperty = "B" }; - var patchDocTyped = new JsonPatchDocument(); - patchDocTyped.Copy(o => o.StringProperty, o => o.AnotherStringProperty); + var patchDocTyped = new JsonPatchDocument(); + patchDocTyped.Copy(o => o.StringProperty, o => o.AnotherStringProperty); var patchDocUntyped = new JsonPatchDocument(); patchDocUntyped.Copy("StringProperty", "AnotherStringProperty"); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs index c8985e3a86..22707add87 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs @@ -7,7 +7,7 @@ using Microsoft.AspNetCore.JsonPatch.Exceptions; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Internal { public class RemoveOperationTests { @@ -73,7 +73,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(obj); var cont = obj as IDictionary; - cont.TryGetValue("Test", out var valueFromDictionary); + cont.TryGetValue("Test", out object valueFromDictionary); Assert.Null(valueFromDictionary); } @@ -94,9 +94,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic { deserialized.ApplyTo(obj); }); + Assert.Equal( - string.Format("The target location specified by path segment '{0}' was not found.", - "test"), + string.Format( + "The target location specified by path segment '{0}' was not found.", + "test"), exception.Message); } @@ -117,7 +119,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(obj); var cont = obj as IDictionary; - cont.TryGetValue("Test", out var valueFromDictionary); + cont.TryGetValue("Test", out object valueFromDictionary); Assert.Null(valueFromDictionary); } @@ -139,8 +141,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic { deserialized.ApplyTo(obj); }); + Assert.Equal( - string.Format("The target location specified by path segment '{0}' was not found.", "test"), + string.Format( + "The target location specified by path segment '{0}' was not found.", + "test"), exception.Message); } @@ -148,7 +153,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic public void NestedRemove() { dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleDTO() + doc.SimpleDTO = new SimpleObject() { StringProperty = "A" }; @@ -168,14 +173,14 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic public void NestedRemove_MixedCase_ThrowsPathNotFoundException() { dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleDTO() + doc.SimpleObject = new SimpleObject() { StringProperty = "A" }; // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("Simpledto/stringProperty"); + patchDoc.Remove("Simpleobject/stringProperty"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); @@ -184,10 +189,12 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic { deserialized.ApplyTo(doc); }); + Assert.Equal( - string.Format("For operation '{0}', the target location specified by path '{1}' was not found.", - "remove", - "/Simpledto/stringProperty"), + string.Format( + "For operation '{0}', the target location specified by path '{1}' was not found.", + "remove", + "/Simpleobject/stringProperty"), exception.Message); } @@ -195,7 +202,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic public void NestedRemoveFromList() { dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleDTO() + doc.SimpleDTO = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; @@ -213,10 +220,10 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic } [Fact] - public void NestedRemoveFromListMixedCase() + public void NestedRemoveFromList_MixedCase() { dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleDTO() + doc.SimpleDTO = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; @@ -237,7 +244,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic public void NestedRemoveFromListInvalidPositionTooLarge() { dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleDTO() + doc.SimpleDTO = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; @@ -262,7 +269,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic public void NestedRemoveFromListInvalidPositionTooSmall() { dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleDTO() + doc.SimpleDTO = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; @@ -287,7 +294,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic public void NestedRemoveFromEndOfList() { dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleDTO() + doc.SimpleDTO = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs index f65b2e6342..000b049b1b 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs @@ -6,14 +6,14 @@ using Microsoft.AspNetCore.JsonPatch.Exceptions; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Internal { public class RemoveTypedOperationTests { [Fact] public void Remove() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { StringProperty = "A" }; @@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void RemoveFromList() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; @@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void RemoveFromListInvalidPositionTooLarge() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; @@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void RemoveFromListInvalidPositionTooSmall() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; @@ -101,7 +101,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void RemoveFromEndOfList() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; @@ -121,9 +121,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void NestedRemove() { - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { StringProperty = "A" } @@ -131,22 +131,22 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("SimpleDTO/StringProperty"); + patchDoc.Remove("SimpleObject/StringProperty"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); deserialized.ApplyTo(doc); - Assert.Null(doc.SimpleDTO.StringProperty); + Assert.Null(doc.SimpleObject.StringProperty); } [Fact] public void NestedRemoveFromList() { - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } @@ -154,22 +154,22 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("SimpleDTO/IntegerList/2"); + patchDoc.Remove("SimpleObject/IntegerList/2"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); deserialized.ApplyTo(doc); - Assert.Equal(new List() { 1, 2 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 2 }, doc.SimpleObject.IntegerList); } [Fact] public void NestedRemoveFromListInvalidPositionTooLarge() { - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } @@ -177,7 +177,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("SimpleDTO/IntegerList/3"); + patchDoc.Remove("SimpleObject/IntegerList/3"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); @@ -194,9 +194,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void NestedRemoveFromListInvalidPositionTooSmall() { - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } @@ -204,7 +204,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("SimpleDTO/IntegerList/-1"); + patchDoc.Remove("SimpleObject/IntegerList/-1"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); @@ -221,9 +221,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void NestedRemoveFromEndOfList() { - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } @@ -231,14 +231,14 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic // create patch var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("SimpleDTO/IntegerList/-"); + patchDoc.Remove("SimpleObject/IntegerList/-"); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); deserialized.ApplyTo(doc); - Assert.Equal(new List() { 1, 2 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 2 }, doc.SimpleObject.IntegerList); } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs index c5936ec1b0..88d1662e1d 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs @@ -9,21 +9,21 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Xunit; -namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Internal { public class ReplaceOperationTests { [Fact] public void ReplaceGuidTest() { - dynamic doc = new SimpleDTO() + dynamic doc = new SimpleObject() { GuidValue = Guid.NewGuid() }; var newGuid = Guid.NewGuid(); // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace("GuidValue", newGuid); // serialize & deserialize @@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic var newGuid = Guid.NewGuid(); // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace("GuidValue", newGuid); // serialize & deserialize @@ -68,7 +68,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic var newGuid = Guid.NewGuid(); // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace("nestedobject/GuidValue", newGuid); // serialize & deserialize @@ -84,19 +84,19 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic public void ReplaceNestedObjectTest() { dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleDTO() + doc.SimpleDTO = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } }; - var newDTO = new SimpleDTO() + var newDTO = new SimpleObject() { DoubleValue = 1 }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace("SimpleDTO", newDTO); // serialize & deserialize @@ -117,7 +117,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.IntegerList = new List() { 1, 2, 3 }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace("IntegerList/0", 5); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -135,7 +135,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.IntegerList = new List() { 1, 2, 3 }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace("IntegerList", new List() { 4, 5, 6 }); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -150,13 +150,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic public void ReplaceInListInList() { dynamic doc = new ExpandoObject(); - doc.SimpleDTOList = new List() { - new SimpleDTO() { + doc.SimpleDTOList = new List() { + new SimpleObject() { IntegerList = new List(){1,2,3} }}; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace("SimpleDTOList/0/IntegerList/0", 4); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -171,13 +171,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic public void ReplaceInListInListAtEnd() { dynamic doc = new ExpandoObject(); - doc.SimpleDTOList = new List() { - new SimpleDTO() { + doc.SimpleDTOList = new List() { + new SimpleObject() { IntegerList = new List(){1,2,3} }}; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace("SimpleDTOList/0/IntegerList/-", 4); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -195,7 +195,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.IntegerList = new List() { 1, 2, 3 }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace("IntegerList", new List() { 4, 5, 6 }); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -213,7 +213,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.IntegerList = new List() { 1, 2, 3 }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace("IntegerList", new Collection() { 4, 5, 6 }); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -231,7 +231,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic doc.IntegerList = new List() { 1, 2, 3 }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace("IntegerList/-", 5); var serialized = JsonConvert.SerializeObject(patchDoc); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceTypedOperationTests.cs index d0bf23f487..94131ff3b5 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceTypedOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceTypedOperationTests.cs @@ -8,21 +8,21 @@ using System.Linq; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Internal { public class ReplaceTypedOperationTests { [Fact] public void ReplaceGuidTest() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { GuidValue = Guid.NewGuid() }; var newGuid = Guid.NewGuid(); // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace("GuidValue", newGuid); // serialize & deserialize @@ -37,23 +37,23 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void SerializeAndReplaceNestedObjectTest() { - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } } }; - var newDTO = new SimpleDTO() + var newDTO = new SimpleObject() { DoubleValue = 1 }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); - patchDoc.Replace("SimpleDTO", newDTO); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace("SimpleObject", newDTO); // serialize & deserialize var serialized = JsonConvert.SerializeObject(patchDoc); @@ -61,21 +61,21 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic deserialized.ApplyTo(doc); - Assert.Equal(1, doc.SimpleDTO.DoubleValue); - Assert.Equal(0, doc.SimpleDTO.IntegerValue); - Assert.Null(doc.SimpleDTO.IntegerList); + Assert.Equal(1, doc.SimpleObject.DoubleValue); + Assert.Equal(0, doc.SimpleObject.IntegerValue); + Assert.Null(doc.SimpleObject.IntegerList); } [Fact] public void ReplaceInList() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace("IntegerList/0", 5); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -89,13 +89,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void ReplaceFullList() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace("IntegerList", new List() { 4, 5, 6 }); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -109,36 +109,36 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void ReplaceInListInList() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { - SimpleDTOList = new List() { - new SimpleDTO() { + SimpleObjectList = new List() { + new SimpleObject() { IntegerList = new List(){1,2,3} }} }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); - patchDoc.Replace("SimpleDTOList/0/IntegerList/0", 4); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace("SimpleObjectList/0/IntegerList/0", 4); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject(serialized); deserialized.ApplyTo(doc); - Assert.Equal(4, doc.SimpleDTOList.First().IntegerList.First()); + Assert.Equal(4, doc.SimpleObjectList.First().IntegerList.First()); } [Fact] public void ReplaceFullListFromEnumerable() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace("IntegerList", new List() { 4, 5, 6 }); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -152,13 +152,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void ReplaceFullListWithCollection() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace("IntegerList", new Collection() { 4, 5, 6 }); var serialized = JsonConvert.SerializeObject(patchDoc); @@ -172,13 +172,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic [Fact] public void ReplaceAtEndOfList() { - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - JsonPatchDocument patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace("IntegerList/-", 5); var serialized = JsonConvert.SerializeObject(patchDoc); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleDTOWithNestedDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleDTOWithNestedDTO.cs deleted file mode 100644 index f8af4bb390..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleDTOWithNestedDTO.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; - -namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic -{ - public class SimpleDTOWithNestedDTO - { - public int IntegerValue { get; set; } - public NestedDTO NestedDTO { get; set; } - public SimpleDTO SimpleDTO { get; set; } - public List ListOfSimpleDTO { get; set; } - - public SimpleDTOWithNestedDTO() - { - NestedDTO = new NestedDTO(); - SimpleDTO = new SimpleDTO(); - ListOfSimpleDTO = new List(); - } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleObject.cs similarity index 81% rename from test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleDTO.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleObject.cs index d4bf19f75a..01a890d7be 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleDTO.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleObject.cs @@ -4,11 +4,11 @@ using System; using System.Collections.Generic; -namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic +namespace Microsoft.AspNetCore.JsonPatch.Internal { - public class SimpleDTO + public class SimpleObject { - public List SimpleDTOList { get; set; } + public List SimpleObjectList { get; set; } public List IntegerList { get; set; } public int IntegerValue { get; set; } public string StringProperty { get; set; } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleObjectWithNestedObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleObjectWithNestedObject.cs new file mode 100644 index 0000000000..aa766b8438 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleObjectWithNestedObject.cs @@ -0,0 +1,22 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + public class SimpleObjectWithNestedObject + { + public int IntegerValue { get; set; } + public NestedObject NestedObject { get; set; } + public SimpleObject SimpleObject { get; set; } + public List ListOfSimpleObject { get; set; } + + public SimpleObjectWithNestedObject() + { + NestedObject = new NestedObject(); + SimpleObject = new SimpleObject(); + ListOfSimpleObject = new List(); + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/DynamicObjectAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/DynamicObjectAdapterTest.cs new file mode 100644 index 0000000000..18bb7a775c --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/DynamicObjectAdapterTest.cs @@ -0,0 +1,231 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using Newtonsoft.Json.Serialization; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + public class DynamicObjectAdapterTest + { + [Fact] + public void TryAdd_AddsNewProperty() + { + // Arrange + var adapter = new DynamicObjectAdapter(); + dynamic target = new DynamicTestObject(); + var segment = "NewProperty"; + var resolver = new DefaultContractResolver(); + + // Act + var status = adapter.TryAdd(target, segment, resolver, "new", out string errorMessage); + + // Assert + Assert.True(status); + Assert.Null(errorMessage); + Assert.Equal("new", target.NewProperty); + } + + [Fact] + public void TryAdd_ReplacesExistingPropertyValue() + { + // Arrange + var adapter = new DynamicObjectAdapter(); + dynamic target = new DynamicTestObject(); + target.List = new List() { 1, 2, 3 }; + var value = new List() { "stringValue1", "stringValue2" }; + var segment = "List"; + var resolver = new DefaultContractResolver(); + + // Act + var status = adapter.TryAdd(target, segment, resolver, value, out string errorMessage); + + // Assert + Assert.True(status); + Assert.Null(errorMessage); + Assert.Equal(value, target.List); + } + + [Fact] + public void TryGet_GetsPropertyValue_ForExistingProperty() + { + // Arrange + var adapter = new DynamicObjectAdapter(); + dynamic target = new DynamicTestObject(); + var segment = "NewProperty"; + var resolver = new DefaultContractResolver(); + + // Act 1 + var addStatus = adapter.TryAdd(target, segment, resolver, "new", out string errorMessage); + + // Assert 1 + Assert.True(addStatus); + Assert.Null(errorMessage); + Assert.Equal("new", target.NewProperty); + + // Act 2 + var getStatus = adapter.TryGet(target, segment, resolver, out object getValue, out string getErrorMessage); + + // Assert 2 + Assert.True(getStatus); + Assert.Null(getErrorMessage); + Assert.Equal(getValue, target.NewProperty); + } + + [Fact] + public void TryGet_ThrowsPathNotFoundException_ForNonExistingProperty() + { + // Arrange + var adapter = new DynamicObjectAdapter(); + dynamic target = new DynamicTestObject(); + var segment = "NewProperty"; + var resolver = new DefaultContractResolver(); + + // Act + var getStatus = adapter.TryGet(target, segment, resolver, out object getValue, out string getErrorMessage); + + // Assert + Assert.False(getStatus); + Assert.Null(getValue); + Assert.Equal($"The target location specified by path segment '{segment}' was not found.", getErrorMessage); + } + + [Fact] + public void TryTraverse_FindsNextTarget() + { + // Arrange + var adapter = new DynamicObjectAdapter(); + dynamic target = new DynamicTestObject(); + target.NestedObject = new DynamicTestObject(); + target.NestedObject.NewProperty = "A"; + var segment = "NestedObject"; + var resolver = new DefaultContractResolver(); + + // Act + var status = adapter.TryTraverse(target, segment, resolver, out object nextTarget, out string errorMessage); + + // Assert + Assert.True(status); + Assert.Null(errorMessage); + Assert.Equal(target.NestedObject, nextTarget); + } + + [Fact] + public void TryTraverse_ThrowsPathNotFoundException_ForNonExistingProperty() + { + // Arrange + var adapter = new DynamicObjectAdapter(); + dynamic target = new DynamicTestObject(); + target.NestedObject = new DynamicTestObject(); + var segment = "NewProperty"; + var resolver = new DefaultContractResolver(); + + // Act + var status = adapter.TryTraverse(target.NestedObject, segment, resolver, out object nextTarget, out string errorMessage); + + // Assert + Assert.False(status); + Assert.Equal($"The target location specified by path segment '{segment}' was not found.", errorMessage); + } + + [Fact] + public void TryReplace_ReplacesPropertyValue() + { + // Arrange + var adapter = new DynamicObjectAdapter(); + dynamic target = new DynamicTestObject(); + target.NewProperty = new object(); + var segment = "NewProperty"; + var resolver = new DefaultContractResolver(); + + // Act + var status = adapter.TryReplace(target, segment, resolver, "new", out string errorMessage); + + // Assert + Assert.True(status); + Assert.Null(errorMessage); + Assert.Equal("new", target.NewProperty); + } + + [Fact] + public void TryReplace_ThrowsPathNotFoundException_ForNonExistingProperty() + { + // Arrange + var adapter = new DynamicObjectAdapter(); + dynamic target = new DynamicTestObject(); + var segment = "NewProperty"; + var resolver = new DefaultContractResolver(); + + // Act + var status = adapter.TryReplace(target, segment, resolver, "test", out string errorMessage); + + // Assert + Assert.False(status); + Assert.Equal($"The target location specified by path segment '{segment}' was not found.", errorMessage); + } + + [Fact] + public void TryReplace_ThrowsPropertyInvalidException_IfNewValueIsNotTheSameTypeAsInitialValue() + { + // Arrange + var adapter = new DynamicObjectAdapter(); + dynamic target = new DynamicTestObject(); + target.NewProperty = 1; + var segment = "NewProperty"; + var resolver = new DefaultContractResolver(); + + // Act + var status = adapter.TryReplace(target, segment, resolver, "test", out string errorMessage); + + // Assert + Assert.False(status); + Assert.Equal($"The value 'test' is invalid for target location.", errorMessage); + } + + [Theory] + [InlineData(1, 0)] + [InlineData("new", null)] + public void TryRemove_SetsPropertyToDefaultOrNull(object value, object expectedValue) + { + // Arrange + var adapter = new DynamicObjectAdapter(); + dynamic target = new DynamicTestObject(); + var segment = "NewProperty"; + var resolver = new DefaultContractResolver(); + + // Act 1 + var addStatus = adapter.TryAdd(target, segment, resolver, value, out string errorMessage); + + // Assert 1 + Assert.True(addStatus); + Assert.Null(errorMessage); + Assert.Equal(value, target.NewProperty); + + // Act 2 + var removeStatus = adapter.TryRemove(target, segment, resolver, out string removeErrorMessage); + + // Assert 2 + Assert.True(removeStatus); + Assert.Null(removeErrorMessage); + Assert.Equal(expectedValue, target.NewProperty); + } + + [Fact] + public void TryRemove_ThrowsPathNotFoundException_ForNonExistingProperty() + { + // Arrange + var adapter = new DynamicObjectAdapter(); + dynamic target = new DynamicTestObject(); + var segment = "NewProperty"; + var resolver = new DefaultContractResolver(); + + // Act + var removeStatus = adapter.TryRemove(target, segment, resolver, out string removeErrorMessage); + + // Assert + Assert.False(removeStatus); + Assert.Equal($"The target location specified by path segment '{segment}' was not found.", removeErrorMessage); + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/DynamicTestObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/DynamicTestObject.cs new file mode 100644 index 0000000000..4268d5526c --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/DynamicTestObject.cs @@ -0,0 +1,87 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Dynamic; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + public class DynamicTestObject : DynamicObject + { + private Dictionary _dictionary = new Dictionary(); + + public object this[string key] { get => ((IDictionary)_dictionary)[key]; set => ((IDictionary)_dictionary)[key] = value; } + + public ICollection Keys => ((IDictionary)_dictionary).Keys; + + public ICollection Values => ((IDictionary)_dictionary).Values; + + public int Count => ((IDictionary)_dictionary).Count; + + public bool IsReadOnly => ((IDictionary)_dictionary).IsReadOnly; + + public void Add(string key, object value) + { + ((IDictionary)_dictionary).Add(key, value); + } + + public void Add(KeyValuePair item) + { + ((IDictionary)_dictionary).Add(item); + } + + public void Clear() + { + ((IDictionary)_dictionary).Clear(); + } + + public bool Contains(KeyValuePair item) + { + return ((IDictionary)_dictionary).Contains(item); + } + + public bool ContainsKey(string key) + { + return ((IDictionary)_dictionary).ContainsKey(key); + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + ((IDictionary)_dictionary).CopyTo(array, arrayIndex); + } + + public IEnumerator> GetEnumerator() + { + return ((IDictionary)_dictionary).GetEnumerator(); + } + + public bool Remove(string key) + { + return ((IDictionary)_dictionary).Remove(key); + } + + public bool Remove(KeyValuePair item) + { + return ((IDictionary)_dictionary).Remove(item); + } + + public bool TryGetValue(string key, out object value) + { + return ((IDictionary)_dictionary).TryGetValue(key, out value); + } + + public override bool TryGetMember(GetMemberBinder binder, out object result) + { + var name = binder.Name; + + return TryGetValue(name, out result); + } + + public override bool TrySetMember(SetMemberBinder binder, object value) + { + _dictionary[binder.Name] = value; + + return true; + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/InheritedDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/InheritedObject.cs similarity index 85% rename from test/Microsoft.AspNetCore.JsonPatch.Test/InheritedDTO.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/InheritedObject.cs index a784a6304b..37b8a10dc9 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/InheritedDTO.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/InheritedObject.cs @@ -3,7 +3,7 @@ namespace Microsoft.AspNetCore.JsonPatch { - public class InheritedDTO : SimpleDTO + public class InheritedObject : SimpleObject { public string AdditionalStringProperty { get; set; } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DynamicObjectIntegrationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DynamicObjectIntegrationTests.cs new file mode 100644 index 0000000000..4b5fc96e24 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DynamicObjectIntegrationTests.cs @@ -0,0 +1,263 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using Microsoft.AspNetCore.JsonPatch.Exceptions; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + public class DynamicObjectIntegrationTests + { + [Fact] + public void AddResults_ShouldReplaceExistingPropertyValue_InNestedDynamicObject() + { + // Arrange + dynamic dynamicTestObject = new DynamicTestObject(); + dynamicTestObject.Nested = new NestedObject(); + dynamicTestObject.Nested.DynamicProperty = new DynamicTestObject(); + dynamicTestObject.Nested.DynamicProperty.InBetweenFirst = new DynamicTestObject(); + dynamicTestObject.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond = new DynamicTestObject(); + dynamicTestObject.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond.StringProperty = "A"; + + var patchDoc = new JsonPatchDocument(); + patchDoc.Add("/Nested/DynamicProperty/InBetweenFirst/InBetweenSecond/StringProperty", "B"); + + // Act + patchDoc.ApplyTo(dynamicTestObject); + + // Assert + Assert.Equal("B", dynamicTestObject.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond.StringProperty); + } + + [Fact] + public void ShouldNotBeAbleToAdd_ToNonExistingProperty_ThatIsNotTheRoot() + { + //Adding to a Nonexistent Target + // + // An example target JSON document: + // { "foo": "bar" } + // A JSON Patch document: + // [ + // { "op": "add", "path": "/baz/bat", "value": "qux" } + // ] + // This JSON Patch document, applied to the target JSON document above, + // would result in an error (therefore, it would not be applied), + // because the "add" operation's target location that references neither + // the root of the document, nor a member of an existing object, nor a + // member of an existing array. + + // Arrange + var nestedObject = new NestedObject() + { + DynamicProperty = new DynamicTestObject() + }; + + var patchDoc = new JsonPatchDocument(); + patchDoc.Add("DynamicProperty/OtherProperty/IntProperty", 1); + + // Act + var exception = Assert.Throws(() => + { + patchDoc.ApplyTo(nestedObject); + }); + + // Assert + Assert.Equal( + string.Format( + "The target location specified by path segment '{0}' was not found.", + "OtherProperty"), + exception.Message); + } + + [Fact] + public void CopyProperties_InNestedDynamicObject() + { + // Arrange + dynamic dynamicTestObject = new DynamicTestObject(); + dynamicTestObject.NestedDynamicObject = new DynamicTestObject(); + dynamicTestObject.NestedDynamicObject.StringProperty = "A"; + dynamicTestObject.NestedDynamicObject.AnotherStringProperty = "B"; + + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy("NestedDynamicObject/StringProperty", "NestedDynamicObject/AnotherStringProperty"); + + // Act + patchDoc.ApplyTo(dynamicTestObject); + + // Assert + Assert.Equal("A", dynamicTestObject.NestedDynamicObject.AnotherStringProperty); + } + + + [Fact] + public void MoveToNonExistingProperty_InDynamicObject_ShouldAddNewProperty() + { + // Arrange + dynamic dynamicTestObject = new DynamicTestObject(); + dynamicTestObject.StringProperty = "A"; + + var patchDoc = new JsonPatchDocument(); + patchDoc.Move("StringProperty", "AnotherStringProperty"); + + // Act + patchDoc.ApplyTo(dynamicTestObject); + dynamicTestObject.TryGetValue("StringProperty", out object valueFromDictionary); + + // Assert + Assert.Equal("A", dynamicTestObject.AnotherStringProperty); + Assert.Null(valueFromDictionary); + } + + [Fact] + public void MovePropertyValue_FromDynamicObject_ToTypedObject() + { + // Arrange + dynamic dynamicTestObject = new DynamicTestObject(); + dynamicTestObject.StringProperty = "A"; + dynamicTestObject.SimpleObject = new SimpleObject() { AnotherStringProperty = "B" }; + + var patchDoc = new JsonPatchDocument(); + patchDoc.Move("StringProperty", "SimpleObject/AnotherStringProperty"); + + // Act + patchDoc.ApplyTo(dynamicTestObject); + dynamicTestObject.TryGetValue("StringProperty", out object valueFromDictionary); + + // Assert + Assert.Equal("A", dynamicTestObject.SimpleObject.AnotherStringProperty); + Assert.Null(valueFromDictionary); + } + + [Fact] + public void MovePropertyValue_FromListToNonList_InNestedTypedObject_InDynamicObject() + { + // Arrange + dynamic dynamicTestObject = new DynamicTestObject(); + dynamicTestObject.Nested = new SimpleObject() + { + IntegerList = new List() { 1, 2, 3 } + }; + + var patchDoc = new JsonPatchDocument(); + patchDoc.Move("Nested/IntegerList/0", "Nested/IntegerValue"); + + // Act + patchDoc.ApplyTo(dynamicTestObject); + + // Assert + Assert.Equal(new List() { 2, 3 }, dynamicTestObject.Nested.IntegerList); + Assert.Equal(1, dynamicTestObject.Nested.IntegerValue); + } + + [Fact] + public void RemoveNestedProperty_FromDynamicObject() + { + // Arrange + dynamic dynamicTestObject = new DynamicTestObject(); + dynamicTestObject.Test = new DynamicTestObject(); + dynamicTestObject.Test.AnotherTest = "A"; + + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove("Test"); + + // Act + patchDoc.ApplyTo(dynamicTestObject); + dynamicTestObject.TryGetValue("Test", out object valueFromDictionary); + + // Assert + Assert.Null(valueFromDictionary); + } + + [Fact] + public void RemoveFromNestedObject_InDynamicObject_MixedCase_ThrowsPathNotFoundException() + { + // Arrange + dynamic dynamicTestObject = new DynamicTestObject(); + dynamicTestObject.SimpleObject = new SimpleObject() + { + StringProperty = "A" + }; + + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove("Simpleobject/stringProperty"); + + // Act + var exception = Assert.Throws(() => + { + patchDoc.ApplyTo(dynamicTestObject); + }); + + // Assert + Assert.Equal( + string.Format("The target location specified by path segment '{0}' was not found.", + "Simpleobject"), + exception.Message); + } + + [Fact] + public void RemoveFromList_NestedInDynamicObject() + { + // Arrange + dynamic dynamicTestObject = new DynamicTestObject(); + dynamicTestObject.SimpleObject = new SimpleObject() + { + IntegerList = new List() { 1, 2, 3 } + }; + + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove("SimpleObject/IntegerList/2"); + + // Act + patchDoc.ApplyTo(dynamicTestObject); + + // Assert + Assert.Equal(new List() { 1, 2 }, dynamicTestObject.SimpleObject.IntegerList); + } + + [Fact] + public void ReplaceNestedTypedObject_InDynamicObject() + { + // Arrange + dynamic dynamicTestObject = new DynamicTestObject(); + dynamicTestObject.SimpleObject = new SimpleObject() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + }; + + var newObject = new SimpleObject() + { + DoubleValue = 1 + }; + + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace("SimpleObject", newObject); + + // Act + patchDoc.ApplyTo(dynamicTestObject); + + // Assert + Assert.Equal(1, dynamicTestObject.SimpleObject.DoubleValue); + Assert.Equal(0, dynamicTestObject.SimpleObject.IntegerValue); + Assert.Null(dynamicTestObject.SimpleObject.IntegerList); + } + + [Fact] + public void ReplaceFullList_InDynamicObject() + { + // Arrange + dynamic dynamicTestObject = new DynamicTestObject(); + dynamicTestObject.IntegerList = new List() { 1, 2, 3 }; + + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace("IntegerList", new List() { 4, 5, 6 }); + + // Act + patchDoc.ApplyTo(dynamicTestObject); + + // Assert + Assert.Equal(new List() { 4, 5, 6 }, dynamicTestObject.IntegerList); + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs index efc780b388..3948b79484 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs @@ -14,14 +14,14 @@ namespace Microsoft.AspNetCore.JsonPatch [Fact] public void Add_WithExpression_RespectsJsonPropertyName_ForModelProperty() { - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add(p => p.Name, "John"); var serialized = JsonConvert.SerializeObject(patchDoc); // serialized value should have "AnotherName" as path // deserialize to a JsonPatchDocument to check var deserialized = - JsonConvert.DeserializeObject>(serialized); + JsonConvert.DeserializeObject>(serialized); // get path var pathToCheck = deserialized.Operations.First().path; @@ -65,19 +65,19 @@ namespace Microsoft.AspNetCore.JsonPatch [Fact] public void Add_WithExpression_RespectsJsonPropertyName_WhenApplyingToDifferentlyTypedClassWithPropertyMatchingJsonPropertyName() { - var patchDocToSerialize = new JsonPatchDocument(); + var patchDocToSerialize = new JsonPatchDocument(); patchDocToSerialize.Add(p => p.Name, "John"); // the patchdoc will deserialize to "anothername". We should thus be able to apply // it to a class that HAS that other property name. - var doc = new JsonPropertyWithAnotherNameDTO() + var doc = new JsonPropertyWithAnotherNameObject() { AnotherName = "InitialValue" }; var serialized = JsonConvert.SerializeObject(patchDocToSerialize); var deserialized = - JsonConvert.DeserializeObject> + JsonConvert.DeserializeObject> (serialized); deserialized.ApplyTo(doc); @@ -88,21 +88,21 @@ namespace Microsoft.AspNetCore.JsonPatch [Fact] public void Add_WithExpression_RespectsJsonPropertyName_WhenApplyingToSameTypedClassWithMatchingJsonPropertyName() { - var patchDocToSerialize = new JsonPatchDocument(); + var patchDocToSerialize = new JsonPatchDocument(); patchDocToSerialize.Add(p => p.Name, "John"); // the patchdoc will deserialize to "anothername". As JsonPropertyDTO has // a JsonProperty signifying that "Name" should be deseriallized from "AnotherName", // we should be able to apply the patchDoc. - var doc = new JsonPropertyDTO() + var doc = new JsonPropertyObject() { Name = "InitialValue" }; var serialized = JsonConvert.SerializeObject(patchDocToSerialize); var deserialized = - JsonConvert.DeserializeObject> + JsonConvert.DeserializeObject> (serialized); deserialized.ApplyTo(doc); @@ -113,7 +113,7 @@ namespace Microsoft.AspNetCore.JsonPatch [Fact] public void Add_OnApplyFromJson_RespectsJsonPropertyNameOnJsonDocument() { - var doc = new JsonPropertyDTO() + var doc = new JsonPropertyObject() { Name = "InitialValue" }; @@ -121,7 +121,7 @@ namespace Microsoft.AspNetCore.JsonPatch // serialization should serialize to "AnotherName" var serialized = "[{\"value\":\"Kevin\",\"path\":\"/AnotherName\",\"op\":\"add\"}]"; var deserialized = - JsonConvert.DeserializeObject>(serialized); + JsonConvert.DeserializeObject>(serialized); deserialized.ApplyTo(doc); @@ -131,7 +131,7 @@ namespace Microsoft.AspNetCore.JsonPatch [Fact] public void Remove_OnApplyFromJson_RespectsJsonPropertyNameOnJsonDocument() { - var doc = new JsonPropertyDTO() + var doc = new JsonPropertyObject() { Name = "InitialValue" }; @@ -139,7 +139,7 @@ namespace Microsoft.AspNetCore.JsonPatch // serialization should serialize to "AnotherName" var serialized = "[{\"path\":\"/AnotherName\",\"op\":\"remove\"}]"; var deserialized = - JsonConvert.DeserializeObject>(serialized); + JsonConvert.DeserializeObject>(serialized); deserialized.ApplyTo(doc); @@ -149,7 +149,7 @@ namespace Microsoft.AspNetCore.JsonPatch [Fact] public void Add_OnApplyFromJson_RespectsInheritedJsonPropertyNameOnJsonDocument() { - var doc = new JsonPropertyWithInheritanceDTO() + var doc = new JsonPropertyWithInheritanceObject() { Name = "InitialName" }; @@ -157,7 +157,7 @@ namespace Microsoft.AspNetCore.JsonPatch // serialization should serialize to "AnotherName" var serialized = "[{\"value\":\"Kevin\",\"path\":\"/AnotherName\",\"op\":\"add\"}]"; var deserialized = - JsonConvert.DeserializeObject>(serialized); + JsonConvert.DeserializeObject>(serialized); deserialized.ApplyTo(doc); @@ -167,14 +167,14 @@ namespace Microsoft.AspNetCore.JsonPatch [Fact] public void Add_WithExpression_RespectsJsonPropertyName_ForInheritedModelProperty() { - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add(p => p.Name, "John"); var serialized = JsonConvert.SerializeObject(patchDoc); // serialized value should have "AnotherName" as path // deserialize to a JsonPatchDocument to check var deserialized = - JsonConvert.DeserializeObject>(serialized); + JsonConvert.DeserializeObject>(serialized); // get path var pathToCheck = deserialized.Operations.First().path; @@ -184,10 +184,10 @@ namespace Microsoft.AspNetCore.JsonPatch [Fact] public void Add_OnApplyFromJson_EscapingHandledOnComplexJsonPropertyNameOnJsonDocument() { - var doc = new JsonPropertyComplexNameDTO() + var doc = new JsonPropertyComplexNameObject() { FooSlashBars = "InitialName", - FooSlashTilde = new SimpleDTO + FooSlashTilde = new SimpleObject { StringProperty = "Initial Value" } @@ -196,7 +196,7 @@ namespace Microsoft.AspNetCore.JsonPatch // serialization should serialize to "AnotherName" var serialized = "[{\"value\":\"Kevin\",\"path\":\"/foo~1bar~0\",\"op\":\"add\"},{\"value\":\"Final Value\",\"path\":\"/foo~1~0/StringProperty\",\"op\":\"replace\"}]"; var deserialized = - JsonConvert.DeserializeObject>(serialized); + JsonConvert.DeserializeObject>(serialized); deserialized.ApplyTo(doc); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyComplexNameDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyComplexNameObject.cs similarity index 78% rename from test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyComplexNameDTO.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyComplexNameObject.cs index 7ff66481ad..a39aa8e30c 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyComplexNameDTO.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyComplexNameObject.cs @@ -5,12 +5,12 @@ using Newtonsoft.Json; namespace Microsoft.AspNetCore.JsonPatch { - public class JsonPropertyComplexNameDTO + public class JsonPropertyComplexNameObject { [JsonProperty("foo/bar~")] public string FooSlashBars { get; set; } [JsonProperty("foo/~")] - public SimpleDTO FooSlashTilde { get; set; } + public SimpleObject FooSlashTilde { get; set; } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyObject.cs similarity index 90% rename from test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyDTO.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyObject.cs index c926d9f5fd..245ae6bb65 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyDTO.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyObject.cs @@ -5,7 +5,7 @@ using Newtonsoft.Json; namespace Microsoft.AspNetCore.JsonPatch { - public class JsonPropertyDTO + public class JsonPropertyObject { [JsonProperty("AnotherName")] public string Name { get; set; } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithAnotherNameDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithAnotherNameObject.cs similarity index 84% rename from test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithAnotherNameDTO.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithAnotherNameObject.cs index 9b61e09005..4581a4826d 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithAnotherNameDTO.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithAnotherNameObject.cs @@ -3,7 +3,7 @@ namespace Microsoft.AspNetCore.JsonPatch { - public class JsonPropertyWithAnotherNameDTO + public class JsonPropertyWithAnotherNameObject { public string AnotherName { get; set; } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithInheritanceDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithInheritanceDTO.cs deleted file mode 100644 index fa69425ea9..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithInheritanceDTO.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Microsoft.AspNetCore.JsonPatch -{ - public class JsonPropertyWithInheritanceDTO : JsonPropertyWithInheritanceBaseDTO - { - public override string Name { get; set; } - } - - public abstract class JsonPropertyWithInheritanceBaseDTO - { - [JsonProperty("AnotherName")] - public abstract string Name { get; set; } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithInheritanceObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithInheritanceObject.cs new file mode 100644 index 0000000000..935ef275ad --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithInheritanceObject.cs @@ -0,0 +1,15 @@ +using Newtonsoft.Json; + +namespace Microsoft.AspNetCore.JsonPatch +{ + public class JsonPropertyWithInheritanceObject : JsonPropertyWithInheritanceBaseObject + { + public override string Name { get; set; } + } + + public abstract class JsonPropertyWithInheritanceBaseObject + { + [JsonProperty("AnotherName")] + public abstract string Name { get; set; } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs index 6a087edd8f..3c692ea150 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs @@ -18,10 +18,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var resolver = new Mock(MockBehavior.Strict); var targetObject = new[] { 20, 30 }; var listAdapter = new ListAdapter(); - string message = null; // Act - var addStatus = listAdapter.TryAdd(targetObject, "0", resolver.Object, "40", out message); + var addStatus = listAdapter.TryAdd(targetObject, "0", resolver.Object, "40", out var message); // Assert Assert.False(addStatus); @@ -41,10 +40,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal targetObject.Add(20); targetObject.Add(30); var listAdapter = new ListAdapter(); - string message = null; // Act - var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, "40", out message); + var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, "40", out var message); // Assert Assert.False(addStatus); @@ -62,11 +60,10 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var resolver = new Mock(MockBehavior.Strict); var targetObject = new List() { "James", "Mike" }; var listAdapter = new ListAdapter(); - string message = null; var position = targetObject.Count.ToString(); // Act - var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, "Rob", out message); + var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, "Rob", out var message); // Assert Assert.Null(message); @@ -85,10 +82,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var resolver = new Mock(MockBehavior.Strict); var targetObject = new List() { "James", "Mike" }; var listAdapter = new ListAdapter(); - string message = null; // Act - var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, "40", out message); + var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, "40", out var message); // Assert Assert.False(addStatus); @@ -106,10 +102,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var resolver = new Mock(MockBehavior.Strict); var targetObject = new List() { "James", "Mike" }; var listAdapter = new ListAdapter(); - string message = null; // Act - var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, "40", out message); + var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, "40", out var message); // Assert Assert.False(addStatus); @@ -143,10 +138,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Arrange var resolver = new Mock(MockBehavior.Strict); var listAdapter = new ListAdapter(); - string message = null; // Act - var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, "20", out message); + var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, "20", out var message); // Assert Assert.True(addStatus); @@ -162,10 +156,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var resolver = new Mock(MockBehavior.Strict); var listAdapter = new ListAdapter(); var targetObject = new List() { "James", "Mike" }; - string message = null; // Act - var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, value: null, errorMessage: out message); + var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, value: null, errorMessage: out var message); // Assert Assert.True(addStatus); @@ -178,21 +171,20 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal public void Add_CompatibleTypeWorks() { // Arrange - var sDto = new SimpleDTO(); - var iDto = new InheritedDTO(); + var sDto = new SimpleObject(); + var iDto = new InheritedObject(); var resolver = new Mock(MockBehavior.Strict); - var targetObject = new List() { sDto }; + var targetObject = new List() { sDto }; var listAdapter = new ListAdapter(); - string message = null; // Act - var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, iDto, out message); + var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, iDto, out var message); // Assert Assert.True(addStatus); Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); Assert.Equal(2, targetObject.Count); - Assert.Equal(new List() { sDto, iDto }, targetObject); + Assert.Equal(new List() { sDto, iDto }, targetObject); } [Fact] @@ -202,10 +194,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var resolver = new Mock(MockBehavior.Strict); var targetObject = new List() { 10, 20 }; var listAdapter = new ListAdapter(); - string message = null; // Act - var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, "James", out message); + var addStatus = listAdapter.TryAdd(targetObject, "-", resolver.Object, "James", out var message); // Assert Assert.False(addStatus); @@ -253,10 +244,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Arrange var resolver = new Mock(MockBehavior.Strict); var listAdapter = new ListAdapter(); - string message = null; // Act - var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, value, out message); + var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, value, out var message); // Assert Assert.True(addStatus); @@ -267,34 +257,34 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal public static TheoryData AddingKeepsObjectReferenceData { get { - var sDto1 = new SimpleDTO(); - var sDto2 = new SimpleDTO(); - var sDto3 = new SimpleDTO(); + var sDto1 = new SimpleObject(); + var sDto2 = new SimpleObject(); + var sDto3 = new SimpleObject(); return new TheoryData() { { - new List() { }, + new List() { }, sDto1, "-", - new List() { sDto1 } + new List() { sDto1 } }, { - new List() { sDto1, sDto2 }, + new List() { sDto1, sDto2 }, sDto3, "-", - new List() { sDto1, sDto2, sDto3 } + new List() { sDto1, sDto2, sDto3 } }, { - new List() { sDto1, sDto2 }, + new List() { sDto1, sDto2 }, sDto3, "0", - new List() { sDto3, sDto1, sDto2 } + new List() { sDto3, sDto1, sDto2 } }, { - new List() { sDto1, sDto2 }, + new List() { sDto1, sDto2 }, sDto3, "1", - new List() { sDto1, sDto3, sDto2 } + new List() { sDto1, sDto3, sDto2 } } }; } @@ -307,10 +297,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Arrange var resolver = new Mock(MockBehavior.Strict); var listAdapter = new ListAdapter(); - string message = null; // Act - var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, value, out message); + var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, value, out var message); // Assert Assert.True(addStatus); @@ -329,11 +318,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var resolver = new Mock(MockBehavior.Strict); var targetObject = new List(input); var listAdapter = new ListAdapter(); - string message = null; - object value = null; // Act - var getStatus = listAdapter.TryGet(targetObject, position, resolver.Object, out value, out message); + var getStatus = listAdapter.TryGet(targetObject, position, resolver.Object, out var value, out var message); // Assert Assert.False(getStatus); @@ -352,11 +339,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var resolver = new Mock(MockBehavior.Strict); var targetObject = new List(input); var listAdapter = new ListAdapter(); - string message = null; - object value = null; // Act - var getStatus = listAdapter.TryGet(targetObject, position, resolver.Object, out value, out message); + var getStatus = listAdapter.TryGet(targetObject, position, resolver.Object, out var value, out var message); // Assert Assert.True(getStatus); @@ -374,10 +359,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var resolver = new Mock(MockBehavior.Strict); var targetObject = new List(input); var listAdapter = new ListAdapter(); - string message = null; // Act - var removeStatus = listAdapter.TryRemove(targetObject, position, resolver.Object, out message); + var removeStatus = listAdapter.TryRemove(targetObject, position, resolver.Object, out var message); // Assert Assert.False(removeStatus); @@ -396,10 +380,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var resolver = new Mock(MockBehavior.Strict); var targetObject = new List(input); var listAdapter = new ListAdapter(); - string message = null; // Act - var removeStatus = listAdapter.TryRemove(targetObject, position, resolver.Object, out message); + var removeStatus = listAdapter.TryRemove(targetObject, position, resolver.Object, out var message); // Assert Assert.True(removeStatus); @@ -413,10 +396,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var resolver = new Mock(MockBehavior.Strict); var targetObject = new List() { 10, 20 }; var listAdapter = new ListAdapter(); - string message = null; // Act - var replaceStatus = listAdapter.TryReplace(targetObject, "-", resolver.Object, "James", out message); + var replaceStatus = listAdapter.TryReplace(targetObject, "-", resolver.Object, "James", out var message); // Assert Assert.False(replaceStatus); @@ -432,10 +414,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var resolver = new Mock(MockBehavior.Strict); var targetObject = new List() { 10, 20 }; var listAdapter = new ListAdapter(); - string message = null; // Act - var replaceStatus = listAdapter.TryReplace(targetObject, "-", resolver.Object, "30", out message); + var replaceStatus = listAdapter.TryReplace(targetObject, "-", resolver.Object, "30", out var message); // Assert Assert.True(replaceStatus); @@ -469,10 +450,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var resolver = new Mock(MockBehavior.Strict); var targetObject = new List() { 10, 20 }; var listAdapter = new ListAdapter(); - string message = null; // Act - var replaceStatus = listAdapter.TryReplace(targetObject, position, resolver.Object, "30", out message); + var replaceStatus = listAdapter.TryReplace(targetObject, position, resolver.Object, "30", out var message); // Assert Assert.True(replaceStatus); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/NestedDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObject.cs similarity index 89% rename from test/Microsoft.AspNetCore.JsonPatch.Test/NestedDTO.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/NestedObject.cs index 90be5152cb..8f0927297e 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/NestedDTO.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObject.cs @@ -3,7 +3,7 @@ namespace Microsoft.AspNetCore.JsonPatch { - public class NestedDTO + public class NestedObject { public string StringProperty { get; set; } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs index 4aa25a3af1..a0b5bd7e3f 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs @@ -15,249 +15,249 @@ namespace Microsoft.AspNetCore.JsonPatch public void ReplacePropertyInNestedObject() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { IntegerValue = 1 }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.NestedDTO.StringProperty, "B"); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.NestedObject.StringProperty, "B"); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal("B", doc.NestedDTO.StringProperty); + Assert.Equal("B", doc.NestedObject.StringProperty); } [Fact] public void ReplacePropertyInNestedObjectWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { IntegerValue = 1 }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.NestedDTO.StringProperty, "B"); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.NestedObject.StringProperty, "B"); // serialize & deserialize var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal("B", doc.NestedDTO.StringProperty); + Assert.Equal("B", doc.NestedObject.StringProperty); } [Fact] public void ReplaceNestedObject() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { IntegerValue = 1 }; - var newNested = new NestedDTO() { StringProperty = "B" }; + var newNested = new NestedObject() { StringProperty = "B" }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.NestedDTO, newNested); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.NestedObject, newNested); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal("B", doc.NestedDTO.StringProperty); + Assert.Equal("B", doc.NestedObject.StringProperty); } [Fact] public void ReplaceNestedObjectWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { IntegerValue = 1 }; - var newNested = new NestedDTO() { StringProperty = "B" }; + var newNested = new NestedObject() { StringProperty = "B" }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.NestedDTO, newNested); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.NestedObject, newNested); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal("B", doc.NestedDTO.StringProperty); + Assert.Equal("B", doc.NestedObject.StringProperty); } [Fact] public void AddResultsInReplace() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { StringProperty = "A" } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleDTO.StringProperty, "B"); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleObject.StringProperty, "B"); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal("B", doc.SimpleDTO.StringProperty); + Assert.Equal("B", doc.SimpleObject.StringProperty); } [Fact] public void AddResultsInReplaceWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { StringProperty = "A" } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleDTO.StringProperty, "B"); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleObject.StringProperty, "B"); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal("B", doc.SimpleDTO.StringProperty); + Assert.Equal("B", doc.SimpleObject.StringProperty); } [Fact] public void AddToList() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleDTO.IntegerList, 4, 0); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleObject.IntegerList, 4, 0); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleObject.IntegerList); } [Fact] public void AddToListWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleDTO.IntegerList, 4, 0); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleObject.IntegerList, 4, 0); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleObject.IntegerList); } [Fact] public void AddToIntegerIList() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerIList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => (List)o.SimpleDTO.IntegerIList, 4, 0); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => (List)o.SimpleObject.IntegerIList, 4, 0); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleDTO.IntegerIList); + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleObject.IntegerIList); } [Fact] public void AddToIntegerIListWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerIList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => (List)o.SimpleDTO.IntegerIList, 4, 0); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => (List)o.SimpleObject.IntegerIList, 4, 0); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleDTO.IntegerIList); + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleObject.IntegerIList); } [Fact] public void AddToNestedIntegerIList() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTOIList = new List + SimpleObjectIList = new List { - new SimpleDTO + new SimpleObject { IntegerIList = new List() { 1, 2, 3 } } @@ -265,25 +265,25 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => (List)o.SimpleDTOIList[0].IntegerIList, 4, 0); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => (List)o.SimpleObjectIList[0].IntegerIList, 4, 0); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleDTOIList[0].IntegerIList); + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleObjectIList[0].IntegerIList); } [Fact] public void AddToNestedIntegerIListWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTOIList = new List + SimpleObjectIList = new List { - new SimpleDTO + new SimpleObject { IntegerIList = new List() { 1, 2, 3 } } @@ -291,32 +291,32 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => (List)o.SimpleDTOIList[0].IntegerIList, 4, 0); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => (List)o.SimpleObjectIList[0].IntegerIList, 4, 0); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleDTOIList[0].IntegerIList); + Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleObjectIList[0].IntegerIList); } [Fact] public void AddToComplextTypeListSpecifyIndex() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTOList = new List() + SimpleObjectList = new List() { - new SimpleDTO + new SimpleObject { StringProperty = "String1" }, - new SimpleDTO + new SimpleObject { StringProperty = "String2" } @@ -324,29 +324,29 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleDTOList[0].StringProperty, "ChangedString1"); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleObjectList[0].StringProperty, "ChangedString1"); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal("ChangedString1", doc.SimpleDTOList[0].StringProperty); + Assert.Equal("ChangedString1", doc.SimpleObjectList[0].StringProperty); } [Fact] public void AddToComplextTypeListSpecifyIndexWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTOList = new List() + SimpleObjectList = new List() { - new SimpleDTO + new SimpleObject { StringProperty = "String1" }, - new SimpleDTO + new SimpleObject { StringProperty = "String2" } @@ -354,34 +354,34 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleDTOList[0].StringProperty, "ChangedString1"); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleObjectList[0].StringProperty, "ChangedString1"); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal("ChangedString1", doc.SimpleDTOList[0].StringProperty); + Assert.Equal("ChangedString1", doc.SimpleObjectList[0].StringProperty); } [Fact] public void AddToListInvalidPositionTooLarge() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleDTO.IntegerList, 4, 4); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleObject.IntegerList, 4, 4); // Act & Assert var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); @@ -395,20 +395,20 @@ namespace Microsoft.AspNetCore.JsonPatch public void AddToListInvalidPositionTooLargeWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleDTO.IntegerList, 4, 4); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleObject.IntegerList, 4, 4); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act & Assert var exception = Assert.Throws(() => @@ -424,19 +424,19 @@ namespace Microsoft.AspNetCore.JsonPatch public void AddToListInvalidPositionTooLarge_LogsError() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleDTO.IntegerList, 4, 4); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleObject.IntegerList, 4, 4); - var logger = new TestErrorLogger(); + var logger = new TestErrorLogger(); patchDoc.ApplyTo(doc, logger.LogErrorMessage); @@ -452,17 +452,17 @@ namespace Microsoft.AspNetCore.JsonPatch public void AddToListInvalidPositionTooSmall() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleDTO.IntegerList, 4, -1); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleObject.IntegerList, 4, -1); // Act & Assert var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); @@ -475,20 +475,20 @@ namespace Microsoft.AspNetCore.JsonPatch public void AddToListInvalidPositionTooSmallWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleDTO.IntegerList, 4, -1); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleObject.IntegerList, 4, -1); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act & Assert var exception = Assert.Throws(() => @@ -504,19 +504,19 @@ namespace Microsoft.AspNetCore.JsonPatch public void AddToListInvalidPositionTooSmall_LogsError() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleDTO.IntegerList, 4, -1); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleObject.IntegerList, 4, -1); - var logger = new TestErrorLogger(); + var logger = new TestErrorLogger(); patchDoc.ApplyTo(doc, logger.LogErrorMessage); @@ -532,164 +532,164 @@ namespace Microsoft.AspNetCore.JsonPatch public void AddToListAppend() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleDTO.IntegerList, 4); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleObject.IntegerList, 4); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(new List() { 1, 2, 3, 4 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 2, 3, 4 }, doc.SimpleObject.IntegerList); } [Fact] public void AddToListAppendWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleDTO.IntegerList, 4); + var patchDoc = new JsonPatchDocument(); + patchDoc.Add(o => o.SimpleObject.IntegerList, 4); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(new List() { 1, 2, 3, 4 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 2, 3, 4 }, doc.SimpleObject.IntegerList); } [Fact] public void Remove() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { StringProperty = "A" } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleDTO.StringProperty); + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleObject.StringProperty); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Null(doc.SimpleDTO.StringProperty); + Assert.Null(doc.SimpleObject.StringProperty); } [Fact] public void RemoveWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { StringProperty = "A" } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleDTO.StringProperty); + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleObject.StringProperty); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Null(doc.SimpleDTO.StringProperty); + Assert.Null(doc.SimpleObject.StringProperty); } [Fact] public void RemoveFromList() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleDTO.IntegerList, 2); + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleObject.IntegerList, 2); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(new List() { 1, 2 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 2 }, doc.SimpleObject.IntegerList); } [Fact] public void RemoveFromListWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleDTO.IntegerList, 2); + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleObject.IntegerList, 2); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(new List() { 1, 2 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 2 }, doc.SimpleObject.IntegerList); } [Fact] public void RemoveFromListInvalidPositionTooLarge() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleDTO.IntegerList, 3); + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleObject.IntegerList, 3); // Act & Assert var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); @@ -702,20 +702,20 @@ namespace Microsoft.AspNetCore.JsonPatch public void RemoveFromListInvalidPositionTooLargeWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleDTO.IntegerList, 3); + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleObject.IntegerList, 3); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act & Assert var exception = Assert.Throws(() => @@ -731,19 +731,19 @@ namespace Microsoft.AspNetCore.JsonPatch public void RemoveFromListInvalidPositionTooLarge_LogsError() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleDTO.IntegerList, 3); + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleObject.IntegerList, 3); - var logger = new TestErrorLogger(); + var logger = new TestErrorLogger(); patchDoc.ApplyTo(doc, logger.LogErrorMessage); @@ -757,17 +757,17 @@ namespace Microsoft.AspNetCore.JsonPatch public void RemoveFromListInvalidPositionTooSmall() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleDTO.IntegerList, -1); + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleObject.IntegerList, -1); // Act & Assert var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); @@ -780,20 +780,20 @@ namespace Microsoft.AspNetCore.JsonPatch public void RemoveFromListInvalidPositionTooSmallWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleDTO.IntegerList, -1); + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleObject.IntegerList, -1); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act & Assert var exception = Assert.Throws(() => @@ -809,19 +809,19 @@ namespace Microsoft.AspNetCore.JsonPatch public void RemoveFromListInvalidPositionTooSmall_LogsError() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleDTO.IntegerList, -1); + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleObject.IntegerList, -1); - var logger = new TestErrorLogger(); + var logger = new TestErrorLogger(); patchDoc.ApplyTo(doc, logger.LogErrorMessage); @@ -836,58 +836,58 @@ namespace Microsoft.AspNetCore.JsonPatch public void RemoveFromEndOfList() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleDTO.IntegerList); + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleObject.IntegerList); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(new List() { 1, 2 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 2 }, doc.SimpleObject.IntegerList); } [Fact] public void RemoveFromEndOfListWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleDTO.IntegerList); + var patchDoc = new JsonPatchDocument(); + patchDoc.Remove(o => o.SimpleObject.IntegerList); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(new List() { 1, 2 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 2 }, doc.SimpleObject.IntegerList); } [Fact] public void Replace() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { StringProperty = "A", DecimalValue = 10 @@ -895,48 +895,48 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleDTO.StringProperty, "B"); - patchDoc.Replace(o => o.SimpleDTO.DecimalValue, 12); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleObject.StringProperty, "B"); + patchDoc.Replace(o => o.SimpleObject.DecimalValue, 12); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal("B", doc.SimpleDTO.StringProperty); - Assert.Equal(12, doc.SimpleDTO.DecimalValue); + Assert.Equal("B", doc.SimpleObject.StringProperty); + Assert.Equal(12, doc.SimpleObject.DecimalValue); } [Fact] public void Replace_DTOWithNullCheck() { // Arrange - var doc = new SimpleDTOWithNestedDTOWithNullCheck() + var doc = new SimpleObjectWithNestedObjectWithNullCheck() { - SimpleDTOWithNullCheck = new SimpleDTOWithNullCheck() + SimpleObjectWithNullCheck = new SimpleObjectWithNullCheck() { StringProperty = "A" } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleDTOWithNullCheck.StringProperty, "B"); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleObjectWithNullCheck.StringProperty, "B"); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal("B", doc.SimpleDTOWithNullCheck.StringProperty); + Assert.Equal("B", doc.SimpleObjectWithNullCheck.StringProperty); } [Fact] public void ReplaceWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { StringProperty = "A", DecimalValue = 10 @@ -944,28 +944,28 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleDTO.StringProperty, "B"); - patchDoc.Replace(o => o.SimpleDTO.DecimalValue, 12); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleObject.StringProperty, "B"); + patchDoc.Replace(o => o.SimpleObject.DecimalValue, 12); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal("B", doc.SimpleDTO.StringProperty); - Assert.Equal(12, doc.SimpleDTO.DecimalValue); + Assert.Equal("B", doc.SimpleObject.StringProperty); + Assert.Equal(12, doc.SimpleObject.DecimalValue); } [Fact] public void SerializationTests() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { StringProperty = "A", DecimalValue = 10, @@ -976,288 +976,288 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleDTO.StringProperty, "B"); - patchDoc.Replace(o => o.SimpleDTO.DecimalValue, 12); - patchDoc.Replace(o => o.SimpleDTO.DoubleValue, 12); - patchDoc.Replace(o => o.SimpleDTO.FloatValue, 12); - patchDoc.Replace(o => o.SimpleDTO.IntegerValue, 12); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleObject.StringProperty, "B"); + patchDoc.Replace(o => o.SimpleObject.DecimalValue, 12); + patchDoc.Replace(o => o.SimpleObject.DoubleValue, 12); + patchDoc.Replace(o => o.SimpleObject.FloatValue, 12); + patchDoc.Replace(o => o.SimpleObject.IntegerValue, 12); // serialize & deserialize var serialized = JsonConvert.SerializeObject(patchDoc); - var deserizalized = JsonConvert.DeserializeObject>(serialized); + var deserizalized = JsonConvert.DeserializeObject>(serialized); // Act deserizalized.ApplyTo(doc); // Assert - Assert.Equal("B", doc.SimpleDTO.StringProperty); - Assert.Equal(12, doc.SimpleDTO.DecimalValue); - Assert.Equal(12, doc.SimpleDTO.DoubleValue); - Assert.Equal(12, doc.SimpleDTO.FloatValue); - Assert.Equal(12, doc.SimpleDTO.IntegerValue); + Assert.Equal("B", doc.SimpleObject.StringProperty); + Assert.Equal(12, doc.SimpleObject.DecimalValue); + Assert.Equal(12, doc.SimpleObject.DoubleValue); + Assert.Equal(12, doc.SimpleObject.FloatValue); + Assert.Equal(12, doc.SimpleObject.IntegerValue); } [Fact] public void ReplaceInList() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5, 0); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleObject.IntegerList, 5, 0); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(new List() { 5, 2, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 5, 2, 3 }, doc.SimpleObject.IntegerList); } [Fact] public void ReplaceInListWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5, 0); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleObject.IntegerList, 5, 0); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(new List() { 5, 2, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 5, 2, 3 }, doc.SimpleObject.IntegerList); } [Fact] public void ReplaceFullList() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace>(o => o.SimpleDTO.IntegerList, new List() { 4, 5, 6 }); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleObject.IntegerList, new List() { 4, 5, 6 }); // Act patchDoc.ApplyTo(doc); // Arrange - Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleObject.IntegerList); } [Fact] public void ReplaceFullListWithSerialiation() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace>(o => o.SimpleDTO.IntegerList, new List() { 4, 5, 6 }); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleObject.IntegerList, new List() { 4, 5, 6 }); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleObject.IntegerList); } [Fact] public void ReplaceFullListFromEnumerable() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace>(o => o.SimpleDTO.IntegerList, new List() { 4, 5, 6 }); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace>(o => o.SimpleObject.IntegerList, new List() { 4, 5, 6 }); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleObject.IntegerList); } [Fact] public void ReplaceFullListFromEnumerableWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace>(o => o.SimpleDTO.IntegerList, new List() { 4, 5, 6 }); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace>(o => o.SimpleObject.IntegerList, new List() { 4, 5, 6 }); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleObject.IntegerList); } [Fact] public void ReplaceFullListWithCollection() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace>(o => o.SimpleDTO.IntegerList, new Collection() { 4, 5, 6 }); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace>(o => o.SimpleObject.IntegerList, new Collection() { 4, 5, 6 }); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleObject.IntegerList); } [Fact] public void ReplaceFullListWithCollectionWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace>(o => o.SimpleDTO.IntegerList, new Collection() { 4, 5, 6 }); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace>(o => o.SimpleObject.IntegerList, new Collection() { 4, 5, 6 }); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleObject.IntegerList); } [Fact] public void ReplaceAtEndOfList() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleObject.IntegerList, 5); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(new List() { 1, 2, 5 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 2, 5 }, doc.SimpleObject.IntegerList); } [Fact] public void ReplaceAtEndOfListWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleObject.IntegerList, 5); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(new List() { 1, 2, 5 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 2, 5 }, doc.SimpleObject.IntegerList); } [Fact] public void ReplaceInListInvalidInvalidPositionTooLarge() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5, 3); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleObject.IntegerList, 5, 3); // Act & Assert var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); @@ -1270,20 +1270,20 @@ namespace Microsoft.AspNetCore.JsonPatch public void ReplaceInListInvalidInvalidPositionTooLargeWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5, 3); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleObject.IntegerList, 5, 3); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act & Assert var exception = Assert.Throws(() => @@ -1299,19 +1299,19 @@ namespace Microsoft.AspNetCore.JsonPatch public void ReplaceInListInvalid_PositionTooLarge_LogsError() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5, 3); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleObject.IntegerList, 5, 3); - var logger = new TestErrorLogger(); + var logger = new TestErrorLogger(); patchDoc.ApplyTo(doc, logger.LogErrorMessage); @@ -1327,17 +1327,17 @@ namespace Microsoft.AspNetCore.JsonPatch public void ReplaceInListInvalidPositionTooSmall() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5, -1); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleObject.IntegerList, 5, -1); // Act & Assert var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); @@ -1350,20 +1350,20 @@ namespace Microsoft.AspNetCore.JsonPatch public void ReplaceInListInvalidPositionTooSmallWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5, -1); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleObject.IntegerList, 5, -1); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act & Assert var exception = Assert.Throws(() => { deserialized.ApplyTo(doc); }); @@ -1376,19 +1376,19 @@ namespace Microsoft.AspNetCore.JsonPatch public void ReplaceInListInvalidPositionTooSmall_LogsError() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleDTO.IntegerList, 5, -1); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleObject.IntegerList, 5, -1); - var logger = new TestErrorLogger(); + var logger = new TestErrorLogger(); patchDoc.ApplyTo(doc, logger.LogErrorMessage); @@ -1404,9 +1404,9 @@ namespace Microsoft.AspNetCore.JsonPatch public void Copy() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { StringProperty = "A", AnotherStringProperty = "B" @@ -1414,23 +1414,23 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleDTO.StringProperty, o => o.SimpleDTO.AnotherStringProperty); + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleObject.StringProperty, o => o.SimpleObject.AnotherStringProperty); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty); + Assert.Equal("A", doc.SimpleObject.AnotherStringProperty); } [Fact] public void CopyWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { StringProperty = "A", AnotherStringProperty = "B" @@ -1438,173 +1438,173 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleDTO.StringProperty, o => o.SimpleDTO.AnotherStringProperty); + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleObject.StringProperty, o => o.SimpleObject.AnotherStringProperty); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty); + Assert.Equal("A", doc.SimpleObject.AnotherStringProperty); } [Fact] public void CopyInList() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerList, 1); + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerList, 1); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(new List() { 1, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 1, 2, 3 }, doc.SimpleObject.IntegerList); } [Fact] public void CopyInListWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerList, 1); + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerList, 1); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(new List() { 1, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 1, 2, 3 }, doc.SimpleObject.IntegerList); } [Fact] public void CopyFromListToEndOfList() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerList); + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerList); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(new List() { 1, 2, 3, 1 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 2, 3, 1 }, doc.SimpleObject.IntegerList); } [Fact] public void CopyFromListToEndOfListWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerList); + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerList); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(new List() { 1, 2, 3, 1 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 2, 3, 1 }, doc.SimpleObject.IntegerList); } [Fact] public void CopyFromListToNonList() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerValue); + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerValue); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(1, doc.SimpleDTO.IntegerValue); + Assert.Equal(1, doc.SimpleObject.IntegerValue); } [Fact] public void CopyFromListToNonListWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerValue); + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerValue); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(1, doc.SimpleDTO.IntegerValue); + Assert.Equal(1, doc.SimpleObject.IntegerValue); } [Fact] public void CopyFromNonListToList() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } @@ -1612,23 +1612,23 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleDTO.IntegerValue, o => o.SimpleDTO.IntegerList, 0); + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleObject.IntegerValue, o => o.SimpleObject.IntegerList, 0); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleObject.IntegerList); } [Fact] public void CopyFromNonListToListWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } @@ -1636,25 +1636,25 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleDTO.IntegerValue, o => o.SimpleDTO.IntegerList, 0); + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleObject.IntegerValue, o => o.SimpleObject.IntegerList, 0); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleObject.IntegerList); } [Fact] public void CopyToEndOfList() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } @@ -1662,23 +1662,23 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleDTO.IntegerValue, o => o.SimpleDTO.IntegerList); + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleObject.IntegerValue, o => o.SimpleObject.IntegerList); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleObject.IntegerList); } [Fact] public void CopyToEndOfListWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } @@ -1686,31 +1686,31 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleDTO.IntegerValue, o => o.SimpleDTO.IntegerList); + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.SimpleObject.IntegerValue, o => o.SimpleObject.IntegerList); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleObject.IntegerList); } [Fact] public void Copy_DeepClonesObject() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { StringProperty = "A", AnotherStringProperty = "B" }, - InheritedDTO = new InheritedDTO() + InheritedObject = new InheritedObject() { StringProperty = "C", AnotherStringProperty = "D" @@ -1718,69 +1718,69 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.InheritedDTO, o => o.SimpleDTO); + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.InheritedObject, o => o.SimpleObject); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal("C", doc.SimpleDTO.StringProperty); - Assert.Equal("D", doc.SimpleDTO.AnotherStringProperty); - Assert.Equal("C", doc.InheritedDTO.StringProperty); - Assert.Equal("D", doc.InheritedDTO.AnotherStringProperty); - Assert.NotSame(doc.SimpleDTO.StringProperty, doc.InheritedDTO.StringProperty); + Assert.Equal("C", doc.SimpleObject.StringProperty); + Assert.Equal("D", doc.SimpleObject.AnotherStringProperty); + Assert.Equal("C", doc.InheritedObject.StringProperty); + Assert.Equal("D", doc.InheritedObject.AnotherStringProperty); + Assert.NotSame(doc.SimpleObject.StringProperty, doc.InheritedObject.StringProperty); } [Fact] public void Copy_KeepsObjectType() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO(), - InheritedDTO = new InheritedDTO() + SimpleObject = new SimpleObject(), + InheritedObject = new InheritedObject() }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.InheritedDTO, o => o.SimpleDTO); + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.InheritedObject, o => o.SimpleObject); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(typeof(InheritedDTO), doc.SimpleDTO.GetType()); + Assert.Equal(typeof(InheritedObject), doc.SimpleObject.GetType()); } [Fact] public void Copy_BreaksObjectReference() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO(), - InheritedDTO = new InheritedDTO() + SimpleObject = new SimpleObject(), + InheritedObject = new InheritedObject() }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.InheritedDTO, o => o.SimpleDTO); + var patchDoc = new JsonPatchDocument(); + patchDoc.Copy(o => o.InheritedObject, o => o.SimpleObject); // Act patchDoc.ApplyTo(doc); // Assert - Assert.NotSame(doc.SimpleDTO, doc.InheritedDTO); + Assert.NotSame(doc.SimpleObject, doc.InheritedObject); } [Fact] public void Move() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { StringProperty = "A", AnotherStringProperty = "B" @@ -1788,24 +1788,24 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleDTO.StringProperty, o => o.SimpleDTO.AnotherStringProperty); + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleObject.StringProperty, o => o.SimpleObject.AnotherStringProperty); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty); - Assert.Null(doc.SimpleDTO.StringProperty); + Assert.Equal("A", doc.SimpleObject.AnotherStringProperty); + Assert.Null(doc.SimpleObject.StringProperty); } [Fact] public void MoveWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { StringProperty = "A", AnotherStringProperty = "B" @@ -1813,150 +1813,150 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleDTO.StringProperty, o => o.SimpleDTO.AnotherStringProperty); + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleObject.StringProperty, o => o.SimpleObject.AnotherStringProperty); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty); - Assert.Null(doc.SimpleDTO.StringProperty); + Assert.Equal("A", doc.SimpleObject.AnotherStringProperty); + Assert.Null(doc.SimpleObject.StringProperty); } [Fact] public void Move_KeepsObjectReference() { // Arrange - var sDto = new SimpleDTO() + var sDto = new SimpleObject() { StringProperty = "A", AnotherStringProperty = "B" }; - var iDto = new InheritedDTO() + var iDto = new InheritedObject() { StringProperty = "C", AnotherStringProperty = "D" }; - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = sDto, - InheritedDTO = iDto + SimpleObject = sDto, + InheritedObject = iDto }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.InheritedDTO, o => o.SimpleDTO); + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.InheritedObject, o => o.SimpleObject); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal("C", doc.SimpleDTO.StringProperty); - Assert.Equal("D", doc.SimpleDTO.AnotherStringProperty); - Assert.Same(iDto, doc.SimpleDTO); - Assert.Null(doc.InheritedDTO); + Assert.Equal("C", doc.SimpleObject.StringProperty); + Assert.Equal("D", doc.SimpleObject.AnotherStringProperty); + Assert.Same(iDto, doc.SimpleObject); + Assert.Null(doc.InheritedObject); } [Fact] public void Move_KeepsObjectReferenceWithSerialization() { // Arrange - var sDto = new SimpleDTO() + var sDto = new SimpleObject() { StringProperty = "A", AnotherStringProperty = "B" }; - var iDto = new InheritedDTO() + var iDto = new InheritedObject() { StringProperty = "C", AnotherStringProperty = "D" }; - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = sDto, - InheritedDTO = iDto + SimpleObject = sDto, + InheritedObject = iDto }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.InheritedDTO, o => o.SimpleDTO); + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.InheritedObject, o => o.SimpleObject); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal("C", doc.SimpleDTO.StringProperty); - Assert.Equal("D", doc.SimpleDTO.AnotherStringProperty); - Assert.Same(iDto, doc.SimpleDTO); - Assert.Null(doc.InheritedDTO); + Assert.Equal("C", doc.SimpleObject.StringProperty); + Assert.Equal("D", doc.SimpleObject.AnotherStringProperty); + Assert.Same(iDto, doc.SimpleObject); + Assert.Null(doc.InheritedObject); } [Fact] public void MoveInList() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerList, 1); + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerList, 1); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(new List() { 2, 1, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 2, 1, 3 }, doc.SimpleObject.IntegerList); } [Fact] public void MoveInListWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerList, 1); + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerList, 1); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(new List() { 2, 1, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 2, 1, 3 }, doc.SimpleObject.IntegerList); } [Fact] public void Move_KeepsObjectReferenceInList() { // Arrange - var sDto1 = new SimpleDTO() { IntegerValue = 1 }; - var sDto2 = new SimpleDTO() { IntegerValue = 2 }; - var sDto3 = new SimpleDTO() { IntegerValue = 3 }; - var doc = new SimpleDTOWithNestedDTO() + var sDto1 = new SimpleObject() { IntegerValue = 1 }; + var sDto2 = new SimpleObject() { IntegerValue = 2 }; + var sDto3 = new SimpleObject() { IntegerValue = 3 }; + var doc = new SimpleObjectWithNestedObject() { - SimpleDTOList = new List() { + SimpleObjectList = new List() { sDto1, sDto2, sDto3 @@ -1964,30 +1964,30 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleDTOList, 0, o => o.SimpleDTOList, 1); + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleObjectList, 0, o => o.SimpleObjectList, 1); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(new List() { sDto2, sDto1, sDto3 }, doc.SimpleDTOList); - Assert.Equal(2, doc.SimpleDTOList[0].IntegerValue); - Assert.Equal(1, doc.SimpleDTOList[1].IntegerValue); - Assert.Same(sDto2, doc.SimpleDTOList[0]); - Assert.Same(sDto1, doc.SimpleDTOList[1]); + Assert.Equal(new List() { sDto2, sDto1, sDto3 }, doc.SimpleObjectList); + Assert.Equal(2, doc.SimpleObjectList[0].IntegerValue); + Assert.Equal(1, doc.SimpleObjectList[1].IntegerValue); + Assert.Same(sDto2, doc.SimpleObjectList[0]); + Assert.Same(sDto1, doc.SimpleObjectList[1]); } [Fact] public void Move_KeepsObjectReferenceInListWithSerialization() { // Arrange - var sDto1 = new SimpleDTO() { IntegerValue = 1 }; - var sDto2 = new SimpleDTO() { IntegerValue = 2 }; - var sDto3 = new SimpleDTO() { IntegerValue = 3 }; - var doc = new SimpleDTOWithNestedDTO() + var sDto1 = new SimpleObject() { IntegerValue = 1 }; + var sDto2 = new SimpleObject() { IntegerValue = 2 }; + var sDto3 = new SimpleObject() { IntegerValue = 3 }; + var doc = new SimpleObjectWithNestedObject() { - SimpleDTOList = new List() { + SimpleObjectList = new List() { sDto1, sDto2, sDto3 @@ -1995,144 +1995,144 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleDTOList, 0, o => o.SimpleDTOList, 1); + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleObjectList, 0, o => o.SimpleObjectList, 1); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(new List() { sDto2, sDto1, sDto3 }, doc.SimpleDTOList); - Assert.Equal(2, doc.SimpleDTOList[0].IntegerValue); - Assert.Equal(1, doc.SimpleDTOList[1].IntegerValue); - Assert.Same(sDto2, doc.SimpleDTOList[0]); - Assert.Same(sDto1, doc.SimpleDTOList[1]); + Assert.Equal(new List() { sDto2, sDto1, sDto3 }, doc.SimpleObjectList); + Assert.Equal(2, doc.SimpleObjectList[0].IntegerValue); + Assert.Equal(1, doc.SimpleObjectList[1].IntegerValue); + Assert.Same(sDto2, doc.SimpleObjectList[0]); + Assert.Same(sDto1, doc.SimpleObjectList[1]); } [Fact] public void MoveFromListToEndOfList() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerList); + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerList); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(new List() { 2, 3, 1 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 2, 3, 1 }, doc.SimpleObject.IntegerList); } [Fact] public void MoveFromListToEndOfListWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerList); + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerList); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(new List() { 2, 3, 1 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 2, 3, 1 }, doc.SimpleObject.IntegerList); } [Fact] public void MoveFomListToNonList() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerValue); + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerValue); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(new List() { 2, 3 }, doc.SimpleDTO.IntegerList); - Assert.Equal(1, doc.SimpleDTO.IntegerValue); + Assert.Equal(new List() { 2, 3 }, doc.SimpleObject.IntegerList); + Assert.Equal(1, doc.SimpleObject.IntegerValue); } [Fact] public void MoveFomListToNonListWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleDTO.IntegerList, 0, o => o.SimpleDTO.IntegerValue); + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerValue); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(new List() { 2, 3 }, doc.SimpleDTO.IntegerList); - Assert.Equal(1, doc.SimpleDTO.IntegerValue); + Assert.Equal(new List() { 2, 3 }, doc.SimpleObject.IntegerList); + Assert.Equal(1, doc.SimpleObject.IntegerValue); } [Fact] public void MoveFomListToNonListBetweenHierarchy() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleDTO.IntegerList, 0, o => o.IntegerValue); + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleObject.IntegerList, 0, o => o.IntegerValue); // Act patchDoc.ApplyTo(doc); // Assert - Assert.Equal(new List() { 2, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 2, 3 }, doc.SimpleObject.IntegerList); Assert.Equal(1, doc.IntegerValue); } @@ -2140,26 +2140,26 @@ namespace Microsoft.AspNetCore.JsonPatch public void MoveFomListToNonListBetweenHierarchyWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } } }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleDTO.IntegerList, 0, o => o.IntegerValue); + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleObject.IntegerList, 0, o => o.IntegerValue); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(new List() { 2, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 2, 3 }, doc.SimpleObject.IntegerList); Assert.Equal(1, doc.IntegerValue); } @@ -2167,9 +2167,9 @@ namespace Microsoft.AspNetCore.JsonPatch public void MoveFromNonListToList() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } @@ -2177,24 +2177,24 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleDTO.IntegerValue, o => o.SimpleDTO.IntegerList, 0); + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleObject.IntegerValue, o => o.SimpleObject.IntegerList, 0); // Act patchDoc.ApplyTo(doc); // Assert Assert.Equal(0, doc.IntegerValue); - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleObject.IntegerList); } [Fact] public void MoveFromNonListToListWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } @@ -2202,27 +2202,27 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleDTO.IntegerValue, o => o.SimpleDTO.IntegerList, 0); + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleObject.IntegerValue, o => o.SimpleObject.IntegerList, 0); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert Assert.Equal(0, doc.IntegerValue); - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleObject.IntegerList); } [Fact] public void MoveToEndOfList() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } @@ -2230,24 +2230,24 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleDTO.IntegerValue, o => o.SimpleDTO.IntegerList); + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleObject.IntegerValue, o => o.SimpleObject.IntegerList); // Act patchDoc.ApplyTo(doc); // Assert Assert.Equal(0, doc.IntegerValue); - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleObject.IntegerList); } [Fact] public void MoveToEndOfListWithSerialization() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } @@ -2255,18 +2255,18 @@ namespace Microsoft.AspNetCore.JsonPatch }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleDTO.IntegerValue, o => o.SimpleDTO.IntegerList); + var patchDoc = new JsonPatchDocument(); + patchDoc.Move(o => o.SimpleObject.IntegerValue, o => o.SimpleObject.IntegerList); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert Assert.Equal(0, doc.IntegerValue); - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleDTO.IntegerList); + Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleObject.IntegerList); } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs index 34a8c97b67..d35f8eb4e9 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs @@ -16,13 +16,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void AddResultsShouldReplace() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { StringProperty = "A" }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add(o => o.StringProperty, "B"); // Act @@ -36,17 +36,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void AddResultsShouldReplaceWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { StringProperty = "A" }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add(o => o.StringProperty, "B"); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -59,13 +59,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void AddToList() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add(o => o.IntegerList, 4, 0); // Act @@ -79,17 +79,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void AddToListWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add(o => o.IntegerList, 4, 0); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -102,13 +102,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void AddToIntegerIList() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerIList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add(o => o.IntegerIList, 4, 0); // Act @@ -122,17 +122,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void AddToIntegerIListWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerIList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add(o => o.IntegerIList, 4, 0); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -145,13 +145,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void AddToListInvalidPositionTooLarge() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add(o => o.IntegerList, 4, 4); // Act & Assert @@ -165,17 +165,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void AddToListInvalidPositionTooLargeWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add(o => o.IntegerList, 4, 4); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act & Assert var exception = Assert.Throws(() => { deserialized.ApplyTo(doc); }); @@ -188,16 +188,16 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void AddToListInvalidPositionTooLarge_LogsError() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add(o => o.IntegerList, 4, 4); - var logger = new TestErrorLogger(); + var logger = new TestErrorLogger(); patchDoc.ApplyTo(doc, logger.LogErrorMessage); @@ -212,13 +212,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void AddToListAtBeginning() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add(o => o.IntegerList, 4, 0); // Act @@ -232,17 +232,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void AddToListAtBeginningWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add(o => o.IntegerList, 4, 0); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -255,13 +255,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void AddToListInvalidPositionTooSmall() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add(o => o.IntegerList, 4, -1); // Act & Assert @@ -275,17 +275,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void AddToListInvalidPositionTooSmallWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add(o => o.IntegerList, 4, -1); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act & Assert var exception = Assert.Throws(() => { deserialized.ApplyTo(doc); }); @@ -298,16 +298,16 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void AddToListInvalidPositionTooSmall_LogsError() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add(o => o.IntegerList, 4, -1); - var logger = new TestErrorLogger(); + var logger = new TestErrorLogger(); patchDoc.ApplyTo(doc, logger.LogErrorMessage); @@ -321,13 +321,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void AddToListAppend() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add(o => o.IntegerList, 4); // Act @@ -341,17 +341,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void AddToListAppendWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add(o => o.IntegerList, 4); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -364,13 +364,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void Remove() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { StringProperty = "A" }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove(o => o.StringProperty); // Act @@ -384,17 +384,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void RemoveWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { StringProperty = "A" }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove(o => o.StringProperty); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -407,13 +407,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void RemoveFromList() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove(o => o.IntegerList, 2); // Act @@ -427,17 +427,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void RemoveFromListWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove(o => o.IntegerList, 2); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -450,13 +450,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void RemoveFromListInvalidPositionTooLarge() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove(o => o.IntegerList, 3); // Act & Assert @@ -470,17 +470,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void RemoveFromListInvalidPositionTooLargeWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove(o => o.IntegerList, 3); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act & Assert var exception = Assert.Throws(() => { deserialized.ApplyTo(doc); }); @@ -493,16 +493,16 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void RemoveFromListInvalidPositionTooLarge_LogsError() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove(o => o.IntegerList, 3); - var logger = new TestErrorLogger(); + var logger = new TestErrorLogger(); patchDoc.ApplyTo(doc, logger.LogErrorMessage); @@ -517,13 +517,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void RemoveFromListInvalidPositionTooSmall() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove(o => o.IntegerList, -1); // Act & Assert @@ -537,17 +537,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void RemoveFromListInvalidPositionTooSmallWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove(o => o.IntegerList, -1); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act & Assert var exception = Assert.Throws(() => { deserialized.ApplyTo(doc); }); @@ -560,16 +560,16 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void RemoveFromListInvalidPositionTooSmall_LogsError() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove(o => o.IntegerList, -1); - var logger = new TestErrorLogger(); + var logger = new TestErrorLogger(); patchDoc.ApplyTo(doc, logger.LogErrorMessage); @@ -585,13 +585,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void RemoveFromEndOfList() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove(o => o.IntegerList); // Act @@ -605,17 +605,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void RemoveFromEndOfListWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove(o => o.IntegerList); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -628,14 +628,14 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void Replace() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { StringProperty = "A", DecimalValue = 10 }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace(o => o.StringProperty, "B"); patchDoc.Replace(o => o.DecimalValue, 12); @@ -652,13 +652,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void Replace_DTOWithNullCheck() { // Arrange - var doc = new SimpleDTOWithNullCheck() + var doc = new SimpleObjectWithNullCheck() { StringProperty = "A", }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace(o => o.StringProperty, "B"); // Act @@ -672,20 +672,20 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void ReplaceWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { StringProperty = "A", DecimalValue = 10 }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace(o => o.StringProperty, "B"); patchDoc.Replace(o => o.DecimalValue, 12); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -699,7 +699,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void SerializationMustNotIncudeEnvelope() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { StringProperty = "A", DecimalValue = 10, @@ -709,7 +709,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace(o => o.StringProperty, "B"); patchDoc.Replace(o => o.DecimalValue, 12); patchDoc.Replace(o => o.DoubleValue, 12); @@ -728,7 +728,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void DeserializationMustWorkWithoutEnvelope() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { StringProperty = "A", DecimalValue = 10, @@ -738,7 +738,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace(o => o.StringProperty, "B"); patchDoc.Replace(o => o.DecimalValue, 12); patchDoc.Replace(o => o.DoubleValue, 12); @@ -749,23 +749,23 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters var serialized = JsonConvert.SerializeObject(patchDoc); // Act - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Assert - Assert.IsType>(deserialized); + Assert.IsType>(deserialized); } [Fact] public void DeserializationMustFailWithEnvelope() { // Arrange - string serialized = "{\"Operations\": [{ \"op\": \"replace\", \"path\": \"/title\", \"value\": \"New Title\"}]}"; + var serialized = "{\"Operations\": [{ \"op\": \"replace\", \"path\": \"/title\", \"value\": \"New Title\"}]}"; // Act & Assert var exception = Assert.Throws(() => { var deserialized - = JsonConvert.DeserializeObject>(serialized); + = JsonConvert.DeserializeObject>(serialized); }); Assert.Equal("The type 'JsonPatchDocument`1' was malformed and could not be parsed.", exception.Message); @@ -775,7 +775,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void SerializationTests() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { StringProperty = "A", DecimalValue = 10, @@ -785,7 +785,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace(o => o.StringProperty, "B"); patchDoc.Replace(o => o.DecimalValue, 12); patchDoc.Replace(o => o.DoubleValue, 12); @@ -794,7 +794,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters // serialize & deserialize var serialized = JsonConvert.SerializeObject(patchDoc); - var deserizalized = JsonConvert.DeserializeObject>(serialized); + var deserizalized = JsonConvert.DeserializeObject>(serialized); // Act deserizalized.ApplyTo(doc); @@ -811,19 +811,19 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void SerializeAndReplaceGuidTest() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { GuidValue = Guid.NewGuid() }; var newGuid = Guid.NewGuid(); // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace(o => o.GuidValue, newGuid); // serialize & deserialize var serialized = JsonConvert.SerializeObject(patchDoc); - var deserizalized = JsonConvert.DeserializeObject>(serialized); + var deserizalized = JsonConvert.DeserializeObject>(serialized); // Act deserizalized.ApplyTo(doc); @@ -836,48 +836,48 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void SerializeAndReplaceNestedObjectTest() { // Arrange - var doc = new SimpleDTOWithNestedDTO() + var doc = new SimpleObjectWithNestedObject() { - SimpleDTO = new SimpleDTO() + SimpleObject = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } } }; - var newDTO = new SimpleDTO() + var newDTO = new SimpleObject() { DoubleValue = 1 }; // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleDTO, newDTO); + var patchDoc = new JsonPatchDocument(); + patchDoc.Replace(o => o.SimpleObject, newDTO); // serialize & deserialize var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); // Assert - Assert.Equal(1, doc.SimpleDTO.DoubleValue); - Assert.Equal(0, doc.SimpleDTO.IntegerValue); - Assert.Null(doc.SimpleDTO.IntegerList); + Assert.Equal(1, doc.SimpleObject.DoubleValue); + Assert.Equal(0, doc.SimpleObject.IntegerValue); + Assert.Null(doc.SimpleObject.IntegerList); } [Fact] public void ReplaceInList() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace(o => o.IntegerList, 5, 0); // Act @@ -891,17 +891,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void ReplaceInListWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace(o => o.IntegerList, 5, 0); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -914,13 +914,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void ReplaceFullList() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace>(o => o.IntegerList, new List() { 4, 5, 6 }); // Act @@ -934,17 +934,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void ReplaceFullListWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace>(o => o.IntegerList, new List() { 4, 5, 6 }); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -957,13 +957,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void ReplaceFullListFromEnumerable() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace>(o => o.IntegerList, new List() { 4, 5, 6 }); // Act @@ -977,17 +977,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void ReplaceFullListFromEnumerableWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace>(o => o.IntegerList, new List() { 4, 5, 6 }); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -1000,13 +1000,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void ReplaceFullListWithCollection() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace>(o => o.IntegerList, new Collection() { 4, 5, 6 }); // Act @@ -1020,17 +1020,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void ReplaceFullListWithCollectionWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace>(o => o.IntegerList, new Collection() { 4, 5, 6 }); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -1043,13 +1043,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void ReplaceAtEndOfList() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace(o => o.IntegerList, 5); // Act @@ -1063,16 +1063,16 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void ReplaceAtEndOfListWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace(o => o.IntegerList, 5); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -1085,13 +1085,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void ReplaceInListInvalidInvalidPositionTooLarge() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace(o => o.IntegerList, 5, 3); // Act & Assert @@ -1108,16 +1108,16 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void ReplaceInListInvalidInvalidPositionTooLargeWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace(o => o.IntegerList, 5, 3); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act & Assert var exception = Assert.Throws(() => @@ -1133,13 +1133,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void ReplaceInListInvalidPositionTooSmall() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace(o => o.IntegerList, 5, -1); // Act & Assert @@ -1156,17 +1156,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void ReplaceInListInvalidPositionTooSmallWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Replace(o => o.IntegerList, 5, -1); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act & Assert var exception = Assert.Throws(() => @@ -1182,14 +1182,14 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void Copy() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { StringProperty = "A", AnotherStringProperty = "B" }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy(o => o.StringProperty, o => o.AnotherStringProperty); // Act @@ -1203,17 +1203,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void CopyWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { StringProperty = "A", AnotherStringProperty = "B" }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy(o => o.StringProperty, o => o.AnotherStringProperty); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -1226,13 +1226,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void CopyInList() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy(o => o.IntegerList, 0, o => o.IntegerList, 1); // Act @@ -1246,17 +1246,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void CopyInListWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy(o => o.IntegerList, 0, o => o.IntegerList, 1); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -1269,13 +1269,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void CopyFromListToEndOfList() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy(o => o.IntegerList, 0, o => o.IntegerList); // Act @@ -1289,17 +1289,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void CopyFromListToEndOfListWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy(o => o.IntegerList, 0, o => o.IntegerList); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -1312,13 +1312,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void CopyFromListToNonList() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy(o => o.IntegerList, 0, o => o.IntegerValue); // Act @@ -1332,17 +1332,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void CopyFromListToNonListWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy(o => o.IntegerList, 0, o => o.IntegerValue); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -1355,14 +1355,14 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void CopyFromNonListToList() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy(o => o.IntegerValue, o => o.IntegerList, 0); // Act @@ -1376,18 +1376,18 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void CopyFromNonListToListWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy(o => o.IntegerValue, o => o.IntegerList, 0); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -1400,14 +1400,14 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void CopyToEndOfList() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy(o => o.IntegerValue, o => o.IntegerList); // Act @@ -1421,18 +1421,18 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void CopyToEndOfListWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Copy(o => o.IntegerValue, o => o.IntegerList); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -1445,14 +1445,14 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void Move() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { StringProperty = "A", AnotherStringProperty = "B" }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move(o => o.StringProperty, o => o.AnotherStringProperty); // Act @@ -1467,18 +1467,18 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void MoveWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { StringProperty = "A", AnotherStringProperty = "B" }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move(o => o.StringProperty, o => o.AnotherStringProperty); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -1492,13 +1492,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void MoveInList() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move(o => o.IntegerList, 0, o => o.IntegerList, 1); // Act @@ -1512,17 +1512,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void MoveInListWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move(o => o.IntegerList, 0, o => o.IntegerList, 1); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -1535,13 +1535,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void MoveFromListToEndOfList() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move(o => o.IntegerList, 0, o => o.IntegerList); // Act @@ -1555,17 +1555,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void MoveFromListToEndOfListWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move(o => o.IntegerList, 0, o => o.IntegerList); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -1578,13 +1578,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void MoveFomListToNonList() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move(o => o.IntegerList, 0, o => o.IntegerValue); // Act @@ -1599,17 +1599,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void MoveFomListToNonListWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move(o => o.IntegerList, 0, o => o.IntegerValue); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -1623,14 +1623,14 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void MoveFromNonListToList() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move(o => o.IntegerValue, o => o.IntegerList, 0); // Act @@ -1645,18 +1645,18 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void MoveFromNonListToListWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move(o => o.IntegerValue, o => o.IntegerList, 0); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -1670,14 +1670,14 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void MoveToEndOfList() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move(o => o.IntegerValue, o => o.IntegerList); // Act @@ -1692,18 +1692,18 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void MoveToEndOfListWithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerValue = 5, IntegerList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Move(o => o.IntegerValue, o => o.IntegerList); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); @@ -1950,13 +1950,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void AddMember_OnPOCO_WithNullPropertyValue_ShouldAddPropertyValue() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { StringProperty = null }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add(o => o.StringProperty, "B"); // Act @@ -2175,13 +2175,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void AddElement_ToList_OnPOCO_ShouldAddValue_AtSuppliedPosition() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { IntegerIList = new List() { 1, 2, 3 } }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Add(o => o.IntegerIList, 4, 0); // Act @@ -2193,7 +2193,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters class Class3 { - public SimpleDTO SimpleDTOProperty { get; set; } = new SimpleDTO(); + public SimpleObject SimpleObjectProperty { get; set; } = new SimpleObject(); } [Fact] @@ -2202,19 +2202,19 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters // Arrange var model = new Class3() { - SimpleDTOProperty = new SimpleDTO() + SimpleObjectProperty = new SimpleObject() { IntegerIList = new List() { 1, 2, 3 } } }; var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleDTOProperty.IntegerIList, value: 4, position: 0); + patchDoc.Add(o => o.SimpleObjectProperty.IntegerIList, value: 4, position: 0); // Act patchDoc.ApplyTo(model); // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, model.SimpleDTOProperty.IntegerIList); + Assert.Equal(new List() { 4, 1, 2, 3 }, model.SimpleObjectProperty.IntegerIList); } [Fact] @@ -2223,13 +2223,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters // Arrange var model = new Class3() { - SimpleDTOProperty = new SimpleDTO() + SimpleObjectProperty = new SimpleObject() { IntegerIList = new List() { 1, 2, 3 } } }; var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleDTOProperty.IntegerIList, value: 4, position: 0); + patchDoc.Add(o => o.SimpleObjectProperty.IntegerIList, value: 4, position: 0); var serialized = JsonConvert.SerializeObject(patchDoc); var deserialized = JsonConvert.DeserializeObject>(serialized); @@ -2237,7 +2237,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters deserialized.ApplyTo(model); // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, model.SimpleDTOProperty.IntegerIList); + Assert.Equal(new List() { 4, 1, 2, 3 }, model.SimpleObjectProperty.IntegerIList); } class Class4 @@ -2267,17 +2267,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters public void Remove_OnNonReferenceType_POCOProperty_ShouldSetDefaultValue_WithSerialization() { // Arrange - var doc = new SimpleDTO() + var doc = new SimpleObject() { StringProperty = "A" }; // create patch - var patchDoc = new JsonPatchDocument(); + var patchDoc = new JsonPatchDocument(); patchDoc.Remove(o => o.StringProperty); var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); + var deserialized = JsonConvert.DeserializeObject>(serialized); // Act deserialized.ApplyTo(doc); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs index 391b5ebe2c..5eddac8685 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs @@ -46,11 +46,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { // Arrange var visitor = new ObjectVisitor(new ParsedPath(path), new DefaultContractResolver()); - IAdapter adapter = null; - string message = null; // Act - var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + var visitStatus = visitor.TryVisit(ref targetObject, out var adapter, out var message); // Assert Assert.True(visitStatus); @@ -81,11 +79,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { // Arrange var visitor = new ObjectVisitor(new ParsedPath(path), new DefaultContractResolver()); - IAdapter adapter = null; - string message = null; // Act - var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + var visitStatus = visitor.TryVisit(ref targetObject, out var adapter, out var message); // Assert Assert.True(visitStatus); @@ -112,11 +108,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { // Arrange var visitor = new ObjectVisitor(new ParsedPath(path), new DefaultContractResolver()); - IAdapter adapter = null; - string message = null; // Act - var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + var visitStatus = visitor.TryVisit(ref targetObject, out var adapter, out var message); // Assert Assert.True(visitStatus); @@ -146,11 +140,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { // Arrange var visitor = new ObjectVisitor(new ParsedPath(path), new DefaultContractResolver()); - IAdapter adapter = null; - string message = null; // Act - var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + var visitStatus = visitor.TryVisit(ref targetObject, out var adapter, out var message); // Assert Assert.True(visitStatus); @@ -168,11 +160,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var visitor = new ObjectVisitor(new ParsedPath($"/Customers/{position}/States/-"), new DefaultContractResolver()); var automobileDepartment = new Class1Nested(); object targetObject = automobileDepartment; - IAdapter adapter = null; - string message = null; // Act - var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + var visitStatus = visitor.TryVisit(ref targetObject, out var adapter, out var message); // Assert Assert.False(visitStatus); @@ -190,11 +180,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var visitor = new ObjectVisitor(new ParsedPath($"/Customers/{position}/States/-"), new DefaultContractResolver()); var automobileDepartment = new Class1Nested(); object targetObject = automobileDepartment; - IAdapter adapter = null; - string message = null; // Act - var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + var visitStatus = visitor.TryVisit(ref targetObject, out var adapter, out var message); // Assert Assert.False(visitStatus); @@ -211,16 +199,30 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var visitor = new ObjectVisitor(new ParsedPath($"/NonExisting"), new DefaultContractResolver()); var model = new Class1(); object targetObject = model; - IAdapter adapter = null; - string message = null; // Act - var visitStatus = visitor.TryVisit(ref targetObject, out adapter, out message); + var visitStatus = visitor.TryVisit(ref targetObject, out var adapter, out var message); // Assert Assert.True(visitStatus); Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); Assert.IsType(adapter); } + + [Fact] + public void Visit_NullTarget_ReturnsNullAdapter() + { + // Arrange + var visitor = new ObjectVisitor(new ParsedPath("test"), new DefaultContractResolver()); + + // Act + object target = null; + var visitStatus = visitor.TryVisit(ref target, out var adapter, out var message); + + // Assert + Assert.False(visitStatus); + Assert.Null(adapter); + Assert.Null(message); + } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTO.cs deleted file mode 100644 index de089eb25f..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTO.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; - -namespace Microsoft.AspNetCore.JsonPatch -{ - public class SimpleDTOWithNestedDTO - { - public int IntegerValue { get; set; } - - public NestedDTO NestedDTO { get; set; } - - public SimpleDTO SimpleDTO { get; set; } - - public InheritedDTO InheritedDTO { get; set; } - - public List SimpleDTOList { get; set; } - - public IList SimpleDTOIList { get; set; } - - public SimpleDTOWithNestedDTO() - { - this.NestedDTO = new NestedDTO(); - this.SimpleDTO = new SimpleDTO(); - this.InheritedDTO = new InheritedDTO(); - this.SimpleDTOList = new List(); - } - } -} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTOWithNullCheck.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTOWithNullCheck.cs deleted file mode 100644 index 308f23b470..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNestedDTOWithNullCheck.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.JsonPatch -{ - public class SimpleDTOWithNestedDTOWithNullCheck - { - public SimpleDTOWithNullCheck SimpleDTOWithNullCheck { get; set; } - - public SimpleDTOWithNestedDTOWithNullCheck() - { - SimpleDTOWithNullCheck = new SimpleDTOWithNullCheck(); - } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTO.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObject.cs similarity index 95% rename from test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTO.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObject.cs index 6dc1f173de..28a9570c2b 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTO.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObject.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; namespace Microsoft.AspNetCore.JsonPatch { - public class SimpleDTO + public class SimpleObject { public List IntegerList { get; set; } public IList IntegerIList { get; set; } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNestedObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNestedObject.cs new file mode 100644 index 0000000000..4d7c0e2bd8 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNestedObject.cs @@ -0,0 +1,30 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; + +namespace Microsoft.AspNetCore.JsonPatch +{ + public class SimpleObjectWithNestedObject + { + public int IntegerValue { get; set; } + + public NestedObject NestedObject { get; set; } + + public SimpleObject SimpleObject { get; set; } + + public InheritedObject InheritedObject { get; set; } + + public List SimpleObjectList { get; set; } + + public IList SimpleObjectIList { get; set; } + + public SimpleObjectWithNestedObject() + { + NestedObject = new NestedObject(); + SimpleObject = new SimpleObject(); + InheritedObject = new InheritedObject(); + SimpleObjectList = new List(); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNestedObjectWithNullCheck.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNestedObjectWithNullCheck.cs new file mode 100644 index 0000000000..f2423700d8 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNestedObjectWithNullCheck.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.AspNetCore.JsonPatch +{ + public class SimpleObjectWithNestedObjectWithNullCheck + { + public SimpleObjectWithNullCheck SimpleObjectWithNullCheck { get; set; } + + public SimpleObjectWithNestedObjectWithNullCheck() + { + SimpleObjectWithNullCheck = new SimpleObjectWithNullCheck(); + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNullCheck.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNullCheck.cs similarity index 93% rename from test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNullCheck.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNullCheck.cs index d2a5fe51a4..83338c5a23 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleDTOWithNullCheck.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNullCheck.cs @@ -5,7 +5,7 @@ using System; namespace Microsoft.AspNetCore.JsonPatch { - public class SimpleDTOWithNullCheck + public class SimpleObjectWithNullCheck { private string stringProperty; From 29fd1b3b33972bc452e043309c901620ef519894 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 25 Aug 2017 09:13:43 -0700 Subject: [PATCH 0581/1029] Update README to show 2.0.0 as the latest packages [ci skip] --- README.md | 6 +++--- src/Microsoft.DotNet.Watcher.Tools/README.md | 2 +- src/Microsoft.Extensions.Caching.SqlConfig.Tools/README.md | 2 +- src/Microsoft.Extensions.SecretManager.Tools/README.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 1a54694858..c007157a78 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,9 @@ Install tools by editing your \*.csproj file and adding a `DotNetCliToolReferenc ```xml - - - + + + ``` diff --git a/src/Microsoft.DotNet.Watcher.Tools/README.md b/src/Microsoft.DotNet.Watcher.Tools/README.md index 32ecfdcc2a..dafbcde2e3 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/README.md +++ b/src/Microsoft.DotNet.Watcher.Tools/README.md @@ -8,7 +8,7 @@ Install `Microsoft.DotNet.Watcher.Tools` as a `DotNetCliToolReference` to your p ```xml - + ``` diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/README.md b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/README.md index ec0c35973a..dae4ad333e 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/README.md +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/README.md @@ -9,7 +9,7 @@ Install `Microsoft.Extensions.Caching.SqlConfig.Tools` as a `DotNetCliToolRefere ```xml - + ``` diff --git a/src/Microsoft.Extensions.SecretManager.Tools/README.md b/src/Microsoft.Extensions.SecretManager.Tools/README.md index a933ba8c30..f23371dc30 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/README.md +++ b/src/Microsoft.Extensions.SecretManager.Tools/README.md @@ -9,7 +9,7 @@ Install `Microsoft.Extensions.SecretManager.Tools` as a `DotNetCliToolReference` ```xml - + ``` From b0b8d6ded3b0e2e7df117908f269a748aadaedbd Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 25 Aug 2017 09:17:38 -0700 Subject: [PATCH 0582/1029] Update test apps to netcoreapp2.0 (#339) --- build/repo.props | 5 +++++ .../dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj | 2 +- .../WatchJavascriptFiles/WatchJavascriptFiles.csproj | 2 +- samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj | 2 +- samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj | 2 +- samples/dotnet-watch/WatchMultipleProjects/watch.proj | 2 +- .../TestProjects/AppWithDeps/AppWithDeps.csproj | 2 +- .../TestProjects/GlobbingApp/GlobbingApp.csproj | 4 ++-- .../TestProjects/NoDepsApp/NoDepsApp.csproj | 4 ++-- .../UserSecretsTestFixture.cs | 4 ++-- 10 files changed, 17 insertions(+), 12 deletions(-) create mode 100644 build/repo.props diff --git a/build/repo.props b/build/repo.props new file mode 100644 index 0000000000..b123ee35e1 --- /dev/null +++ b/build/repo.props @@ -0,0 +1,5 @@ + + + + + diff --git a/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj b/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj index 80e25acb9c..1a5ab09de4 100644 --- a/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj +++ b/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj @@ -1,6 +1,6 @@ - netcoreapp1.1 + netcoreapp2.0 diff --git a/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj b/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj index 4ff79540da..3b2818d532 100755 --- a/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj +++ b/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj @@ -1,7 +1,7 @@ - netcoreapp1.1 + netcoreapp2.0 diff --git a/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj b/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj index 7c8da8f68a..694a96f3f9 100755 --- a/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj +++ b/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj @@ -1,7 +1,7 @@ - netcoreapp1.1 + netcoreapp2.0 diff --git a/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj b/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj index 4b6806ff93..0bc2f3e71b 100755 --- a/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj +++ b/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj @@ -1,7 +1,7 @@ - netcoreapp1.1 + netcoreapp2.0 diff --git a/samples/dotnet-watch/WatchMultipleProjects/watch.proj b/samples/dotnet-watch/WatchMultipleProjects/watch.proj index fd05a8a4e9..c66bcda4c7 100644 --- a/samples/dotnet-watch/WatchMultipleProjects/watch.proj +++ b/samples/dotnet-watch/WatchMultipleProjects/watch.proj @@ -1,6 +1,6 @@ - netcoreapp1.1 + netcoreapp2.0 diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj index eced22cfbb..3a4f75ddc6 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj @@ -1,7 +1,7 @@ - netcoreapp1.1 + netcoreapp2.0 exe diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj index fa5c47e125..d18211405e 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj @@ -1,7 +1,7 @@  - netcoreapp1.0 + netcoreapp2.0 exe false @@ -10,4 +10,4 @@ - \ No newline at end of file + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj index 80621241e8..161a1c9290 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj @@ -1,8 +1,8 @@  - netcoreapp1.0 + netcoreapp2.0 exe - \ No newline at end of file + diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs index acc027e840..36a9e524ae 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs @@ -35,7 +35,7 @@ namespace Microsoft.Extensions.Configuration.UserSecrets.Tests private const string ProjectTemplate = @" Exe - netcoreapp1.0 + netcoreapp2.0 {0} false @@ -94,4 +94,4 @@ namespace Microsoft.Extensions.Configuration.UserSecrets.Tests } } } -} \ No newline at end of file +} From 97b9ff3b33d0b282b1bc3b1bba6c9646d237a6f6 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 25 Aug 2017 16:34:50 -0700 Subject: [PATCH 0583/1029] Use PackageLineup to manage PackageReference versions --- Directory.Build.props | 1 - Directory.Build.targets | 14 +++++++++++++- NuGet.config | 1 - build/dependencies.props | 13 ------------- build/repo.props | 2 ++ src/Directory.Build.props | 4 ++-- ...ft.AspNetCore.CertificateGeneration.Task.csproj | 2 +- .../Microsoft.DotNet.Watcher.Tools.csproj | 4 ++-- ...osoft.Extensions.Caching.SqlConfig.Tools.csproj | 4 ++-- ...Microsoft.Extensions.SecretManager.Tools.csproj | 4 ++-- test/Directory.Build.props | 12 ++++++------ ...NetCore.CertificateGeneration.Task.Tests.csproj | 4 ++++ ...oft.DotNet.Watcher.Tools.FunctionalTests.csproj | 4 ++-- .../AssertEx.cs | 10 +++++++++- .../Microsoft.DotNet.Watcher.Tools.Tests.csproj | 4 ---- testWorkDir/Directory.Build.props | 3 +++ testWorkDir/Directory.Build.targets | 3 +++ 17 files changed, 51 insertions(+), 38 deletions(-) delete mode 100644 build/dependencies.props create mode 100644 testWorkDir/Directory.Build.props create mode 100644 testWorkDir/Directory.Build.targets diff --git a/Directory.Build.props b/Directory.Build.props index 267a97877a..bff80fce71 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,4 @@ - diff --git a/Directory.Build.targets b/Directory.Build.targets index 8c119d5413..bc118fd907 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,2 +1,14 @@ - + + + + <_BootstrapperFile Condition=" $([MSBuild]::IsOSUnixLike()) ">build.sh + <_BootstrapperFile Condition="! $([MSBuild]::IsOSUnixLike()) ">build.cmd + <_BootstrapperError> + Package references have not been pinned. Run './$(_BootstrapperFile) /t:Pin'. + Also, you can run './$(_BootstrapperFile) /t:Restore' which will pin *and* restore packages. '$(_BootstrapperFile)' can be found in '$(MSBuildThisFileDirectory)'. + + + + + diff --git a/NuGet.config b/NuGet.config index 4e8a1f6de1..20060c934e 100644 --- a/NuGet.config +++ b/NuGet.config @@ -3,7 +3,6 @@ - diff --git a/build/dependencies.props b/build/dependencies.props deleted file mode 100644 index 9946d7ccab..0000000000 --- a/build/dependencies.props +++ /dev/null @@ -1,13 +0,0 @@ - - - 2.1.0-* - 4.4.0-* - 2.1.1-* - 15.3.409 - 2.0.0-* - 2.0.0-* - 15.3.0 - 2.3.0-beta4-build3742 - 0.6.1 - - diff --git a/build/repo.props b/build/repo.props index b123ee35e1..a48caedc22 100644 --- a/build/repo.props +++ b/build/repo.props @@ -1,5 +1,7 @@ + + diff --git a/src/Directory.Build.props b/src/Directory.Build.props index e150035ea9..9d9a3de33a 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,7 +1,7 @@ - + - + diff --git a/src/Microsoft.AspNetCore.CertificateGeneration.Task/Microsoft.AspNetCore.CertificateGeneration.Task.csproj b/src/Microsoft.AspNetCore.CertificateGeneration.Task/Microsoft.AspNetCore.CertificateGeneration.Task.csproj index 33922b9ab1..5c1dc7f13d 100644 --- a/src/Microsoft.AspNetCore.CertificateGeneration.Task/Microsoft.AspNetCore.CertificateGeneration.Task.csproj +++ b/src/Microsoft.AspNetCore.CertificateGeneration.Task/Microsoft.AspNetCore.CertificateGeneration.Task.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj index f8860e118f..6315f6e6b0 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj @@ -19,8 +19,8 @@ - - + + diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj index 62243363fa..61f55ddb17 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj @@ -16,8 +16,8 @@ - - + + diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj index 3dc5343a79..aaf954865a 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj @@ -18,8 +18,8 @@ - - + + diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 607b54f498..82ba457f18 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -1,11 +1,11 @@ - + - - - - - + + + + + diff --git a/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj b/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj index 41303778f3..a09751f552 100644 --- a/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj +++ b/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj @@ -8,4 +8,8 @@ + + + + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj index c00a30bc00..07cb79b4c3 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj @@ -19,8 +19,8 @@ - - + + diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs index 58e0f06ebd..0ffba97152 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using Xunit; +using Xunit.Sdk; namespace Microsoft.DotNet.Watcher.Tools.Tests { @@ -21,7 +22,14 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests { Func normalize = p => p.Replace('\\', '/'); var expected = new HashSet(expectedFiles.Select(normalize)); - Assert.True(expected.SetEquals(actualFiles.Where(p => !string.IsNullOrEmpty(p)).Select(normalize)), "File sets should be equal"); + var actual = new HashSet(actualFiles.Where(p => !string.IsNullOrEmpty(p)).Select(normalize)); + if (!expected.SetEquals(actual)) + { + throw new AssertActualExpectedException( + expected: string.Join("\n", expected), + actual: string.Join("\n", actual), + userMessage: "File sets should be equal"); + } } } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj index 14920c0f1e..1bc4dc44ae 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj @@ -15,8 +15,4 @@ - - - - diff --git a/testWorkDir/Directory.Build.props b/testWorkDir/Directory.Build.props new file mode 100644 index 0000000000..b959507df8 --- /dev/null +++ b/testWorkDir/Directory.Build.props @@ -0,0 +1,3 @@ + + + diff --git a/testWorkDir/Directory.Build.targets b/testWorkDir/Directory.Build.targets new file mode 100644 index 0000000000..b959507df8 --- /dev/null +++ b/testWorkDir/Directory.Build.targets @@ -0,0 +1,3 @@ + + + From 51781762195bcc463d837d5c8914f218a6d43659 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 29 Aug 2017 09:41:12 -0700 Subject: [PATCH 0584/1029] Use Directory.Build.props/targets --- appveyor.yml => .appveyor.yml | 0 build/common.props => Directory.Build.props | 8 ++++---- Directory.Build.targets | 2 ++ .../Microsoft.AspNetCore.Html.Abstractions.csproj | 2 -- .../Microsoft.Extensions.WebEncoders.csproj | 2 -- test/Directory.Build.props | 10 ++++++++++ .../Microsoft.AspNetCore.Html.Abstractions.Test.csproj | 9 --------- .../Microsoft.Extensions.WebEncoders.Tests.csproj | 5 ----- 8 files changed, 16 insertions(+), 22 deletions(-) rename appveyor.yml => .appveyor.yml (100%) rename build/common.props => Directory.Build.props (75%) create mode 100644 Directory.Build.targets create mode 100644 test/Directory.Build.props diff --git a/appveyor.yml b/.appveyor.yml similarity index 100% rename from appveyor.yml rename to .appveyor.yml diff --git a/build/common.props b/Directory.Build.props similarity index 75% rename from build/common.props rename to Directory.Build.props index c03e5c1314..620aa5b381 100644 --- a/build/common.props +++ b/Directory.Build.props @@ -1,11 +1,11 @@ - - - + + + https://github.com/aspnet/HtmlAbstractions git - $(MSBuildThisFileDirectory)Key.snk + $(MSBuildThisFileDirectory)build\Key.snk true true $(VersionSuffix)-$(BuildNumber) diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 0000000000..f75adf7e4d --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,2 @@ + + diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj b/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj index c26d590912..d6d301320f 100755 --- a/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj +++ b/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj @@ -1,7 +1,5 @@  - - Microsoft ASP.NET Core ASP.NET Core HTML abstractions used for building HTML content. diff --git a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj index de62d482f9..04359f96f5 100755 --- a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj +++ b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj @@ -1,7 +1,5 @@  - - Microsoft .NET Extensions Contains registration and configuration APIs to add the core framework encoders to a dependency injection container. diff --git a/test/Directory.Build.props b/test/Directory.Build.props new file mode 100644 index 0000000000..98d33955fd --- /dev/null +++ b/test/Directory.Build.props @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj index 5030f90ad5..f899e1a699 100755 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj @@ -1,7 +1,5 @@  - - netcoreapp2.0;net461 netcoreapp2.0 @@ -12,11 +10,4 @@ - - - - - - - diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj index 19406979f2..0236c3e9af 100755 --- a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj +++ b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj @@ -1,7 +1,5 @@  - - netcoreapp2.0;net461 netcoreapp2.0 @@ -13,9 +11,6 @@ - - - From 11377e08f6ceff699aa2d64a568bb81bc0d48f20 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 29 Aug 2017 09:42:24 -0700 Subject: [PATCH 0585/1029] Use PackageLineup to manage PackageReference versions --- Directory.Build.props | 3 +-- Directory.Build.targets | 14 +++++++++++++- NuGet.config | 1 - build/dependencies.props | 12 ------------ build/repo.props | 6 ++++++ .../Microsoft.AspNetCore.Html.Abstractions.csproj | 2 +- .../Microsoft.Extensions.WebEncoders.csproj | 6 +++--- test/Directory.Build.props | 8 ++++---- .../Microsoft.Extensions.WebEncoders.Tests.csproj | 2 +- 9 files changed, 29 insertions(+), 25 deletions(-) delete mode 100644 build/dependencies.props create mode 100644 build/repo.props diff --git a/Directory.Build.props b/Directory.Build.props index 620aa5b381..74b2f8246d 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,4 @@  - @@ -13,7 +12,7 @@ - + diff --git a/Directory.Build.targets b/Directory.Build.targets index f75adf7e4d..bc118fd907 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,2 +1,14 @@ - + + + + <_BootstrapperFile Condition=" $([MSBuild]::IsOSUnixLike()) ">build.sh + <_BootstrapperFile Condition="! $([MSBuild]::IsOSUnixLike()) ">build.cmd + <_BootstrapperError> + Package references have not been pinned. Run './$(_BootstrapperFile) /t:Pin'. + Also, you can run './$(_BootstrapperFile) /t:Restore' which will pin *and* restore packages. '$(_BootstrapperFile)' can be found in '$(MSBuildThisFileDirectory)'. + + + + + diff --git a/NuGet.config b/NuGet.config index 4e8a1f6de1..20060c934e 100644 --- a/NuGet.config +++ b/NuGet.config @@ -3,7 +3,6 @@ - diff --git a/build/dependencies.props b/build/dependencies.props deleted file mode 100644 index 1235e00530..0000000000 --- a/build/dependencies.props +++ /dev/null @@ -1,12 +0,0 @@ - - - 2.1.0-* - 4.4.0-* - 2.1.1-* - 2.0.0-* - 2.0.0-* - 2.0.0-* - 15.3.0 - 2.3.0-beta4-build3742 - - diff --git a/build/repo.props b/build/repo.props new file mode 100644 index 0000000000..13fe1c296a --- /dev/null +++ b/build/repo.props @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj b/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj index d6d301320f..79e5ea01a5 100755 --- a/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj +++ b/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj @@ -12,7 +12,7 @@ Microsoft.AspNetCore.Html.IHtmlContent - + diff --git a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj index 04359f96f5..cd0c144633 100755 --- a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj +++ b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj @@ -11,9 +11,9 @@ - - - + + + diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 98d33955fd..a728ed268e 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -2,9 +2,9 @@ - - - - + + + + diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj index 0236c3e9af..c019c8b97e 100755 --- a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj +++ b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj @@ -10,7 +10,7 @@ - + From 0f51c56c3fa120edeeaec51629117338c6265fd3 Mon Sep 17 00:00:00 2001 From: Jass Bagga Date: Tue, 5 Sep 2017 16:07:25 -0700 Subject: [PATCH 0586/1029] Combine ExpandoObjectAdapter and DictionaryAdapter (#106) Use JsonDictionaryContract in the DictionaryAdapter and combine with ExpandoObjectAdapter --- .../Internal/DictionaryAdapter.cs | 111 ------------ ...ectAdapter.cs => DictionaryAdapterOfTU.cs} | 115 ++++++++---- .../Internal/ObjectVisitor.cs | 27 +-- .../JsonPatchDocumentOfT.cs | 14 +- .../Properties/Resources.Designer.cs | 14 ++ .../Resources.resx | 3 + .../DictionaryAdapterTest.cs | 171 +++++++++++++++--- .../Dynamic/ReplaceOperationTests.cs | 60 ++---- .../ObjectVisitorTest.cs | 8 +- 9 files changed, 273 insertions(+), 250 deletions(-) delete mode 100644 src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapter.cs rename src/Microsoft.AspNetCore.JsonPatch/Internal/{ExpandoObjectAdapter.cs => DictionaryAdapterOfTU.cs} (52%) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapter.cs deleted file mode 100644 index 4c7651e475..0000000000 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapter.cs +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections; -using Newtonsoft.Json.Serialization; - -namespace Microsoft.AspNetCore.JsonPatch.Internal -{ - public class DictionaryAdapter : IAdapter - { - public bool TryAdd( - object target, - string segment, - IContractResolver contractResolver, - object value, - out string errorMessage) - { - var dictionary = (IDictionary)target; - - // As per JsonPatch spec, if a key already exists, adding should replace the existing value - dictionary[segment] = value; - - errorMessage = null; - return true; - } - - public bool TryGet( - object target, - string segment, - IContractResolver contractResolver, - out object value, - out string errorMessage) - { - var dictionary = (IDictionary)target; - - value = dictionary[segment]; - errorMessage = null; - return true; - } - - public bool TryRemove( - object target, - string segment, - IContractResolver contractResolver, - out string errorMessage) - { - var dictionary = (IDictionary)target; - - // As per JsonPatch spec, the target location must exist for remove to be successful - if (!dictionary.Contains(segment)) - { - errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); - return false; - } - - dictionary.Remove(segment); - errorMessage = null; - return true; - } - - public bool TryReplace( - object target, - string segment, - IContractResolver contractResolver, - object value, - out string errorMessage) - { - var dictionary = (IDictionary)target; - - // As per JsonPatch spec, the target location must exist for remove to be successful - if (!dictionary.Contains(segment)) - { - errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); - return false; - } - - dictionary[segment] = value; - errorMessage = null; - return true; - } - - public bool TryTraverse( - object target, - string segment, - IContractResolver contractResolver, - out object nextTarget, - out string errorMessage) - { - var dictionary = target as IDictionary; - if (dictionary == null) - { - nextTarget = null; - errorMessage = null; - return false; - } - - if (dictionary.Contains(segment)) - { - nextTarget = dictionary[segment]; - errorMessage = null; - return true; - } - else - { - nextTarget = null; - errorMessage = null; - return false; - } - } - } -} diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ExpandoObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapterOfTU.cs similarity index 52% rename from src/Microsoft.AspNetCore.JsonPatch/Internal/ExpandoObjectAdapter.cs rename to src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapterOfTU.cs index c35d1b702c..67fd33e231 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/ExpandoObjectAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapterOfTU.cs @@ -2,12 +2,11 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; -using System.Dynamic; using Newtonsoft.Json.Serialization; namespace Microsoft.AspNetCore.JsonPatch.Internal { - public class ExpandoObjectAdapter : IAdapter + public class DictionaryAdapter : IAdapter { public bool TryAdd( object target, @@ -18,11 +17,20 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType()); var key = contract.DictionaryKeyResolver(segment); - var dictionary = (IDictionary)target; + var dictionary = (IDictionary)target; // As per JsonPatch spec, if a key already exists, adding should replace the existing value - dictionary[key] = ConvertValue(dictionary, key, value); + if (!TryConvertKey(key, out var convertedKey, out errorMessage)) + { + return false; + } + if (!TryConvertValue(value, out var convertedValue, out errorMessage)) + { + return false; + } + + dictionary[convertedKey] = convertedValue; errorMessage = null; return true; } @@ -36,10 +44,22 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType()); var key = contract.DictionaryKeyResolver(segment); - var dictionary = (IDictionary)target; + var dictionary = (IDictionary)target; - value = dictionary[key]; + if (!TryConvertKey(key, out var convertedKey, out errorMessage)) + { + value = null; + return false; + } + if (!dictionary.ContainsKey(convertedKey)) + { + value = null; + errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); + return false; + } + + value = dictionary[convertedKey]; errorMessage = null; return true; } @@ -52,16 +72,21 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType()); var key = contract.DictionaryKeyResolver(segment); - var dictionary = (IDictionary)target; + var dictionary = (IDictionary)target; + + if (!TryConvertKey(key, out var convertedKey, out errorMessage)) + { + return false; + } // As per JsonPatch spec, the target location must exist for remove to be successful - if (!dictionary.ContainsKey(key)) + if (!dictionary.ContainsKey(convertedKey)) { errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); return false; } - dictionary.Remove(key); + dictionary.Remove(convertedKey); errorMessage = null; return true; @@ -76,16 +101,26 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType()); var key = contract.DictionaryKeyResolver(segment); - var dictionary = (IDictionary)target; + var dictionary = (IDictionary)target; + + if (!TryConvertKey(key, out var convertedKey, out errorMessage)) + { + return false; + } // As per JsonPatch spec, the target location must exist for remove to be successful - if (!dictionary.ContainsKey(key)) + if (!dictionary.ContainsKey(convertedKey)) { errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); return false; } - dictionary[key] = ConvertValue(dictionary, key, value); + if (!TryConvertValue(value, out var convertedValue, out errorMessage)) + { + return false; + } + + dictionary[convertedKey] = convertedValue; errorMessage = null; return true; @@ -98,21 +133,19 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal out object nextTarget, out string errorMessage) { - var expandoObject = target as ExpandoObject; - if (expandoObject == null) + var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType()); + var key = contract.DictionaryKeyResolver(segment); + var dictionary = (IDictionary)target; + + if (!TryConvertKey(key, out var convertedKey, out errorMessage)) { - errorMessage = null; nextTarget = null; return false; } - var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType()); - var key = contract.DictionaryKeyResolver(segment); - var dictionary = (IDictionary)expandoObject; - - if (dictionary.ContainsKey(key)) + if (dictionary.ContainsKey(convertedKey)) { - nextTarget = dictionary[key]; + nextTarget = dictionary[convertedKey]; errorMessage = null; return true; } @@ -124,20 +157,38 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - private object ConvertValue(IDictionary dictionary, string key, object newValue) + private bool TryConvertKey(string key, out TKey convertedKey, out string errorMessage) { - if (dictionary.TryGetValue(key, out var existingValue)) + var conversionResult = ConversionResultProvider.ConvertTo(key, typeof(TKey)); + if (conversionResult.CanBeConverted) { - if (existingValue != null) - { - var conversionResult = ConversionResultProvider.ConvertTo(newValue, existingValue.GetType()); - if (conversionResult.CanBeConverted) - { - return conversionResult.ConvertedInstance; - } - } + errorMessage = null; + convertedKey = (TKey)conversionResult.ConvertedInstance; + return true; + } + else + { + errorMessage = Resources.FormatInvalidPathSegment(key); + convertedKey = default(TKey); + return false; + } + } + + private bool TryConvertValue(object value, out TValue convertedValue, out string errorMessage) + { + var conversionResult = ConversionResultProvider.ConvertTo(value, typeof(TValue)); + if (conversionResult.CanBeConverted) + { + errorMessage = null; + convertedValue = (TValue)conversionResult.ConvertedInstance; + return true; + } + else + { + errorMessage = Resources.FormatInvalidValueForProperty(value); + convertedValue = default(TValue); + return false; } - return newValue; } } } diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs index bbf6db4ff6..97f108c0a0 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs @@ -3,7 +3,9 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Dynamic; +using Microsoft.AspNetCore.JsonPatch.Adapters; using Newtonsoft.Json.Serialization; namespace Microsoft.AspNetCore.JsonPatch.Internal @@ -49,22 +51,21 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal private IAdapter SelectAdapater(object targetObject) { - if (targetObject is ExpandoObject) - { - return new ExpandoObjectAdapter(); - } - else if (targetObject is IDynamicMetaObjectProvider) - { - return new DynamicObjectAdapter(); - } - else if (targetObject is IDictionary) - { - return new DictionaryAdapter(); - } - else if (targetObject is IList) + var jsonContract = _contractResolver.ResolveContract(targetObject.GetType()); + + if (targetObject is IList) { return new ListAdapter(); } + else if (jsonContract is JsonDictionaryContract jsonDictionaryContract) + { + var type = typeof(DictionaryAdapter<,>).MakeGenericType(jsonDictionaryContract.DictionaryKeyType, jsonDictionaryContract.DictionaryValueType); + return (IAdapter)Activator.CreateInstance(type); + } + else if (jsonContract is JsonDynamicContract) + { + return new DynamicObjectAdapter(); + } else { return new PocoAdapter(); diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs index c81c4e4d6c..d669970407 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs @@ -37,18 +37,8 @@ namespace Microsoft.AspNetCore.JsonPatch // Create from list of operations public JsonPatchDocument(List> operations, IContractResolver contractResolver) { - if (operations == null) - { - throw new ArgumentNullException(nameof(operations)); - } - - if (contractResolver == null) - { - throw new ArgumentNullException(nameof(contractResolver)); - } - - Operations = operations; - ContractResolver = contractResolver; + Operations = operations ?? throw new ArgumentNullException(nameof(operations)); + ContractResolver = contractResolver ?? throw new ArgumentNullException(nameof(contractResolver)); } /// diff --git a/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs index cd99292061..896a3d2ad4 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs @@ -206,6 +206,20 @@ namespace Microsoft.AspNetCore.JsonPatch internal static string FormatPatchNotSupportedForNonGenericLists(object p0) => string.Format(CultureInfo.CurrentCulture, GetString("PatchNotSupportedForNonGenericLists"), p0); + /// + /// The provided path segment '{0}' cannot be converted to the target type. + /// + internal static string InvalidPathSegment + { + get => GetString("InvalidPathSegment"); + } + + /// + /// The provided path segment '{0}' cannot be converted to the target type. + /// + internal static string FormatInvalidPathSegment(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("InvalidPathSegment"), p0); + /// /// The target location specified by path segment '{0}' was not found. /// diff --git a/src/Microsoft.AspNetCore.JsonPatch/Resources.resx b/src/Microsoft.AspNetCore.JsonPatch/Resources.resx index 87ed5c0a17..0b67084233 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Resources.resx +++ b/src/Microsoft.AspNetCore.JsonPatch/Resources.resx @@ -144,6 +144,9 @@ Invalid JsonPatch operation '{0}'. + + The provided path segment '{0}' cannot be converted to the target type. + The provided string '{0}' is an invalid path. diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs index 084aa57379..cfb99d61ce 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using Moq; using Newtonsoft.Json.Serialization; using Xunit; @@ -15,33 +14,83 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal public void Add_KeyWhichAlreadyExists_ReplacesExistingValue() { // Arrange - var nameKey = "Name"; - var dictionary = new Dictionary(StringComparer.Ordinal); - dictionary[nameKey] = "Mike"; - var dictionaryAdapter = new DictionaryAdapter(); - var resolver = new Mock(MockBehavior.Strict); + var key = "Status"; + var dictionary = new Dictionary(StringComparer.Ordinal); + dictionary[key] = 404; + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new DefaultContractResolver(); // Act - var addStatus = dictionaryAdapter.TryAdd(dictionary, nameKey, resolver.Object, "James", out var message); + var addStatus = dictionaryAdapter.TryAdd(dictionary, key, resolver, 200, out var message); // Assert Assert.True(addStatus); Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); Assert.Single(dictionary); - Assert.Equal("James", dictionary[nameKey]); + Assert.Equal(200, dictionary[key]); + } + + [Fact] + public void Add_IntKeyWhichAlreadyExists_ReplacesExistingValue() + { + // Arrange + var intKey = 1; + var dictionary = new Dictionary(); + dictionary[intKey] = "Mike"; + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new DefaultContractResolver(); + + // Act + var addStatus = dictionaryAdapter.TryAdd(dictionary, intKey.ToString(), resolver, "James", out var message); + + // Assert + Assert.True(addStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Single(dictionary); + Assert.Equal("James", dictionary[intKey]); + } + + [Fact] + public void GetInvalidKey_ThrowsInvalidPathSegmentException() + { + // Arrange + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new DefaultContractResolver(); + var key = 1; + var dictionary = new Dictionary(); + + // Act + var addStatus = dictionaryAdapter.TryAdd(dictionary, key.ToString(), resolver, "James", out var message); + + // Assert + Assert.True(addStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Single(dictionary); + Assert.Equal("James", dictionary[key]); + + // Act + var guidKey = new Guid(); + var getStatus = dictionaryAdapter.TryGet(dictionary, guidKey.ToString(), resolver, out var outValue, out message); + + // Assert + Assert.False(getStatus); + Assert.Equal( + string.Format("The provided path segment '{0}' cannot be converted to the target type.", guidKey.ToString()), + message); + Assert.Null(outValue); } [Fact] public void Get_UsingCaseSensitiveKey_FailureScenario() { // Arrange - var dictionaryAdapter = new DictionaryAdapter(); - var resolver = new Mock(MockBehavior.Strict); + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new DefaultContractResolver(); var nameKey = "Name"; var dictionary = new Dictionary(StringComparer.Ordinal); // Act - var addStatus = dictionaryAdapter.TryAdd(dictionary, nameKey, resolver.Object, "James", out var message); + var addStatus = dictionaryAdapter.TryAdd(dictionary, nameKey, resolver, "James", out var message); // Assert Assert.True(addStatus); @@ -50,11 +99,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.Equal("James", dictionary[nameKey]); // Act - addStatus = dictionaryAdapter.TryGet(dictionary, nameKey.ToUpper(), resolver.Object, out var outValue, out message); + var getStatus = dictionaryAdapter.TryGet(dictionary, nameKey.ToUpper(), resolver, out var outValue, out message); // Assert - Assert.True(addStatus); - Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.False(getStatus); + Assert.Equal( + string.Format("The target location specified by path segment '{0}' was not found.", nameKey.ToUpper()), + message); Assert.Null(outValue); } @@ -62,13 +113,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal public void Get_UsingCaseSensitiveKey_SuccessScenario() { // Arrange - var dictionaryAdapter = new DictionaryAdapter(); - var resolver = new Mock(MockBehavior.Strict); + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new DefaultContractResolver(); var nameKey = "Name"; var dictionary = new Dictionary(StringComparer.Ordinal); // Act - var addStatus = dictionaryAdapter.TryAdd(dictionary, nameKey, resolver.Object, "James", out var message); + var addStatus = dictionaryAdapter.TryAdd(dictionary, nameKey, resolver, "James", out var message); // Assert Assert.True(addStatus); @@ -77,7 +128,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.Equal("James", dictionary[nameKey]); // Act - addStatus = dictionaryAdapter.TryGet(dictionary, nameKey, resolver.Object, out var outValue, out message); + addStatus = dictionaryAdapter.TryGet(dictionary, nameKey, resolver, out var outValue, out message); // Assert Assert.True(addStatus); @@ -92,11 +143,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var nameKey = "Name"; var dictionary = new Dictionary(StringComparer.Ordinal); dictionary.Add(nameKey, "Mike"); - var dictionaryAdapter = new DictionaryAdapter(); - var resolver = new Mock(MockBehavior.Strict); + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new DefaultContractResolver(); // Act - var replaceStatus = dictionaryAdapter.TryReplace(dictionary, nameKey, resolver.Object, "James", out var message); + var replaceStatus = dictionaryAdapter.TryReplace(dictionary, nameKey, resolver, "James", out var message); // Assert Assert.True(replaceStatus); @@ -105,17 +156,58 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.Equal("James", dictionary[nameKey]); } + [Fact] + public void ReplacingExistingItem_WithGuidKey() + { + // Arrange + var guidKey = new Guid(); + var dictionary = new Dictionary(); + dictionary.Add(guidKey, "Mike"); + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new DefaultContractResolver(); + + // Act + var replaceStatus = dictionaryAdapter.TryReplace(dictionary, guidKey.ToString(), resolver, "James", out var message); + + // Assert + Assert.True(replaceStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Single(dictionary); + Assert.Equal("James", dictionary[guidKey]); + } + + [Fact] + public void ReplacingWithInvalidValue_ThrowsInvalidValueForPropertyException() + { + // Arrange + var guidKey = new Guid(); + var dictionary = new Dictionary(); + dictionary.Add(guidKey, 5); + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new DefaultContractResolver(); + + // Act + var replaceStatus = dictionaryAdapter.TryReplace(dictionary, guidKey.ToString(), resolver, "test", out var message); + + // Assert + Assert.False(replaceStatus); + Assert.Equal( + string.Format("The value '{0}' is invalid for target location.", "test"), + message); + Assert.Equal(5, dictionary[guidKey]); + } + [Fact] public void Replace_NonExistingKey_Fails() { // Arrange var nameKey = "Name"; var dictionary = new Dictionary(StringComparer.Ordinal); - var dictionaryAdapter = new DictionaryAdapter(); - var resolver = new Mock(MockBehavior.Strict); + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new DefaultContractResolver(); // Act - var replaceStatus = dictionaryAdapter.TryReplace(dictionary, nameKey, resolver.Object, "Mike", out var message); + var replaceStatus = dictionaryAdapter.TryReplace(dictionary, nameKey, resolver, "Mike", out var message); // Assert Assert.False(replaceStatus); @@ -131,11 +223,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Arrange var nameKey = "Name"; var dictionary = new Dictionary(StringComparer.Ordinal); - var dictionaryAdapter = new DictionaryAdapter(); - var resolver = new Mock(MockBehavior.Strict); + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new DefaultContractResolver(); // Act - var removeStatus = dictionaryAdapter.TryRemove(dictionary, nameKey, resolver.Object, out var message); + var removeStatus = dictionaryAdapter.TryRemove(dictionary, nameKey, resolver, out var message); // Assert Assert.False(removeStatus); @@ -152,11 +244,30 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var nameKey = "Name"; var dictionary = new Dictionary(StringComparer.Ordinal); dictionary[nameKey] = "James"; - var dictionaryAdapter = new DictionaryAdapter(); - var resolver = new Mock(MockBehavior.Strict); + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new DefaultContractResolver(); // Act - var removeStatus = dictionaryAdapter.TryRemove(dictionary, nameKey, resolver.Object, out var message); + var removeStatus = dictionaryAdapter.TryRemove(dictionary, nameKey, resolver, out var message); + + //Assert + Assert.True(removeStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + Assert.Empty(dictionary); + } + + [Fact] + public void Remove_RemovesFromDictionary_WithUriKey() + { + // Arrange + var uriKey = new Uri("http://www.test.com/name"); + var dictionary = new Dictionary(); + dictionary[uriKey] = "James"; + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new DefaultContractResolver(); + + // Act + var removeStatus = dictionaryAdapter.TryRemove(dictionary, uriKey.ToString(), resolver, out var message); //Assert Assert.True(removeStatus); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs index 88d1662e1d..5d1fa77d85 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs @@ -5,8 +5,6 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Dynamic; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Xunit; namespace Microsoft.AspNetCore.JsonPatch.Internal @@ -26,11 +24,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var patchDoc = new JsonPatchDocument(); patchDoc.Replace("GuidValue", newGuid); - // serialize & deserialize - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserizalized = JsonConvert.DeserializeObject(serialized); - - deserizalized.ApplyTo(doc); + patchDoc.ApplyTo(doc); Assert.Equal(newGuid, doc.GuidValue); } @@ -46,11 +40,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var patchDoc = new JsonPatchDocument(); patchDoc.Replace("GuidValue", newGuid); - // serialize & deserialize - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserizalized = JsonConvert.DeserializeObject(serialized); - - deserizalized.ApplyTo(doc); + patchDoc.ApplyTo(doc); Assert.Equal(newGuid, doc.GuidValue); } @@ -71,11 +61,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var patchDoc = new JsonPatchDocument(); patchDoc.Replace("nestedobject/GuidValue", newGuid); - // serialize & deserialize - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserizalized = JsonConvert.DeserializeObject(serialized); - - deserizalized.ApplyTo(doc); + patchDoc.ApplyTo(doc); Assert.Equal(newGuid, doc.NestedObject.GuidValue); } @@ -99,11 +85,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var patchDoc = new JsonPatchDocument(); patchDoc.Replace("SimpleDTO", newDTO); - // serialize & deserialize - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); + patchDoc.ApplyTo(doc); Assert.Equal(1, doc.SimpleDTO.DoubleValue); Assert.Equal(0, doc.SimpleDTO.IntegerValue); @@ -120,10 +102,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var patchDoc = new JsonPatchDocument(); patchDoc.Replace("IntegerList/0", 5); - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); + patchDoc.ApplyTo(doc); Assert.Equal(new List() { 5, 2, 3 }, doc.IntegerList); } @@ -138,10 +117,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var patchDoc = new JsonPatchDocument(); patchDoc.Replace("IntegerList", new List() { 4, 5, 6 }); - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); + patchDoc.ApplyTo(doc); Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); } @@ -159,10 +135,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var patchDoc = new JsonPatchDocument(); patchDoc.Replace("SimpleDTOList/0/IntegerList/0", 4); - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); + patchDoc.ApplyTo(doc); Assert.Equal(4, doc.SimpleDTOList[0].IntegerList[0]); } @@ -180,10 +153,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var patchDoc = new JsonPatchDocument(); patchDoc.Replace("SimpleDTOList/0/IntegerList/-", 4); - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); + patchDoc.ApplyTo(doc); Assert.Equal(4, doc.SimpleDTOList[0].IntegerList[2]); } @@ -198,10 +168,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var patchDoc = new JsonPatchDocument(); patchDoc.Replace("IntegerList", new List() { 4, 5, 6 }); - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); + patchDoc.ApplyTo(doc); Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); } @@ -216,10 +183,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var patchDoc = new JsonPatchDocument(); patchDoc.Replace("IntegerList", new Collection() { 4, 5, 6 }); - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); + patchDoc.ApplyTo(doc); Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); } @@ -234,9 +198,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var patchDoc = new JsonPatchDocument(); patchDoc.Replace("IntegerList/-", 5); - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(doc); + patchDoc.ApplyTo(doc); Assert.Equal(new List() { 1, 2, 5 }, doc.IntegerList); } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs index 5eddac8685..3384986c28 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Dynamic; using Newtonsoft.Json.Serialization; @@ -87,7 +88,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.True(visitStatus); Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); Assert.Same(expectedTargetObject, targetObject); - Assert.IsType(adapter); + Assert.Equal(typeof(DictionaryAdapter), adapter.GetType()); } public static IEnumerable ReturnsExpandoAdapterData @@ -107,7 +108,8 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal public void Visit_ValidPathToExpandoObject_ReturnsExpandoAdapter(object targetObject, string path, object expectedTargetObject) { // Arrange - var visitor = new ObjectVisitor(new ParsedPath(path), new DefaultContractResolver()); + var contractResolver = new DefaultContractResolver(); + var visitor = new ObjectVisitor(new ParsedPath(path), contractResolver); // Act var visitStatus = visitor.TryVisit(ref targetObject, out var adapter, out var message); @@ -116,7 +118,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.True(visitStatus); Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); Assert.Same(expectedTargetObject, targetObject); - Assert.IsType(adapter); + Assert.Same(typeof(DictionaryAdapter), adapter.GetType()); } public static IEnumerable ReturnsPocoAdapterData From bf5c043de39d1f415baedc38f559db23ebc4d2e2 Mon Sep 17 00:00:00 2001 From: Jass Bagga Date: Mon, 11 Sep 2017 09:54:29 -0700 Subject: [PATCH 0587/1029] Refactor GetPath in JsonPatchDocumentOfT (#107) Addresses #98 --- .../JsonPatchDocumentOfT.cs | 167 ++++++++---------- .../Properties/AssemblyInfo.cs | 7 + .../Properties/Resources.Designer.cs | 42 +++-- .../Resources.resx | 3 + .../JsonPatchDocumentGetPathTest.cs | 124 +++++++++++++ ...nPatchDocumentJsonPropertyAttributeTest.cs | 31 ++++ ...Microsoft.AspNetCore.JsonPatch.Test.csproj | 4 + 7 files changed, 274 insertions(+), 104 deletions(-) create mode 100644 src/Microsoft.AspNetCore.JsonPatch/Properties/AssemblyInfo.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentGetPathTest.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs index d669970407..33e1e5033f 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs @@ -58,7 +58,7 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "add", - GetPath(path), + GetPath(path, null), from: null, value: value)); @@ -85,7 +85,7 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "add", - GetPath(path) + "/" + position, + GetPath(path, position.ToString()), from: null, value: value)); @@ -93,7 +93,7 @@ namespace Microsoft.AspNetCore.JsonPatch } /// - /// At value at end of list + /// Add value to the end of the list /// /// value type /// target location @@ -108,7 +108,7 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "add", - GetPath(path) + "/-", + GetPath(path, "-"), from: null, value: value)); @@ -128,7 +128,7 @@ namespace Microsoft.AspNetCore.JsonPatch throw new ArgumentNullException(nameof(path)); } - Operations.Add(new Operation("remove", GetPath(path), from: null)); + Operations.Add(new Operation("remove", GetPath(path, null), from: null)); return this; } @@ -149,7 +149,7 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "remove", - GetPath(path) + "/" + position, + GetPath(path, position.ToString()), from: null)); return this; @@ -170,7 +170,7 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "remove", - GetPath(path) + "/-", + GetPath(path, "-"), from: null)); return this; @@ -192,7 +192,7 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "replace", - GetPath(path), + GetPath(path, null), from: null, value: value)); @@ -217,7 +217,7 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "replace", - GetPath(path) + "/" + position, + GetPath(path, position.ToString()), from: null, value: value)); @@ -240,7 +240,7 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "replace", - GetPath(path) + "/-", + GetPath(path, "-"), from: null, value: value)); @@ -270,8 +270,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "move", - GetPath(path), - GetPath(from))); + GetPath(path, null), + GetPath(from, null))); return this; } @@ -301,8 +301,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "move", - GetPath(path), - GetPath(from) + "/" + positionFrom)); + GetPath(path, null), + GetPath(from, positionFrom.ToString()))); return this; } @@ -332,8 +332,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "move", - GetPath(path) + "/" + positionTo, - GetPath(from))); + GetPath(path, positionTo.ToString()), + GetPath(from, null))); return this; } @@ -365,8 +365,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "move", - GetPath(path) + "/" + positionTo, - GetPath(from) + "/" + positionFrom)); + GetPath(path, positionTo.ToString()), + GetPath(from, positionFrom.ToString()))); return this; } @@ -396,8 +396,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "move", - GetPath(path) + "/-", - GetPath(from) + "/" + positionFrom)); + GetPath(path, "-"), + GetPath(from, positionFrom.ToString()))); return this; } @@ -425,8 +425,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "move", - GetPath(path) + "/-", - GetPath(from))); + GetPath(path, "-"), + GetPath(from, null))); return this; } @@ -454,8 +454,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "copy", - GetPath(path) - , GetPath(from))); + GetPath(path, null), + GetPath(from, null))); return this; } @@ -485,8 +485,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "copy", - GetPath(path), - GetPath(from) + "/" + positionFrom)); + GetPath(path, null), + GetPath(from, positionFrom.ToString()))); return this; } @@ -516,8 +516,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "copy", - GetPath(path) + "/" + positionTo, - GetPath(from))); + GetPath(path, positionTo.ToString()), + GetPath(from, null))); return this; } @@ -549,8 +549,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "copy", - GetPath(path) + "/" + positionTo, - GetPath(from) + "/" + positionFrom)); + GetPath(path, positionTo.ToString()), + GetPath(from, positionFrom.ToString()))); return this; } @@ -580,8 +580,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "copy", - GetPath(path) + "/-", - GetPath(from) + "/" + positionFrom)); + GetPath(path, "-"), + GetPath(from, positionFrom.ToString()))); return this; } @@ -609,8 +609,8 @@ namespace Microsoft.AspNetCore.JsonPatch Operations.Add(new Operation( "copy", - GetPath(path) + "/-", - GetPath(from))); + GetPath(path, "-"), + GetPath(from, null))); return this; } @@ -705,61 +705,57 @@ namespace Microsoft.AspNetCore.JsonPatch return allOps; } - private string GetPath(Expression> expr) + // Internal for testing + internal string GetPath(Expression> expr, string position) { - return "/" + GetPath(expr.Body, true).ToLowerInvariant(); + var segments = GetPathSegments(expr.Body); + var path = String.Join("/", segments); + if (position != null) + { + path += "/" + position; + if (segments.Count == 0) + { + return path.ToLowerInvariant(); + } + } + + return "/" + path.ToLowerInvariant(); } - private string GetPath(Expression expr, bool firstTime) + private List GetPathSegments(Expression expr) { + var listOfSegments = new List(); switch (expr.NodeType) { case ExpressionType.ArrayIndex: var binaryExpression = (BinaryExpression)expr; + listOfSegments.AddRange(GetPathSegments(binaryExpression.Left)); + listOfSegments.Add(binaryExpression.Right.ToString()); + return listOfSegments; - if (ContinueWithSubPath(binaryExpression.Left.NodeType, false)) - { - var leftFromBinaryExpression = GetPath(binaryExpression.Left, false); - return leftFromBinaryExpression + "/" + binaryExpression.Right.ToString(); - } - else - { - return binaryExpression.Right.ToString(); - } case ExpressionType.Call: var methodCallExpression = (MethodCallExpression)expr; + listOfSegments.AddRange(GetPathSegments(methodCallExpression.Object)); + listOfSegments.Add(EvaluateExpression(methodCallExpression.Arguments[0])); + return listOfSegments; - if (ContinueWithSubPath(methodCallExpression.Object.NodeType, false)) - { - var leftFromMemberCallExpression = GetPath(methodCallExpression.Object, false); - return leftFromMemberCallExpression + "/" + - GetIndexerInvocation(methodCallExpression.Arguments[0]); - } - else - { - return GetIndexerInvocation(methodCallExpression.Arguments[0]); - } case ExpressionType.Convert: - return GetPath(((UnaryExpression)expr).Operand, false); + listOfSegments.AddRange(GetPathSegments(((UnaryExpression)expr).Operand)); + return listOfSegments; + case ExpressionType.MemberAccess: var memberExpression = expr as MemberExpression; + listOfSegments.AddRange(GetPathSegments(memberExpression.Expression)); + // Get property name, respecting JsonProperty attribute + listOfSegments.Add(GetPropertyNameFromMemberExpression(memberExpression)); + return listOfSegments; - if (ContinueWithSubPath(memberExpression.Expression.NodeType, false)) - { - var left = GetPath(memberExpression.Expression, false); - // Get property name, respecting JsonProperty attribute - return left + "/" + GetPropertyNameFromMemberExpression(memberExpression); - } - else - { - // Get property name, respecting JsonProperty attribute - return GetPropertyNameFromMemberExpression(memberExpression); - } case ExpressionType.Parameter: // Fits "x => x" (the whole document which is "" as JSON pointer) - return firstTime ? string.Empty : null; + return listOfSegments; + default: - return string.Empty; + throw new InvalidOperationException(Resources.FormatExpressionTypeNotSupported(expr)); } } @@ -776,33 +772,24 @@ namespace Microsoft.AspNetCore.JsonPatch return null; } - private static bool ContinueWithSubPath(ExpressionType expressionType, bool firstTime) + private static bool ContinueWithSubPath(ExpressionType expressionType) { - if (firstTime) - { - return (expressionType == ExpressionType.ArrayIndex - || expressionType == ExpressionType.Call - || expressionType == ExpressionType.Convert - || expressionType == ExpressionType.MemberAccess - || expressionType == ExpressionType.Parameter); - } - else - { - return (expressionType == ExpressionType.ArrayIndex - || expressionType == ExpressionType.Call - || expressionType == ExpressionType.Convert - || expressionType == ExpressionType.MemberAccess); - } + return (expressionType == ExpressionType.ArrayIndex + || expressionType == ExpressionType.Call + || expressionType == ExpressionType.Convert + || expressionType == ExpressionType.MemberAccess); + } - private static string GetIndexerInvocation(Expression expression) + // Evaluates the value of the key or index which may be an int or a string, + // or some other expression type. + // The expression is converted to a delegate and the result of executing the delegate is returned as a string. + private static string EvaluateExpression(Expression expression) { var converted = Expression.Convert(expression, typeof(object)); var fakeParameter = Expression.Parameter(typeof(object), null); var lambda = Expression.Lambda>(converted, fakeParameter); - Func func; - - func = lambda.Compile(); + var func = lambda.Compile(); return Convert.ToString(func(null), CultureInfo.InvariantCulture); } diff --git a/src/Microsoft.AspNetCore.JsonPatch/Properties/AssemblyInfo.cs b/src/Microsoft.AspNetCore.JsonPatch/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..08e6f5e01c --- /dev/null +++ b/src/Microsoft.AspNetCore.JsonPatch/Properties/AssemblyInfo.cs @@ -0,0 +1,7 @@ + +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.JsonPatch.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs index 896a3d2ad4..432fab2cbf 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs @@ -80,6 +80,20 @@ namespace Microsoft.AspNetCore.JsonPatch internal static string FormatCannotUpdateProperty(object p0) => string.Format(CultureInfo.CurrentCulture, GetString("CannotUpdateProperty"), p0); + /// + /// The expression '{0}' is not supported. + /// + internal static string ExpressionTypeNotSupported + { + get => GetString("ExpressionTypeNotSupported"); + } + + /// + /// The expression '{0}' is not supported. + /// + internal static string FormatExpressionTypeNotSupported(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("ExpressionTypeNotSupported"), p0); + /// /// The index value provided by path segment '{0}' is out of bounds of the array size. /// @@ -136,6 +150,20 @@ namespace Microsoft.AspNetCore.JsonPatch internal static string FormatInvalidJsonPatchOperation(object p0) => string.Format(CultureInfo.CurrentCulture, GetString("InvalidJsonPatchOperation"), p0); + /// + /// The provided path segment '{0}' cannot be converted to the target type. + /// + internal static string InvalidPathSegment + { + get => GetString("InvalidPathSegment"); + } + + /// + /// The provided path segment '{0}' cannot be converted to the target type. + /// + internal static string FormatInvalidPathSegment(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("InvalidPathSegment"), p0); + /// /// The provided string '{0}' is an invalid path. /// @@ -206,20 +234,6 @@ namespace Microsoft.AspNetCore.JsonPatch internal static string FormatPatchNotSupportedForNonGenericLists(object p0) => string.Format(CultureInfo.CurrentCulture, GetString("PatchNotSupportedForNonGenericLists"), p0); - /// - /// The provided path segment '{0}' cannot be converted to the target type. - /// - internal static string InvalidPathSegment - { - get => GetString("InvalidPathSegment"); - } - - /// - /// The provided path segment '{0}' cannot be converted to the target type. - /// - internal static string FormatInvalidPathSegment(object p0) - => string.Format(CultureInfo.CurrentCulture, GetString("InvalidPathSegment"), p0); - /// /// The target location specified by path segment '{0}' was not found. /// diff --git a/src/Microsoft.AspNetCore.JsonPatch/Resources.resx b/src/Microsoft.AspNetCore.JsonPatch/Resources.resx index 0b67084233..bf07e4a31e 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Resources.resx +++ b/src/Microsoft.AspNetCore.JsonPatch/Resources.resx @@ -132,6 +132,9 @@ The property at path '{0}' could not be updated. + + The expression '{0}' is not supported. Supported expressions include member access and indexer expressions. + The index value provided by path segment '{0}' is out of bounds of the array size. diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentGetPathTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentGetPathTest.cs new file mode 100644 index 0000000000..dcde4b442d --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentGetPathTest.cs @@ -0,0 +1,124 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch +{ + public class JsonPatchDocumentGetPathTest + { + [Fact] + public void ExpressionType_MemberAccess() + { + // Arrange + var patchDocument = new JsonPatchDocument(); + + // Act + var path = patchDocument.GetPath(p => p.SimpleObject.IntegerList, "-"); + + // Assert + Assert.Equal("/simpleobject/integerlist/-", path); + } + + [Fact] + public void ExpressionType_ArrayIndex() + { + // Arrange + var patchDocument = new JsonPatchDocument(); + + // Act + var path = patchDocument.GetPath(p => p[3], null); + + // Assert + Assert.Equal("/3", path); + } + + [Fact] + public void ExpressionType_Call() + { + // Arrange + var patchDocument = new JsonPatchDocument>(); + + // Act + var path = patchDocument.GetPath(p => p["key"], "3"); + + // Assert + Assert.Equal("/key/3", path); + } + + [Fact] + public void ExpressionType_Parameter_NullPosition() + { + // Arrange + var patchDocument = new JsonPatchDocument(); + + // Act + var path = patchDocument.GetPath(p => p, null); + + // Assert + Assert.Equal("/", path); + } + + [Fact] + public void ExpressionType_Parameter_WithPosition() + { + // Arrange + var patchDocument = new JsonPatchDocument(); + + // Act + var path = patchDocument.GetPath(p => p, "-"); + + // Assert + Assert.Equal("/-", path); + } + + [Fact] + public void ExpressionType_Convert() + { + // Arrange + var patchDocument = new JsonPatchDocument(); + + // Act + var path = patchDocument.GetPath(p => (BaseClass)p.DerivedObject, null); + + // Assert + Assert.Equal("/derivedobject", path); + } + + [Fact] + public void ExpressionType_NotSupported() + { + // Arrange + var patchDocument = new JsonPatchDocument(); + + // Act + var exception = Assert.Throws(() => + { + patchDocument.GetPath(p => p.IntegerValue >= 4, null); + }); + + // Assert + Assert.Equal( + string.Format("The expression '(p.IntegerValue >= 4)' is not supported. Supported expressions include member access and indexer expressions."), + exception.Message); + } + } + + internal class DerivedClass : BaseClass + { + public DerivedClass() + { + } + } + + internal class NestedObjectWithDerivedClass + { + public DerivedClass DerivedObject { get; set; } + } + + internal class BaseClass + { + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs index 3948b79484..50ab6a9f5b 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Collections.Generic; using System.Linq; using System.Reflection; using Newtonsoft.Json; @@ -11,6 +12,36 @@ namespace Microsoft.AspNetCore.JsonPatch { public class JsonPatchDocumentJsonPropertyAttributeTest { + [Fact] + public void Add_ToRoot_OfListOfObjects_AtEndOfList() + { + var patchDoc = new JsonPatchDocument>(); + patchDoc.Add(p => p, new JsonPropertyObject()); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = + JsonConvert.DeserializeObject>(serialized); + + // get path + var pathToCheck = deserialized.Operations.First().path; + Assert.Equal("/-", pathToCheck); + } + + [Fact] + public void Add_ToRoot_OfListOfObjects_AtGivenPosition() + { + var patchDoc = new JsonPatchDocument>(); + patchDoc.Add(p => p[3], new JsonPropertyObject()); + + var serialized = JsonConvert.SerializeObject(patchDoc); + var deserialized = + JsonConvert.DeserializeObject>(serialized); + + // get path + var pathToCheck = deserialized.Operations.First().path; + Assert.Equal("/3", pathToCheck); + } + [Fact] public void Add_WithExpression_RespectsJsonPropertyName_ForModelProperty() { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj index 2e4f68b538..6d7b403a79 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj @@ -14,4 +14,8 @@ + + + + From 71a11d5ed6408af6417b2b9ed1e48c0246b67291 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 22 Aug 2017 16:02:46 -0700 Subject: [PATCH 0588/1029] Remove redundant calls to TimeoutAfter --- .../GlobbingAppTests.cs | 16 +++++++--------- .../NoDepsAppTests.cs | 12 ++++++------ .../Scenario/WatchableApp.cs | 8 +++++--- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs index e5b83b1112..4e958f71f5 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs @@ -14,8 +14,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { public class GlobbingAppTests : IDisposable { - private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(30); - private GlobbingApp _app; public GlobbingAppTests(ITestOutputHelper logger) { @@ -30,7 +28,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests _app.UsePollingWatcher = usePollingWatcher; await _app.StartWatcherAsync(); - var types = await _app.GetCompiledAppDefinedTypes().TimeoutAfter(DefaultTimeout); + var types = await _app.GetCompiledAppDefinedTypes(); Assert.Equal(2, types); var fileToChange = Path.Combine(_app.SourceDirectory, "include", "Foo.cs"); @@ -38,7 +36,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests File.WriteAllText(fileToChange, programCs); await _app.HasRestarted(); - types = await _app.GetCompiledAppDefinedTypes().TimeoutAfter(DefaultTimeout); + types = await _app.GetCompiledAppDefinedTypes(); Assert.Equal(2, types); } @@ -47,14 +45,14 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { await _app.StartWatcherAsync(); - var types = await _app.GetCompiledAppDefinedTypes().TimeoutAfter(DefaultTimeout); + var types = await _app.GetCompiledAppDefinedTypes(); Assert.Equal(2, types); var fileToChange = Path.Combine(_app.SourceDirectory, "include", "Foo.cs"); File.Delete(fileToChange); await _app.HasRestarted(); - types = await _app.GetCompiledAppDefinedTypes().TimeoutAfter(DefaultTimeout); + types = await _app.GetCompiledAppDefinedTypes(); Assert.Equal(1, types); } @@ -63,14 +61,14 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { await _app.StartWatcherAsync(); - var types = await _app.GetCompiledAppDefinedTypes().TimeoutAfter(DefaultTimeout); + var types = await _app.GetCompiledAppDefinedTypes(); Assert.Equal(2, types); var folderToDelete = Path.Combine(_app.SourceDirectory, "include"); Directory.Delete(folderToDelete, recursive: true); await _app.HasRestarted(); - types = await _app.GetCompiledAppDefinedTypes().TimeoutAfter(DefaultTimeout); + types = await _app.GetCompiledAppDefinedTypes(); Assert.Equal(1, types); } @@ -131,7 +129,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public async Task GetCompiledAppDefinedTypes() { - var definedTypesMessage = await Process.GetOutputLineAsync(m => m.StartsWith("Defined types = ")); + var definedTypesMessage = await Process.GetOutputLineAsync(m => m.StartsWith("Defined types = ")).TimeoutAfter(TimeSpan.FromSeconds(30)); return int.Parse(definedTypesMessage.Split('=').Last()); } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs index 214e7f2984..ea9ffbec03 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs @@ -26,7 +26,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public async Task RestartProcessOnFileChange() { await _app.StartWatcherAsync(new[] { "--no-exit" }); - var pid = await _app.GetProcessId().TimeoutAfter(DefaultTimeout); + var pid = await _app.GetProcessId(); // Then wait for it to restart when we change a file var fileToChange = Path.Combine(_app.SourceDirectory, "Program.cs"); @@ -34,7 +34,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests File.WriteAllText(fileToChange, programCs); await _app.HasRestarted(); - var pid2 = await _app.GetProcessId().TimeoutAfter(DefaultTimeout); + var pid2 = await _app.GetProcessId(); Assert.NotEqual(pid, pid2); // first app should have shut down @@ -45,17 +45,17 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public async Task RestartProcessThatTerminatesAfterFileChange() { await _app.StartWatcherAsync(); - var pid = await _app.GetProcessId().TimeoutAfter(DefaultTimeout); - await _app.HasExited().TimeoutAfter(DefaultTimeout); // process should exit after run + var pid = await _app.GetProcessId(); + await _app.HasExited(); // process should exit after run var fileToChange = Path.Combine(_app.SourceDirectory, "Program.cs"); var programCs = File.ReadAllText(fileToChange); File.WriteAllText(fileToChange, programCs); await _app.HasRestarted(); - var pid2 = await _app.GetProcessId().TimeoutAfter(DefaultTimeout); + var pid2 = await _app.GetProcessId(); Assert.NotEqual(pid, pid2); - await _app.HasExited().TimeoutAfter(DefaultTimeout); // process should exit after run + await _app.HasExited(); // process should exit after run } public void Dispose() diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs index 8fad2e5486..070cede829 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs @@ -15,6 +15,8 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { public class WatchableApp : IDisposable { + private static readonly TimeSpan DefaultMessageTimeOut = TimeSpan.FromSeconds(30); + private const string StartedMessage = "Started"; private const string ExitingMessage = "Exiting"; @@ -39,16 +41,16 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public string SourceDirectory { get; } public Task HasRestarted() - => Process.GetOutputLineAsync(StartedMessage).TimeoutAfter(TimeSpan.FromMinutes(2)); + => Process.GetOutputLineAsync(StartedMessage).TimeoutAfter(DefaultMessageTimeOut); public Task HasExited() - => Process.GetOutputLineAsync(ExitingMessage); + => Process.GetOutputLineAsync(ExitingMessage).TimeoutAfter(DefaultMessageTimeOut); public bool UsePollingWatcher { get; set; } public async Task GetProcessId() { - var line = await Process.GetOutputLineAsync(l => l.StartsWith("PID =")); + var line = await Process.GetOutputLineAsync(l => l.StartsWith("PID =")).TimeoutAfter(DefaultMessageTimeOut); var pid = line.Split('=').Last(); return int.Parse(pid); } From 8a01a1f7909a3654c58c6f861d8fd949c0318485 Mon Sep 17 00:00:00 2001 From: Chris Ross Date: Thu, 21 Sep 2017 15:09:22 -0700 Subject: [PATCH 0589/1029] Remove explicit LangVersion (#345) --- .../Microsoft.DotNet.Watcher.Tools.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj index 6315f6e6b0..6b11bd5bcf 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj @@ -1,7 +1,6 @@  - latest netcoreapp2.0 dotnet-watch exe From aa93ce9299eb5694e45d3bc298837bf3ad21e9ef Mon Sep 17 00:00:00 2001 From: Justin Kotalik Date: Thu, 21 Sep 2017 17:46:42 -0700 Subject: [PATCH 0590/1029] Increase Minimum Version of Visual Studio to 15.3.0 --- DotNetTools.sln | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DotNetTools.sln b/DotNetTools.sln index caea9174df..8e317e7fc0 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -1,7 +1,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26815.3 -MinimumVisualStudioVersion = 10.0.40219.1 +MinimumVisualStudioVersion = 15.0.26730.03 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66517987-2A5A-4330-B130-207039378FD4}" ProjectSection(SolutionItems) = preProject src\Directory.Build.props = src\Directory.Build.props From 148942979220ea964f10191cf676d8865a13d9d3 Mon Sep 17 00:00:00 2001 From: Justin Kotalik Date: Thu, 21 Sep 2017 17:47:46 -0700 Subject: [PATCH 0591/1029] Increase Minimum Version of Visual Studio to 15.3.0 --- HtmlAbstractions.sln | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HtmlAbstractions.sln b/HtmlAbstractions.sln index 5b6b09416f..5ee1cb4612 100644 --- a/HtmlAbstractions.sln +++ b/HtmlAbstractions.sln @@ -1,7 +1,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26127.0 -MinimumVisualStudioVersion = 10.0.40219.1 +MinimumVisualStudioVersion = 15.0.26730.03 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A5A15F1C-885A-452A-A731-B0173DDBD913}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F31FF137-390C-49BF-A3BD-7C6ED3597C21}" From 34f59ad305166e1efe64d17f96c5e5e30d728628 Mon Sep 17 00:00:00 2001 From: Justin Kotalik Date: Thu, 21 Sep 2017 17:49:32 -0700 Subject: [PATCH 0592/1029] Increase Minimum Version of Visual Studio to 15.3.0 --- JsonPatch.sln | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JsonPatch.sln b/JsonPatch.sln index 87b48a8ea1..f0b6a578f1 100644 --- a/JsonPatch.sln +++ b/JsonPatch.sln @@ -1,7 +1,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26815.3 -MinimumVisualStudioVersion = 10.0.40219.1 +MinimumVisualStudioVersion = 15.0.26730.03 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{430B59ED-F960-4D3A-8FFE-3370008E168D}" ProjectSection(SolutionItems) = preProject src\Directory.Build.props = src\Directory.Build.props From 3dd029a8b54a3dac3542f11ba479ad40a29246f3 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 22 Sep 2017 12:19:39 -0700 Subject: [PATCH 0593/1029] Simplify the MSBuild targets in dotnet-watch Use CustomAfterMicrosoftCommonTargets instead of MSBuildProjectExtensionsPath. - No more need to write to obj/$(Project).g.dotnetwatch.targets - Works on project that have changed default file locations via BaseIntermediateOutputPath Simplify DotNetWatch targets - Condense to one targets file - Simplify dependency chain of targets - Build project references in a parallel --- Directory.Build.props | 2 + .../CommandLineOptions.cs | 8 -- .../Internal/MsBuildFileSetFactory.cs | 80 ++++++++----------- .../Microsoft.DotNet.Watcher.Tools.csproj | 5 +- src/Microsoft.DotNet.Watcher.Tools/Program.cs | 27 +------ .../dotnetwatch.targets | 18 ----- .../toolassets/DotNetWatch.targets | 68 ++++++++++++++++ .../toolassets/DotNetWatchCommon.targets | 28 ------- .../toolassets/DotNetWatchInner.targets | 70 ---------------- .../toolassets/DotNetWatchOuter.targets | 69 ---------------- .../DotNetWatcherTests.cs | 5 -- ...otNet.Watcher.Tools.FunctionalTests.csproj | 4 +- .../Scenario/WatchableApp.cs | 7 +- .../KitchenSink/KitchenSink.csproj | 1 + .../AssertEx.cs | 6 +- ...icrosoft.DotNet.Watcher.Tools.Tests.csproj | 4 +- .../MsBuildFileSetFactoryTest.cs | 15 +--- 17 files changed, 119 insertions(+), 298 deletions(-) delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/dotnetwatch.targets create mode 100644 src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatch.targets delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatchCommon.targets delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatchInner.targets delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatchOuter.targets diff --git a/Directory.Build.props b/Directory.Build.props index bff80fce71..90338e5345 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,6 +13,8 @@ false + $(MSBuildThisFileDirectory)obj\$(MSBuildProjectName)\ + $(MSBuildThisFileDirectory)bin\$(MSBuildProjectName)\ diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs index 22705c9265..e6e23890d5 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs @@ -13,7 +13,6 @@ namespace Microsoft.DotNet.Watcher internal class CommandLineOptions { public string Project { get; private set; } - public string MSBuildProjectExtensionsPath { get; private set; } public bool IsHelp { get; private set; } public bool IsQuiet { get; private set; } public bool IsVerbose { get; private set; } @@ -78,12 +77,6 @@ Examples: var optProjects = app.Option("-p|--project ", "The project to watch", CommandOptionType.SingleValue); - var optMSBuildProjectExtensionsPath = app.Option("--msbuildprojectextensionspath ", - "The MSBuild project extensions path. Defaults to \"obj\".", - CommandOptionType.SingleValue); - // Hide from help text because this is an internal option that will hopefully go away when/if #244 is resolved. - optMSBuildProjectExtensionsPath.ShowInHelpText = false; - var optQuiet = app.Option("-q|--quiet", "Suppresses all output except warnings and errors", CommandOptionType.NoValue); var optVerbose = app.VerboseOption(); @@ -113,7 +106,6 @@ Examples: return new CommandLineOptions { Project = optProjects.Value(), - MSBuildProjectExtensionsPath = optMSBuildProjectExtensionsPath.Value(), IsQuiet = optQuiet.HasValue(), IsVerbose = optVerbose.HasValue(), RemainingArguments = app.RemainingArguments, diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs index 0190b089ca..837881c907 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs @@ -17,21 +17,19 @@ namespace Microsoft.DotNet.Watcher.Internal public class MsBuildFileSetFactory : IFileSetFactory { private const string TargetName = "GenerateWatchList"; - private const string ProjectExtensionFileExtension = ".dotnetwatch.g.targets"; - private const string WatchTargetsFileName = "DotNetWatchCommon.targets"; + private const string WatchTargetsFileName = "DotNetWatch.targets"; private readonly IReporter _reporter; private readonly string _projectFile; - private readonly string _projectExtensionsPath; - private readonly string _watchTargetsDir; private readonly OutputSink _outputSink; private readonly ProcessRunner _processRunner; private readonly bool _waitOnError; + private readonly IReadOnlyList _buildFlags; public MsBuildFileSetFactory(IReporter reporter, string projectFile, - string msBuildProjectExtensionsPath, - bool waitOnError) - : this(reporter, projectFile, msBuildProjectExtensionsPath, new OutputSink()) + bool waitOnError, + bool trace) + : this(reporter, projectFile, new OutputSink(), trace) { _waitOnError = waitOnError; } @@ -39,8 +37,8 @@ namespace Microsoft.DotNet.Watcher.Internal // output sink is for testing internal MsBuildFileSetFactory(IReporter reporter, string projectFile, - string msBuildProjectExtensionsPath, - OutputSink outputSink) + OutputSink outputSink, + bool trace) { Ensure.NotNull(reporter, nameof(reporter)); Ensure.NotNullOrEmpty(projectFile, nameof(projectFile)); @@ -48,29 +46,13 @@ namespace Microsoft.DotNet.Watcher.Internal _reporter = reporter; _projectFile = projectFile; - _watchTargetsDir = FindWatchTargetsDir(); _outputSink = outputSink; _processRunner = new ProcessRunner(reporter); - - // default value for MSBuildProjectExtensionsPath is $(BaseIntermediateOutputPath), which defaults to 'obj/'. - _projectExtensionsPath = string.IsNullOrEmpty(msBuildProjectExtensionsPath) - ? Path.Combine(Path.GetDirectoryName(_projectFile), "obj") - : msBuildProjectExtensionsPath; + _buildFlags = InitializeArgs(FindTargetsFile(), trace); } - internal List BuildFlags { get; } = new List - { - "/nologo", - "/v:n", - "/t:" + TargetName, - "/p:DotNetWatchBuild=true", // extensibility point for users - "/p:DesignTimeBuild=true", // don't do expensive things - }; - public async Task CreateAsync(CancellationToken cancellationToken) { - EnsureInitialized(); - var watchList = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); try { @@ -91,9 +73,8 @@ namespace Microsoft.DotNet.Watcher.Internal { "msbuild", _projectFile, - $"/p:_DotNetWatchTargetsLocation={_watchTargetsDir}", // add our dotnet-watch targets $"/p:_DotNetWatchListFile={watchList}" - }.Concat(BuildFlags), + }.Concat(_buildFlags), OutputCapture = capture }; @@ -162,29 +143,31 @@ namespace Microsoft.DotNet.Watcher.Internal } } - // Ensures file exists in $(MSBuildProjectExtensionsPath)/$(MSBuildProjectFile).dotnetwatch.targets - private void EnsureInitialized() + private IReadOnlyList InitializeArgs(string watchTargetsFile, bool trace) { - // see https://github.com/Microsoft/msbuild/blob/bf9b21cc7869b96ea2289ff31f6aaa5e1d525a26/src/XMakeTasks/Microsoft.Common.targets#L127 - var projectExtensionFile = Path.Combine(_projectExtensionsPath, - Path.GetFileName(_projectFile) + ProjectExtensionFileExtension); - - if (!File.Exists(projectExtensionFile)) + var args = new List { - // ensure obj folder is available - Directory.CreateDirectory(Path.GetDirectoryName(projectExtensionFile)); + "/nologo", + "/v:n", + "/t:" + TargetName, + "/p:DotNetWatchBuild=true", // extensibility point for users + "/p:DesignTimeBuild=true", // don't do expensive things + "/p:CustomAfterMicrosoftCommonTargets=" + watchTargetsFile, + "/p:CustomAfterMicrosoftCommonCrossTargetingTargets=" + watchTargetsFile, + }; - using (var fileStream = new FileStream(projectExtensionFile, FileMode.Create)) - using (var assemblyStream = GetType().GetTypeInfo().Assembly.GetManifestResourceStream("dotnetwatch.targets")) - { - assemblyStream.CopyTo(fileStream); - } + if (trace) + { + // enables capturing markers to know which projects have been visited + args.Add("/p:_DotNetWatchTraceOutput=true"); } + + return args; } - private string FindWatchTargetsDir() + private string FindTargetsFile() { - var assemblyDir = Path.GetDirectoryName(GetType().GetTypeInfo().Assembly.Location); + var assemblyDir = Path.GetDirectoryName(typeof(MsBuildFileSetFactory).Assembly.Location); var searchPaths = new[] { AppContext.BaseDirectory, @@ -194,8 +177,13 @@ namespace Microsoft.DotNet.Watcher.Internal Path.Combine(AppContext.BaseDirectory, "../../toolassets"), // relative to packaged deps.json }; - var targetPath = searchPaths.Select(p => Path.Combine(p, WatchTargetsFileName)).First(File.Exists); - return Path.GetDirectoryName(targetPath); + var targetPath = searchPaths.Select(p => Path.Combine(p, WatchTargetsFileName)).FirstOrDefault(File.Exists); + if (targetPath == null) + { + _reporter.Error("Fatal error: could not find DotNetWatch.targets"); + return null; + } + return targetPath; } } } diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj index 6b11bd5bcf..443587cf07 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj @@ -12,9 +12,8 @@ - - - + + diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index 019c95a329..7e8200b102 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -87,14 +87,12 @@ namespace Microsoft.DotNet.Watcher { return await ListFilesAsync(_reporter, options.Project, - options.MSBuildProjectExtensionsPath, _cts.Token); } else { return await MainInternalAsync(_reporter, options.Project, - options.MSBuildProjectExtensionsPath, options.RemainingArguments, _cts.Token); } @@ -129,7 +127,6 @@ namespace Microsoft.DotNet.Watcher private async Task MainInternalAsync( IReporter reporter, string project, - string msbuildProjectExtensionsPath, ICollection args, CancellationToken cancellationToken) { @@ -147,8 +144,8 @@ namespace Microsoft.DotNet.Watcher var fileSetFactory = new MsBuildFileSetFactory(reporter, projectFile, - NormalizePath(msbuildProjectExtensionsPath), - waitOnError: true); + waitOnError: true, + trace: false); var processInfo = new ProcessSpec { Executable = DotNetMuxer.MuxerPathOrDefault(), @@ -174,7 +171,6 @@ namespace Microsoft.DotNet.Watcher private async Task ListFilesAsync( IReporter reporter, string project, - string msbuildProjectExtensionsPath, CancellationToken cancellationToken) { // TODO multiple projects should be easy enough to add here @@ -191,8 +187,8 @@ namespace Microsoft.DotNet.Watcher var fileSetFactory = new MsBuildFileSetFactory(reporter, projectFile, - NormalizePath(msbuildProjectExtensionsPath), - waitOnError: false); + waitOnError: false, + trace: false); var files = await fileSetFactory.CreateAsync(cancellationToken); if (files == null) @@ -211,21 +207,6 @@ namespace Microsoft.DotNet.Watcher private static IReporter CreateReporter(bool verbose, bool quiet, IConsole console) => new PrefixConsoleReporter(console, verbose || CliContext.IsGlobalVerbose(), quiet); - private string NormalizePath(string path) - { - if (path == null || Path.IsPathRooted(path)) - { - return path; - } - - if (string.IsNullOrWhiteSpace(path)) - { - return _workingDir; - } - - return Path.Combine(_workingDir, path); - } - public void Dispose() { _console.CancelKeyPress -= OnCancelKeyPress; diff --git a/src/Microsoft.DotNet.Watcher.Tools/dotnetwatch.targets b/src/Microsoft.DotNet.Watcher.Tools/dotnetwatch.targets deleted file mode 100644 index d3e73557be..0000000000 --- a/src/Microsoft.DotNet.Watcher.Tools/dotnetwatch.targets +++ /dev/null @@ -1,18 +0,0 @@ - - - - <_DotNetWatchTargetsFile Condition="'$(_DotNetWatchTargetsFile)' == ''">$(MSBuildThisFileFullPath) - - - - - - - - - - - \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatch.targets b/src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatch.targets new file mode 100644 index 0000000000..5ce4f08672 --- /dev/null +++ b/src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatch.targets @@ -0,0 +1,68 @@ + + + + + + + + + <_CollectWatchItemsDependsOn Condition=" '$(TargetFrameworks)' != '' AND '$(TargetFramework)' == '' "> + _CollectWatchItemsPerFramework; + + <_CollectWatchItemsDependsOn Condition=" '$(TargetFramework)' != '' "> + _CoreCollectWatchItems; + + + + + + + + <_TargetFramework Include="$(TargetFrameworks)" /> + + + + + + + + + + + + + + + + + + <_WatchProjects Include="%(ProjectReference.Identity)" Condition="'%(ProjectReference.Watch)' != 'false'" /> + + + + + + + + diff --git a/src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatchCommon.targets b/src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatchCommon.targets deleted file mode 100644 index c3477393fc..0000000000 --- a/src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatchCommon.targets +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatchInner.targets b/src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatchInner.targets deleted file mode 100644 index 9bdd83dd6d..0000000000 --- a/src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatchInner.targets +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - <_DotNetWatchProjects Include="@(ProjectReference->'%(FullPath)')" Condition="'%(ProjectReference.Watch)' != 'false'" /> - <_DotNetWatchImportsTargets Include="@(_DotNetWatchProjects->'%(RelativeDir)obj\%(FileName)%(Extension).dotnetwatch.targets')"> - $(_DotNetWatchTargetsFile) - - - - - - - - - - - <_DotNetWatchProjects Include="$(MSBuildProjectFullPath)"/> - - - \ No newline at end of file diff --git a/src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatchOuter.targets b/src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatchOuter.targets deleted file mode 100644 index f2dfb9e104..0000000000 --- a/src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatchOuter.targets +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - <_TargetFramework Include="$(TargetFrameworks)" /> - - - - - - - - - - <_TargetFramework Include="$(TargetFrameworks)" /> - - - - - - diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/DotNetWatcherTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/DotNetWatcherTests.cs index ed89240fb3..368c55a202 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/DotNetWatcherTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/DotNetWatcherTests.cs @@ -41,11 +41,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests : base("KitchenSink", logger) { } - - protected override IEnumerable GetDefaultArgs() - { - return new[] { "--msbuildprojectextensionspath", ".net/obj", "run", "--" }; - } } } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj index 07cb79b4c3..d0bac72314 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj @@ -8,9 +8,7 @@ - - - + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs index 070cede829..d204d5159a 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs @@ -99,7 +99,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests await PrepareAsync(); } - var args = GetDefaultArgs().Concat(arguments); + var args = new[] { "run", "--" }.Concat(arguments); Start(args, name); // Make this timeout long because it depends much on the MSBuild compilation speed. @@ -107,11 +107,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests await Process.GetOutputLineAsync(StartedMessage).TimeoutAfter(TimeSpan.FromMinutes(2)); } - protected virtual IEnumerable GetDefaultArgs() - { - return new[] { "run", "--" }; - } - public virtual void Dispose() { _logger?.WriteLine("Disposing WatchableApp"); diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj index 64ce763e70..aeb186ac39 100755 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj @@ -2,6 +2,7 @@ .net/obj + .net/bin diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs index 0ffba97152..4d897058fd 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs @@ -20,14 +20,14 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests public static void EqualFileList(IEnumerable expectedFiles, IEnumerable actualFiles) { - Func normalize = p => p.Replace('\\', '/'); + string normalize(string p) => p.Replace('\\', '/'); var expected = new HashSet(expectedFiles.Select(normalize)); var actual = new HashSet(actualFiles.Where(p => !string.IsNullOrEmpty(p)).Select(normalize)); if (!expected.SetEquals(actual)) { throw new AssertActualExpectedException( - expected: string.Join("\n", expected), - actual: string.Join("\n", actual), + expected: "\n" + string.Join("\n", expected), + actual: "\n" + string.Join("\n", actual), userMessage: "File sets should be equal"); } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj index 1bc4dc44ae..c005f40d88 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj @@ -6,9 +6,7 @@ - - - + diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs index 064dc79902..dde03d31ab 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs @@ -238,11 +238,7 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests graph.Find("A").WithProjectReference(graph.Find("W"), watch: false); var output = new OutputSink(); - var filesetFactory = new MsBuildFileSetFactory(_reporter, graph.GetOrCreate("A").Path, null, output) - { - // enables capturing markers to know which projects have been visited - BuildFlags = { "/p:_DotNetWatchTraceOutput=true" } - }; + var filesetFactory = new MsBuildFileSetFactory(_reporter, graph.GetOrCreate("A").Path, output, trace: true); var fileset = await GetFileSet(filesetFactory); @@ -270,17 +266,10 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests Assert.Single(output.Current.Lines, line => line.Contains($"Collecting watch items from '{projectName}'")) ); - - // ensure each project is only visited once to collect project references - Assert.All(includedProjects, - projectName => - Assert.Single(output.Current.Lines, - line => line.Contains($"Collecting referenced projects from '{projectName}'")) - ); } private Task GetFileSet(TemporaryCSharpProject target) - => GetFileSet(new MsBuildFileSetFactory(_reporter, target.Path, null, waitOnError: false)); + => GetFileSet(new MsBuildFileSetFactory(_reporter, target.Path, waitOnError: false, trace: false)); private async Task GetFileSet(MsBuildFileSetFactory filesetFactory) { From f3bb4080b0f810628fb3de9b6df003c66dda9ec2 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 22 Sep 2017 12:29:07 -0700 Subject: [PATCH 0594/1029] Use CustomAfterMicrosoftCommonTargets in dotnet-user-secrets --- .../Internal/ProjectIdResolver.cs | 44 ++++++++++--------- ...soft.Extensions.SecretManager.Tools.csproj | 4 +- .../resources/ProjectIdResolverTargets.xml | 5 --- .../toolassets/SecretManager.targets | 5 +++ ...xtensions.SecretManager.Tools.Tests.csproj | 1 + .../MsBuildProjectFinderTest.cs | 2 +- .../TemporaryFileProvider.cs | 4 +- 7 files changed, 35 insertions(+), 30 deletions(-) delete mode 100644 src/Microsoft.Extensions.SecretManager.Tools/resources/ProjectIdResolverTargets.xml create mode 100644 src/Microsoft.Extensions.SecretManager.Tools/toolassets/SecretManager.targets diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs index cf3105cea2..66d08b008b 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs +++ b/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; using System.IO; +using System.Linq; using System.Reflection; using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Tools.Internal; @@ -14,19 +15,20 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal { private const string DefaultConfig = "Debug"; private readonly IReporter _reporter; + private readonly string _targetsFile; private readonly string _workingDirectory; public ProjectIdResolver(IReporter reporter, string workingDirectory) { _workingDirectory = workingDirectory; _reporter = reporter; + _targetsFile = FindTargetsFile(); } public string Resolve(string project, string configuration) { var finder = new MsBuildProjectFinder(_workingDirectory); var projectFile = finder.FindMsBuildProject(project); - EnsureProjectExtensionTargetsExist(projectFile); _reporter.Verbose(Resources.FormatMessage_Project_File_Path(projectFile)); @@ -42,9 +44,11 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal "msbuild", projectFile, "/nologo", - "/t:_ExtractUserSecretsMetadata", // defined in ProjectIdResolverTargets.xml - $"/p:_UserSecretsMetadataFile={outputFile}", - $"/p:Configuration={configuration}" + "/t:_ExtractUserSecretsMetadata", // defined in SecretManager.targets + "/p:_UserSecretsMetadataFile=" + outputFile, + "/p:Configuration=" + configuration, + "/p:CustomAfterMicrosoftCommonTargets=" + _targetsFile, + "/p:CustomAfterMicrosoftCommonCrossTargetingTargets=" + _targetsFile, }; var psi = new ProcessStartInfo { @@ -82,25 +86,25 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal } } - private void EnsureProjectExtensionTargetsExist(string projectFile) + private string FindTargetsFile() { - // relies on MSBuildProjectExtensionsPath and Microsoft.Common.targets to import this file - // into the target project - var projectExtensionsPath = Path.Combine( - Path.GetDirectoryName(projectFile), - "obj", - $"{Path.GetFileName(projectFile)}.usersecrets.targets"); - - Directory.CreateDirectory(Path.GetDirectoryName(projectExtensionsPath)); - - // should overwrite the file always. Hypothetically, another version of the user-secrets tool - // could have already put a file here. We want to ensure the target file matches the currently - // running tool - using (var resource = GetType().GetTypeInfo().Assembly.GetManifestResourceStream("ProjectIdResolverTargets.xml")) - using (var stream = new FileStream(projectExtensionsPath, FileMode.Create)) + var assemblyDir = Path.GetDirectoryName(typeof(ProjectIdResolver).Assembly.Location); + var searchPaths = new[] { - resource.CopyTo(stream); + AppContext.BaseDirectory, + assemblyDir, + Path.Combine(assemblyDir, "../../toolassets"), // from nuget cache + Path.Combine(assemblyDir, "toolassets"), // from local build + Path.Combine(AppContext.BaseDirectory, "../../toolassets"), // relative to packaged deps.json + }; + + var targetPath = searchPaths.Select(p => Path.Combine(p, "SecretManager.targets")).FirstOrDefault(File.Exists); + if (targetPath == null) + { + _reporter.Error("Fatal error: could not find SecretManager.targets"); + return null; } + return targetPath; } private static void TryDelete(string file) diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj index aaf954865a..261b94791f 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj @@ -13,8 +13,8 @@ - - + + diff --git a/src/Microsoft.Extensions.SecretManager.Tools/resources/ProjectIdResolverTargets.xml b/src/Microsoft.Extensions.SecretManager.Tools/resources/ProjectIdResolverTargets.xml deleted file mode 100644 index a30a87d34a..0000000000 --- a/src/Microsoft.Extensions.SecretManager.Tools/resources/ProjectIdResolverTargets.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/Microsoft.Extensions.SecretManager.Tools/toolassets/SecretManager.targets b/src/Microsoft.Extensions.SecretManager.Tools/toolassets/SecretManager.targets new file mode 100644 index 0000000000..8cf63eac00 --- /dev/null +++ b/src/Microsoft.Extensions.SecretManager.Tools/toolassets/SecretManager.targets @@ -0,0 +1,5 @@ + + + + + diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj index 5ac356aa2e..67ace090c0 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj @@ -6,6 +6,7 @@ + diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/MsBuildProjectFinderTest.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/MsBuildProjectFinderTest.cs index ec79f8ef4a..6e7a290834 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/MsBuildProjectFinderTest.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/MsBuildProjectFinderTest.cs @@ -5,7 +5,7 @@ using System.IO; using Microsoft.Extensions.SecretManager.Tools.Internal; using Xunit; -namespace Microsoft.Extensions.SecretsManager.Tools.Tests +namespace Microsoft.Extensions.SecretManager.Tools.Tests { public class MsBuildProjectFinderTest { diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/TemporaryFileProvider.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/TemporaryFileProvider.cs index 08e4449d0c..34c2e8e2ba 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/TemporaryFileProvider.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/TemporaryFileProvider.cs @@ -5,7 +5,7 @@ using System; using System.IO; using System.Text; -namespace Microsoft.Extensions.SecretsManager.Tools.Tests +namespace Microsoft.Extensions.SecretManager.Tools.Tests { internal class TemporaryFileProvider : IDisposable { @@ -26,4 +26,4 @@ namespace Microsoft.Extensions.SecretsManager.Tools.Tests Directory.Delete(Root, recursive: true); } } -} \ No newline at end of file +} From f3ae0489befacdbc9d1361f8bedcc45d6dd5b302 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Wed, 20 Sep 2017 13:20:26 -0700 Subject: [PATCH 0595/1029] Update bootstrappers --- .appveyor.yml | 4 +- build.cmd | 2 +- build.sh | 197 +------------------------------------- run.cmd | 2 + build.ps1 => run.ps1 | 56 +++++++---- run.sh | 223 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 266 insertions(+), 218 deletions(-) create mode 100644 run.cmd rename build.ps1 => run.ps1 (73%) create mode 100755 run.sh diff --git a/.appveyor.yml b/.appveyor.yml index 31efd8196f..46038786c9 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,4 +1,4 @@ -init: +init: - git config --global core.autocrlf true branches: only: @@ -7,7 +7,7 @@ branches: - dev - /^(.*\/)?ci-.*$/ build_script: - - ps: .\build.ps1 + - ps: .\run.ps1 default-build clone_depth: 1 environment: global: diff --git a/build.cmd b/build.cmd index b6c8d24864..c0050bda12 100644 --- a/build.cmd +++ b/build.cmd @@ -1,2 +1,2 @@ @ECHO OFF -PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*; exit $LASTEXITCODE" +PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' default-build %*; exit $LASTEXITCODE" diff --git a/build.sh b/build.sh index 11cdbe5504..98a4b22765 100755 --- a/build.sh +++ b/build.sh @@ -1,199 +1,8 @@ #!/usr/bin/env bash set -euo pipefail - -# -# variables -# - -RESET="\033[0m" -RED="\033[0;31m" -MAGENTA="\033[0;95m" DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" -config_file="$DIR/version.xml" -verbose=false -update=false -repo_path="$DIR" -channel='' -tools_source='' -# -# Functions -# -__usage() { - echo "Usage: $(basename "${BASH_SOURCE[0]}") [options] [[--] ...]" - echo "" - echo "Arguments:" - echo " ... Arguments passed to MSBuild. Variable number of arguments allowed." - echo "" - echo "Options:" - echo " --verbose Show verbose output." - echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." - echo " --config-file TThe path to the configuration file that stores values. Defaults to version.xml." - echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." - echo " --path The directory to build. Defaults to the directory containing the script." - echo " -s|--tools-source The base url where build tools can be downloaded. Overrides the value from the config file." - echo " -u|--update Update to the latest KoreBuild even if the lock file is present." - echo "" - echo "Description:" - echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." - echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel." - - if [[ "${1:-}" != '--no-exit' ]]; then - exit 2 - fi -} - -get_korebuild() { - local version - local lock_file="$repo_path/korebuild-lock.txt" - if [ ! -f "$lock_file" ] || [ "$update" = true ]; then - __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" - fi - version="$(grep 'version:*' -m 1 "$lock_file")" - if [[ "$version" == '' ]]; then - __error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'" - return 1 - fi - version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" - local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" - - { - if [ ! -d "$korebuild_path" ]; then - mkdir -p "$korebuild_path" - local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" - tmpfile="$(mktemp)" - echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" - if __get_remote_file "$remote_path" "$tmpfile"; then - unzip -q -d "$korebuild_path" "$tmpfile" - fi - rm "$tmpfile" || true - fi - - source "$korebuild_path/KoreBuild.sh" - } || { - if [ -d "$korebuild_path" ]; then - echo "Cleaning up after failed installation" - rm -rf "$korebuild_path" || true - fi - return 1 - } -} - -__error() { - echo -e "${RED}$*${RESET}" 1>&2 -} - -__machine_has() { - hash "$1" > /dev/null 2>&1 - return $? -} - -__get_remote_file() { - local remote_path=$1 - local local_path=$2 - - if [[ "$remote_path" != 'http'* ]]; then - cp "$remote_path" "$local_path" - return 0 - fi - - local failed=false - if __machine_has wget; then - wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true - else - failed=true - fi - - if [ "$failed" = true ] && __machine_has curl; then - failed=false - curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true - fi - - if [ "$failed" = true ]; then - __error "Download failed: $remote_path" 1>&2 - return 1 - fi -} - -__read_dom () { local IFS=\> ; read -r -d \< ENTITY CONTENT ;} - -# -# main -# - -while [[ $# -gt 0 ]]; do - case $1 in - -\?|-h|--help) - __usage --no-exit - exit 0 - ;; - -c|--channel|-Channel) - shift - channel="${1:-}" - [ -z "$channel" ] && __usage - ;; - --config-file|-ConfigFile) - shift - config_file="${1:-}" - [ -z "$config_file" ] && __usage - ;; - -d|--dotnet-home|-DotNetHome) - shift - DOTNET_HOME="${1:-}" - [ -z "$DOTNET_HOME" ] && __usage - ;; - --path|-Path) - shift - repo_path="${1:-}" - [ -z "$repo_path" ] && __usage - ;; - -s|--tools-source|-ToolsSource) - shift - tools_source="${1:-}" - [ -z "$tools_source" ] && __usage - ;; - -u|--update|-Update) - update=true - ;; - --verbose|-Verbose) - verbose=true - ;; - --) - shift - break - ;; - *) - break - ;; - esac - shift -done - -if ! __machine_has unzip; then - __error 'Missing required command: unzip' - exit 1 -fi - -if ! __machine_has curl && ! __machine_has wget; then - __error 'Missing required command. Either wget or curl is required.' - exit 1 -fi - -if [ -f "$config_file" ]; then - comment=false - while __read_dom; do - if [ "$comment" = true ]; then [[ $CONTENT == *'-->'* ]] && comment=false ; continue; fi - if [[ $ENTITY == '!--'* ]]; then comment=true; continue; fi - if [ -z "$channel" ] && [[ $ENTITY == "KoreBuildChannel" ]]; then channel=$CONTENT; fi - if [ -z "$tools_source" ] && [[ $ENTITY == "KoreBuildToolsSource" ]]; then tools_source=$CONTENT; fi - done < "$config_file" -fi - -[ -z "$channel" ] && channel='dev' -[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' - -get_korebuild -install_tools "$tools_source" "$DOTNET_HOME" -invoke_repository_build "$repo_path" "$@" +# Call "sync" between "chmod" and execution to prevent "text file busy" error in Docker (aufs) +chmod +x "$DIR/run.sh"; sync +"$DIR/run.sh" default-build "$@" diff --git a/run.cmd b/run.cmd new file mode 100644 index 0000000000..d52d5c7e68 --- /dev/null +++ b/run.cmd @@ -0,0 +1,2 @@ +@ECHO OFF +PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' %*; exit $LASTEXITCODE" diff --git a/build.ps1 b/run.ps1 similarity index 73% rename from build.ps1 rename to run.ps1 index d5eb4d5cf2..49c2899856 100644 --- a/build.ps1 +++ b/run.ps1 @@ -3,10 +3,13 @@ <# .SYNOPSIS -Build this repository +Executes KoreBuild commands. .DESCRIPTION -Downloads korebuild if required. Then builds the repository. +Downloads korebuild if required. Then executes the KoreBuild command. To see available commands, execute with `-Command help`. + +.PARAMETER Command +The KoreBuild command to run. .PARAMETER Path The folder to build. Defaults to the folder containing this script. @@ -24,31 +27,32 @@ The base url where build tools can be downloaded. Overrides the value from the c Updates KoreBuild to the latest version even if a lock file is present. .PARAMETER ConfigFile -The path to the configuration file that stores values. Defaults to version.xml. +The path to the configuration file that stores values. Defaults to korebuild.json. -.PARAMETER MSBuildArgs -Arguments to be passed to MSBuild +.PARAMETER Arguments +Arguments to be passed to the command .NOTES This function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be. When the lockfile is not present, KoreBuild will create one using latest available version from $Channel. -The $ConfigFile is expected to be an XML file. It is optional, and the configuration values in it are optional as well. +The $ConfigFile is expected to be an JSON file. It is optional, and the configuration values in it are optional as well. Any options set +in the file are overridden by command line parameters. .EXAMPLE Example config file: -```xml - - - - dev - https://aspnetcore.blob.core.windows.net/buildtools - - +```json +{ + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", + "channel": "dev", + "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" +} ``` #> [CmdletBinding(PositionalBinding = $false)] param( + [Parameter(Mandatory=$true, Position = 0)] + [string]$Command, [string]$Path = $PSScriptRoot, [Alias('c')] [string]$Channel, @@ -58,9 +62,9 @@ param( [string]$ToolsSource, [Alias('u')] [switch]$Update, - [string]$ConfigFile = (Join-Path $PSScriptRoot 'version.xml'), + [string]$ConfigFile, [Parameter(ValueFromRemainingArguments = $true)] - [string[]]$MSBuildArgs + [string[]]$Arguments ) Set-StrictMode -Version 2 @@ -147,10 +151,20 @@ function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) { # Load configuration or set defaults +$Path = Resolve-Path $Path +if (!$ConfigFile) { $ConfigFile = Join-Path $Path 'korebuild.json' } + if (Test-Path $ConfigFile) { - [xml] $config = Get-Content $ConfigFile - if (!($Channel)) { [string] $Channel = Select-Xml -Xml $config -XPath '/Project/PropertyGroup/KoreBuildChannel' } - if (!($ToolsSource)) { [string] $ToolsSource = Select-Xml -Xml $config -XPath '/Project/PropertyGroup/KoreBuildToolsSource' } + try { + $config = Get-Content -Raw -Encoding UTF8 -Path $ConfigFile | ConvertFrom-Json + if ($config) { + if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel } + if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource} + } + } catch { + Write-Warning "$ConfigFile could not be read. Its settings will be ignored." + Write-Warning $Error[0] + } } if (!$DotNetHome) { @@ -169,8 +183,8 @@ $korebuildPath = Get-KoreBuild Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1') try { - Install-Tools $ToolsSource $DotNetHome - Invoke-RepositoryBuild $Path @MSBuildArgs + Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile + Invoke-KoreBuildCommand $Command @Arguments } finally { Remove-Module 'KoreBuild' -ErrorAction Ignore diff --git a/run.sh b/run.sh new file mode 100755 index 0000000000..c278423acc --- /dev/null +++ b/run.sh @@ -0,0 +1,223 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# +# variables +# + +RESET="\033[0m" +RED="\033[0;31m" +YELLOW="\033[0;33m" +MAGENTA="\033[0;95m" +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" +verbose=false +update=false +repo_path="$DIR" +channel='' +tools_source='' + +# +# Functions +# +__usage() { + echo "Usage: $(basename "${BASH_SOURCE[0]}") command [options] [[--] ...]" + echo "" + echo "Arguments:" + echo " command The command to be run." + echo " ... Arguments passed to the command. Variable number of arguments allowed." + echo "" + echo "Options:" + echo " --verbose Show verbose output." + echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." + echo " --config-file The path to the configuration file that stores values. Defaults to korebuild.json." + echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." + echo " --path The directory to build. Defaults to the directory containing the script." + echo " -s|--tools-source|-ToolsSource The base url where build tools can be downloaded. Overrides the value from the config file." + echo " -u|--update Update to the latest KoreBuild even if the lock file is present." + echo "" + echo "Description:" + echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." + echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel." + + if [[ "${1:-}" != '--no-exit' ]]; then + exit 2 + fi +} + +get_korebuild() { + local version + local lock_file="$repo_path/korebuild-lock.txt" + if [ ! -f "$lock_file" ] || [ "$update" = true ]; then + __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" + fi + version="$(grep 'version:*' -m 1 "$lock_file")" + if [[ "$version" == '' ]]; then + __error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'" + return 1 + fi + version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" + + { + if [ ! -d "$korebuild_path" ]; then + mkdir -p "$korebuild_path" + local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" + tmpfile="$(mktemp)" + echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" + if __get_remote_file "$remote_path" "$tmpfile"; then + unzip -q -d "$korebuild_path" "$tmpfile" + fi + rm "$tmpfile" || true + fi + + source "$korebuild_path/KoreBuild.sh" + } || { + if [ -d "$korebuild_path" ]; then + echo "Cleaning up after failed installation" + rm -rf "$korebuild_path" || true + fi + return 1 + } +} + +__error() { + echo -e "${RED}error: $*${RESET}" 1>&2 +} + +__warn() { + echo -e "${YELLOW}warning: $*${RESET}" +} + +__machine_has() { + hash "$1" > /dev/null 2>&1 + return $? +} + +__get_remote_file() { + local remote_path=$1 + local local_path=$2 + + if [[ "$remote_path" != 'http'* ]]; then + cp "$remote_path" "$local_path" + return 0 + fi + + local failed=false + if __machine_has wget; then + wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true + else + failed=true + fi + + if [ "$failed" = true ] && __machine_has curl; then + failed=false + curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true + fi + + if [ "$failed" = true ]; then + __error "Download failed: $remote_path" 1>&2 + return 1 + fi +} + +# +# main +# + +command="${1:-}" +shift + +while [[ $# -gt 0 ]]; do + case $1 in + -\?|-h|--help) + __usage --no-exit + exit 0 + ;; + -c|--channel|-Channel) + shift + channel="${1:-}" + [ -z "$channel" ] && __usage + ;; + --config-file|-ConfigFile) + shift + config_file="${1:-}" + [ -z "$config_file" ] && __usage + if [ ! -f "$config_file" ]; then + __error "Invalid value for --config-file. $config_file does not exist." + exit 1 + fi + ;; + -d|--dotnet-home|-DotNetHome) + shift + DOTNET_HOME="${1:-}" + [ -z "$DOTNET_HOME" ] && __usage + ;; + --path|-Path) + shift + repo_path="${1:-}" + [ -z "$repo_path" ] && __usage + ;; + -s|--tools-source|-ToolsSource) + shift + tools_source="${1:-}" + [ -z "$tools_source" ] && __usage + ;; + -u|--update|-Update) + update=true + ;; + --verbose|-Verbose) + verbose=true + ;; + --) + shift + break + ;; + *) + break + ;; + esac + shift +done + +if ! __machine_has unzip; then + __error 'Missing required command: unzip' + exit 1 +fi + +if ! __machine_has curl && ! __machine_has wget; then + __error 'Missing required command. Either wget or curl is required.' + exit 1 +fi + +[ -z "${config_file:-}" ] && config_file="$repo_path/korebuild.json" +if [ -f "$config_file" ]; then + if __machine_has jq ; then + if jq '.' "$config_file" >/dev/null ; then + config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" + config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")" + else + __warn "$config_file is invalid JSON. Its settings will be ignored." + fi + elif __machine_has python ; then + if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then + config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" + config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" + else + __warn "$config_file is invalid JSON. Its settings will be ignored." + fi + else + __warn 'Missing required command: jq or pyton. Could not parse the JSON file. Its settings will be ignored.' + fi + + [ ! -z "${config_channel:-}" ] && channel="$config_channel" + [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" +fi + +[ -z "$channel" ] && channel='dev' +[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' + +get_korebuild +set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file" +invoke_korebuild_command "$command" "$@" From e4a412e1644dfea026b20c8625a6f5a636ee1134 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Wed, 20 Sep 2017 13:21:17 -0700 Subject: [PATCH 0596/1029] Update bootstrappers --- .appveyor.yml | 4 +- build.cmd | 2 +- build.sh | 197 +------------------------------------- run.cmd | 2 + build.ps1 => run.ps1 | 56 +++++++---- run.sh | 223 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 266 insertions(+), 218 deletions(-) create mode 100644 run.cmd rename build.ps1 => run.ps1 (73%) create mode 100755 run.sh diff --git a/.appveyor.yml b/.appveyor.yml index 31efd8196f..46038786c9 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,4 +1,4 @@ -init: +init: - git config --global core.autocrlf true branches: only: @@ -7,7 +7,7 @@ branches: - dev - /^(.*\/)?ci-.*$/ build_script: - - ps: .\build.ps1 + - ps: .\run.ps1 default-build clone_depth: 1 environment: global: diff --git a/build.cmd b/build.cmd index b6c8d24864..c0050bda12 100644 --- a/build.cmd +++ b/build.cmd @@ -1,2 +1,2 @@ @ECHO OFF -PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*; exit $LASTEXITCODE" +PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' default-build %*; exit $LASTEXITCODE" diff --git a/build.sh b/build.sh index 11cdbe5504..98a4b22765 100755 --- a/build.sh +++ b/build.sh @@ -1,199 +1,8 @@ #!/usr/bin/env bash set -euo pipefail - -# -# variables -# - -RESET="\033[0m" -RED="\033[0;31m" -MAGENTA="\033[0;95m" DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" -config_file="$DIR/version.xml" -verbose=false -update=false -repo_path="$DIR" -channel='' -tools_source='' -# -# Functions -# -__usage() { - echo "Usage: $(basename "${BASH_SOURCE[0]}") [options] [[--] ...]" - echo "" - echo "Arguments:" - echo " ... Arguments passed to MSBuild. Variable number of arguments allowed." - echo "" - echo "Options:" - echo " --verbose Show verbose output." - echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." - echo " --config-file TThe path to the configuration file that stores values. Defaults to version.xml." - echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." - echo " --path The directory to build. Defaults to the directory containing the script." - echo " -s|--tools-source The base url where build tools can be downloaded. Overrides the value from the config file." - echo " -u|--update Update to the latest KoreBuild even if the lock file is present." - echo "" - echo "Description:" - echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." - echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel." - - if [[ "${1:-}" != '--no-exit' ]]; then - exit 2 - fi -} - -get_korebuild() { - local version - local lock_file="$repo_path/korebuild-lock.txt" - if [ ! -f "$lock_file" ] || [ "$update" = true ]; then - __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" - fi - version="$(grep 'version:*' -m 1 "$lock_file")" - if [[ "$version" == '' ]]; then - __error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'" - return 1 - fi - version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" - local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" - - { - if [ ! -d "$korebuild_path" ]; then - mkdir -p "$korebuild_path" - local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" - tmpfile="$(mktemp)" - echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" - if __get_remote_file "$remote_path" "$tmpfile"; then - unzip -q -d "$korebuild_path" "$tmpfile" - fi - rm "$tmpfile" || true - fi - - source "$korebuild_path/KoreBuild.sh" - } || { - if [ -d "$korebuild_path" ]; then - echo "Cleaning up after failed installation" - rm -rf "$korebuild_path" || true - fi - return 1 - } -} - -__error() { - echo -e "${RED}$*${RESET}" 1>&2 -} - -__machine_has() { - hash "$1" > /dev/null 2>&1 - return $? -} - -__get_remote_file() { - local remote_path=$1 - local local_path=$2 - - if [[ "$remote_path" != 'http'* ]]; then - cp "$remote_path" "$local_path" - return 0 - fi - - local failed=false - if __machine_has wget; then - wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true - else - failed=true - fi - - if [ "$failed" = true ] && __machine_has curl; then - failed=false - curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true - fi - - if [ "$failed" = true ]; then - __error "Download failed: $remote_path" 1>&2 - return 1 - fi -} - -__read_dom () { local IFS=\> ; read -r -d \< ENTITY CONTENT ;} - -# -# main -# - -while [[ $# -gt 0 ]]; do - case $1 in - -\?|-h|--help) - __usage --no-exit - exit 0 - ;; - -c|--channel|-Channel) - shift - channel="${1:-}" - [ -z "$channel" ] && __usage - ;; - --config-file|-ConfigFile) - shift - config_file="${1:-}" - [ -z "$config_file" ] && __usage - ;; - -d|--dotnet-home|-DotNetHome) - shift - DOTNET_HOME="${1:-}" - [ -z "$DOTNET_HOME" ] && __usage - ;; - --path|-Path) - shift - repo_path="${1:-}" - [ -z "$repo_path" ] && __usage - ;; - -s|--tools-source|-ToolsSource) - shift - tools_source="${1:-}" - [ -z "$tools_source" ] && __usage - ;; - -u|--update|-Update) - update=true - ;; - --verbose|-Verbose) - verbose=true - ;; - --) - shift - break - ;; - *) - break - ;; - esac - shift -done - -if ! __machine_has unzip; then - __error 'Missing required command: unzip' - exit 1 -fi - -if ! __machine_has curl && ! __machine_has wget; then - __error 'Missing required command. Either wget or curl is required.' - exit 1 -fi - -if [ -f "$config_file" ]; then - comment=false - while __read_dom; do - if [ "$comment" = true ]; then [[ $CONTENT == *'-->'* ]] && comment=false ; continue; fi - if [[ $ENTITY == '!--'* ]]; then comment=true; continue; fi - if [ -z "$channel" ] && [[ $ENTITY == "KoreBuildChannel" ]]; then channel=$CONTENT; fi - if [ -z "$tools_source" ] && [[ $ENTITY == "KoreBuildToolsSource" ]]; then tools_source=$CONTENT; fi - done < "$config_file" -fi - -[ -z "$channel" ] && channel='dev' -[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' - -get_korebuild -install_tools "$tools_source" "$DOTNET_HOME" -invoke_repository_build "$repo_path" "$@" +# Call "sync" between "chmod" and execution to prevent "text file busy" error in Docker (aufs) +chmod +x "$DIR/run.sh"; sync +"$DIR/run.sh" default-build "$@" diff --git a/run.cmd b/run.cmd new file mode 100644 index 0000000000..d52d5c7e68 --- /dev/null +++ b/run.cmd @@ -0,0 +1,2 @@ +@ECHO OFF +PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' %*; exit $LASTEXITCODE" diff --git a/build.ps1 b/run.ps1 similarity index 73% rename from build.ps1 rename to run.ps1 index d5eb4d5cf2..49c2899856 100644 --- a/build.ps1 +++ b/run.ps1 @@ -3,10 +3,13 @@ <# .SYNOPSIS -Build this repository +Executes KoreBuild commands. .DESCRIPTION -Downloads korebuild if required. Then builds the repository. +Downloads korebuild if required. Then executes the KoreBuild command. To see available commands, execute with `-Command help`. + +.PARAMETER Command +The KoreBuild command to run. .PARAMETER Path The folder to build. Defaults to the folder containing this script. @@ -24,31 +27,32 @@ The base url where build tools can be downloaded. Overrides the value from the c Updates KoreBuild to the latest version even if a lock file is present. .PARAMETER ConfigFile -The path to the configuration file that stores values. Defaults to version.xml. +The path to the configuration file that stores values. Defaults to korebuild.json. -.PARAMETER MSBuildArgs -Arguments to be passed to MSBuild +.PARAMETER Arguments +Arguments to be passed to the command .NOTES This function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be. When the lockfile is not present, KoreBuild will create one using latest available version from $Channel. -The $ConfigFile is expected to be an XML file. It is optional, and the configuration values in it are optional as well. +The $ConfigFile is expected to be an JSON file. It is optional, and the configuration values in it are optional as well. Any options set +in the file are overridden by command line parameters. .EXAMPLE Example config file: -```xml - - - - dev - https://aspnetcore.blob.core.windows.net/buildtools - - +```json +{ + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", + "channel": "dev", + "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" +} ``` #> [CmdletBinding(PositionalBinding = $false)] param( + [Parameter(Mandatory=$true, Position = 0)] + [string]$Command, [string]$Path = $PSScriptRoot, [Alias('c')] [string]$Channel, @@ -58,9 +62,9 @@ param( [string]$ToolsSource, [Alias('u')] [switch]$Update, - [string]$ConfigFile = (Join-Path $PSScriptRoot 'version.xml'), + [string]$ConfigFile, [Parameter(ValueFromRemainingArguments = $true)] - [string[]]$MSBuildArgs + [string[]]$Arguments ) Set-StrictMode -Version 2 @@ -147,10 +151,20 @@ function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) { # Load configuration or set defaults +$Path = Resolve-Path $Path +if (!$ConfigFile) { $ConfigFile = Join-Path $Path 'korebuild.json' } + if (Test-Path $ConfigFile) { - [xml] $config = Get-Content $ConfigFile - if (!($Channel)) { [string] $Channel = Select-Xml -Xml $config -XPath '/Project/PropertyGroup/KoreBuildChannel' } - if (!($ToolsSource)) { [string] $ToolsSource = Select-Xml -Xml $config -XPath '/Project/PropertyGroup/KoreBuildToolsSource' } + try { + $config = Get-Content -Raw -Encoding UTF8 -Path $ConfigFile | ConvertFrom-Json + if ($config) { + if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel } + if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource} + } + } catch { + Write-Warning "$ConfigFile could not be read. Its settings will be ignored." + Write-Warning $Error[0] + } } if (!$DotNetHome) { @@ -169,8 +183,8 @@ $korebuildPath = Get-KoreBuild Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1') try { - Install-Tools $ToolsSource $DotNetHome - Invoke-RepositoryBuild $Path @MSBuildArgs + Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile + Invoke-KoreBuildCommand $Command @Arguments } finally { Remove-Module 'KoreBuild' -ErrorAction Ignore diff --git a/run.sh b/run.sh new file mode 100755 index 0000000000..c278423acc --- /dev/null +++ b/run.sh @@ -0,0 +1,223 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# +# variables +# + +RESET="\033[0m" +RED="\033[0;31m" +YELLOW="\033[0;33m" +MAGENTA="\033[0;95m" +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" +verbose=false +update=false +repo_path="$DIR" +channel='' +tools_source='' + +# +# Functions +# +__usage() { + echo "Usage: $(basename "${BASH_SOURCE[0]}") command [options] [[--] ...]" + echo "" + echo "Arguments:" + echo " command The command to be run." + echo " ... Arguments passed to the command. Variable number of arguments allowed." + echo "" + echo "Options:" + echo " --verbose Show verbose output." + echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." + echo " --config-file The path to the configuration file that stores values. Defaults to korebuild.json." + echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." + echo " --path The directory to build. Defaults to the directory containing the script." + echo " -s|--tools-source|-ToolsSource The base url where build tools can be downloaded. Overrides the value from the config file." + echo " -u|--update Update to the latest KoreBuild even if the lock file is present." + echo "" + echo "Description:" + echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." + echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel." + + if [[ "${1:-}" != '--no-exit' ]]; then + exit 2 + fi +} + +get_korebuild() { + local version + local lock_file="$repo_path/korebuild-lock.txt" + if [ ! -f "$lock_file" ] || [ "$update" = true ]; then + __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" + fi + version="$(grep 'version:*' -m 1 "$lock_file")" + if [[ "$version" == '' ]]; then + __error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'" + return 1 + fi + version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" + + { + if [ ! -d "$korebuild_path" ]; then + mkdir -p "$korebuild_path" + local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" + tmpfile="$(mktemp)" + echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" + if __get_remote_file "$remote_path" "$tmpfile"; then + unzip -q -d "$korebuild_path" "$tmpfile" + fi + rm "$tmpfile" || true + fi + + source "$korebuild_path/KoreBuild.sh" + } || { + if [ -d "$korebuild_path" ]; then + echo "Cleaning up after failed installation" + rm -rf "$korebuild_path" || true + fi + return 1 + } +} + +__error() { + echo -e "${RED}error: $*${RESET}" 1>&2 +} + +__warn() { + echo -e "${YELLOW}warning: $*${RESET}" +} + +__machine_has() { + hash "$1" > /dev/null 2>&1 + return $? +} + +__get_remote_file() { + local remote_path=$1 + local local_path=$2 + + if [[ "$remote_path" != 'http'* ]]; then + cp "$remote_path" "$local_path" + return 0 + fi + + local failed=false + if __machine_has wget; then + wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true + else + failed=true + fi + + if [ "$failed" = true ] && __machine_has curl; then + failed=false + curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true + fi + + if [ "$failed" = true ]; then + __error "Download failed: $remote_path" 1>&2 + return 1 + fi +} + +# +# main +# + +command="${1:-}" +shift + +while [[ $# -gt 0 ]]; do + case $1 in + -\?|-h|--help) + __usage --no-exit + exit 0 + ;; + -c|--channel|-Channel) + shift + channel="${1:-}" + [ -z "$channel" ] && __usage + ;; + --config-file|-ConfigFile) + shift + config_file="${1:-}" + [ -z "$config_file" ] && __usage + if [ ! -f "$config_file" ]; then + __error "Invalid value for --config-file. $config_file does not exist." + exit 1 + fi + ;; + -d|--dotnet-home|-DotNetHome) + shift + DOTNET_HOME="${1:-}" + [ -z "$DOTNET_HOME" ] && __usage + ;; + --path|-Path) + shift + repo_path="${1:-}" + [ -z "$repo_path" ] && __usage + ;; + -s|--tools-source|-ToolsSource) + shift + tools_source="${1:-}" + [ -z "$tools_source" ] && __usage + ;; + -u|--update|-Update) + update=true + ;; + --verbose|-Verbose) + verbose=true + ;; + --) + shift + break + ;; + *) + break + ;; + esac + shift +done + +if ! __machine_has unzip; then + __error 'Missing required command: unzip' + exit 1 +fi + +if ! __machine_has curl && ! __machine_has wget; then + __error 'Missing required command. Either wget or curl is required.' + exit 1 +fi + +[ -z "${config_file:-}" ] && config_file="$repo_path/korebuild.json" +if [ -f "$config_file" ]; then + if __machine_has jq ; then + if jq '.' "$config_file" >/dev/null ; then + config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" + config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")" + else + __warn "$config_file is invalid JSON. Its settings will be ignored." + fi + elif __machine_has python ; then + if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then + config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" + config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" + else + __warn "$config_file is invalid JSON. Its settings will be ignored." + fi + else + __warn 'Missing required command: jq or pyton. Could not parse the JSON file. Its settings will be ignored.' + fi + + [ ! -z "${config_channel:-}" ] && channel="$config_channel" + [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" +fi + +[ -z "$channel" ] && channel='dev' +[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' + +get_korebuild +set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file" +invoke_korebuild_command "$command" "$@" From c4788107f50d58bc730a420516f9f62505159652 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Wed, 20 Sep 2017 13:19:32 -0700 Subject: [PATCH 0597/1029] Update bootstrappers --- .appveyor.yml | 4 +- build.cmd | 2 +- build.sh | 197 +------------------------------------- run.cmd | 2 + build.ps1 => run.ps1 | 56 +++++++---- run.sh | 223 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 266 insertions(+), 218 deletions(-) create mode 100644 run.cmd rename build.ps1 => run.ps1 (73%) create mode 100755 run.sh diff --git a/.appveyor.yml b/.appveyor.yml index 8a514a70a3..6ee7cf4664 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,4 +1,4 @@ -init: +init: - git config --global core.autocrlf true branches: only: @@ -8,7 +8,7 @@ branches: - dev - /^(.*\/)?ci-.*$/ build_script: - - ps: .\build.ps1 + - ps: .\run.ps1 default-build clone_depth: 1 environment: global: diff --git a/build.cmd b/build.cmd index b6c8d24864..c0050bda12 100644 --- a/build.cmd +++ b/build.cmd @@ -1,2 +1,2 @@ @ECHO OFF -PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*; exit $LASTEXITCODE" +PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' default-build %*; exit $LASTEXITCODE" diff --git a/build.sh b/build.sh index 11cdbe5504..98a4b22765 100755 --- a/build.sh +++ b/build.sh @@ -1,199 +1,8 @@ #!/usr/bin/env bash set -euo pipefail - -# -# variables -# - -RESET="\033[0m" -RED="\033[0;31m" -MAGENTA="\033[0;95m" DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" -config_file="$DIR/version.xml" -verbose=false -update=false -repo_path="$DIR" -channel='' -tools_source='' -# -# Functions -# -__usage() { - echo "Usage: $(basename "${BASH_SOURCE[0]}") [options] [[--] ...]" - echo "" - echo "Arguments:" - echo " ... Arguments passed to MSBuild. Variable number of arguments allowed." - echo "" - echo "Options:" - echo " --verbose Show verbose output." - echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." - echo " --config-file TThe path to the configuration file that stores values. Defaults to version.xml." - echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." - echo " --path The directory to build. Defaults to the directory containing the script." - echo " -s|--tools-source The base url where build tools can be downloaded. Overrides the value from the config file." - echo " -u|--update Update to the latest KoreBuild even if the lock file is present." - echo "" - echo "Description:" - echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." - echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel." - - if [[ "${1:-}" != '--no-exit' ]]; then - exit 2 - fi -} - -get_korebuild() { - local version - local lock_file="$repo_path/korebuild-lock.txt" - if [ ! -f "$lock_file" ] || [ "$update" = true ]; then - __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" - fi - version="$(grep 'version:*' -m 1 "$lock_file")" - if [[ "$version" == '' ]]; then - __error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'" - return 1 - fi - version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" - local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" - - { - if [ ! -d "$korebuild_path" ]; then - mkdir -p "$korebuild_path" - local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" - tmpfile="$(mktemp)" - echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" - if __get_remote_file "$remote_path" "$tmpfile"; then - unzip -q -d "$korebuild_path" "$tmpfile" - fi - rm "$tmpfile" || true - fi - - source "$korebuild_path/KoreBuild.sh" - } || { - if [ -d "$korebuild_path" ]; then - echo "Cleaning up after failed installation" - rm -rf "$korebuild_path" || true - fi - return 1 - } -} - -__error() { - echo -e "${RED}$*${RESET}" 1>&2 -} - -__machine_has() { - hash "$1" > /dev/null 2>&1 - return $? -} - -__get_remote_file() { - local remote_path=$1 - local local_path=$2 - - if [[ "$remote_path" != 'http'* ]]; then - cp "$remote_path" "$local_path" - return 0 - fi - - local failed=false - if __machine_has wget; then - wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true - else - failed=true - fi - - if [ "$failed" = true ] && __machine_has curl; then - failed=false - curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true - fi - - if [ "$failed" = true ]; then - __error "Download failed: $remote_path" 1>&2 - return 1 - fi -} - -__read_dom () { local IFS=\> ; read -r -d \< ENTITY CONTENT ;} - -# -# main -# - -while [[ $# -gt 0 ]]; do - case $1 in - -\?|-h|--help) - __usage --no-exit - exit 0 - ;; - -c|--channel|-Channel) - shift - channel="${1:-}" - [ -z "$channel" ] && __usage - ;; - --config-file|-ConfigFile) - shift - config_file="${1:-}" - [ -z "$config_file" ] && __usage - ;; - -d|--dotnet-home|-DotNetHome) - shift - DOTNET_HOME="${1:-}" - [ -z "$DOTNET_HOME" ] && __usage - ;; - --path|-Path) - shift - repo_path="${1:-}" - [ -z "$repo_path" ] && __usage - ;; - -s|--tools-source|-ToolsSource) - shift - tools_source="${1:-}" - [ -z "$tools_source" ] && __usage - ;; - -u|--update|-Update) - update=true - ;; - --verbose|-Verbose) - verbose=true - ;; - --) - shift - break - ;; - *) - break - ;; - esac - shift -done - -if ! __machine_has unzip; then - __error 'Missing required command: unzip' - exit 1 -fi - -if ! __machine_has curl && ! __machine_has wget; then - __error 'Missing required command. Either wget or curl is required.' - exit 1 -fi - -if [ -f "$config_file" ]; then - comment=false - while __read_dom; do - if [ "$comment" = true ]; then [[ $CONTENT == *'-->'* ]] && comment=false ; continue; fi - if [[ $ENTITY == '!--'* ]]; then comment=true; continue; fi - if [ -z "$channel" ] && [[ $ENTITY == "KoreBuildChannel" ]]; then channel=$CONTENT; fi - if [ -z "$tools_source" ] && [[ $ENTITY == "KoreBuildToolsSource" ]]; then tools_source=$CONTENT; fi - done < "$config_file" -fi - -[ -z "$channel" ] && channel='dev' -[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' - -get_korebuild -install_tools "$tools_source" "$DOTNET_HOME" -invoke_repository_build "$repo_path" "$@" +# Call "sync" between "chmod" and execution to prevent "text file busy" error in Docker (aufs) +chmod +x "$DIR/run.sh"; sync +"$DIR/run.sh" default-build "$@" diff --git a/run.cmd b/run.cmd new file mode 100644 index 0000000000..d52d5c7e68 --- /dev/null +++ b/run.cmd @@ -0,0 +1,2 @@ +@ECHO OFF +PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' %*; exit $LASTEXITCODE" diff --git a/build.ps1 b/run.ps1 similarity index 73% rename from build.ps1 rename to run.ps1 index d5eb4d5cf2..49c2899856 100644 --- a/build.ps1 +++ b/run.ps1 @@ -3,10 +3,13 @@ <# .SYNOPSIS -Build this repository +Executes KoreBuild commands. .DESCRIPTION -Downloads korebuild if required. Then builds the repository. +Downloads korebuild if required. Then executes the KoreBuild command. To see available commands, execute with `-Command help`. + +.PARAMETER Command +The KoreBuild command to run. .PARAMETER Path The folder to build. Defaults to the folder containing this script. @@ -24,31 +27,32 @@ The base url where build tools can be downloaded. Overrides the value from the c Updates KoreBuild to the latest version even if a lock file is present. .PARAMETER ConfigFile -The path to the configuration file that stores values. Defaults to version.xml. +The path to the configuration file that stores values. Defaults to korebuild.json. -.PARAMETER MSBuildArgs -Arguments to be passed to MSBuild +.PARAMETER Arguments +Arguments to be passed to the command .NOTES This function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be. When the lockfile is not present, KoreBuild will create one using latest available version from $Channel. -The $ConfigFile is expected to be an XML file. It is optional, and the configuration values in it are optional as well. +The $ConfigFile is expected to be an JSON file. It is optional, and the configuration values in it are optional as well. Any options set +in the file are overridden by command line parameters. .EXAMPLE Example config file: -```xml - - - - dev - https://aspnetcore.blob.core.windows.net/buildtools - - +```json +{ + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", + "channel": "dev", + "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" +} ``` #> [CmdletBinding(PositionalBinding = $false)] param( + [Parameter(Mandatory=$true, Position = 0)] + [string]$Command, [string]$Path = $PSScriptRoot, [Alias('c')] [string]$Channel, @@ -58,9 +62,9 @@ param( [string]$ToolsSource, [Alias('u')] [switch]$Update, - [string]$ConfigFile = (Join-Path $PSScriptRoot 'version.xml'), + [string]$ConfigFile, [Parameter(ValueFromRemainingArguments = $true)] - [string[]]$MSBuildArgs + [string[]]$Arguments ) Set-StrictMode -Version 2 @@ -147,10 +151,20 @@ function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) { # Load configuration or set defaults +$Path = Resolve-Path $Path +if (!$ConfigFile) { $ConfigFile = Join-Path $Path 'korebuild.json' } + if (Test-Path $ConfigFile) { - [xml] $config = Get-Content $ConfigFile - if (!($Channel)) { [string] $Channel = Select-Xml -Xml $config -XPath '/Project/PropertyGroup/KoreBuildChannel' } - if (!($ToolsSource)) { [string] $ToolsSource = Select-Xml -Xml $config -XPath '/Project/PropertyGroup/KoreBuildToolsSource' } + try { + $config = Get-Content -Raw -Encoding UTF8 -Path $ConfigFile | ConvertFrom-Json + if ($config) { + if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel } + if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource} + } + } catch { + Write-Warning "$ConfigFile could not be read. Its settings will be ignored." + Write-Warning $Error[0] + } } if (!$DotNetHome) { @@ -169,8 +183,8 @@ $korebuildPath = Get-KoreBuild Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1') try { - Install-Tools $ToolsSource $DotNetHome - Invoke-RepositoryBuild $Path @MSBuildArgs + Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile + Invoke-KoreBuildCommand $Command @Arguments } finally { Remove-Module 'KoreBuild' -ErrorAction Ignore diff --git a/run.sh b/run.sh new file mode 100755 index 0000000000..c278423acc --- /dev/null +++ b/run.sh @@ -0,0 +1,223 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# +# variables +# + +RESET="\033[0m" +RED="\033[0;31m" +YELLOW="\033[0;33m" +MAGENTA="\033[0;95m" +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" +verbose=false +update=false +repo_path="$DIR" +channel='' +tools_source='' + +# +# Functions +# +__usage() { + echo "Usage: $(basename "${BASH_SOURCE[0]}") command [options] [[--] ...]" + echo "" + echo "Arguments:" + echo " command The command to be run." + echo " ... Arguments passed to the command. Variable number of arguments allowed." + echo "" + echo "Options:" + echo " --verbose Show verbose output." + echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." + echo " --config-file The path to the configuration file that stores values. Defaults to korebuild.json." + echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." + echo " --path The directory to build. Defaults to the directory containing the script." + echo " -s|--tools-source|-ToolsSource The base url where build tools can be downloaded. Overrides the value from the config file." + echo " -u|--update Update to the latest KoreBuild even if the lock file is present." + echo "" + echo "Description:" + echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." + echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel." + + if [[ "${1:-}" != '--no-exit' ]]; then + exit 2 + fi +} + +get_korebuild() { + local version + local lock_file="$repo_path/korebuild-lock.txt" + if [ ! -f "$lock_file" ] || [ "$update" = true ]; then + __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" + fi + version="$(grep 'version:*' -m 1 "$lock_file")" + if [[ "$version" == '' ]]; then + __error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'" + return 1 + fi + version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" + + { + if [ ! -d "$korebuild_path" ]; then + mkdir -p "$korebuild_path" + local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" + tmpfile="$(mktemp)" + echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" + if __get_remote_file "$remote_path" "$tmpfile"; then + unzip -q -d "$korebuild_path" "$tmpfile" + fi + rm "$tmpfile" || true + fi + + source "$korebuild_path/KoreBuild.sh" + } || { + if [ -d "$korebuild_path" ]; then + echo "Cleaning up after failed installation" + rm -rf "$korebuild_path" || true + fi + return 1 + } +} + +__error() { + echo -e "${RED}error: $*${RESET}" 1>&2 +} + +__warn() { + echo -e "${YELLOW}warning: $*${RESET}" +} + +__machine_has() { + hash "$1" > /dev/null 2>&1 + return $? +} + +__get_remote_file() { + local remote_path=$1 + local local_path=$2 + + if [[ "$remote_path" != 'http'* ]]; then + cp "$remote_path" "$local_path" + return 0 + fi + + local failed=false + if __machine_has wget; then + wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true + else + failed=true + fi + + if [ "$failed" = true ] && __machine_has curl; then + failed=false + curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true + fi + + if [ "$failed" = true ]; then + __error "Download failed: $remote_path" 1>&2 + return 1 + fi +} + +# +# main +# + +command="${1:-}" +shift + +while [[ $# -gt 0 ]]; do + case $1 in + -\?|-h|--help) + __usage --no-exit + exit 0 + ;; + -c|--channel|-Channel) + shift + channel="${1:-}" + [ -z "$channel" ] && __usage + ;; + --config-file|-ConfigFile) + shift + config_file="${1:-}" + [ -z "$config_file" ] && __usage + if [ ! -f "$config_file" ]; then + __error "Invalid value for --config-file. $config_file does not exist." + exit 1 + fi + ;; + -d|--dotnet-home|-DotNetHome) + shift + DOTNET_HOME="${1:-}" + [ -z "$DOTNET_HOME" ] && __usage + ;; + --path|-Path) + shift + repo_path="${1:-}" + [ -z "$repo_path" ] && __usage + ;; + -s|--tools-source|-ToolsSource) + shift + tools_source="${1:-}" + [ -z "$tools_source" ] && __usage + ;; + -u|--update|-Update) + update=true + ;; + --verbose|-Verbose) + verbose=true + ;; + --) + shift + break + ;; + *) + break + ;; + esac + shift +done + +if ! __machine_has unzip; then + __error 'Missing required command: unzip' + exit 1 +fi + +if ! __machine_has curl && ! __machine_has wget; then + __error 'Missing required command. Either wget or curl is required.' + exit 1 +fi + +[ -z "${config_file:-}" ] && config_file="$repo_path/korebuild.json" +if [ -f "$config_file" ]; then + if __machine_has jq ; then + if jq '.' "$config_file" >/dev/null ; then + config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" + config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")" + else + __warn "$config_file is invalid JSON. Its settings will be ignored." + fi + elif __machine_has python ; then + if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then + config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" + config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" + else + __warn "$config_file is invalid JSON. Its settings will be ignored." + fi + else + __warn 'Missing required command: jq or pyton. Could not parse the JSON file. Its settings will be ignored.' + fi + + [ ! -z "${config_channel:-}" ] && channel="$config_channel" + [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" +fi + +[ -z "$channel" ] && channel='dev' +[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' + +get_korebuild +set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file" +invoke_korebuild_command "$command" "$@" From f1efb29b18d1dece867300f2d6f2115e9fd0e248 Mon Sep 17 00:00:00 2001 From: Jass Bagga Date: Wed, 11 Oct 2017 14:09:35 -0700 Subject: [PATCH 0598/1029] Use ContractResolver instead of forcing to lower case (#112) Addresses #90 --- .../JsonPatchDocumentOfT.cs | 17 +++++++++-------- .../JsonPatchDocumentGetPathTest.cs | 4 ++-- ...sonPatchDocumentJsonPropertyAttributeTest.cs | 14 +++++++------- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs index 33e1e5033f..5b9df2b52b 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs @@ -691,12 +691,13 @@ namespace Microsoft.AspNetCore.JsonPatch { foreach (var op in Operations) { - var untypedOp = new Operation(); - - untypedOp.op = op.op; - untypedOp.value = op.value; - untypedOp.path = op.path; - untypedOp.from = op.from; + var untypedOp = new Operation + { + op = op.op, + value = op.value, + path = op.path, + from = op.from + }; allOps.Add(untypedOp); } @@ -715,11 +716,11 @@ namespace Microsoft.AspNetCore.JsonPatch path += "/" + position; if (segments.Count == 0) { - return path.ToLowerInvariant(); + return path; } } - return "/" + path.ToLowerInvariant(); + return "/" + path; } private List GetPathSegments(Expression expr) diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentGetPathTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentGetPathTest.cs index dcde4b442d..7d3331231c 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentGetPathTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentGetPathTest.cs @@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.JsonPatch var path = patchDocument.GetPath(p => p.SimpleObject.IntegerList, "-"); // Assert - Assert.Equal("/simpleobject/integerlist/-", path); + Assert.Equal("/SimpleObject/IntegerList/-", path); } [Fact] @@ -84,7 +84,7 @@ namespace Microsoft.AspNetCore.JsonPatch var path = patchDocument.GetPath(p => (BaseClass)p.DerivedObject, null); // Assert - Assert.Equal("/derivedobject", path); + Assert.Equal("/DerivedObject", path); } [Fact] diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs index 50ab6a9f5b..882e09ffe7 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs @@ -56,7 +56,7 @@ namespace Microsoft.AspNetCore.JsonPatch // get path var pathToCheck = deserialized.Operations.First().path; - Assert.Equal("/anothername", pathToCheck); + Assert.Equal("/AnotherName", pathToCheck); } [Fact] @@ -73,7 +73,7 @@ namespace Microsoft.AspNetCore.JsonPatch // Assert var pathToCheck = deserialized.Operations.First().path; - Assert.Equal("/stringproperty", pathToCheck); + Assert.Equal("/StringProperty", pathToCheck); } [Fact] @@ -90,7 +90,7 @@ namespace Microsoft.AspNetCore.JsonPatch // Assert var pathToCheck = deserialized.Operations.First().path; - Assert.Equal("/arrayproperty/-", pathToCheck); + Assert.Equal("/ArrayProperty/-", pathToCheck); } [Fact] @@ -209,7 +209,7 @@ namespace Microsoft.AspNetCore.JsonPatch // get path var pathToCheck = deserialized.Operations.First().path; - Assert.Equal("/anothername", pathToCheck); + Assert.Equal("/AnotherName", pathToCheck); } [Fact] @@ -249,9 +249,9 @@ namespace Microsoft.AspNetCore.JsonPatch // Assert var fromPath = deserialized.Operations.First().from; - Assert.Equal("/stringproperty", fromPath); + Assert.Equal("/StringProperty", fromPath); var toPath = deserialized.Operations.First().path; - Assert.Equal("/stringproperty2", toPath); + Assert.Equal("/StringProperty2", toPath); } [Fact] @@ -269,7 +269,7 @@ namespace Microsoft.AspNetCore.JsonPatch // Assert var path = deserialized.Operations.First().path; - Assert.Equal("/socialsecuritynumber", path); + Assert.Equal("/SocialSecurityNumber", path); } private class JsonPropertyWithNoPropertyName From ff0f112d7bc6b6d8f84f7ec3655f14d3d3d64a4e Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Mon, 9 Oct 2017 13:29:57 -0700 Subject: [PATCH 0599/1029] Add HTTPS developer certificate management tool --- DotNetTools.sln | 21 +- NuGetPackageVerifier.json | 10 +- .../CertificateManager.cs | 96 -------- .../GenerateSSLCertificateTask.cs | 43 ---- ...pNetCore.CertificateGeneration.Task.csproj | 18 -- .../README.md | 48 ---- ...NetCore.CertificateGeneration.Task.targets | 20 -- ...NetCore.DeveloperCertificates.Tools.csproj | 35 +++ .../Program.cs | 144 +++++++++++ .../prefercliruntime | 0 .../GenerateSSLCertificateTaskTest.cs | 229 ------------------ ...re.CertificateGeneration.Task.Tests.csproj | 15 -- 12 files changed, 190 insertions(+), 489 deletions(-) delete mode 100644 src/Microsoft.AspNetCore.CertificateGeneration.Task/CertificateManager.cs delete mode 100644 src/Microsoft.AspNetCore.CertificateGeneration.Task/GenerateSSLCertificateTask.cs delete mode 100644 src/Microsoft.AspNetCore.CertificateGeneration.Task/Microsoft.AspNetCore.CertificateGeneration.Task.csproj delete mode 100644 src/Microsoft.AspNetCore.CertificateGeneration.Task/README.md delete mode 100644 src/Microsoft.AspNetCore.CertificateGeneration.Task/build/Microsoft.AspNetCore.CertificateGeneration.Task.targets create mode 100644 src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj create mode 100644 src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Program.cs create mode 100644 src/Microsoft.AspNetCore.DeveloperCertificates.Tools/prefercliruntime delete mode 100644 test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/GenerateSSLCertificateTaskTest.cs delete mode 100644 test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj diff --git a/DotNetTools.sln b/DotNetTools.sln index 8e317e7fc0..d3c6048370 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26815.3 +VisualStudioVersion = 15.0.26927.1 MinimumVisualStudioVersion = 15.0.26730.03 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66517987-2A5A-4330-B130-207039378FD4}" ProjectSection(SolutionItems) = preProject @@ -44,9 +44,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Watcher.To EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Caching.SqlConfig.Tools", "src\Microsoft.Extensions.Caching.SqlConfig.Tools\Microsoft.Extensions.Caching.SqlConfig.Tools.csproj", "{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.CertificateGeneration.Task", "src\Microsoft.AspNetCore.CertificateGeneration.Task\Microsoft.AspNetCore.CertificateGeneration.Task.csproj", "{7B293291-26F4-47F0-9C2F-E396F35A4280}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.CertificateGeneration.Task.Tests", "test\Microsoft.AspNetcore.CertificateGeneration.Task.Tests\Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj", "{3A7EF01A-073B-4123-850D-DFA4701EBE5B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.DeveloperCertificates.Tools", "src\Microsoft.AspNetCore.DeveloperCertificates.Tools\Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj", "{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -78,14 +76,10 @@ Global {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.Build.0 = Debug|Any CPU {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.ActiveCfg = Release|Any CPU {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.Build.0 = Release|Any CPU - {7B293291-26F4-47F0-9C2F-E396F35A4280}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7B293291-26F4-47F0-9C2F-E396F35A4280}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7B293291-26F4-47F0-9C2F-E396F35A4280}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7B293291-26F4-47F0-9C2F-E396F35A4280}.Release|Any CPU.Build.0 = Release|Any CPU - {3A7EF01A-073B-4123-850D-DFA4701EBE5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3A7EF01A-073B-4123-850D-DFA4701EBE5B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3A7EF01A-073B-4123-850D-DFA4701EBE5B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3A7EF01A-073B-4123-850D-DFA4701EBE5B}.Release|Any CPU.Build.0 = Release|Any CPU + {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -97,8 +91,7 @@ Global {7B331122-83B1-4F08-A119-DC846959844C} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {8A2E6961-6B12-4A8E-8215-3E7301D52EAC} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {53F3B53D-303A-4DAA-9C38-4F55195FA5B9} = {66517987-2A5A-4330-B130-207039378FD4} - {7B293291-26F4-47F0-9C2F-E396F35A4280} = {66517987-2A5A-4330-B130-207039378FD4} - {3A7EF01A-073B-4123-850D-DFA4701EBE5B} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} + {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8} = {66517987-2A5A-4330-B130-207039378FD4} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {57C07F14-2EAC-44FF-A277-B9221B4B2BF7} diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index 214ca77a9c..d5e919176f 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -19,12 +19,10 @@ "DotnetCliTool" ] }, - "Microsoft.AspNetCore.CertificateGeneration.Task": { - "exclusions":{ - "BUILD_ITEMS_FRAMEWORK": { - "*": "This is an MSBuild task intended to run through dotnet msbuild /t:Target independently of whether your project targets full framework or .net core." - } - } + "Microsoft.AspNetCore.DeveloperCertificates.Tools": { + "packageTypes": [ + "DotnetCliTool" + ] } } }, diff --git a/src/Microsoft.AspNetCore.CertificateGeneration.Task/CertificateManager.cs b/src/Microsoft.AspNetCore.CertificateGeneration.Task/CertificateManager.cs deleted file mode 100644 index e53c6b8743..0000000000 --- a/src/Microsoft.AspNetCore.CertificateGeneration.Task/CertificateManager.cs +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; - -namespace Microsoft.AspNetCore.CertificateGeneration.Task -{ - internal static class CertificateManager - { - public static X509Certificate2 GenerateSSLCertificate( - string subjectName, - IEnumerable subjectAlternativeName, - string friendlyName, - DateTimeOffset notBefore, - DateTimeOffset expires, - StoreName storeName, - StoreLocation storeLocation) - { - using (var rsa = RSA.Create(2048)) - { - var signingRequest = new CertificateRequest( - new X500DistinguishedName(subjectName), rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); - - var enhancedKeyUsage = new OidCollection(); - enhancedKeyUsage.Add(new Oid("1.3.6.1.5.5.7.3.1", "Server Authentication")); - signingRequest.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(enhancedKeyUsage, critical: true)); - signingRequest.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.KeyEncipherment, critical: true)); - signingRequest.CertificateExtensions.Add( - new X509BasicConstraintsExtension( - certificateAuthority: false, - hasPathLengthConstraint: false, - pathLengthConstraint: 0, - critical: true)); - - var sanBuilder = new SubjectAlternativeNameBuilder(); - foreach (var alternativeName in subjectAlternativeName) - { - sanBuilder.AddDnsName(alternativeName); - } - signingRequest.CertificateExtensions.Add(sanBuilder.Build()); - - var certificate = signingRequest.CreateSelfSigned(notBefore, expires); - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - certificate.FriendlyName = friendlyName; - } - - SaveCertificate(storeName, storeLocation, certificate); - - return certificate; - } - } - - private static void SaveCertificate(StoreName storeName, StoreLocation storeLocation, X509Certificate2 certificate) - { - // We need to take this step so that the key gets persisted. - var imported = certificate; - if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - var export = certificate.Export(X509ContentType.Pkcs12, ""); - imported = new X509Certificate2(export, "", X509KeyStorageFlags.PersistKeySet); - Array.Clear(export, 0, export.Length); - } - - using (var store = new X509Store(storeName, storeLocation)) - { - store.Open(OpenFlags.ReadWrite); - store.Add(imported); - store.Close(); - }; - } - - public static X509Certificate2 FindCertificate(string subjectValue, StoreName storeName, StoreLocation storeLocation) - { - using (var store = new X509Store(storeName, storeLocation)) - { - store.Open(OpenFlags.ReadOnly); - var certificates = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName, subjectValue, validOnly: false); - var current = DateTimeOffset.UtcNow; - - var found = certificates.OfType() - .Where(c => c.NotBefore <= current && current <= c.NotAfter && c.HasPrivateKey) - .FirstOrDefault(); - store.Close(); - - return found; - }; - } - } -} diff --git a/src/Microsoft.AspNetCore.CertificateGeneration.Task/GenerateSSLCertificateTask.cs b/src/Microsoft.AspNetCore.CertificateGeneration.Task/GenerateSSLCertificateTask.cs deleted file mode 100644 index 30ccf8bacb..0000000000 --- a/src/Microsoft.AspNetCore.CertificateGeneration.Task/GenerateSSLCertificateTask.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Security.Cryptography.X509Certificates; -using Microsoft.Build.Framework; - -namespace Microsoft.AspNetCore.CertificateGeneration.Task -{ - public class GenerateSSLCertificateTask : Build.Utilities.Task - { - public bool Force { get; set; } - - protected string Subject { get; set; } = "CN=localhost"; - - public override bool Execute() - { - var subjectValue = Subject; - var sansValue = new List { "localhost" }; - var friendlyNameValue = "ASP.NET Core HTTPS development certificate"; - var notBeforeValue = DateTime.UtcNow; - var expiresValue = DateTime.UtcNow.AddYears(1); - var storeNameValue = StoreName.My; - var storeLocationValue = StoreLocation.CurrentUser; - - var cert = CertificateManager.FindCertificate(subjectValue, storeNameValue, storeLocationValue); - - if (cert != null && !Force) - { - LogMessage($"A certificate with subject name '{Subject}' already exists. Skipping certificate generation."); - return true; - } - - var generated = CertificateManager.GenerateSSLCertificate(subjectValue, sansValue, friendlyNameValue, notBeforeValue, expiresValue, storeNameValue, storeLocationValue); - LogMessage($"Generated certificate {generated.SubjectName.Name} - {generated.Thumbprint} - {generated.FriendlyName}"); - - return true; - } - - protected virtual void LogMessage(string message) => Log.LogMessage(MessageImportance.High, message); - } -} diff --git a/src/Microsoft.AspNetCore.CertificateGeneration.Task/Microsoft.AspNetCore.CertificateGeneration.Task.csproj b/src/Microsoft.AspNetCore.CertificateGeneration.Task/Microsoft.AspNetCore.CertificateGeneration.Task.csproj deleted file mode 100644 index 5c1dc7f13d..0000000000 --- a/src/Microsoft.AspNetCore.CertificateGeneration.Task/Microsoft.AspNetCore.CertificateGeneration.Task.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - netcoreapp2.0 - MSBuild target for generating HTTPS certificates for development cross-platform. - tools - asp.net;ssl;certificates - - - - - - - - - - - diff --git a/src/Microsoft.AspNetCore.CertificateGeneration.Task/README.md b/src/Microsoft.AspNetCore.CertificateGeneration.Task/README.md deleted file mode 100644 index 4dfea325ab..0000000000 --- a/src/Microsoft.AspNetCore.CertificateGeneration.Task/README.md +++ /dev/null @@ -1,48 +0,0 @@ -Microsoft.AspNetCore.CertificateGeneration.Task -=============================================== -Microsoft.AspNetCore.CertificateGeneration.Task is an MSBuild task to generate SSL certificates -for use in ASP.NET Core for development purposes. - -### How To Install - -Install `Microsoft.AspNetCore.CertificateGeneration.Task` as a `PackageReference` to your project. - -```xml - - - -``` - -### How To Use - -The command must be executed in the directory that contains the project with the reference to the package. - - Usage: dotnet msbuild /t:GenerateSSLCertificate [/p:ForceGenerateSSLCertificate=true] - -### Testing scenarios - -On a machine without an SSL certificate generated by this task. Create a netcoreapp2.0 mvc application using - -``` -dotnet new mvc -``` - -Then try to run the app using: - -``` -dotnet run -``` - -When the application fails to run due to a missing SSL certificate. Run: - -``` -dotnet msbuild /t:GenerateSSLCertificate -``` - -Run the application again using: - -``` -dotnet run -``` - -The application should run successfully. You will still have to trust the certificate as a separate step. diff --git a/src/Microsoft.AspNetCore.CertificateGeneration.Task/build/Microsoft.AspNetCore.CertificateGeneration.Task.targets b/src/Microsoft.AspNetCore.CertificateGeneration.Task/build/Microsoft.AspNetCore.CertificateGeneration.Task.targets deleted file mode 100644 index 1deeb55dbb..0000000000 --- a/src/Microsoft.AspNetCore.CertificateGeneration.Task/build/Microsoft.AspNetCore.CertificateGeneration.Task.targets +++ /dev/null @@ -1,20 +0,0 @@ - - - - - <_SSLCertificateGenerationTaskAssembly>$(MSBuildThisFileDirectory)..\tools\netcoreapp2.0\Microsoft.AspNetCore.CertificateGeneration.Task.dll - - - - - - - - diff --git a/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj b/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj new file mode 100644 index 0000000000..438e88f121 --- /dev/null +++ b/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj @@ -0,0 +1,35 @@ + + + + netcoreapp2.0 + dotnet-developercertificates + exe + Command line tool to generate certificates used in ASP.NET Core during development. + Microsoft.AspNetCore.DeveloperCertificates.Tools + dotnet;developercertificates + DotnetCliTool + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Program.cs b/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Program.cs new file mode 100644 index 0000000000..f07f7bbe3e --- /dev/null +++ b/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Program.cs @@ -0,0 +1,144 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Security.Cryptography.X509Certificates; +using System.Text.RegularExpressions; +using Microsoft.AspNetCore.Certificates.Generation; +using Microsoft.Extensions.CommandLineUtils; +using Microsoft.Extensions.Tools.Internal; + +namespace Microsoft.AspNetCore.DeveloperCertificates.Tools +{ + class Program + { + private const int CriticalError = -1; + private const int Success = 0; + private const int ErrorCreatingTheCertificate = 1; + private const int ErrorSavingTheCertificate = 2; + private const int ErrorExportingTheCertificate = 3; + private const int ErrorTrustingTheCertificate = 4; + + public static readonly TimeSpan HttpsCertificateValidity = TimeSpan.FromDays(365); + + public static int Main(string[] args) + { + try + { + var app = new CommandLineApplication + { + Name = "dotnet-developercertificates" + }; + + app.Command("https", c => + { + var exportPath = c.Option("-ep|--export-path", + "Full path to the exported certificate", + CommandOptionType.SingleValue); + + var password = c.Option("-p|--password", + "Password to use when exporting the certificate with the private key into a pfx file", + CommandOptionType.SingleValue); + + CommandOption trust = null; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + trust = c.Option("-t|--trust", + "Trust the certificate on the current platform", + CommandOptionType.NoValue); + } + + var verbose = c.Option("-v|--verbose", + "Display more debug information.", + CommandOptionType.NoValue); + + var quiet = c.Option("-q|--quiet", + "Display warnings and errors only.", + CommandOptionType.NoValue); + + c.HelpOption("-h|--help"); + + c.OnExecute(() => + { + var reporter = new ConsoleReporter(PhysicalConsole.Singleton, verbose.HasValue(), quiet.HasValue()); + return EnsureHttpsCertificate(exportPath, password, trust, reporter); + }); + }); + + app.HelpOption("-h|--help"); + + app.OnExecute(() => + { + app.ShowHelp(); + return Success; + }); + + return app.Execute(args); + } + catch + { + return CriticalError; + } + } + + private static int EnsureHttpsCertificate(CommandOption exportPath, CommandOption password, CommandOption trust, IReporter reporter) + { + var now = DateTimeOffset.Now; + var manager = new CertificateManager(); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && trust?.HasValue() == true) + { + reporter.Warn("Trusting the HTTPS development certificate was requested. If the certificate is not " + + "already trusted we will run the following command:" + Environment.NewLine + + "'sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <>'" + + Environment.NewLine + "This command might prompt you for your password to install the certificate " + + "on the system keychain."); + } + + var result = manager.EnsureAspNetCoreHttpsDevelopmentCertificate( + now, + now.Add(HttpsCertificateValidity), + exportPath.Value(), + trust == null ? false : trust.HasValue(), + password.HasValue(), + password.Value()); + + switch (result) + { + case EnsureCertificateResult.Succeeded: + reporter.Output("The HTTPS developer certificate was generated successfully."); + if (exportPath.Value() != null) + { + reporter.Verbose($"The certificate was exported to {Path.GetFullPath(exportPath.Value())}"); + } + return Success; + case EnsureCertificateResult.ValidCertificatePresent: + reporter.Output("A valid HTTPS certificate is already present."); + if (exportPath.Value() != null) + { + reporter.Verbose($"The certificate was exported to {Path.GetFullPath(exportPath.Value())}"); + } + return Success; + case EnsureCertificateResult.ErrorCreatingTheCertificate: + reporter.Error("There was an error creating the HTTPS developer certificate."); + return ErrorCreatingTheCertificate; + case EnsureCertificateResult.ErrorSavingTheCertificateIntoTheCurrentUserPersonalStore: + reporter.Error("There was an error saving the HTTPS developer certificate to the current user personal certificate store."); + return ErrorSavingTheCertificate; + case EnsureCertificateResult.ErrorExportingTheCertificate: + reporter.Warn("There was an error exporting HTTPS developer certificate to a file."); + return ErrorExportingTheCertificate; + case EnsureCertificateResult.FailedToTrustTheCertificate: + reporter.Warn("There was an error trusting HTTPS developer certificate."); + return ErrorTrustingTheCertificate; + default: + reporter.Error("Something went wrong. The HTTPS developer certificate could not be created."); + return CriticalError; + } + } + } +} diff --git a/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/prefercliruntime b/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/prefercliruntime new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/GenerateSSLCertificateTaskTest.cs b/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/GenerateSSLCertificateTaskTest.cs deleted file mode 100644 index 3ed7ef69db..0000000000 --- a/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/GenerateSSLCertificateTaskTest.cs +++ /dev/null @@ -1,229 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -using Xunit; - -namespace Microsoft.AspNetCore.CertificateGeneration.Task -{ - public class GenerateSSLCertificateTaskTest : IDisposable - { - private const string TestSubject = "CN=test.ssl.localhost"; - - [Fact] - public void GenerateSSLCertificateTaskTest_CreatesCertificate_IfNoCertificateIsFound() - { - // Arrange - EnsureCleanUp(); - var task = new TestGenerateSSLCertificateTask(); - - // Act - var result = task.Execute(); - - // Assert - Assert.True(result); - var certificates = GetTestCertificates(); - Assert.Single(certificates); - Assert.Single(task.Messages); - Assert.StartsWith($"Generated certificate {TestSubject}", task.Messages[0]); - } - - [Fact] - public void GenerateSSLCertificateTaskTest_CreatesCertificate_IfFoundCertificateHasExpired() - { - // Arrange - EnsureCleanUp(); - CreateCertificate(notBefore: DateTimeOffset.UtcNow.AddYears(-2), expires: DateTimeOffset.UtcNow.AddYears(-1)); - - var task = new TestGenerateSSLCertificateTask(); - - // Act - var result = task.Execute(); - - // Assert - Assert.True(result); - var certificates = GetTestCertificates(); - Assert.Equal(2, certificates.Count); - Assert.Single(task.Messages); - Assert.StartsWith($"Generated certificate {TestSubject}", task.Messages[0]); - } - - [Fact] - public void GenerateSSLCertificateTaskTest_CreatesCertificate_IfFoundCertificateIsNotYetValid() - { - // Arrange - EnsureCleanUp(); - CreateCertificate(notBefore: DateTimeOffset.UtcNow.AddYears(1), expires: DateTimeOffset.UtcNow.AddYears(2)); - - var task = new TestGenerateSSLCertificateTask(); - - // Act - var result = task.Execute(); - - // Assert - Assert.True(result); - var certificates = GetTestCertificates(); - Assert.Equal(2, certificates.Count); - Assert.Equal(1, task.Messages.Count); - Assert.StartsWith($"Generated certificate {TestSubject}", task.Messages[0]); - } - - [Fact] - public void GenerateSSLCertificateTaskTest_CreatesCertificate_IfFoundCertificateDoesNotHavePrivateKeys() - { - // Arrange - EnsureCleanUp(); - CreateCertificate(savePrivateKey: false); - var task = new TestGenerateSSLCertificateTask(); - - // Act - var result = task.Execute(); - - // Assert - Assert.True(result); - var certificates = GetTestCertificates(); - Assert.Equal(2, certificates.Count); - Assert.Single(task.Messages); - Assert.StartsWith($"Generated certificate {TestSubject}", task.Messages[0]); - } - - [Fact] - public void GenerateSSLCertificateTaskTest_DoesNothing_IfValidCertificateIsFound() - { - // Arrange - EnsureCleanUp(); - CreateCertificate(); - var task = new TestGenerateSSLCertificateTask(); - - // Act - var result = task.Execute(); - - // Assert - Assert.True(result); - var certificates = GetTestCertificates(); - Assert.Single(certificates); - Assert.Single(task.Messages); - Assert.Equal($"A certificate with subject name '{TestSubject}' already exists. Skipping certificate generation.", task.Messages[0]); - } - - [Fact] - public void GenerateSSLCertificateTaskTest_CreatesACertificateWhenThereIsAlreadyAValidCertificate_IfForceIsSpecified() - { - // Arrange - EnsureCleanUp(); - CreateCertificate(); - var task = new TestGenerateSSLCertificateTask() { Force = true }; - - // Act - var result = task.Execute(); - - // Assert - Assert.True(result); - var certificates = GetTestCertificates(); - Assert.Equal(2, certificates.Count); - Assert.Single(task.Messages); - Assert.StartsWith($"Generated certificate {TestSubject}", task.Messages[0]); - } - - public X509CertificateCollection GetTestCertificates() - { - using (var store = new X509Store(StoreName.My, StoreLocation.CurrentUser)) - { - store.Open(OpenFlags.ReadWrite); - var certificates = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName, TestSubject, validOnly: false); - store.Close(); - - return certificates; - } - } - - private void EnsureCleanUp() - { - using (var store = new X509Store(StoreName.My, StoreLocation.CurrentUser)) - { - store.Open(OpenFlags.ReadWrite); - var certificates = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName, TestSubject, validOnly: false); - store.RemoveRange(certificates); - store.Close(); - } - } - - public void Dispose() - { - EnsureCleanUp(); - } - - private void CreateCertificate( - DateTimeOffset notBefore = default(DateTimeOffset), - DateTimeOffset expires = default(DateTimeOffset), - bool savePrivateKey = true) - { - using (var rsa = RSA.Create(2048)) - { - var signingRequest = new CertificateRequest( - new X500DistinguishedName(TestSubject), rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); - - var enhancedKeyUsage = new OidCollection - { - new Oid("1.3.6.1.5.5.7.3.1", "Server Authentication") - }; - signingRequest.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(enhancedKeyUsage, critical: true)); - signingRequest.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.KeyEncipherment, critical: true)); - signingRequest.CertificateExtensions.Add( - new X509BasicConstraintsExtension( - certificateAuthority: false, - hasPathLengthConstraint: false, - pathLengthConstraint: 0, - critical: true)); - - var sanBuilder = new SubjectAlternativeNameBuilder(); - sanBuilder.AddDnsName(TestSubject.Replace("CN=", "")); - signingRequest.CertificateExtensions.Add(sanBuilder.Build()); - - var certificate = signingRequest.CreateSelfSigned( - notBefore == default(DateTimeOffset) ? DateTimeOffset.Now : notBefore, - expires == default(DateTimeOffset) ? DateTimeOffset.Now.AddYears(1) : expires); - - - var imported = certificate; - if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && savePrivateKey) - { - var export = certificate.Export(X509ContentType.Pkcs12, ""); - - imported = new X509Certificate2(export, "", X509KeyStorageFlags.PersistKeySet); - Array.Clear(export, 0, export.Length); - } - else if (!savePrivateKey) - { - var export = certificate.Export(X509ContentType.Cert, ""); - - imported = new X509Certificate2(export, "", X509KeyStorageFlags.PersistKeySet); - Array.Clear(export, 0, export.Length); - } - - using (var store = new X509Store(StoreName.My, StoreLocation.CurrentUser)) - { - store.Open(OpenFlags.ReadWrite); - store.Add(imported); - store.Close(); - }; - } - } - - private class TestGenerateSSLCertificateTask : GenerateSSLCertificateTask - { - public TestGenerateSSLCertificateTask() - { - Subject = TestSubject; - } - - public IList Messages { get; set; } = new List(); - - protected override void LogMessage(string message) => Messages.Add(message); - } - } -} diff --git a/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj b/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj deleted file mode 100644 index a09751f552..0000000000 --- a/test/Microsoft.AspNetcore.CertificateGeneration.Task.Tests/Microsoft.AspNetCore.CertificateGeneration.Task.Tests.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - netcoreapp2.0 - - - - - - - - - - - From c793d319352696000d075a58a834ad31407c4fd2 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Mon, 16 Oct 2017 12:48:58 -0700 Subject: [PATCH 0600/1029] Add RepositoryRoot --- Directory.Build.props | 1 + 1 file changed, 1 insertion(+) diff --git a/Directory.Build.props b/Directory.Build.props index 90338e5345..a42c6f0597 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -5,6 +5,7 @@ Microsoft .NET https://github.com/aspnet/DotNetTools git + $(MSBuildThisFileDirectory) $(MSBuildThisFileDirectory)build\Key.snk true true From b1ccd606e56843726cbe253736a789c7f9d6fa82 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Mon, 16 Oct 2017 12:49:40 -0700 Subject: [PATCH 0601/1029] Add RepositoryRoot --- Directory.Build.props | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 74b2f8246d..50b555b540 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,9 +1,10 @@ - + https://github.com/aspnet/HtmlAbstractions git + $(MSBuildThisFileDirectory) $(MSBuildThisFileDirectory)build\Key.snk true true From e245de21fcc6bda605991f5b9963f1a6b9bb6125 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Mon, 16 Oct 2017 12:50:35 -0700 Subject: [PATCH 0602/1029] Add RepositoryRoot --- Directory.Build.props | 1 + 1 file changed, 1 insertion(+) diff --git a/Directory.Build.props b/Directory.Build.props index 57d9ef7e6a..fb7dfae923 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -5,6 +5,7 @@ Microsoft ASP.NET Core https://github.com/aspnet/JsonPatch git + $(MSBuildThisFileDirectory) $(MSBuildThisFileDirectory)build\Key.snk true true From 8eefe0fdc22793f6573f82c9856abcbe36a7bb80 Mon Sep 17 00:00:00 2001 From: Jass Bagga Date: Thu, 19 Oct 2017 10:46:08 -0700 Subject: [PATCH 0603/1029] Add Test Operation (#114) Addresses #1 --- .../Adapters/IObjectAdapter.cs | 95 ++++++- .../Adapters/IObjectAdapterWithTest.cs | 32 +++ .../Adapters/ObjectAdapter.cs | 172 +++---------- .../Internal/DictionaryAdapterOfTU.cs | 51 ++++ .../Internal/DynamicObjectAdapter.cs | 32 +++ .../Internal/IAdapter.cs | 7 + .../Internal/ListAdapter.cs | 39 +++ .../Internal/ObjectVisitor.cs | 9 +- .../Internal/PocoAdapter.cs | 39 +++ .../JsonPatchDocument.cs | 18 ++ .../JsonPatchDocumentOfT.cs | 71 ++++++ .../Operations/Operation.cs | 10 +- .../Operations/OperationOfT.cs | 11 +- .../Properties/Resources.Designer.cs | 46 +++- .../Resources.resx | 9 + .../{ => Adapters}/DictionaryAdapterTest.cs | 37 +++ .../DynamicObjectAdapterTest.cs | 37 +++ .../{ => Adapters}/ListAdapterTest.cs | 50 ++++ .../Adapters/PocoAdapterTest.cs | 241 ++++++++++++++++++ ...tegrationTests.cs => DynamicObjectTest.cs} | 42 ++- .../JsonPatchDocumentTest.cs | 36 --- 21 files changed, 895 insertions(+), 189 deletions(-) create mode 100644 src/Microsoft.AspNetCore.JsonPatch/Adapters/IObjectAdapterWithTest.cs rename test/Microsoft.AspNetCore.JsonPatch.Test/{ => Adapters}/DictionaryAdapterTest.cs (88%) rename test/Microsoft.AspNetCore.JsonPatch.Test/{ => Adapters}/DynamicObjectAdapterTest.cs (85%) rename test/Microsoft.AspNetCore.JsonPatch.Test/{ => Adapters}/ListAdapterTest.cs (89%) create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/PocoAdapterTest.cs rename test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/{DynamicObjectIntegrationTests.cs => DynamicObjectTest.cs} (86%) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/IObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/IObjectAdapter.cs index f699755ed4..e5206bfa0d 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Adapters/IObjectAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/IObjectAdapter.cs @@ -8,12 +8,105 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters /// /// Defines the operations that can be performed on a JSON patch document. /// - public interface IObjectAdapter + public interface IObjectAdapter { + /// + /// Using the "add" operation a new value is inserted into the root of the target + /// document, into the target array at the specified valid index, or to a target object at + /// the specified location. + /// + /// When adding to arrays, the specified index MUST NOT be greater than the number of elements in the array. + /// To append the value to the array, the index of "-" character is used (see [RFC6901]). + /// + /// When adding to an object, if an object member does not already exist, a new member is added to the object at the + /// specified location or if an object member does exist, that member's value is replaced. + /// + /// The operation object MUST contain a "value" member whose content + /// specifies the value to be added. + /// + /// For example: + /// + /// { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] } + /// + /// See RFC 6902 https://tools.ietf.org/html/rfc6902#page-4 + /// + /// The add operation. + /// Object to apply the operation to. void Add(Operation operation, object objectToApplyTo); + + /// + /// Using the "copy" operation, a value is copied from a specified location to the + /// target location. + /// + /// The operation object MUST contain a "from" member, which references the location in the + /// target document to copy the value from. + /// + /// The "from" location MUST exist for the operation to be successful. + /// + /// For example: + /// + /// { "op": "copy", "from": "/a/b/c", "path": "/a/b/e" } + /// + /// See RFC 6902 https://tools.ietf.org/html/rfc6902#page-7 + /// + /// The copy operation. + /// Object to apply the operation to. void Copy(Operation operation, object objectToApplyTo); + + /// + /// Using the "move" operation the value at a specified location is removed and + /// added to the target location. + /// + /// The operation object MUST contain a "from" member, which references the location in the + /// target document to move the value from. + /// + /// The "from" location MUST exist for the operation to be successful. + /// + /// For example: + /// + /// { "op": "move", "from": "/a/b/c", "path": "/a/b/d" } + /// + /// A location cannot be moved into one of its children. + /// + /// See RFC 6902 https://tools.ietf.org/html/rfc6902#page-6 + /// + /// The move operation. + /// Object to apply the operation to. void Move(Operation operation, object objectToApplyTo); + + /// + /// Using the "remove" operation the value at the target location is removed. + /// + /// The target location MUST exist for the operation to be successful. + /// + /// For example: + /// + /// { "op": "remove", "path": "/a/b/c" } + /// + /// If removing an element from an array, any elements above the + /// specified index are shifted one position to the left. + /// + /// See RFC 6902 https://tools.ietf.org/html/rfc6902#page-6 + /// + /// The remove operation. + /// Object to apply the operation to. void Remove(Operation operation, object objectToApplyTo); + + /// + /// Using the "replace" operation he value at the target location is replaced + /// with a new value. The operation object MUST contain a "value" member + /// which specifies the replacement value. + /// + /// The target location MUST exist for the operation to be successful. + /// + /// For example: + /// + /// { "op": "replace", "path": "/a/b/c", "value": 42 } + /// + /// See RFC 6902 https://tools.ietf.org/html/rfc6902#page-6 + /// + /// The replace operation. + /// Object to apply the operation to. void Replace(Operation operation, object objectToApplyTo); } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/IObjectAdapterWithTest.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/IObjectAdapterWithTest.cs new file mode 100644 index 0000000000..e1b4ce7950 --- /dev/null +++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/IObjectAdapterWithTest.cs @@ -0,0 +1,32 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNetCore.JsonPatch.Operations; + +namespace Microsoft.AspNetCore.JsonPatch.Adapters +{ + /// + /// Defines the operations that can be performed on a JSON patch document, including "test". + /// + public interface IObjectAdapterWithTest : IObjectAdapter + { + /// + /// Using the "test" operation a value at the target location is compared for + /// equality to a specified value. + /// + /// The operation object MUST contain a "value" member that specifies + /// value to be compared to the target location's value. + /// + /// The target location MUST be equal to the "value" value for the + /// operation to be considered successful. + /// + /// For example: + /// { "op": "test", "path": "/a/b/c", "value": "foo" } + /// + /// See RFC 6902 https://tools.ietf.org/html/rfc6902#page-7 + /// + /// The test operation. + /// Object to apply the operation to. + void Test(Operation operation, object objectToApplyTo); + } +} diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs index a30343868a..73095b52c2 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs @@ -9,7 +9,7 @@ using Newtonsoft.Json.Serialization; namespace Microsoft.AspNetCore.JsonPatch.Adapters { /// - public class ObjectAdapter : IObjectAdapter + public class ObjectAdapter : IObjectAdapterWithTest { /// /// Initializes a new instance of . @@ -34,66 +34,6 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters /// public Action LogErrorAction { get; } - /// - /// The "add" operation performs one of the following functions, - /// depending upon what the target location references: - /// - /// o If the target location specifies an array index, a new value is - /// inserted into the array at the specified index. - /// - /// o If the target location specifies an object member that does not - /// already exist, a new member is added to the object. - /// - /// o If the target location specifies an object member that does exist, - /// that member's value is replaced. - /// - /// The operation object MUST contain a "value" member whose content - /// specifies the value to be added. - /// - /// For example: - /// - /// { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] } - /// - /// When the operation is applied, the target location MUST reference one - /// of: - /// - /// o The root of the target document - whereupon the specified value - /// becomes the entire content of the target document. - /// - /// o A member to add to an existing object - whereupon the supplied - /// value is added to that object at the indicated location. If the - /// member already exists, it is replaced by the specified value. - /// - /// o An element to add to an existing array - whereupon the supplied - /// value is added to the array at the indicated location. Any - /// elements at or above the specified index are shifted one position - /// to the right. The specified index MUST NOT be greater than the - /// number of elements in the array. If the "-" character is used to - /// index the end of the array (see [RFC6901]), this has the effect of - /// appending the value to the array. - /// - /// Because this operation is designed to add to existing objects and - /// arrays, its target location will often not exist. Although the - /// pointer's error handling algorithm will thus be invoked, this - /// specification defines the error handling behavior for "add" pointers - /// to ignore that error and add the value as specified. - /// - /// However, the object itself or an array containing it does need to - /// exist, and it remains an error for that not to be the case. For - /// example, an "add" with a target location of "/a/b" starting with this - /// document: - /// - /// { "a": { "foo": 1 } } - /// - /// is not an error, because "a" exists, and "b" will be added to its - /// value. It is an error in this document: - /// - /// { "q": { "bar": 2 } } - /// - /// because "a" does not exist. - /// - /// The add operation. - /// Object to apply the operation to. public void Add(Operation operation, object objectToApplyTo) { if (operation == null) @@ -153,29 +93,6 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters } } - /// - /// The "move" operation removes the value at a specified location and - /// adds it to the target location. - /// - /// The operation object MUST contain a "from" member, which is a string - /// containing a JSON Pointer value that references the location in the - /// target document to move the value from. - /// - /// The "from" location MUST exist for the operation to be successful. - /// - /// For example: - /// - /// { "op": "move", "from": "/a/b/c", "path": "/a/b/d" } - /// - /// This operation is functionally identical to a "remove" operation on - /// the "from" location, followed immediately by an "add" operation at - /// the target location with the value that was just removed. - /// - /// The "from" location MUST NOT be a proper prefix of the "path" - /// location; i.e., a location cannot be moved into one of its children. - /// - /// The move operation. - /// Object to apply the operation to. public void Move(Operation operation, object objectToApplyTo) { if (operation == null) @@ -202,20 +119,6 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters } } - /// - /// The "remove" operation removes the value at the target location. - /// - /// The target location MUST exist for the operation to be successful. - /// - /// For example: - /// - /// { "op": "remove", "path": "/a/b/c" } - /// - /// If removing an element from an array, any elements above the - /// specified index are shifted one position to the left. - /// - /// The remove operation. - /// Object to apply the operation to. public void Remove(Operation operation, object objectToApplyTo) { if (operation == null) @@ -259,26 +162,6 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters } } - /// - /// The "replace" operation replaces the value at the target location - /// with a new value. The operation object MUST contain a "value" member - /// whose content specifies the replacement value. - /// - /// The target location MUST exist for the operation to be successful. - /// - /// For example: - /// - /// { "op": "replace", "path": "/a/b/c", "value": 42 } - /// - /// This operation is functionally identical to a "remove" operation for - /// a value, followed immediately by an "add" operation at the same - /// location with the replacement value. - /// - /// Note: even though it's the same functionally, we do not call remove + add - /// for performance reasons (multiple checks of same requirements). - /// - /// The replace operation. - /// Object to apply the operation to. public void Replace(Operation operation, object objectToApplyTo) { if (operation == null) @@ -310,28 +193,6 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters } } - /// - /// The "copy" operation copies the value at a specified location to the - /// target location. - /// - /// The operation object MUST contain a "from" member, which is a string - /// containing a JSON Pointer value that references the location in the - /// target document to copy the value from. - /// - /// The "from" location MUST exist for the operation to be successful. - /// - /// For example: - /// - /// { "op": "copy", "from": "/a/b/c", "path": "/a/b/e" } - /// - /// This operation is functionally identical to an "add" operation at the - /// target location using the value specified in the "from" member. - /// - /// Note: even though it's the same functionally, we do not call add with - /// the value specified in from for performance reasons (multiple checks of same requirements). - /// - /// The copy operation. - /// Object to apply the operation to. public void Copy(Operation operation, object objectToApplyTo) { if (operation == null) @@ -365,6 +226,37 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters } } + public void Test(Operation operation, object objectToApplyTo) + { + if (operation == null) + { + throw new ArgumentNullException(nameof(operation)); + } + + if (objectToApplyTo == null) + { + throw new ArgumentNullException(nameof(objectToApplyTo)); + } + + var parsedPath = new ParsedPath(operation.path); + var visitor = new ObjectVisitor(parsedPath, ContractResolver); + + var target = objectToApplyTo; + if (!visitor.TryVisit(ref target, out var adapter, out var errorMessage)) + { + var error = CreatePathNotFoundError(objectToApplyTo, operation.path, operation, errorMessage); + ErrorReporter(error); + return; + } + + if (!adapter.TryTest(target, parsedPath.LastSegment, ContractResolver, operation.value, out errorMessage)) + { + var error = CreateOperationFailedError(objectToApplyTo, operation.path, operation, errorMessage); + ErrorReporter(error); + return; + } + } + private bool TryGetValue( string fromLocation, object objectToGetValueFrom, diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapterOfTU.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapterOfTU.cs index 67fd33e231..8a344e24ee 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapterOfTU.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapterOfTU.cs @@ -2,6 +2,8 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; namespace Microsoft.AspNetCore.JsonPatch.Internal @@ -126,6 +128,55 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } + public bool TryTest( + object target, + string segment, + IContractResolver contractResolver, + object value, + out string errorMessage) + { + var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType()); + var key = contract.DictionaryKeyResolver(segment); + var dictionary = (IDictionary)target; + + if (!TryConvertKey(key, out var convertedKey, out errorMessage)) + { + return false; + } + + // As per JsonPatch spec, the target location must exist for test to be successful + if (!dictionary.ContainsKey(convertedKey)) + { + errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); + return false; + } + + if (!TryConvertValue(value, out var convertedValue, out errorMessage)) + { + return false; + } + + var currentValue = dictionary[convertedKey]; + + // The target segment does not have an assigned value to compare the test value with + if (currentValue == null || string.IsNullOrEmpty(currentValue.ToString())) + { + errorMessage = Resources.FormatValueForTargetSegmentCannotBeNullOrEmpty(segment); + return false; + } + + if (!JToken.DeepEquals(JsonConvert.SerializeObject(currentValue), JsonConvert.SerializeObject(convertedValue))) + { + errorMessage = Resources.FormatValueNotEqualToTestValue(currentValue, value, segment); + return false; + } + else + { + errorMessage = null; + return true; + } + } + public bool TryTraverse( object target, string segment, diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs index 433326ce53..fb4adeb1f2 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs @@ -6,6 +6,8 @@ using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using Microsoft.CSharp.RuntimeBinder; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; using CSharpBinder = Microsoft.CSharp.RuntimeBinder; @@ -103,6 +105,36 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } + public bool TryTest( + object target, + string segment, + IContractResolver contractResolver, + object value, + out string errorMessage) + { + if (!TryGetDynamicObjectProperty(target, contractResolver, segment, out var property, out errorMessage)) + { + return false; + } + + if (!TryConvertValue(value, property.GetType(), out var convertedValue)) + { + errorMessage = Resources.FormatInvalidValueForProperty(value); + return false; + } + + if (!JToken.DeepEquals(JsonConvert.SerializeObject(property), JsonConvert.SerializeObject(convertedValue))) + { + errorMessage = Resources.FormatValueNotEqualToTestValue(property, value, segment); + return false; + } + else + { + errorMessage = null; + return true; + } + } + public bool TryTraverse( object target, string segment, diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/IAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/IAdapter.cs index 1866b42ed4..ec28131f7d 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/IAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/IAdapter.cs @@ -40,5 +40,12 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal IContractResolver contractResolver, object value, out string errorMessage); + + bool TryTest( + object target, + string segment, + IContractResolver contractResolver, + object value, + out string errorMessage); } } diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs index a1c0498e47..d1348fd5c6 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs @@ -5,6 +5,8 @@ using System; using System.Collections; using System.Collections.Generic; using Microsoft.Extensions.Internal; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; namespace Microsoft.AspNetCore.JsonPatch.Internal @@ -150,6 +152,43 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } + public bool TryTest( + object target, + string segment, + IContractResolver contractResolver, + object value, + out string errorMessage) + { + var list = (IList)target; + + if (!TryGetListTypeArgument(list, out var typeArgument, out errorMessage)) + { + return false; + } + + if (!TryGetPositionInfo(list, segment, OperationType.Replace, out var positionInfo, out errorMessage)) + { + return false; + } + + if (!TryConvertValue(value, typeArgument, segment, out var convertedValue, out errorMessage)) + { + return false; + } + + var currentValue = list[positionInfo.Index]; + if (!JToken.DeepEquals(JsonConvert.SerializeObject(currentValue), JsonConvert.SerializeObject(convertedValue))) + { + errorMessage = Resources.FormatValueAtListPositionNotEqualToTestValue(currentValue, value, positionInfo.Index); + return false; + } + else + { + errorMessage = null; + return true; + } + } + public bool TryTraverse( object target, string segment, diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs index 97f108c0a0..8994f0aa52 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs @@ -3,9 +3,6 @@ using System; using System.Collections; -using System.Collections.Generic; -using System.Dynamic; -using Microsoft.AspNetCore.JsonPatch.Adapters; using Newtonsoft.Json.Serialization; namespace Microsoft.AspNetCore.JsonPatch.Internal @@ -30,7 +27,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return false; } - adapter = SelectAdapater(target); + adapter = SelectAdapter(target); // Traverse until the penultimate segment to get the target object and adapter for (var i = 0; i < _path.Segments.Count - 1; i++) @@ -42,14 +39,14 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } target = next; - adapter = SelectAdapater(target); + adapter = SelectAdapter(target); } errorMessage = null; return true; } - private IAdapter SelectAdapater(object targetObject) + private IAdapter SelectAdapter(object targetObject) { var jsonContract = _contractResolver.ResolveContract(targetObject.GetType()); diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs index eab16a3035..0eee0fc889 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs @@ -4,6 +4,8 @@ using System; using System.Linq; using System.Reflection; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; namespace Microsoft.AspNetCore.JsonPatch.Internal @@ -132,6 +134,43 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } + public bool TryTest( + object target, + string segment, + IContractResolver + contractResolver, + object value, + out string errorMessage) + { + if (!TryGetJsonProperty(target, contractResolver, segment, out var jsonProperty)) + { + errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); + return false; + } + + if (!jsonProperty.Readable) + { + errorMessage = Resources.FormatCannotReadProperty(segment); + return false; + } + + if (!TryConvertValue(value, jsonProperty.PropertyType, out var convertedValue)) + { + errorMessage = Resources.FormatInvalidValueForProperty(value); + return false; + } + + var currentValue = jsonProperty.ValueProvider.GetValue(target); + if (!JToken.DeepEquals(JsonConvert.SerializeObject(currentValue), JsonConvert.SerializeObject(convertedValue))) + { + errorMessage = Resources.FormatValueNotEqualToTestValue(currentValue, value, segment); + return false; + } + + errorMessage = null; + return true; + } + public bool TryTraverse( object target, string segment, diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs index 4da2bdbe1e..4420e576bf 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs @@ -99,6 +99,24 @@ namespace Microsoft.AspNetCore.JsonPatch return this; } + /// + /// Test value. Will result in, for example, + /// { "op": "test", "path": "/a/b/c", "value": 42 } + /// + /// target location + /// value + /// + public JsonPatchDocument Test(string path, object value) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation("test", PathHelpers.NormalizePath(path), null, value)); + return this; + } + /// /// Removes value at specified location and add it to the target location. Will result in, for example: /// { "op": "move", "from": "/a/b/c", "path": "/a/b/d" } diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs index 5b9df2b52b..8ae1430185 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs @@ -247,6 +247,77 @@ namespace Microsoft.AspNetCore.JsonPatch return this; } + /// + /// Test value. Will result in, for example, + /// { "op": "test", "path": "/a/b/c", "value": 42 } + /// + /// target location + /// value + /// + public JsonPatchDocument Test(Expression> path, TProp value) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "test", + GetPath(path, null), + from: null, + value: value)); + + return this; + } + + /// + /// Test value in a list at given position + /// + /// value type + /// target location + /// value + /// position + /// + public JsonPatchDocument Test(Expression>> path, + TProp value, int position) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "test", + GetPath(path, position.ToString()), + from: null, + value: value)); + + return this; + } + + /// + /// Test value at end of a list + /// + /// value type + /// target location + /// value + /// + public JsonPatchDocument Test(Expression>> path, TProp value) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + Operations.Add(new Operation( + "test", + GetPath(path, "-"), + from: null, + value: value)); + + return this; + } + /// /// Removes value at specified location and add it to the target location. Will result in, for example: /// { "op": "move", "from": "/a/b/c", "path": "/a/b/d" } diff --git a/src/Microsoft.AspNetCore.JsonPatch/Operations/Operation.cs b/src/Microsoft.AspNetCore.JsonPatch/Operations/Operation.cs index ea81b0c668..690ade4776 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Operations/Operation.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Operations/Operation.cs @@ -58,7 +58,15 @@ namespace Microsoft.AspNetCore.JsonPatch.Operations adapter.Copy(this, objectToApplyTo); break; case OperationType.Test: - throw new NotSupportedException(Resources.TestOperationNotSupported); + if (adapter is IObjectAdapterWithTest adapterWithTest) + { + adapterWithTest.Test(this, objectToApplyTo); + break; + } + else + { + throw new NotSupportedException(Resources.TestOperationNotSupported); + } default: break; } diff --git a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationOfT.cs b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationOfT.cs index 7189cf8210..bd13528775 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationOfT.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationOfT.cs @@ -74,7 +74,15 @@ namespace Microsoft.AspNetCore.JsonPatch.Operations adapter.Copy(this, objectToApplyTo); break; case OperationType.Test: - throw new JsonPatchException(new JsonPatchError(objectToApplyTo, this, Resources.TestOperationNotSupported)); + if (adapter is IObjectAdapterWithTest adapterWithTest) + { + adapterWithTest.Test(this, objectToApplyTo); + break; + } + else + { + throw new JsonPatchException(new JsonPatchError(objectToApplyTo, this, Resources.TestOperationNotSupported)); + } case OperationType.Invalid: throw new JsonPatchException( Resources.FormatInvalidJsonPatchOperation(op), innerException: null); @@ -82,6 +90,5 @@ namespace Microsoft.AspNetCore.JsonPatch.Operations break; } } - } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs index 432fab2cbf..cfb8e087d0 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs @@ -81,7 +81,7 @@ namespace Microsoft.AspNetCore.JsonPatch => string.Format(CultureInfo.CurrentCulture, GetString("CannotUpdateProperty"), p0); /// - /// The expression '{0}' is not supported. + /// The expression '{0}' is not supported. Supported expressions include member access and indexer expressions. /// internal static string ExpressionTypeNotSupported { @@ -89,7 +89,7 @@ namespace Microsoft.AspNetCore.JsonPatch } /// - /// The expression '{0}' is not supported. + /// The expression '{0}' is not supported. Supported expressions include member access and indexer expressions. /// internal static string FormatExpressionTypeNotSupported(object p0) => string.Format(CultureInfo.CurrentCulture, GetString("ExpressionTypeNotSupported"), p0); @@ -276,6 +276,48 @@ namespace Microsoft.AspNetCore.JsonPatch internal static string FormatTestOperationNotSupported() => GetString("TestOperationNotSupported"); + /// + /// The current value '{0}' at position '{2}' is not equal to the test value '{1}'. + /// + internal static string ValueAtListPositionNotEqualToTestValue + { + get => GetString("ValueAtListPositionNotEqualToTestValue"); + } + + /// + /// The current value '{0}' at position '{2}' is not equal to the test value '{1}'. + /// + internal static string FormatValueAtListPositionNotEqualToTestValue(object p0, object p1, object p2) + => string.Format(CultureInfo.CurrentCulture, GetString("ValueAtListPositionNotEqualToTestValue"), p0, p1, p2); + + /// + /// The value at '{0}' cannot be null or empty to perform the test operation. + /// + internal static string ValueForTargetSegmentCannotBeNullOrEmpty + { + get => GetString("ValueForTargetSegmentCannotBeNullOrEmpty"); + } + + /// + /// The value at '{0}' cannot be null or empty to perform the test operation. + /// + internal static string FormatValueForTargetSegmentCannotBeNullOrEmpty(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("ValueForTargetSegmentCannotBeNullOrEmpty"), p0); + + /// + /// The current value '{0}' at path '{2}' is not equal to the test value '{1}'. + /// + internal static string ValueNotEqualToTestValue + { + get => GetString("ValueNotEqualToTestValue"); + } + + /// + /// The current value '{0}' at path '{2}' is not equal to the test value '{1}'. + /// + internal static string FormatValueNotEqualToTestValue(object p0, object p1, object p2) + => string.Format(CultureInfo.CurrentCulture, GetString("ValueNotEqualToTestValue"), p0, p1, p2); + private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); diff --git a/src/Microsoft.AspNetCore.JsonPatch/Resources.resx b/src/Microsoft.AspNetCore.JsonPatch/Resources.resx index bf07e4a31e..3763e4a841 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Resources.resx +++ b/src/Microsoft.AspNetCore.JsonPatch/Resources.resx @@ -174,4 +174,13 @@ The test operation is not supported. + + The current value '{0}' at position '{2}' is not equal to the test value '{1}'. + + + The value at '{0}' cannot be null or empty to perform the test operation. + + + The current value '{0}' at path '{2}' is not equal to the test value '{1}'. + \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/DictionaryAdapterTest.cs similarity index 88% rename from test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/DictionaryAdapterTest.cs index cfb99d61ce..d1d2216c2c 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/DictionaryAdapterTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/DictionaryAdapterTest.cs @@ -274,5 +274,42 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); Assert.Empty(dictionary); } + + [Fact] + public void Test_DoesNotThrowException_IfTestIsSuccessful() + { + // Arrange + var key = "Name"; + var dictionary = new Dictionary(); + dictionary[key] = "James"; + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new DefaultContractResolver(); + + // Act + var testStatus = dictionaryAdapter.TryTest(dictionary, key, resolver, "James", out var message); + + //Assert + Assert.True(testStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + } + + [Fact] + public void Test_ThrowsJsonPatchException_IfTestFails() + { + // Arrange + var key = "Name"; + var dictionary = new Dictionary(); + dictionary[key] = "James"; + var dictionaryAdapter = new DictionaryAdapter(); + var resolver = new DefaultContractResolver(); + var expectedErrorMessage = "The current value 'James' at path 'Name' is not equal to the test value 'John'."; + + // Act + var testStatus = dictionaryAdapter.TryTest(dictionary, key, resolver, "John", out var errorMessage); + + //Assert + Assert.False(testStatus); + Assert.Equal(expectedErrorMessage, errorMessage); + } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/DynamicObjectAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/DynamicObjectAdapterTest.cs similarity index 85% rename from test/Microsoft.AspNetCore.JsonPatch.Test/DynamicObjectAdapterTest.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/DynamicObjectAdapterTest.cs index 18bb7a775c..9ed9a51ed0 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/DynamicObjectAdapterTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/DynamicObjectAdapterTest.cs @@ -227,5 +227,42 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.False(removeStatus); Assert.Equal($"The target location specified by path segment '{segment}' was not found.", removeErrorMessage); } + + [Fact] + public void TryTest_DoesNotThrowException_IfTestSuccessful() + { + var adapter = new DynamicObjectAdapter(); + dynamic target = new DynamicTestObject(); + target.NewProperty = "Joana"; + var segment = "NewProperty"; + var resolver = new DefaultContractResolver(); + + // Act + var testStatus = adapter.TryTest(target, segment, resolver, "Joana", out string errorMessage); + + // Assert + Assert.Equal("Joana", target.NewProperty); + Assert.True(testStatus); + Assert.True(string.IsNullOrEmpty(errorMessage), "Expected no error message"); + } + + [Fact] + public void TryTest_ThrowsJsonPatchException_IfTestFails() + { + // Arrange + var adapter = new DynamicObjectAdapter(); + dynamic target = new DynamicTestObject(); + target.NewProperty = "Joana"; + var segment = "NewProperty"; + var resolver = new DefaultContractResolver(); + var expectedErrorMessage = $"The current value 'Joana' at path '{segment}' is not equal to the test value 'John'."; + + // Act + var testStatus = adapter.TryTest(target, segment, resolver, "John", out string errorMessage); + + // Assert + Assert.False(testStatus); + Assert.Equal(expectedErrorMessage, errorMessage); + } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/ListAdapterTest.cs similarity index 89% rename from test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/ListAdapterTest.cs index 3c692ea150..25d8ae387b 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ListAdapterTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/ListAdapterTest.cs @@ -459,5 +459,55 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); Assert.Equal(expected, targetObject); } + + [Fact] + public void Test_DoesNotThrowException_IfTestIsSuccessful() + { + // Arrange + var resolver = new Mock(MockBehavior.Strict); + var targetObject = new List() { 10, 20 }; + var listAdapter = new ListAdapter(); + + // Act + var testStatus = listAdapter.TryTest(targetObject, "0", resolver.Object, "10", out var message); + + //Assert + Assert.True(testStatus); + Assert.True(string.IsNullOrEmpty(message), "Expected no error message"); + } + + [Fact] + public void Test_ThrowsJsonPatchException_IfTestFails() + { + // Arrange + var resolver = new Mock(MockBehavior.Strict); + var targetObject = new List() { 10, 20 }; + var listAdapter = new ListAdapter(); + var expectedErrorMessage = "The current value '20' at position '1' is not equal to the test value '10'."; + + // Act + var testStatus = listAdapter.TryTest(targetObject, "1", resolver.Object, "10", out var errorMessage); + + //Assert + Assert.False(testStatus); + Assert.Equal(expectedErrorMessage, errorMessage); + } + + [Fact] + public void Test_ThrowsJsonPatchException_IfListPositionOutOfBounds() + { + // Arrange + var resolver = new Mock(MockBehavior.Strict); + var targetObject = new List() { 10, 20 }; + var listAdapter = new ListAdapter(); + var expectedErrorMessage = "The index value provided by path segment '2' is out of bounds of the array size."; + + // Act + var testStatus = listAdapter.TryTest(targetObject, "2", resolver.Object, "10", out var errorMessage); + + //Assert + Assert.False(testStatus); + Assert.Equal(expectedErrorMessage, errorMessage); + } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/PocoAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/PocoAdapterTest.cs new file mode 100644 index 0000000000..9a31ea11a8 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/PocoAdapterTest.cs @@ -0,0 +1,241 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Newtonsoft.Json.Serialization; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + public class PocoAdapterTest + { + [Fact] + public void TryAdd_ReplacesExistingProperty() + { + // Arrange + var adapter = new PocoAdapter(); + var contractResolver = new DefaultContractResolver(); + var model = new Customer + { + Name = "Joana" + }; + + // Act + var addStatus = adapter.TryAdd(model, "Name", contractResolver, "John", out var errorMessage); + + // Assert + Assert.Equal("John", model.Name); + Assert.True(addStatus); + Assert.True(string.IsNullOrEmpty(errorMessage), "Expected no error message"); + } + + [Fact] + public void TryAdd_ThrowsJsonPatchException_IfPropertyDoesNotExist() + { + // Arrange + var adapter = new PocoAdapter(); + var contractResolver = new DefaultContractResolver(); + var model = new Customer + { + Name = "Joana" + }; + var expectedErrorMessage = "The target location specified by path segment 'LastName' was not found."; + + // Act + var addStatus = adapter.TryAdd(model, "LastName", contractResolver, "Smith", out var errorMessage); + + // Assert + Assert.False(addStatus); + Assert.Equal(expectedErrorMessage, errorMessage); + } + + [Fact] + public void TryGet_ExistingProperty() + { + // Arrange + var adapter = new PocoAdapter(); + var contractResolver = new DefaultContractResolver(); + var model = new Customer + { + Name = "Joana" + }; + + // Act + var getStatus = adapter.TryGet(model, "Name", contractResolver, out var value, out var errorMessage); + + // Assert + Assert.Equal("Joana", value); + Assert.True(getStatus); + Assert.True(string.IsNullOrEmpty(errorMessage), "Expected no error message"); + } + + [Fact] + public void TryGet_ThrowsJsonPatchException_IfPropertyDoesNotExist() + { + // Arrange + var adapter = new PocoAdapter(); + var contractResolver = new DefaultContractResolver(); + var model = new Customer + { + Name = "Joana" + }; + var expectedErrorMessage = "The target location specified by path segment 'LastName' was not found."; + + // Act + var getStatus = adapter.TryGet(model, "LastName", contractResolver, out var value, out var errorMessage); + + // Assert + Assert.Null(value); + Assert.False(getStatus); + Assert.Equal(expectedErrorMessage, errorMessage); + } + + [Fact] + public void TryRemove_SetsPropertyToNull() + { + // Arrange + var adapter = new PocoAdapter(); + var contractResolver = new DefaultContractResolver(); + var model = new Customer + { + Name = "Joana" + }; + + // Act + var removeStatus = adapter.TryRemove(model, "Name", contractResolver, out var errorMessage); + + // Assert + Assert.Null(model.Name); + Assert.True(removeStatus); + Assert.True(string.IsNullOrEmpty(errorMessage), "Expected no error message"); + } + + [Fact] + public void TryRemove_ThrowsJsonPatchException_IfPropertyDoesNotExist() + { + // Arrange + var adapter = new PocoAdapter(); + var contractResolver = new DefaultContractResolver(); + var model = new Customer + { + Name = "Joana" + }; + var expectedErrorMessage = "The target location specified by path segment 'LastName' was not found."; + + // Act + var removeStatus = adapter.TryRemove(model, "LastName", contractResolver, out var errorMessage); + + // Assert + Assert.False(removeStatus); + Assert.Equal(expectedErrorMessage, errorMessage); + } + + [Fact] + public void TryReplace_OverwritesExistingValue() + { + // Arrange + var adapter = new PocoAdapter(); + var contractResolver = new DefaultContractResolver(); + var model = new Customer + { + Name = "Joana" + }; + + // Act + var replaceStatus = adapter.TryReplace(model, "Name", contractResolver, "John", out var errorMessage); + + // Assert + Assert.Equal("John", model.Name); + Assert.True(replaceStatus); + Assert.True(string.IsNullOrEmpty(errorMessage), "Expected no error message"); + } + + [Fact] + public void TryReplace_ThrowsJsonPatchException_IfNewValueIsInvalidType() + { + // Arrange + var adapter = new PocoAdapter(); + var contractResolver = new DefaultContractResolver(); + var model = new Customer + { + Age = 25 + }; + + var expectedErrorMessage = "The value 'TwentySix' is invalid for target location."; + + // Act + var replaceStatus = adapter.TryReplace(model, "Age", contractResolver, "TwentySix", out var errorMessage); + + // Assert + Assert.Equal(25, model.Age); + Assert.False(replaceStatus); + Assert.Equal(expectedErrorMessage, errorMessage); + } + + [Fact] + public void TryReplace_ThrowsJsonPatchException_IfPropertyDoesNotExist() + { + // Arrange + var adapter = new PocoAdapter(); + var contractResolver = new DefaultContractResolver(); + var model = new Customer + { + Name = "Joana" + }; + var expectedErrorMessage = "The target location specified by path segment 'LastName' was not found."; + + // Act + var replaceStatus = adapter.TryReplace(model, "LastName", contractResolver, "Smith", out var errorMessage); + + // Assert + Assert.Equal("Joana", model.Name); + Assert.False(replaceStatus); + Assert.Equal(expectedErrorMessage, errorMessage); + } + + [Fact] + public void TryTest_DoesNotThrowException_IfTestSuccessful() + { + var adapter = new PocoAdapter(); + var contractResolver = new DefaultContractResolver(); + var model = new Customer + { + Name = "Joana" + }; + + // Act + var testStatus = adapter.TryTest(model, "Name", contractResolver, "Joana", out var errorMessage); + + // Assert + Assert.Equal("Joana", model.Name); + Assert.True(testStatus); + Assert.True(string.IsNullOrEmpty(errorMessage), "Expected no error message"); + } + + [Fact] + public void TryTest_ThrowsJsonPatchException_IfTestFails() + { + // Arrange + var adapter = new PocoAdapter(); + var contractResolver = new DefaultContractResolver(); + var model = new Customer + { + Name = "Joana" + }; + var expectedErrorMessage = "The current value 'Joana' at path 'Name' is not equal to the test value 'John'."; + + // Act + var testStatus = adapter.TryTest(model, "Name", contractResolver, "John", out var errorMessage); + + // Assert + Assert.False(testStatus); + Assert.Equal(expectedErrorMessage, errorMessage); + } + + private class Customer + { + public string Name { get; set; } + + public int Age { get; set; } + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DynamicObjectIntegrationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DynamicObjectTest.cs similarity index 86% rename from test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DynamicObjectIntegrationTests.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DynamicObjectTest.cs index 4b5fc96e24..be7738419f 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DynamicObjectIntegrationTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DynamicObjectTest.cs @@ -7,7 +7,7 @@ using Xunit; namespace Microsoft.AspNetCore.JsonPatch.Internal { - public class DynamicObjectIntegrationTests + public class DynamicObjectTest { [Fact] public void AddResults_ShouldReplaceExistingPropertyValue_InNestedDynamicObject() @@ -259,5 +259,45 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.Equal(new List() { 4, 5, 6 }, dynamicTestObject.IntegerList); } + + [Fact] + public void TestPropertyValue_FromListToNonList_InNestedTypedObject_InDynamicObject() + { + // Arrange + dynamic dynamicTestObject = new DynamicTestObject(); + dynamicTestObject.Nested = new SimpleObject() + { + IntegerList = new List() { 1, 2, 3 } + }; + + var patchDoc = new JsonPatchDocument(); + patchDoc.Test("Nested/IntegerList/1", 2); + + // Act & Assert + patchDoc.ApplyTo(dynamicTestObject); + } + + [Fact] + public void TestPropertyValue_FromListToNonList_InNestedTypedObject_InDynamicObject_ThrowsJsonPatchException_IfTestFails() + { + // Arrange + dynamic dynamicTestObject = new DynamicTestObject(); + dynamicTestObject.Nested = new SimpleObject() + { + IntegerList = new List() { 1, 2, 3 } + }; + + var patchDoc = new JsonPatchDocument(); + patchDoc.Test("Nested/IntegerList/0", 2); + + // Act + var exception = Assert.Throws(() => + { + patchDoc.ApplyTo(dynamicTestObject); + }); + + // Assert + Assert.Equal("The current value '1' at position '0' is not equal to the test value '2'.", exception.Message); + } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs index 723ef15b64..d754e8da5b 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs @@ -9,42 +9,6 @@ namespace Microsoft.AspNetCore.JsonPatch.Test { public class JsonPatchDocumentTest { - [Fact] - public void TestOperation_ThrowsException_CallsIntoLogErrorAction() - { - // Arrange - var serialized = "[{\"value\":\"John\",\"path\":\"/Name\",\"op\":\"test\"}]"; - var jsonPatchDocument = JsonConvert.DeserializeObject>(serialized); - var model = new Customer(); - var expectedErrorMessage = "The test operation is not supported."; - string actualErrorMessage = null; - - // Act - jsonPatchDocument.ApplyTo(model, (jsonPatchError) => - { - actualErrorMessage = jsonPatchError.ErrorMessage; - }); - - // Assert - Assert.Equal(expectedErrorMessage, actualErrorMessage); - } - - [Fact] - public void TestOperation_NoLogErrorAction_ThrowsJsonPatchException() - { - // Arrange - var serialized = "[{\"value\":\"John\",\"path\":\"/Name\",\"op\":\"test\"}]"; - var jsonPatchDocument = JsonConvert.DeserializeObject>(serialized); - var model = new Customer(); - var expectedErrorMessage = "The test operation is not supported."; - - // Act - var jsonPatchException = Assert.Throws(() => jsonPatchDocument.ApplyTo(model)); - - // Assert - Assert.Equal(expectedErrorMessage, jsonPatchException.Message); - } - [Fact] public void InvalidOperation_ThrowsException_CallsIntoLogErrorAction() { From e46ba481c8b281b04fbb682ca4db92bee6799d24 Mon Sep 17 00:00:00 2001 From: Jass Bagga Date: Thu, 19 Oct 2017 13:32:04 -0700 Subject: [PATCH 0604/1029] Throw JsonSerializationException from converters (#116) --- .../Converters/JsonPatchDocumentConverter.cs | 2 +- .../TypedJsonPatchDocumentConverter.cs | 3 +-- .../Properties/Resources.Designer.cs | 8 +++---- .../Resources.resx | 2 +- .../ObjectAdapterTests.cs | 24 +++++++++++++++---- 5 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Converters/JsonPatchDocumentConverter.cs b/src/Microsoft.AspNetCore.JsonPatch/Converters/JsonPatchDocumentConverter.cs index e93e84e12a..aed9c48474 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Converters/JsonPatchDocumentConverter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Converters/JsonPatchDocumentConverter.cs @@ -57,7 +57,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Converters } catch (Exception ex) { - throw new JsonPatchException(Resources.FormatInvalidJsonPatchDocument(objectType.Name), ex); + throw new JsonSerializationException(Resources.InvalidJsonPatchDocument, ex); } } diff --git a/src/Microsoft.AspNetCore.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs b/src/Microsoft.AspNetCore.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs index 292a3be556..fd779ba4ee 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Reflection; -using Microsoft.AspNetCore.JsonPatch.Exceptions; using Microsoft.AspNetCore.JsonPatch.Operations; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -58,7 +57,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Converters } catch (Exception ex) { - throw new JsonPatchException(Resources.FormatInvalidJsonPatchDocument(objectType.Name), ex); + throw new JsonSerializationException(Resources.InvalidJsonPatchDocument, ex); } } } diff --git a/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs index cfb8e087d0..c314465238 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs @@ -123,7 +123,7 @@ namespace Microsoft.AspNetCore.JsonPatch => string.Format(CultureInfo.CurrentCulture, GetString("InvalidIndexValue"), p0); /// - /// The type '{0}' was malformed and could not be parsed. + /// The JSON patch document was malformed and could not be parsed. /// internal static string InvalidJsonPatchDocument { @@ -131,10 +131,10 @@ namespace Microsoft.AspNetCore.JsonPatch } /// - /// The type '{0}' was malformed and could not be parsed. + /// The JSON patch document was malformed and could not be parsed. /// - internal static string FormatInvalidJsonPatchDocument(object p0) - => string.Format(CultureInfo.CurrentCulture, GetString("InvalidJsonPatchDocument"), p0); + internal static string FormatInvalidJsonPatchDocument() + => GetString("InvalidJsonPatchDocument"); /// /// Invalid JsonPatch operation '{0}'. diff --git a/src/Microsoft.AspNetCore.JsonPatch/Resources.resx b/src/Microsoft.AspNetCore.JsonPatch/Resources.resx index 3763e4a841..87cc399c62 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Resources.resx +++ b/src/Microsoft.AspNetCore.JsonPatch/Resources.resx @@ -142,7 +142,7 @@ The path segment '{0}' is invalid for an array index. - The type '{0}' was malformed and could not be parsed. + The JSON patch document was malformed and could not be parsed. Invalid JsonPatch operation '{0}'. diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs index d35f8eb4e9..c1d005e897 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs @@ -725,7 +725,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters } [Fact] - public void DeserializationMustWorkWithoutEnvelope() + public void Deserialization_Successful_ForValidJsonPatchDocument() { // Arrange var doc = new SimpleObject() @@ -756,19 +756,35 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters } [Fact] - public void DeserializationMustFailWithEnvelope() + public void Deserialization_Fails_ForInvalidJsonPatchDocument() { // Arrange var serialized = "{\"Operations\": [{ \"op\": \"replace\", \"path\": \"/title\", \"value\": \"New Title\"}]}"; // Act & Assert - var exception = Assert.Throws(() => + var exception = Assert.Throws(() => + { + var deserialized + = JsonConvert.DeserializeObject(serialized); + }); + + Assert.Equal("The JSON patch document was malformed and could not be parsed.", exception.Message); + } + + [Fact] + public void Deserialization_Fails_ForInvalidTypedJsonPatchDocument() + { + // Arrange + var serialized = "{\"Operations\": [{ \"op\": \"replace\", \"path\": \"/title\", \"value\": \"New Title\"}]}"; + + // Act & Assert + var exception = Assert.Throws(() => { var deserialized = JsonConvert.DeserializeObject>(serialized); }); - Assert.Equal("The type 'JsonPatchDocument`1' was malformed and could not be parsed.", exception.Message); + Assert.Equal("The JSON patch document was malformed and could not be parsed.", exception.Message); } [Fact] From e453fafad52649daff689c24fa2374a143f43654 Mon Sep 17 00:00:00 2001 From: Jass Bagga Date: Thu, 26 Oct 2017 12:51:06 -0700 Subject: [PATCH 0605/1029] Reorganize tests (#117) Addresses #105 --- .../CustomNamingStrategyTests.cs | 153 ++ .../Dynamic/AddOperationTests.cs | 553 ---- .../Dynamic/AddTypedOperationTests.cs | 121 - .../Dynamic/CopyOperationTests.cs | 245 -- .../Dynamic/CopyTypedOperationTests.cs | 268 -- .../Dynamic/CustomNamingStrategyTests.cs | 154 -- .../Dynamic/InheritedObject.cs | 10 - .../Dynamic/MoveOperationTests.cs | 333 --- .../Dynamic/MoveTypedOperationTests.cs | 138 - .../Dynamic/PatchDocumentTests.cs | 95 - .../Dynamic/RemoveOperationTests.cs | 313 --- .../Dynamic/RemoveTypedOperationTests.cs | 244 -- .../Dynamic/ReplaceOperationTests.cs | 206 -- .../Dynamic/ReplaceTypedOperationTests.cs | 191 -- .../Dynamic/SimpleObject.cs | 21 - .../Dynamic/SimpleObjectWithNestedObject.cs | 22 - .../AnonymousObjectIntegrationTest.cs | 190 ++ .../DictionaryIntegrationTest.cs | 319 +++ ...est.cs => DynamicObjectIntegrationTest.cs} | 141 +- .../ExpandoObjectIntegrationTest.cs | 327 +++ .../IntegrationTests/ListIntegrationTest.cs | 366 +++ .../NestedObjectIntegrationTest.cs | 342 +++ .../SimpleObjectIntegrationTest.cs | 128 + .../DictionaryAdapterTest.cs | 34 +- .../DynamicObjectAdapterTest.cs | 12 +- .../{Adapters => Internal}/ListAdapterTest.cs | 40 +- .../{ => Internal}/ObjectVisitorTest.cs | 10 +- .../{ => Internal}/ParsedPathTests.cs | 7 +- .../{Adapters => Internal}/PocoAdapterTest.cs | 0 .../JsonPatchDocumentGetPathTest.cs | 4 +- ...nPatchDocumentJsonPropertyAttributeTest.cs | 271 +- .../JsonPatchDocumentTest.cs | 171 +- .../JsonPropertyComplexNameObject.cs | 16 - .../JsonPropertyObject.cs | 13 - .../JsonPropertyWithAnotherNameObject.cs | 10 - .../JsonPropertyWithInheritanceObject.cs | 15 - .../NestedObject.cs | 10 - .../NestedObjectTests.cs | 2272 ---------------- .../ObjectAdapterTests.cs | 2331 ----------------- ...mpleObjectWithNestedObjectWithNullCheck.cs | 15 - .../SimpleObjectWithNullCheck.cs | 30 - .../TestObjectModels/Customer.cs | 17 + .../DynamicTestObject.cs | 2 +- .../{ => TestObjectModels}/InheritedObject.cs | 0 .../NestedObject.cs | 4 +- .../{ => TestObjectModels}/SimpleObject.cs | 2 + .../SimpleObjectWithNestedObject.cs | 0 47 files changed, 2091 insertions(+), 8075 deletions(-) create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/CustomNamingStrategyTests.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyOperationTests.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CustomNamingStrategyTests.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/InheritedObject.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveOperationTests.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/PatchDocumentTests.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceTypedOperationTests.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleObject.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleObjectWithNestedObject.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/AnonymousObjectIntegrationTest.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DictionaryIntegrationTest.cs rename test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/{DynamicObjectTest.cs => DynamicObjectIntegrationTest.cs} (58%) create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/ExpandoObjectIntegrationTest.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/ListIntegrationTest.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/NestedObjectIntegrationTest.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/SimpleObjectIntegrationTest.cs rename test/Microsoft.AspNetCore.JsonPatch.Test/{Adapters => Internal}/DictionaryAdapterTest.cs (91%) rename test/Microsoft.AspNetCore.JsonPatch.Test/{Adapters => Internal}/DynamicObjectAdapterTest.cs (97%) rename test/Microsoft.AspNetCore.JsonPatch.Test/{Adapters => Internal}/ListAdapterTest.cs (91%) rename test/Microsoft.AspNetCore.JsonPatch.Test/{ => Internal}/ObjectVisitorTest.cs (95%) rename test/Microsoft.AspNetCore.JsonPatch.Test/{ => Internal}/ParsedPathTests.cs (91%) rename test/Microsoft.AspNetCore.JsonPatch.Test/{Adapters => Internal}/PocoAdapterTest.cs (100%) delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyComplexNameObject.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyObject.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithAnotherNameObject.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithInheritanceObject.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/NestedObject.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNestedObjectWithNullCheck.cs delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNullCheck.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/Customer.cs rename test/Microsoft.AspNetCore.JsonPatch.Test/{ => TestObjectModels}/DynamicTestObject.cs (98%) rename test/Microsoft.AspNetCore.JsonPatch.Test/{ => TestObjectModels}/InheritedObject.cs (100%) rename test/Microsoft.AspNetCore.JsonPatch.Test/{Dynamic => TestObjectModels}/NestedObject.cs (85%) rename test/Microsoft.AspNetCore.JsonPatch.Test/{ => TestObjectModels}/SimpleObject.cs (86%) rename test/Microsoft.AspNetCore.JsonPatch.Test/{ => TestObjectModels}/SimpleObjectWithNestedObject.cs (100%) diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/CustomNamingStrategyTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/CustomNamingStrategyTests.cs new file mode 100644 index 0000000000..ebc45874d9 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/CustomNamingStrategyTests.cs @@ -0,0 +1,153 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Dynamic; +using Newtonsoft.Json.Serialization; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch +{ + public class CustomNamingStrategyTests + { + [Fact] + public void AddProperty_ToDynamicTestObject_WithCustomNamingStrategy() + { + // Arrange + var contractResolver = new DefaultContractResolver + { + NamingStrategy = new TestNamingStrategy() + }; + + dynamic targetObject = new DynamicTestObject(); + targetObject.Test = 1; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Add("NewInt", 1); + patchDocument.ContractResolver = contractResolver; + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(1, targetObject.customNewInt); + Assert.Equal(1, targetObject.Test); + } + + [Fact] + public void CopyPropertyValue_ToDynamicTestObject_WithCustomNamingStrategy() + { + // Arrange + var contractResolver = new DefaultContractResolver + { + NamingStrategy = new TestNamingStrategy() + }; + + dynamic targetObject = new DynamicTestObject(); + targetObject.customStringProperty = "A"; + targetObject.customAnotherStringProperty = "B"; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Copy("StringProperty", "AnotherStringProperty"); + patchDocument.ContractResolver = contractResolver; + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal("A", targetObject.customAnotherStringProperty); + } + + [Fact] + public void MovePropertyValue_ForExpandoObject_WithCustomNamingStrategy() + { + // Arrange + var contractResolver = new DefaultContractResolver + { + NamingStrategy = new TestNamingStrategy() + }; + + dynamic targetObject = new ExpandoObject(); + targetObject.customStringProperty = "A"; + targetObject.customAnotherStringProperty = "B"; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Move("StringProperty", "AnotherStringProperty"); + patchDocument.ContractResolver = contractResolver; + + // Act + patchDocument.ApplyTo(targetObject); + var cont = targetObject as IDictionary; + cont.TryGetValue("customStringProperty", out var valueFromDictionary); + + // Assert + Assert.Equal("A", targetObject.customAnotherStringProperty); + Assert.Null(valueFromDictionary); + } + + [Fact] + public void RemoveProperty_FromDictionaryObject_WithCustomNamingStrategy() + { + // Arrange + var contractResolver = new DefaultContractResolver + { + NamingStrategy = new TestNamingStrategy() + }; + + var targetObject = new Dictionary() + { + { "customTest", 1}, + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Remove("Test"); + patchDocument.ContractResolver = contractResolver; + + // Act + patchDocument.ApplyTo(targetObject); + var cont = targetObject as IDictionary; + cont.TryGetValue("customTest", out var valueFromDictionary); + + // Assert + Assert.Equal(0, valueFromDictionary); + } + + [Fact] + public void ReplacePropertyValue_ForExpandoObject_WithCustomNamingStrategy() + { + // Arrange + var contractResolver = new DefaultContractResolver + { + NamingStrategy = new TestNamingStrategy() + }; + + dynamic targetObject = new ExpandoObject(); + targetObject.customTest = 1; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Replace("Test", 2); + patchDocument.ContractResolver = contractResolver; + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(2, targetObject.customTest); + } + + private class TestNamingStrategy : NamingStrategy + { + public new bool ProcessDictionaryKeys => true; + + public override string GetDictionaryKey(string key) + { + return "custom" + key; + } + + protected override string ResolvePropertyName(string name) + { + return name; + } + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs deleted file mode 100644 index 493444066b..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddOperationTests.cs +++ /dev/null @@ -1,553 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Dynamic; -using Microsoft.AspNetCore.JsonPatch.Exceptions; -using Newtonsoft.Json; -using Xunit; - -namespace Microsoft.AspNetCore.JsonPatch.Internal -{ - public class AddOperationTests - { - [Fact] - public void AddNewPropertyShouldFailIfRootIsNotAnExpandoObject() - { - dynamic doc = new - { - Test = 1 - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("NewInt", 1); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The target location specified by path segment '{0}' was not found.", "NewInt"), - exception.Message); - } - - [Fact] - public void AddNewProperty() - { - dynamic obj = new ExpandoObject(); - obj.Test = 1; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("NewInt", 1); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(obj); - - Assert.Equal(1, obj.NewInt); - Assert.Equal(1, obj.Test); - } - - [Fact] - public void AddNewPropertyToNestedAnonymousObjectShouldFail() - { - dynamic doc = new - { - Test = 1, - nested = new { } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("Nested/NewInt", 1); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The target location specified by path segment '{0}' was not found.", "NewInt"), - exception.Message); - } - - [Fact] - public void AddNewPropertyToTypedObjectShouldFail() - { - dynamic doc = new - { - Test = 1, - nested = new NestedObject() - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("Nested/NewInt", 1); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The target location specified by path segment '{0}' was not found.", "NewInt"), - exception.Message); - } - - [Fact] - public void AddToExistingPropertyOnNestedObject() - { - dynamic doc = new - { - Test = 1, - nested = new NestedObject() - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("Nested/StringProperty", "A"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal("A", doc.nested.StringProperty); - Assert.Equal(1, doc.Test); - } - - [Fact] - public void AddNewPropertyToExpandoOject() - { - dynamic doc = new - { - Test = 1, - nested = new ExpandoObject() - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("Nested/NewInt", 1); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(1, doc.nested.NewInt); - Assert.Equal(1, doc.Test); - } - - [Fact] - public void AddNewPropertyToExpandoOjectInTypedObject() - { - var doc = new NestedObject() - { - DynamicProperty = new ExpandoObject() - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("DynamicProperty/NewInt", 1); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(1, doc.DynamicProperty.NewInt); - } - - [Fact] - public void AddNewPropertyToTypedObjectInExpandoObject() - { - dynamic dynamicProperty = new ExpandoObject(); - dynamicProperty.StringProperty = "A"; - - var doc = new NestedObject() - { - DynamicProperty = dynamicProperty - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("DynamicProperty/StringProperty", "B"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal("B", doc.DynamicProperty.StringProperty); - } - - [Fact] - public void AddNewPropertyToAnonymousObjectShouldFail() - { - dynamic doc = new - { - Test = 1 - }; - - dynamic valueToAdd = new { IntValue = 1, StringValue = "test", GuidValue = Guid.NewGuid() }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("ComplexProperty", valueToAdd); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The target location specified by path segment '{0}' was not found.", "ComplexProperty"), - exception.Message); - } - - [Fact] - public void AddResultsReplaceShouldFailOnAnonymousDueToNoSetter() - { - var doc = new - { - StringProperty = "A" - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("StringProperty", "B"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The property at path '{0}' could not be updated.", "StringProperty"), - exception.Message); - } - - [Fact] - public void AddResultsShouldReplace() - { - dynamic doc = new ExpandoObject(); - doc.StringProperty = "A"; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("StringProperty", "B"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal("B", doc.StringProperty); - } - - [Fact] - public void AddResultsShouldReplaceInNested() - { - dynamic doc = new ExpandoObject(); - doc.InBetweenFirst = new ExpandoObject(); - doc.InBetweenFirst.InBetweenSecond = new ExpandoObject(); - doc.InBetweenFirst.InBetweenSecond.StringProperty = "A"; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("/InBetweenFirst/InBetweenSecond/StringProperty", "B"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal("B", doc.InBetweenFirst.InBetweenSecond.StringProperty); - } - - [Fact] - public void AddResultsShouldReplaceInNestedInDynamic() - { - dynamic doc = new ExpandoObject(); - doc.Nested = new NestedObject(); - doc.Nested.DynamicProperty = new ExpandoObject(); - doc.Nested.DynamicProperty.InBetweenFirst = new ExpandoObject(); - doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond = new ExpandoObject(); - doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond.StringProperty = "A"; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("/Nested/DynamicProperty/InBetweenFirst/InBetweenSecond/StringProperty", "B"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal("B", doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond.StringProperty); - } - - [Fact] - public void ShouldNotBeAbleToAddToNonExistingPropertyThatIsNotTheRoot() - { - //Adding to a Nonexistent Target - // - // An example target JSON document: - // { "foo": "bar" } - // A JSON Patch document: - // [ - // { "op": "add", "path": "/baz/bat", "value": "qux" } - // ] - // This JSON Patch document, applied to the target JSON document above, - // would result in an error (therefore, it would not be applied), - // because the "add" operation's target location that references neither - // the root of the document, nor a member of an existing object, nor a - // member of an existing array. - - var doc = new NestedObject() - { - DynamicProperty = new ExpandoObject() - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("DynamicProperty/OtherProperty/IntProperty", 1); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format( - "For operation '{0}', the target location specified by path '{1}' was not found.", - "add", - "/DynamicProperty/OtherProperty/IntProperty"), - exception.Message); - } - - [Fact] - public void ShouldNotBeAbleToAddToNonExistingPropertyInNestedPropertyThatIsNotTheRoot() - { - //Adding to a Nonexistent Target - // - // An example target JSON document: - // { "foo": "bar" } - // A JSON Patch document: - // [ - // { "op": "add", "path": "/baz/bat", "value": "qux" } - // ] - // This JSON Patch document, applied to the target JSON document above, - // would result in an error (therefore, it would not be applied), - // because the "add" operation's target location that references neither - // the root of the document, nor a member of an existing object, nor a - // member of an existing array. - - var doc = new - { - Foo = "bar" - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("baz/bat", "qux"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The target location specified by path segment '{0}' was not found.", "baz"), - exception.Message); - } - - [Fact] - public void ShouldNotReplacePropertyWithDifferentCase() - { - dynamic doc = new ExpandoObject(); - doc.StringProperty = "A"; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("stringproperty", "B"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal("A", doc.StringProperty); - Assert.Equal("B", doc.stringproperty); - } - - [Fact] - public void AddToList() - { - var doc = new - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("IntegerList/0", 4); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void AddToListNegativePosition() - { - dynamic doc = new ExpandoObject(); - doc.IntegerList = new List() { 1, 2, 3 }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("IntegerList/-1", 4); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - exception.Message); - } - - [Fact] - public void ShouldAddToListWithDifferentCase() - { - var doc = new - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("integerlist/0", 4); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void AddToListInvalidPositionTooLarge() - { - var doc = new - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("IntegerList/4", 4); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "4"), - exception.Message); - } - - [Fact] - public void AddToListAtBeginning() - { - var doc = new - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("IntegerList/0", 4); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void AddToListInvalidPositionTooSmall() - { - var doc = new - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("IntegerList/-1", 4); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - exception.Message); - } - - [Fact] - public void AddToListAppend() - { - var doc = new - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("IntegerList/-", 4); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 2, 3, 4 }, doc.IntegerList); - } - } -} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs deleted file mode 100644 index b2eb4d3a3c..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/AddTypedOperationTests.cs +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using Microsoft.AspNetCore.JsonPatch.Exceptions; -using Newtonsoft.Json; -using Xunit; - -namespace Microsoft.AspNetCore.JsonPatch.Internal -{ - public class AddTypedOperationTests - { - [Fact] - public void AddToListNegativePosition() - { - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("IntegerList/-1", 4); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - exception.Message); - } - - [Fact] - public void AddToListInList() - { - var doc = new SimpleObjectWithNestedObject() - { - ListOfSimpleObject = new List() - { - new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("ListOfSimpleObject/0/IntegerList/0", 4); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.ListOfSimpleObject[0].IntegerList); - } - - [Fact] - public void AddToListInListInvalidPositionTooSmall() - { - var doc = new SimpleObjectWithNestedObject() - { - ListOfSimpleObject = new List() - { - new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("ListOfSimpleObject/-1/IntegerList/0", 4); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - exception.Message); - } - - [Fact] - public void AddToListInListInvalidPositionTooLarge() - { - var doc = new SimpleObjectWithNestedObject() - { - ListOfSimpleObject = new List() - { - new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - } - }; - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("ListOfSimpleObject/20/IntegerList/0", 4); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "20"), - exception.Message); - } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyOperationTests.cs deleted file mode 100644 index b2faff25a0..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyOperationTests.cs +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using System.Dynamic; -using Newtonsoft.Json; -using Xunit; - -namespace Microsoft.AspNetCore.JsonPatch.Internal -{ - public class CopyOperationTests - { - [Fact] - public void Copy() - { - dynamic doc = new ExpandoObject(); - - doc.StringProperty = "A"; - doc.AnotherStringProperty = "B"; - - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("StringProperty", "AnotherStringProperty"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(doc); - - Assert.Equal("A", doc.AnotherStringProperty); - } - - [Fact] - public void CopyInList() - { - dynamic doc = new ExpandoObject(); - doc.IntegerList = new List() { 1, 2, 3 }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("IntegerList/0", "IntegerList/1"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 1, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void CopyFromListToEndOfList() - { - dynamic doc = new ExpandoObject(); - doc.IntegerList = new List() { 1, 2, 3 }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("IntegerList/0", "IntegerList/-"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 2, 3, 1 }, doc.IntegerList); - } - - [Fact] - public void CopyFromListToNonList() - { - dynamic doc = new ExpandoObject(); - doc.IntegerList = new List() { 1, 2, 3 }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("IntegerList/0", "IntegerValue"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(1, doc.IntegerValue); - } - - [Fact] - public void CopyFromNonListToList() - { - dynamic doc = new ExpandoObject(); - doc.IntegerValue = 5; - doc.IntegerList = new List() { 1, 2, 3 }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("IntegerValue", "IntegerList/0"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void CopyToEndOfList() - { - dynamic doc = new ExpandoObject(); - doc.IntegerValue = 5; - doc.IntegerList = new List() { 1, 2, 3 }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("IntegerValue", "IntegerList/-"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.IntegerList); - } - - [Fact] - public void NestedCopy() - { - dynamic doc = new ExpandoObject(); - doc.SimpleObject = new SimpleObject() - { - StringProperty = "A", - AnotherStringProperty = "B" - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleObject/StringProperty", "SimpleObject/AnotherStringProperty"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal("A", doc.SimpleObject.AnotherStringProperty); - } - - [Fact] - public void NestedCopyInList() - { - dynamic doc = new ExpandoObject(); - doc.SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleObject/IntegerList/0", "SimpleObject/IntegerList/1"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 1, 2, 3 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void NestedCopyFromListToEndOfList() - { - dynamic doc = new ExpandoObject(); - doc.SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleObject/IntegerList/0", "SimpleObject/IntegerList/-"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 2, 3, 1 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void NestedCopyFromListToNonList() - { - dynamic doc = new ExpandoObject(); - doc.SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleObject/IntegerList/0", "SimpleObject/IntegerValue"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(doc); - - Assert.Equal(1, doc.SimpleObject.IntegerValue); - } - - [Fact] - public void NestedCopyFromNonListToList() - { - dynamic doc = new ExpandoObject(); - doc.SimpleObject = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleObject/IntegerValue", "SimpleObject/IntegerList/0"); - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void NestedCopyToEndOfList() - { - dynamic doc = new ExpandoObject(); - doc.SimpleObject = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleObject/IntegerValue", "SimpleObject/IntegerList/-"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleObject.IntegerList); - } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs deleted file mode 100644 index d0b0847c71..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CopyTypedOperationTests.cs +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using Newtonsoft.Json; -using Xunit; - -namespace Microsoft.AspNetCore.JsonPatch.Internal -{ - public class CopyTypedOperationTests - { - [Fact] - public void Copy() - { - var doc = new SimpleObject() - { - StringProperty = "A", - AnotherStringProperty = "B" - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("StringProperty", "AnotherStringProperty"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(doc); - - Assert.Equal("A", doc.AnotherStringProperty); - } - - [Fact] - public void CopyInList() - { - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("IntegerList/0", "IntegerList/1"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 1, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void CopyFromListToEndOfList() - { - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("IntegerList/0", "IntegerList/-"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 2, 3, 1 }, doc.IntegerList); - } - - [Fact] - public void CopyFromListToNonList() - { - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("IntegerList/0", "IntegerValue"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(1, doc.IntegerValue); - } - - [Fact] - public void CopyFromNonListToList() - { - var doc = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("IntegerValue", "IntegerList/0"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void CopyToEndOfList() - { - var doc = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("IntegerValue", "IntegerList/-"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.IntegerList); - } - - [Fact] - public void NestedCopy() - { - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - StringProperty = "A", - AnotherStringProperty = "B" - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleObject/StringProperty", "SimpleObject/AnotherStringProperty"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal("A", doc.SimpleObject.AnotherStringProperty); - } - - [Fact] - public void NestedCopyInList() - { - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleObject/IntegerList/0", "SimpleObject/IntegerList/1"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 1, 2, 3 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void NestedCopyFromListToEndOfList() - { - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleObject/IntegerList/0", "SimpleObject/IntegerList/-"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 2, 3, 1 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void NestedCopyFromListToNonList() - { - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleObject/IntegerList/0", "SimpleObject/IntegerValue"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(doc); - - Assert.Equal(1, doc.SimpleObject.IntegerValue); - } - - [Fact] - public void NestedCopyFromNonListToList() - { - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleObject/IntegerValue", "SimpleObject/IntegerList/0"); - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void NestedCopyToEndOfList() - { - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("SimpleObject/IntegerValue", "SimpleObject/IntegerList/-"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleObject.IntegerList); - } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CustomNamingStrategyTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CustomNamingStrategyTests.cs deleted file mode 100644 index b829b81902..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/CustomNamingStrategyTests.cs +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using System.Dynamic; -using Newtonsoft.Json.Serialization; -using Xunit; - -namespace Microsoft.AspNetCore.JsonPatch.Test.Dynamic -{ - public class CustomNamingStrategyTests - { - [Fact] - public void AddProperty_ToExpandoObject_WithCustomNamingStrategy() - { - // Arrange - var contractResolver = new DefaultContractResolver - { - NamingStrategy = new TestNamingStrategy() - }; - - dynamic obj = new ExpandoObject(); - obj.Test = 1; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("NewInt", 1); - patchDoc.ContractResolver = contractResolver; - - // Act - patchDoc.ApplyTo(obj); - - // Assert - Assert.Equal(1, obj.customNewInt); - Assert.Equal(1, obj.Test); - } - - [Fact] - public void CopyPropertyValue_ForExpandoObject_WithCustomNamingStrategy() - { - // Arrange - var contractResolver = new DefaultContractResolver - { - NamingStrategy = new TestNamingStrategy() - }; - - dynamic obj = new ExpandoObject(); - obj.customStringProperty = "A"; - obj.customAnotherStringProperty = "B"; - - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("StringProperty", "AnotherStringProperty"); - patchDoc.ContractResolver = contractResolver; - - // Act - patchDoc.ApplyTo(obj); - - // Assert - Assert.Equal("A", obj.customAnotherStringProperty); - } - - [Fact] - public void MovePropertyValue_ForExpandoObject_WithCustomNamingStrategy() - { - // Arrange - var contractResolver = new DefaultContractResolver - { - NamingStrategy = new TestNamingStrategy() - }; - - dynamic obj = new ExpandoObject(); - obj.customStringProperty = "A"; - obj.customAnotherStringProperty = "B"; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("StringProperty", "AnotherStringProperty"); - patchDoc.ContractResolver = contractResolver; - - // Act - patchDoc.ApplyTo(obj); - var cont = obj as IDictionary; - cont.TryGetValue("customStringProperty", out var valueFromDictionary); - - // Assert - Assert.Equal("A", obj.customAnotherStringProperty); - Assert.Null(valueFromDictionary); - } - - [Fact] - public void RemoveProperty_FromExpandoObject_WithCustomNamingStrategy() - { - // Arrange - var contractResolver = new DefaultContractResolver - { - NamingStrategy = new TestNamingStrategy() - }; - - dynamic obj = new ExpandoObject(); - obj.customTest = 1; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("Test"); - patchDoc.ContractResolver = contractResolver; - - // Act - patchDoc.ApplyTo(obj); - var cont = obj as IDictionary; - cont.TryGetValue("customTest", out var valueFromDictionary); - - // Assert - Assert.Null(valueFromDictionary); - } - - [Fact] - public void ReplacePropertyValue_ForExpandoObject_WithCustomNamingStrategy() - { - // Arrange - var contractResolver = new DefaultContractResolver - { - NamingStrategy = new TestNamingStrategy() - }; - - dynamic obj = new ExpandoObject(); - obj.customTest = 1; - - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("Test", 2); - patchDoc.ContractResolver = contractResolver; - - // Act - patchDoc.ApplyTo(obj); - - // Assert - Assert.Equal(2, obj.customTest); - } - - private class TestNamingStrategy : NamingStrategy - { - public new bool ProcessDictionaryKeys => true; - - public override string GetDictionaryKey(string key) - { - return "custom" + key; - } - - protected override string ResolvePropertyName(string name) - { - return name; - } - } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/InheritedObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/InheritedObject.cs deleted file mode 100644 index 29424d591e..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/InheritedObject.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.JsonPatch.Internal -{ - public class InheritedObject : SimpleObject - { - public string AdditionalStringProperty { get; set; } - } -} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveOperationTests.cs deleted file mode 100644 index 31f58c4b82..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveOperationTests.cs +++ /dev/null @@ -1,333 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using System.Dynamic; -using Newtonsoft.Json; -using Xunit; - -namespace Microsoft.AspNetCore.JsonPatch.Internal -{ - public class MoveOperationTests - { - [Fact] - public void Move() - { - dynamic doc = new ExpandoObject(); - doc.StringProperty = "A"; - doc.AnotherStringProperty = "B"; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("StringProperty", "AnotherStringProperty"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal("A", doc.AnotherStringProperty); - - var cont = doc as IDictionary; - cont.TryGetValue("StringProperty", out object valueFromDictionary); - Assert.Null(valueFromDictionary); - } - - [Fact] - public void MoveToNonExisting() - { - dynamic doc = new ExpandoObject(); - doc.StringProperty = "A"; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("StringProperty", "AnotherStringProperty"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal("A", doc.AnotherStringProperty); - - var cont = doc as IDictionary; - cont.TryGetValue("StringProperty", out var valueFromDictionary); - Assert.Null(valueFromDictionary); - } - - [Fact] - public void MoveDynamicToTyped() - { - dynamic doc = new ExpandoObject(); - doc.StringProperty = "A"; - doc.SimpleDTO = new SimpleObject() { AnotherStringProperty = "B" }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("StringProperty", "SimpleDTO/AnotherStringProperty"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal("A", doc.SimpleDTO.AnotherStringProperty); - - var cont = doc as IDictionary; - cont.TryGetValue("StringProperty", out object valueFromDictionary); - Assert.Null(valueFromDictionary); - } - - [Fact] - public void MoveTypedToDynamic() - { - dynamic doc = new ExpandoObject(); - doc.StringProperty = "A"; - doc.SimpleDTO = new SimpleObject() { AnotherStringProperty = "B" }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("SimpleDTO/AnotherStringProperty", "StringProperty"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal("B", doc.StringProperty); - Assert.Null(doc.SimpleDTO.AnotherStringProperty); - } - - [Fact] - public void NestedMove() - { - dynamic doc = new ExpandoObject(); - doc.Nested = new SimpleObject() - { - StringProperty = "A", - AnotherStringProperty = "B" - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("Nested/StringProperty", "Nested/AnotherStringProperty"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal("A", doc.Nested.AnotherStringProperty); - Assert.Null(doc.Nested.StringProperty); - } - - [Fact] - public void MoveInList() - { - dynamic doc = new ExpandoObject(); - doc.IntegerList = new List() { 1, 2, 3 }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("IntegerList/0", "IntegerList/1"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 2, 1, 3 }, doc.IntegerList); - } - - [Fact] - public void NestedMoveInList() - { - dynamic doc = new ExpandoObject(); - doc.Nested = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("Nested/IntegerList/0", "Nested/IntegerList/1"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 2, 1, 3 }, doc.Nested.IntegerList); - } - - [Fact] - public void MoveFromListToEndOfList() - { - dynamic doc = new ExpandoObject(); - doc.IntegerList = new List() { 1, 2, 3 }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("IntegerList/0", "IntegerList/-"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 2, 3, 1 }, doc.IntegerList); - } - - [Fact] - public void NestedMoveFromListToEndOfList() - { - dynamic doc = new ExpandoObject(); - doc.Nested = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("Nested/IntegerList/0", "Nested/IntegerList/-"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 2, 3, 1 }, doc.Nested.IntegerList); - } - - [Fact] - public void MoveFomListToNonList() - { - dynamic doc = new ExpandoObject(); - doc.IntegerList = new List() { 1, 2, 3 }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("IntegerList/0", "IntegerValue"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 2, 3 }, doc.IntegerList); - Assert.Equal(1, doc.IntegerValue); - } - - [Fact] - public void NestedMoveFomListToNonList() - { - dynamic doc = new ExpandoObject(); - doc.Nested = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("Nested/IntegerList/0", "Nested/IntegerValue"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 2, 3 }, doc.Nested.IntegerList); - Assert.Equal(1, doc.Nested.IntegerValue); - } - - [Fact] - public void MoveFromNonListToList() - { - dynamic doc = new ExpandoObject(); - doc.IntegerValue = 5; - doc.IntegerList = new List() { 1, 2, 3 }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("IntegerValue", "IntegerList/0"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - var cont = doc as IDictionary; - cont.TryGetValue("IntegerValue", out object valueFromDictionary); - Assert.Null(valueFromDictionary); - - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void NestedMoveFromNonListToList() - { - dynamic doc = new ExpandoObject(); - doc.Nested = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("Nested/IntegerValue", "Nested/IntegerList/0"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(0, doc.Nested.IntegerValue); - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.Nested.IntegerList); - } - - [Fact] - public void MoveToEndOfList() - { - dynamic doc = new ExpandoObject(); - doc.IntegerValue = 5; - doc.IntegerList = new List() { 1, 2, 3 }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("IntegerValue", "IntegerList/-"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - var cont = doc as IDictionary; - cont.TryGetValue("IntegerValue", out var valueFromDictionary); - Assert.Null(valueFromDictionary); - - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.IntegerList); - } - - [Fact] - public void NestedMoveToEndOfList() - { - dynamic doc = new ExpandoObject(); - doc.Nested = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("Nested/IntegerValue", "Nested/IntegerList/-"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(0, doc.Nested.IntegerValue); - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.Nested.IntegerList); - } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs deleted file mode 100644 index 4638718a59..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/MoveTypedOperationTests.cs +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using Newtonsoft.Json; -using Xunit; - -namespace Microsoft.AspNetCore.JsonPatch.Internal -{ - public class MoveTypedOperationTests - { - [Fact] - public void Move() - { - var doc = new SimpleObject() - { - StringProperty = "A", - AnotherStringProperty = "B" - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("StringProperty", "AnotherStringProperty"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal("A", doc.AnotherStringProperty); - Assert.Null(doc.StringProperty); - } - - [Fact] - public void MoveInList() - { - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("IntegerList/0", "IntegerList/1"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 2, 1, 3 }, doc.IntegerList); - } - - [Fact] - public void MoveFromListToEndOfList() - { - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("IntegerList/0", "IntegerList/-"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 2, 3, 1 }, doc.IntegerList); - } - - [Fact] - public void MoveFomListToNonList() - { - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("IntegerList/0", "IntegerValue"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 2, 3 }, doc.IntegerList); - Assert.Equal(1, doc.IntegerValue); - } - - [Fact] - public void MoveFromNonListToList() - { - var doc = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("IntegerValue", "IntegerList/0"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(0, doc.IntegerValue); - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void MoveToEndOfList() - { - var doc = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("IntegerValue", "IntegerList/-"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(0, doc.IntegerValue); - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.IntegerList); - } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/PatchDocumentTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/PatchDocumentTests.cs deleted file mode 100644 index 403238bf99..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/PatchDocumentTests.cs +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.JsonPatch.Exceptions; -using Newtonsoft.Json; -using Xunit; - -namespace Microsoft.AspNetCore.JsonPatch.Internal -{ - public class PatchDocumentTests - { - [Fact] - public void InvalidPathAtBeginningShouldThrowException() - { - var patchDoc = new JsonPatchDocument(); - var exception = Assert.Throws(() => - { - patchDoc.Add("//NewInt", 1); - }); - Assert.Equal( - "The provided string '//NewInt' is an invalid path.", - exception.Message); - } - - [Fact] - public void InvalidPathAtEndShouldThrowException() - { - var patchDoc = new JsonPatchDocument(); - var exception = Assert.Throws(() => - { - patchDoc.Add("NewInt//", 1); - }); - Assert.Equal( - "The provided string 'NewInt//' is an invalid path.", - exception.Message); - } - - [Fact] - public void InvalidPathWithDotShouldThrowException() - { - var patchDoc = new JsonPatchDocument(); - var exception = Assert.Throws(() => - { - patchDoc.Add("NewInt.Test", 1); - }); - Assert.Equal( - "The provided string 'NewInt.Test' is an invalid path.", - exception.Message); - } - - [Fact] - public void NonGenericPatchDocToGenericMustSerialize() - { - var doc = new SimpleObject() - { - StringProperty = "A", - AnotherStringProperty = "B" - }; - - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("StringProperty", "AnotherStringProperty"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal("A", doc.AnotherStringProperty); - } - - [Fact] - public void GenericPatchDocToNonGenericMustSerialize() - { - var doc = new SimpleObject() - { - StringProperty = "A", - AnotherStringProperty = "B" - }; - - var patchDocTyped = new JsonPatchDocument(); - patchDocTyped.Copy(o => o.StringProperty, o => o.AnotherStringProperty); - - var patchDocUntyped = new JsonPatchDocument(); - patchDocUntyped.Copy("StringProperty", "AnotherStringProperty"); - - var serializedTyped = JsonConvert.SerializeObject(patchDocTyped); - var serializedUntyped = JsonConvert.SerializeObject(patchDocUntyped); - var deserialized = JsonConvert.DeserializeObject(serializedTyped); - - deserialized.ApplyTo(doc); - - Assert.Equal("A", doc.AnotherStringProperty); - } - } -} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs deleted file mode 100644 index 22707add87..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveOperationTests.cs +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using System.Dynamic; -using Microsoft.AspNetCore.JsonPatch.Exceptions; -using Newtonsoft.Json; -using Xunit; - -namespace Microsoft.AspNetCore.JsonPatch.Internal -{ - public class RemoveOperationTests - { - [Fact] - public void RemovePropertyShouldFailIfRootIsAnonymous() - { - dynamic doc = new - { - Test = 1 - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("Test"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The property at path '{0}' could not be updated.", "Test"), - exception.Message); - } - - [Fact] - public void RemovePropertyShouldFailIfItDoesntExist() - { - dynamic doc = new ExpandoObject(); - doc.Test = 1; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("NonExisting"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The target location specified by path segment '{0}' was not found.", "NonExisting"), - exception.Message); - } - - [Fact] - public void RemovePropertyFromExpandoObject() - { - dynamic obj = new ExpandoObject(); - obj.Test = 1; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("Test"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(obj); - - var cont = obj as IDictionary; - cont.TryGetValue("Test", out object valueFromDictionary); - Assert.Null(valueFromDictionary); - } - - [Fact] - public void RemoveProperty_FromExpandoObject_MixedCase_ThrowsPathNotFoundException() - { - dynamic obj = new ExpandoObject(); - obj.Test = 1; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("test"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(obj); - }); - - Assert.Equal( - string.Format( - "The target location specified by path segment '{0}' was not found.", - "test"), - exception.Message); - } - - [Fact] - public void RemoveNestedPropertyFromExpandoObject() - { - dynamic obj = new ExpandoObject(); - obj.Test = new ExpandoObject(); - obj.Test.AnotherTest = "A"; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("Test"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(obj); - - var cont = obj as IDictionary; - cont.TryGetValue("Test", out object valueFromDictionary); - Assert.Null(valueFromDictionary); - } - - [Fact] - public void RemoveNestedProperty_FromExpandoObject_MixedCase_ThrowsPathNotFoundException() - { - dynamic obj = new ExpandoObject(); - obj.Test = new ExpandoObject(); - obj.Test.AnotherTest = "A"; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("test"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(obj); - }); - - Assert.Equal( - string.Format( - "The target location specified by path segment '{0}' was not found.", - "test"), - exception.Message); - } - - [Fact] - public void NestedRemove() - { - dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleObject() - { - StringProperty = "A" - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("SimpleDTO/StringProperty"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - Assert.Null(doc.SimpleDTO.StringProperty); - } - - [Fact] - public void NestedRemove_MixedCase_ThrowsPathNotFoundException() - { - dynamic doc = new ExpandoObject(); - doc.SimpleObject = new SimpleObject() - { - StringProperty = "A" - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("Simpleobject/stringProperty"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - - Assert.Equal( - string.Format( - "For operation '{0}', the target location specified by path '{1}' was not found.", - "remove", - "/Simpleobject/stringProperty"), - exception.Message); - } - - [Fact] - public void NestedRemoveFromList() - { - dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("SimpleDTO/IntegerList/2"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 2 }, doc.SimpleDTO.IntegerList); - } - - [Fact] - public void NestedRemoveFromList_MixedCase() - { - dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("SimpleDTO/Integerlist/2"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 2 }, doc.SimpleDTO.IntegerList); - } - - [Fact] - public void NestedRemoveFromListInvalidPositionTooLarge() - { - dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("SimpleDTO/IntegerList/3"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), - exception.Message); - } - - [Fact] - public void NestedRemoveFromListInvalidPositionTooSmall() - { - dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("SimpleDTO/IntegerList/-1"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - exception.Message); - } - - [Fact] - public void NestedRemoveFromEndOfList() - { - dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("SimpleDTO/IntegerList/-"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - Assert.Equal(new List() { 1, 2 }, doc.SimpleDTO.IntegerList); - } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs deleted file mode 100644 index 000b049b1b..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/RemoveTypedOperationTests.cs +++ /dev/null @@ -1,244 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using Microsoft.AspNetCore.JsonPatch.Exceptions; -using Newtonsoft.Json; -using Xunit; - -namespace Microsoft.AspNetCore.JsonPatch.Internal -{ - public class RemoveTypedOperationTests - { - [Fact] - public void Remove() - { - var doc = new SimpleObject() - { - StringProperty = "A" - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("StringProperty"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Null(doc.StringProperty); - } - - [Fact] - public void RemoveFromList() - { - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("IntegerList/2"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 2 }, doc.IntegerList); - } - - [Fact] - public void RemoveFromListInvalidPositionTooLarge() - { - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("IntegerList/3"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), - exception.Message); - } - - [Fact] - public void RemoveFromListInvalidPositionTooSmall() - { - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("IntegerList/-1"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - exception.Message); - } - - [Fact] - public void RemoveFromEndOfList() - { - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("IntegerList/-"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 2 }, doc.IntegerList); - } - - [Fact] - public void NestedRemove() - { - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - StringProperty = "A" - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("SimpleObject/StringProperty"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Null(doc.SimpleObject.StringProperty); - } - - [Fact] - public void NestedRemoveFromList() - { - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("SimpleObject/IntegerList/2"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 2 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void NestedRemoveFromListInvalidPositionTooLarge() - { - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("SimpleObject/IntegerList/3"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), - exception.Message); - } - - [Fact] - public void NestedRemoveFromListInvalidPositionTooSmall() - { - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("SimpleObject/IntegerList/-1"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - exception.Message); - } - - [Fact] - public void NestedRemoveFromEndOfList() - { - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("SimpleObject/IntegerList/-"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 2 }, doc.SimpleObject.IntegerList); - } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs deleted file mode 100644 index 5d1fa77d85..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceOperationTests.cs +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Dynamic; -using Xunit; - -namespace Microsoft.AspNetCore.JsonPatch.Internal -{ - public class ReplaceOperationTests - { - [Fact] - public void ReplaceGuidTest() - { - dynamic doc = new SimpleObject() - { - GuidValue = Guid.NewGuid() - }; - - var newGuid = Guid.NewGuid(); - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("GuidValue", newGuid); - - patchDoc.ApplyTo(doc); - - Assert.Equal(newGuid, doc.GuidValue); - } - - [Fact] - public void ReplaceGuidTestExpandoObject() - { - dynamic doc = new ExpandoObject(); - doc.GuidValue = Guid.NewGuid(); - - var newGuid = Guid.NewGuid(); - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("GuidValue", newGuid); - - patchDoc.ApplyTo(doc); - - Assert.Equal(newGuid, doc.GuidValue); - } - - [Fact] - public void ReplaceGuidTestExpandoObjectInAnonymous() - { - dynamic nestedObject = new ExpandoObject(); - nestedObject.GuidValue = Guid.NewGuid(); - - dynamic doc = new - { - NestedObject = nestedObject - }; - - var newGuid = Guid.NewGuid(); - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("nestedobject/GuidValue", newGuid); - - patchDoc.ApplyTo(doc); - - Assert.Equal(newGuid, doc.NestedObject.GuidValue); - } - - [Fact] - public void ReplaceNestedObjectTest() - { - dynamic doc = new ExpandoObject(); - doc.SimpleDTO = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - }; - - var newDTO = new SimpleObject() - { - DoubleValue = 1 - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("SimpleDTO", newDTO); - - patchDoc.ApplyTo(doc); - - Assert.Equal(1, doc.SimpleDTO.DoubleValue); - Assert.Equal(0, doc.SimpleDTO.IntegerValue); - Assert.Null(doc.SimpleDTO.IntegerList); - } - - [Fact] - public void ReplaceInList() - { - dynamic doc = new ExpandoObject(); - doc.IntegerList = new List() { 1, 2, 3 }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("IntegerList/0", 5); - - patchDoc.ApplyTo(doc); - - Assert.Equal(new List() { 5, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void ReplaceFullList() - { - dynamic doc = new ExpandoObject(); - doc.IntegerList = new List() { 1, 2, 3 }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("IntegerList", new List() { 4, 5, 6 }); - - patchDoc.ApplyTo(doc); - - Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); - } - - [Fact] - public void ReplaceInListInList() - { - dynamic doc = new ExpandoObject(); - doc.SimpleDTOList = new List() { - new SimpleObject() { - IntegerList = new List(){1,2,3} - }}; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("SimpleDTOList/0/IntegerList/0", 4); - - patchDoc.ApplyTo(doc); - - Assert.Equal(4, doc.SimpleDTOList[0].IntegerList[0]); - } - - [Fact] - public void ReplaceInListInListAtEnd() - { - dynamic doc = new ExpandoObject(); - doc.SimpleDTOList = new List() { - new SimpleObject() { - IntegerList = new List(){1,2,3} - }}; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("SimpleDTOList/0/IntegerList/-", 4); - - patchDoc.ApplyTo(doc); - - Assert.Equal(4, doc.SimpleDTOList[0].IntegerList[2]); - } - - [Fact] - public void ReplaceFullListFromEnumerable() - { - dynamic doc = new ExpandoObject(); - doc.IntegerList = new List() { 1, 2, 3 }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("IntegerList", new List() { 4, 5, 6 }); - - patchDoc.ApplyTo(doc); - - Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); - } - - [Fact] - public void ReplaceFullListWithCollection() - { - dynamic doc = new ExpandoObject(); - doc.IntegerList = new List() { 1, 2, 3 }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("IntegerList", new Collection() { 4, 5, 6 }); - - patchDoc.ApplyTo(doc); - - Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); - } - - [Fact] - public void ReplaceAtEndOfList() - { - dynamic doc = new ExpandoObject(); - doc.IntegerList = new List() { 1, 2, 3 }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("IntegerList/-", 5); - - patchDoc.ApplyTo(doc); - - Assert.Equal(new List() { 1, 2, 5 }, doc.IntegerList); - } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceTypedOperationTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceTypedOperationTests.cs deleted file mode 100644 index 94131ff3b5..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/ReplaceTypedOperationTests.cs +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using Newtonsoft.Json; -using Xunit; - -namespace Microsoft.AspNetCore.JsonPatch.Internal -{ - public class ReplaceTypedOperationTests - { - [Fact] - public void ReplaceGuidTest() - { - var doc = new SimpleObject() - { - GuidValue = Guid.NewGuid() - }; - - var newGuid = Guid.NewGuid(); - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("GuidValue", newGuid); - - // serialize & deserialize - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserizalized = JsonConvert.DeserializeObject(serialized); - - deserizalized.ApplyTo(doc); - - Assert.Equal(newGuid, doc.GuidValue); - } - - [Fact] - public void SerializeAndReplaceNestedObjectTest() - { - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - } - }; - - var newDTO = new SimpleObject() - { - DoubleValue = 1 - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("SimpleObject", newDTO); - - // serialize & deserialize - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(1, doc.SimpleObject.DoubleValue); - Assert.Equal(0, doc.SimpleObject.IntegerValue); - Assert.Null(doc.SimpleObject.IntegerList); - } - - [Fact] - public void ReplaceInList() - { - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("IntegerList/0", 5); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 5, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void ReplaceFullList() - { - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("IntegerList", new List() { 4, 5, 6 }); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); - } - - [Fact] - public void ReplaceInListInList() - { - var doc = new SimpleObject() - { - SimpleObjectList = new List() { - new SimpleObject() { - IntegerList = new List(){1,2,3} - }} - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("SimpleObjectList/0/IntegerList/0", 4); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(4, doc.SimpleObjectList.First().IntegerList.First()); - } - - [Fact] - public void ReplaceFullListFromEnumerable() - { - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("IntegerList", new List() { 4, 5, 6 }); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); - } - - [Fact] - public void ReplaceFullListWithCollection() - { - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("IntegerList", new Collection() { 4, 5, 6 }); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); - } - - [Fact] - public void ReplaceAtEndOfList() - { - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("IntegerList/-", 5); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject(serialized); - deserialized.ApplyTo(doc); - - Assert.Equal(new List() { 1, 2, 5 }, doc.IntegerList); - } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleObject.cs deleted file mode 100644 index 01a890d7be..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleObject.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; - -namespace Microsoft.AspNetCore.JsonPatch.Internal -{ - public class SimpleObject - { - public List SimpleObjectList { get; set; } - public List IntegerList { get; set; } - public int IntegerValue { get; set; } - public string StringProperty { get; set; } - public string AnotherStringProperty { get; set; } - public decimal DecimalValue { get; set; } - public double DoubleValue { get; set; } - public float FloatValue { get; set; } - public Guid GuidValue { get; set; } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleObjectWithNestedObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleObjectWithNestedObject.cs deleted file mode 100644 index aa766b8438..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/SimpleObjectWithNestedObject.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; - -namespace Microsoft.AspNetCore.JsonPatch.Internal -{ - public class SimpleObjectWithNestedObject - { - public int IntegerValue { get; set; } - public NestedObject NestedObject { get; set; } - public SimpleObject SimpleObject { get; set; } - public List ListOfSimpleObject { get; set; } - - public SimpleObjectWithNestedObject() - { - NestedObject = new NestedObject(); - SimpleObject = new SimpleObject(); - ListOfSimpleObject = new List(); - } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/AnonymousObjectIntegrationTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/AnonymousObjectIntegrationTest.cs new file mode 100644 index 0000000000..4f290aae2f --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/AnonymousObjectIntegrationTest.cs @@ -0,0 +1,190 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNetCore.JsonPatch.Exceptions; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch.IntegrationTests +{ + public class AnonymousObjectIntegrationTest + { + [Fact] + public void AddNewProperty_ShouldFail() + { + // Arrange + var targetObject = new { }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Add("NewProperty", 4); + + // Act + var exception = Assert.Throws(() => + { + patchDocument.ApplyTo(targetObject); + }); + + // Assert + Assert.Equal("The target location specified by path segment 'NewProperty' was not found.", + exception.Message); + } + + [Fact] + public void AddNewProperty_ToNestedAnonymousObject_ShouldFail() + { + // Arrange + dynamic targetObject = new + { + Test = 1, + nested = new { } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Add("Nested/NewInt", 1); + + // Act + var exception = Assert.Throws(() => + { + patchDocument.ApplyTo(targetObject); + }); + + // Assert + Assert.Equal("The target location specified by path segment 'NewInt' was not found.", + exception.Message); + } + + [Fact] + public void AddDoesNotReplace() + { + // Arrange + var targetObject = new + { + StringProperty = "A" + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Add("StringProperty", "B"); + + // Act + var exception = Assert.Throws(() => + { + patchDocument.ApplyTo(targetObject); + }); + + // Assert + Assert.Equal("The property at path 'StringProperty' could not be updated.", + exception.Message); + } + + [Fact] + public void RemoveProperty_ShouldFail() + { + // Arrange + dynamic targetObject = new + { + Test = 1 + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Remove("Test"); + + // Act + var exception = Assert.Throws(() => + { + patchDocument.ApplyTo(targetObject); + }); + + // Assert + Assert.Equal("The property at path 'Test' could not be updated.", + exception.Message); + } + + [Fact] + public void ReplaceProperty_ShouldFail() + { + // Arrange + var targetObject = new + { + StringProperty = "A", + AnotherStringProperty = "B" + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Replace("StringProperty", "AnotherStringProperty"); + + // Act + var exception = Assert.Throws(() => + { + patchDocument.ApplyTo(targetObject); + }); + + // Assert + Assert.Equal("The property at path 'StringProperty' could not be updated.", + exception.Message); + } + + [Fact] + public void MoveProperty_ShouldFail() + { + // Arrange + var targetObject = new + { + StringProperty = "A", + AnotherStringProperty = "B" + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Move("StringProperty", "AnotherStringProperty"); + + // Act + var exception = Assert.Throws(() => + { + patchDocument.ApplyTo(targetObject); + }); + + // Assert + Assert.Equal("The property at path 'StringProperty' could not be updated.", + exception.Message); + } + + [Fact] + public void TestStringProperty_IsSucessful() + { + // Arrange + var targetObject = new + { + StringProperty = "A", + AnotherStringProperty = "B" + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Test("StringProperty", "A"); + + // Act & Assert + patchDocument.ApplyTo(targetObject); + } + + [Fact] + public void TestStringProperty_Fails() + { + // Arrange + var targetObject = new + { + StringProperty = "A", + AnotherStringProperty = "B" + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Test("StringProperty", "B"); + + // Act + var exception = Assert.Throws(() => + { + patchDocument.ApplyTo(targetObject); + }); + + // Assert + Assert.Equal("The current value 'A' at path 'StringProperty' is not equal to the test value 'B'.", + exception.Message); + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DictionaryIntegrationTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DictionaryIntegrationTest.cs new file mode 100644 index 0000000000..da990e3e8c --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DictionaryIntegrationTest.cs @@ -0,0 +1,319 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using Microsoft.AspNetCore.JsonPatch.Exceptions; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch.IntegrationTests +{ + public class DictionaryTest + { + [Fact] + public void TestIntegerValue_IsSuccessful() + { + // Arrange + var model = new IntDictionary(); + model.DictionaryOfStringToInteger["one"] = 1; + model.DictionaryOfStringToInteger["two"] = 2; + var patchDocument = new JsonPatchDocument(); + patchDocument.Test("/DictionaryOfStringToInteger/two", 2); + + // Act & Assert + patchDocument.ApplyTo(model); + } + + [Fact] + public void AddIntegerValue_Succeeds() + { + // Arrange + var model = new IntDictionary(); + model.DictionaryOfStringToInteger["one"] = 1; + model.DictionaryOfStringToInteger["two"] = 2; + var patchDocument = new JsonPatchDocument(); + patchDocument.Add("/DictionaryOfStringToInteger/three", 3); + + // Act + patchDocument.ApplyTo(model); + + // Assert + Assert.Equal(3, model.DictionaryOfStringToInteger.Count); + Assert.Equal(1, model.DictionaryOfStringToInteger["one"]); + Assert.Equal(2, model.DictionaryOfStringToInteger["two"]); + Assert.Equal(3, model.DictionaryOfStringToInteger["three"]); + } + + [Fact] + public void RemoveIntegerValue_Succeeds() + { + // Arrange + var model = new IntDictionary(); + model.DictionaryOfStringToInteger["one"] = 1; + model.DictionaryOfStringToInteger["two"] = 2; + var patchDocument = new JsonPatchDocument(); + patchDocument.Remove("/DictionaryOfStringToInteger/two"); + + // Act + patchDocument.ApplyTo(model); + + // Assert + Assert.Equal(1, model.DictionaryOfStringToInteger.Count); + Assert.Equal(1, model.DictionaryOfStringToInteger["one"]); + } + + [Fact] + public void MoveIntegerValue_Succeeds() + { + // Arrange + var model = new IntDictionary(); + model.DictionaryOfStringToInteger["one"] = 1; + model.DictionaryOfStringToInteger["two"] = 2; + var patchDocument = new JsonPatchDocument(); + patchDocument.Move("/DictionaryOfStringToInteger/one", "/DictionaryOfStringToInteger/two"); + + // Act + patchDocument.ApplyTo(model); + + // Assert + Assert.Equal(1, model.DictionaryOfStringToInteger.Count); + Assert.Equal(1, model.DictionaryOfStringToInteger["two"]); + } + + [Fact] + public void ReplaceIntegerValue_Succeeds() + { + // Arrange + var model = new IntDictionary(); + model.DictionaryOfStringToInteger["one"] = 1; + model.DictionaryOfStringToInteger["two"] = 2; + var patchDocument = new JsonPatchDocument(); + patchDocument.Replace("/DictionaryOfStringToInteger/two", 20); + + // Act + patchDocument.ApplyTo(model); + + // Assert + Assert.Equal(2, model.DictionaryOfStringToInteger.Count); + Assert.Equal(1, model.DictionaryOfStringToInteger["one"]); + Assert.Equal(20, model.DictionaryOfStringToInteger["two"]); + } + + [Fact] + public void CopyIntegerValue_Succeeds() + { + // Arrange + var model = new IntDictionary(); + model.DictionaryOfStringToInteger["one"] = 1; + model.DictionaryOfStringToInteger["two"] = 2; + var patchDocument = new JsonPatchDocument(); + patchDocument.Copy("/DictionaryOfStringToInteger/one", "/DictionaryOfStringToInteger/two"); + + // Act + patchDocument.ApplyTo(model); + + // Assert + Assert.Equal(2, model.DictionaryOfStringToInteger.Count); + Assert.Equal(1, model.DictionaryOfStringToInteger["one"]); + Assert.Equal(1, model.DictionaryOfStringToInteger["two"]); + } + + private class Customer + { + public string Name { get; set; } + public Address Address { get; set; } + } + + private class Address + { + public string City { get; set; } + } + + private class IntDictionary + { + public IDictionary DictionaryOfStringToInteger { get; } = new Dictionary(); + } + + private class CustomerDictionary + { + public IDictionary DictionaryOfStringToCustomer { get; } = new Dictionary(); + } + + [Fact] + public void TestPocoObject_Succeeds() + { + // Arrange + var key1 = 100; + var value1 = new Customer() { Name = "James" }; + var model = new CustomerDictionary(); + model.DictionaryOfStringToCustomer[key1] = value1; + var patchDocument = new JsonPatchDocument(); + patchDocument.Test($"/DictionaryOfStringToCustomer/{key1}/Name", "James"); + + // Act & Assert + patchDocument.ApplyTo(model); + } + + [Fact] + public void TestPocoObject_FailsWhenTestValueIsNotEqualToObjectValue() + { + // Arrange + var key1 = 100; + var value1 = new Customer() { Name = "James" }; + var model = new CustomerDictionary(); + model.DictionaryOfStringToCustomer[key1] = value1; + var patchDocument = new JsonPatchDocument(); + patchDocument.Test($"/DictionaryOfStringToCustomer/{key1}/Name", "Mike"); + + // Act + var exception = Assert.Throws(() => + { + patchDocument.ApplyTo(model); + }); + + // Assert + Assert.Equal("The current value 'James' at path 'Name' is not equal to the test value 'Mike'.", exception.Message); + } + + [Fact] + public void AddReplacesPocoObject_Succeeds() + { + // Arrange + var key1 = 100; + var value1 = new Customer() { Name = "Jamesss" }; + var key2 = 200; + var value2 = new Customer() { Name = "Mike" }; + var model = new CustomerDictionary(); + model.DictionaryOfStringToCustomer[key1] = value1; + model.DictionaryOfStringToCustomer[key2] = value2; + var patchDocument = new JsonPatchDocument(); + patchDocument.Add($"/DictionaryOfStringToCustomer/{key1}/Name", "James"); + + // Act + patchDocument.ApplyTo(model); + + // Assert + Assert.Equal(2, model.DictionaryOfStringToCustomer.Count); + var actualValue1 = model.DictionaryOfStringToCustomer[key1]; + Assert.NotNull(actualValue1); + Assert.Equal("James", actualValue1.Name); + } + + [Fact] + public void RemovePocoObject_Succeeds() + { + // Arrange + var key1 = 100; + var value1 = new Customer() { Name = "Jamesss" }; + var key2 = 200; + var value2 = new Customer() { Name = "Mike" }; + var model = new CustomerDictionary(); + model.DictionaryOfStringToCustomer[key1] = value1; + model.DictionaryOfStringToCustomer[key2] = value2; + var patchDocument = new JsonPatchDocument(); + patchDocument.Remove($"/DictionaryOfStringToCustomer/{key1}/Name"); + + // Act + patchDocument.ApplyTo(model); + + // Assert + var actualValue1 = model.DictionaryOfStringToCustomer[key1]; + Assert.Null(actualValue1.Name); + } + + [Fact] + public void MovePocoObject_Succeeds() + { + // Arrange + var key1 = 100; + var value1 = new Customer() { Name = "James" }; + var key2 = 200; + var value2 = new Customer() { Name = "Mike" }; + var model = new CustomerDictionary(); + model.DictionaryOfStringToCustomer[key1] = value1; + model.DictionaryOfStringToCustomer[key2] = value2; + var patchDocument = new JsonPatchDocument(); + patchDocument.Move($"/DictionaryOfStringToCustomer/{key1}/Name", $"/DictionaryOfStringToCustomer/{key2}/Name"); + + // Act + patchDocument.ApplyTo(model); + + // Assert + var actualValue2 = model.DictionaryOfStringToCustomer[key2]; + Assert.NotNull(actualValue2); + Assert.Equal("James", actualValue2.Name); + } + + [Fact] + public void CopyPocoObject_Succeeds() + { + // Arrange + var key1 = 100; + var value1 = new Customer() { Name = "James" }; + var key2 = 200; + var value2 = new Customer() { Name = "Mike" }; + var model = new CustomerDictionary(); + model.DictionaryOfStringToCustomer[key1] = value1; + model.DictionaryOfStringToCustomer[key2] = value2; + var patchDocument = new JsonPatchDocument(); + patchDocument.Copy($"/DictionaryOfStringToCustomer/{key1}/Name", $"/DictionaryOfStringToCustomer/{key2}/Name"); + + // Act + patchDocument.ApplyTo(model); + + // Assert + Assert.Equal(2, model.DictionaryOfStringToCustomer.Count); + var actualValue2 = model.DictionaryOfStringToCustomer[key2]; + Assert.NotNull(actualValue2); + Assert.Equal("James", actualValue2.Name); + } + + [Fact] + public void ReplacePocoObject_Succeeds() + { + // Arrange + var key1 = 100; + var value1 = new Customer() { Name = "Jamesss" }; + var key2 = 200; + var value2 = new Customer() { Name = "Mike" }; + var model = new CustomerDictionary(); + model.DictionaryOfStringToCustomer[key1] = value1; + model.DictionaryOfStringToCustomer[key2] = value2; + var patchDocument = new JsonPatchDocument(); + patchDocument.Replace($"/DictionaryOfStringToCustomer/{key1}/Name", "James"); + + // Act + patchDocument.ApplyTo(model); + + // Assert + Assert.Equal(2, model.DictionaryOfStringToCustomer.Count); + var actualValue1 = model.DictionaryOfStringToCustomer[key1]; + Assert.NotNull(actualValue1); + Assert.Equal("James", actualValue1.Name); + } + + [Fact] + public void ReplacePocoObject_WithEscaping_Succeeds() + { + // Arrange + var key1 = "Foo/Name"; + var value1 = 100; + var key2 = "Foo"; + var value2 = 200; + var model = new IntDictionary(); + model.DictionaryOfStringToInteger[key1] = value1; + model.DictionaryOfStringToInteger[key2] = value2; + var patchDocument = new JsonPatchDocument(); + patchDocument.Replace($"/DictionaryOfStringToInteger/Foo~1Name", 300); + + // Act + patchDocument.ApplyTo(model); + + // Assert + Assert.Equal(2, model.DictionaryOfStringToInteger.Count); + var actualValue1 = model.DictionaryOfStringToInteger[key1]; + var actualValue2 = model.DictionaryOfStringToInteger[key2]; + Assert.Equal(300, actualValue1); + Assert.Equal(200, actualValue2); + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DynamicObjectTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DynamicObjectIntegrationTest.cs similarity index 58% rename from test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DynamicObjectTest.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DynamicObjectIntegrationTest.cs index be7738419f..ec15951a85 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DynamicObjectTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DynamicObjectIntegrationTest.cs @@ -5,9 +5,9 @@ using System.Collections.Generic; using Microsoft.AspNetCore.JsonPatch.Exceptions; using Xunit; -namespace Microsoft.AspNetCore.JsonPatch.Internal +namespace Microsoft.AspNetCore.JsonPatch.IntegrationTests { - public class DynamicObjectTest + public class DynamicObjectIntegrationTest { [Fact] public void AddResults_ShouldReplaceExistingPropertyValue_InNestedDynamicObject() @@ -20,11 +20,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal dynamicTestObject.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond = new DynamicTestObject(); dynamicTestObject.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond.StringProperty = "A"; - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("/Nested/DynamicProperty/InBetweenFirst/InBetweenSecond/StringProperty", "B"); + var patchDocument = new JsonPatchDocument(); + patchDocument.Add("/Nested/DynamicProperty/InBetweenFirst/InBetweenSecond/StringProperty", "B"); // Act - patchDoc.ApplyTo(dynamicTestObject); + patchDocument.ApplyTo(dynamicTestObject); // Assert Assert.Equal("B", dynamicTestObject.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond.StringProperty); @@ -53,21 +53,17 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal DynamicProperty = new DynamicTestObject() }; - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("DynamicProperty/OtherProperty/IntProperty", 1); + var patchDocument = new JsonPatchDocument(); + patchDocument.Add("DynamicProperty/OtherProperty/IntProperty", 1); // Act var exception = Assert.Throws(() => { - patchDoc.ApplyTo(nestedObject); + patchDocument.ApplyTo(nestedObject); }); // Assert - Assert.Equal( - string.Format( - "The target location specified by path segment '{0}' was not found.", - "OtherProperty"), - exception.Message); + Assert.Equal("The target location specified by path segment 'OtherProperty' was not found.", exception.Message); } [Fact] @@ -79,11 +75,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal dynamicTestObject.NestedDynamicObject.StringProperty = "A"; dynamicTestObject.NestedDynamicObject.AnotherStringProperty = "B"; - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy("NestedDynamicObject/StringProperty", "NestedDynamicObject/AnotherStringProperty"); + var patchDocument = new JsonPatchDocument(); + patchDocument.Copy("NestedDynamicObject/StringProperty", "NestedDynamicObject/AnotherStringProperty"); // Act - patchDoc.ApplyTo(dynamicTestObject); + patchDocument.ApplyTo(dynamicTestObject); // Assert Assert.Equal("A", dynamicTestObject.NestedDynamicObject.AnotherStringProperty); @@ -97,11 +93,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal dynamic dynamicTestObject = new DynamicTestObject(); dynamicTestObject.StringProperty = "A"; - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("StringProperty", "AnotherStringProperty"); + var patchDocument = new JsonPatchDocument(); + patchDocument.Move("StringProperty", "AnotherStringProperty"); // Act - patchDoc.ApplyTo(dynamicTestObject); + patchDocument.ApplyTo(dynamicTestObject); dynamicTestObject.TryGetValue("StringProperty", out object valueFromDictionary); // Assert @@ -117,11 +113,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal dynamicTestObject.StringProperty = "A"; dynamicTestObject.SimpleObject = new SimpleObject() { AnotherStringProperty = "B" }; - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("StringProperty", "SimpleObject/AnotherStringProperty"); + var patchDocument = new JsonPatchDocument(); + patchDocument.Move("StringProperty", "SimpleObject/AnotherStringProperty"); // Act - patchDoc.ApplyTo(dynamicTestObject); + patchDocument.ApplyTo(dynamicTestObject); dynamicTestObject.TryGetValue("StringProperty", out object valueFromDictionary); // Assert @@ -129,27 +125,6 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.Null(valueFromDictionary); } - [Fact] - public void MovePropertyValue_FromListToNonList_InNestedTypedObject_InDynamicObject() - { - // Arrange - dynamic dynamicTestObject = new DynamicTestObject(); - dynamicTestObject.Nested = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - var patchDoc = new JsonPatchDocument(); - patchDoc.Move("Nested/IntegerList/0", "Nested/IntegerValue"); - - // Act - patchDoc.ApplyTo(dynamicTestObject); - - // Assert - Assert.Equal(new List() { 2, 3 }, dynamicTestObject.Nested.IntegerList); - Assert.Equal(1, dynamicTestObject.Nested.IntegerValue); - } - [Fact] public void RemoveNestedProperty_FromDynamicObject() { @@ -158,11 +133,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal dynamicTestObject.Test = new DynamicTestObject(); dynamicTestObject.Test.AnotherTest = "A"; - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("Test"); + var patchDocument = new JsonPatchDocument(); + patchDocument.Remove("Test"); // Act - patchDoc.ApplyTo(dynamicTestObject); + patchDocument.ApplyTo(dynamicTestObject); dynamicTestObject.TryGetValue("Test", out object valueFromDictionary); // Assert @@ -179,41 +154,19 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal StringProperty = "A" }; - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("Simpleobject/stringProperty"); + var patchDocument = new JsonPatchDocument(); + patchDocument.Remove("Simpleobject/stringProperty"); // Act var exception = Assert.Throws(() => { - patchDoc.ApplyTo(dynamicTestObject); + patchDocument.ApplyTo(dynamicTestObject); }); // Assert - Assert.Equal( - string.Format("The target location specified by path segment '{0}' was not found.", - "Simpleobject"), - exception.Message); + Assert.Equal("The target location specified by path segment 'Simpleobject' was not found.", exception.Message); } - [Fact] - public void RemoveFromList_NestedInDynamicObject() - { - // Arrange - dynamic dynamicTestObject = new DynamicTestObject(); - dynamicTestObject.SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove("SimpleObject/IntegerList/2"); - - // Act - patchDoc.ApplyTo(dynamicTestObject); - - // Assert - Assert.Equal(new List() { 1, 2 }, dynamicTestObject.SimpleObject.IntegerList); - } [Fact] public void ReplaceNestedTypedObject_InDynamicObject() @@ -231,11 +184,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal DoubleValue = 1 }; - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("SimpleObject", newObject); + var patchDocument = new JsonPatchDocument(); + patchDocument.Replace("SimpleObject", newObject); // Act - patchDoc.ApplyTo(dynamicTestObject); + patchDocument.ApplyTo(dynamicTestObject); // Assert Assert.Equal(1, dynamicTestObject.SimpleObject.DoubleValue); @@ -244,41 +197,21 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } [Fact] - public void ReplaceFullList_InDynamicObject() + public void TestStringPropertyValue_IsSuccessful() { // Arrange dynamic dynamicTestObject = new DynamicTestObject(); - dynamicTestObject.IntegerList = new List() { 1, 2, 3 }; + dynamicTestObject.Property = "A"; - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace("IntegerList", new List() { 4, 5, 6 }); - - // Act - patchDoc.ApplyTo(dynamicTestObject); - - // Assert - Assert.Equal(new List() { 4, 5, 6 }, dynamicTestObject.IntegerList); - } - - [Fact] - public void TestPropertyValue_FromListToNonList_InNestedTypedObject_InDynamicObject() - { - // Arrange - dynamic dynamicTestObject = new DynamicTestObject(); - dynamicTestObject.Nested = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - var patchDoc = new JsonPatchDocument(); - patchDoc.Test("Nested/IntegerList/1", 2); + var patchDocument = new JsonPatchDocument(); + patchDocument.Test("Property", "A"); // Act & Assert - patchDoc.ApplyTo(dynamicTestObject); + patchDocument.ApplyTo(dynamicTestObject); } [Fact] - public void TestPropertyValue_FromListToNonList_InNestedTypedObject_InDynamicObject_ThrowsJsonPatchException_IfTestFails() + public void TestIntegerPropertyValue_ThrowsJsonPatchException_IfTestFails() { // Arrange dynamic dynamicTestObject = new DynamicTestObject(); @@ -287,13 +220,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal IntegerList = new List() { 1, 2, 3 } }; - var patchDoc = new JsonPatchDocument(); - patchDoc.Test("Nested/IntegerList/0", 2); + var patchDocument = new JsonPatchDocument(); + patchDocument.Test("Nested/IntegerList/0", 2); // Act var exception = Assert.Throws(() => { - patchDoc.ApplyTo(dynamicTestObject); + patchDocument.ApplyTo(dynamicTestObject); }); // Assert diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/ExpandoObjectIntegrationTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/ExpandoObjectIntegrationTest.cs new file mode 100644 index 0000000000..b1b58556f0 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/ExpandoObjectIntegrationTest.cs @@ -0,0 +1,327 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Dynamic; +using Microsoft.AspNetCore.JsonPatch.Exceptions; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch.IntegrationTests +{ + public class ExpandoObjectIntegrationTest + { + [Fact] + public void AddNewIntProperty() + { + // Arrange + dynamic targetObject = new ExpandoObject(); + targetObject.Test = 1; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Add("NewInt", 1); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(1, targetObject.NewInt); + Assert.Equal(1, targetObject.Test); + } + + [Fact] + public void AddNewProperty_ToTypedObject_InExpandoObject() + { + // Arrange + dynamic dynamicProperty = new ExpandoObject(); + dynamicProperty.StringProperty = "A"; + + var targetObject = new NestedObject() + { + DynamicProperty = dynamicProperty + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Add("DynamicProperty/StringProperty", "B"); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal("B", targetObject.DynamicProperty.StringProperty); + } + + [Fact] + public void AddReplaces_ExistingProperty() + { + // Arrange + dynamic targetObject = new ExpandoObject(); + targetObject.StringProperty = "A"; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Add("StringProperty", "B"); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal("B", targetObject.StringProperty); + } + + [Fact] + public void AddReplaces_ExistingProperty_InNestedExpandoObject() + { + // Arrange + dynamic targetObject = new ExpandoObject(); + targetObject.InBetweenFirst = new ExpandoObject(); + targetObject.InBetweenFirst.InBetweenSecond = new ExpandoObject(); + targetObject.InBetweenFirst.InBetweenSecond.StringProperty = "A"; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Add("/InBetweenFirst/InBetweenSecond/StringProperty", "B"); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal("B", targetObject.InBetweenFirst.InBetweenSecond.StringProperty); + } + + [Fact] + public void ShouldNotReplaceProperty_WithDifferentCase() + { + // Arrange + dynamic targetObject = new ExpandoObject(); + targetObject.StringProperty = "A"; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Add("stringproperty", "B"); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal("A", targetObject.StringProperty); + Assert.Equal("B", targetObject.stringproperty); + } + + [Fact] + public void TestIntegerProperty_IsSucessful() + { + // Arrange + dynamic targetObject = new ExpandoObject(); + targetObject.Test = 1; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Test("Test", 1); + + // Act & Assert + patchDocument.ApplyTo(targetObject); + } + + [Fact] + public void TestStringProperty_ThrowsJsonPatchException_IfTestFails() + { + // Arrange + dynamic targetObject = new ExpandoObject(); + targetObject.Test = "Value"; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Test("Test", "TestValue"); + + // Act + var exception = Assert.Throws(() => + { + patchDocument.ApplyTo(targetObject); + }); + + // Assert + Assert.Equal("The current value 'Value' at path 'Test' is not equal to the test value 'TestValue'.", + exception.Message); + } + + [Fact] + public void CopyStringProperty_ToAnotherStringProperty() + { + // Arrange + dynamic targetObject = new ExpandoObject(); + + targetObject.StringProperty = "A"; + targetObject.AnotherStringProperty = "B"; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Copy("StringProperty", "AnotherStringProperty"); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal("A", targetObject.AnotherStringProperty); + } + + [Fact] + public void MoveIntegerValue_ToAnotherIntegerProperty() + { + // Arrange + dynamic targetObject = new ExpandoObject(); + targetObject.IntegerValue = 100; + targetObject.AnotherIntegerValue = 200; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Move("IntegerValue", "AnotherIntegerValue"); + + // Act + patchDocument.ApplyTo(targetObject); + + Assert.Equal(100, targetObject.AnotherIntegerValue); + + var cont = targetObject as IDictionary; + cont.TryGetValue("IntegerValue", out object valueFromDictionary); + + // Assert + Assert.Null(valueFromDictionary); + } + + [Fact] + public void Move_ToNonExistingProperty() + { + // Arrange + dynamic targetObject = new ExpandoObject(); + targetObject.StringProperty = "A"; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Move("StringProperty", "AnotherStringProperty"); + + // Act + patchDocument.ApplyTo(targetObject); + + Assert.Equal("A", targetObject.AnotherStringProperty); + + var cont = targetObject as IDictionary; + cont.TryGetValue("StringProperty", out var valueFromDictionary); + + // Assert + Assert.Null(valueFromDictionary); + } + + [Fact] + public void RemoveProperty_ShouldFail_IfItDoesntExist() + { + // Arrange + dynamic targetObject = new ExpandoObject(); + targetObject.Test = 1; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Remove("NonExisting"); + + // Act + var exception = Assert.Throws(() => + { + patchDocument.ApplyTo(targetObject); + }); + + // Assert + Assert.Equal("The target location specified by path segment 'NonExisting' was not found.", exception.Message); + } + + [Fact] + public void RemoveStringProperty() + { + // Arrange + dynamic targetObject = new ExpandoObject(); + targetObject.Test = 1; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Remove("Test"); + + // Act + patchDocument.ApplyTo(targetObject); + + var cont = targetObject as IDictionary; + cont.TryGetValue("Test", out object valueFromDictionary); + + // Assert + Assert.Null(valueFromDictionary); + } + + [Fact] + public void RemoveProperty_MixedCase_ThrowsPathNotFoundException() + { + // Arrange + dynamic targetObject = new ExpandoObject(); + targetObject.Test = 1; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Remove("test"); + + // Act + var exception = Assert.Throws(() => + { + patchDocument.ApplyTo(targetObject); + }); + + // Assert + Assert.Equal("The target location specified by path segment 'test' was not found.", exception.Message); + } + + [Fact] + public void RemoveNestedProperty() + { + // Arrange + dynamic targetObject = new ExpandoObject(); + targetObject.Test = new ExpandoObject(); + targetObject.Test.AnotherTest = "A"; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Remove("Test"); + + // Act + patchDocument.ApplyTo(targetObject); + + var cont = targetObject as IDictionary; + cont.TryGetValue("Test", out object valueFromDictionary); + + // Assert + Assert.Null(valueFromDictionary); + } + + [Fact] + public void RemoveNestedProperty_MixedCase_ThrowsPathNotFoundException() + { + // Arrange + dynamic targetObject = new ExpandoObject(); + targetObject.Test = new ExpandoObject(); + targetObject.Test.AnotherTest = "A"; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Remove("test"); + + // Act + var exception = Assert.Throws(() => + { + patchDocument.ApplyTo(targetObject); + }); + + // Assert + Assert.Equal("The target location specified by path segment 'test' was not found.", exception.Message); + } + + [Fact] + public void ReplaceGuid() + { + // Arrange + dynamic targetObject = new ExpandoObject(); + targetObject.GuidValue = Guid.NewGuid(); + + var newGuid = Guid.NewGuid(); + var patchDocument = new JsonPatchDocument(); + patchDocument.Replace("GuidValue", newGuid); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(newGuid, targetObject.GuidValue); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/ListIntegrationTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/ListIntegrationTest.cs new file mode 100644 index 0000000000..5e261ea08b --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/ListIntegrationTest.cs @@ -0,0 +1,366 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Microsoft.AspNetCore.JsonPatch.Exceptions; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch.IntegrationTests +{ + public class ListIntegrationTest + { + [Fact] + public void TestInList_IsSuccessful() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObject() + { + SimpleObject = new SimpleObject() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Test(o => o.SimpleObject.IntegerList, 3, 2); + + // Act & Assert + patchDocument.ApplyTo(targetObject); + } + + [Fact] + public void TestInList_InvalidPosition() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObject() + { + SimpleObject = new SimpleObject() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Test(o => o.SimpleObject.IntegerList, 4, -1); + + // Act & Assert + var exception = Assert.Throws(() => { patchDocument.ApplyTo(targetObject); }); + Assert.Equal("The index value provided by path segment '-1' is out of bounds of the array size.", + exception.Message); + } + + [Fact] + public void AddToIntegerIList() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObject() + { + SimpleObject = new SimpleObject() + { + IntegerIList = new List() { 1, 2, 3 } + } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Add(o => (List)o.SimpleObject.IntegerIList, 4, 0); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(new List() { 4, 1, 2, 3 }, targetObject.SimpleObject.IntegerIList); + } + + [Fact] + public void AddToComplextTypeList_SpecifyIndex() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObject() + { + SimpleObjectList = new List() + { + new SimpleObject + { + StringProperty = "String1" + }, + new SimpleObject + { + StringProperty = "String2" + } + } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Add(o => o.SimpleObjectList[0].StringProperty, "ChangedString1"); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal("ChangedString1", targetObject.SimpleObjectList[0].StringProperty); + } + + [Fact] + public void AddToListAppend() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObject() + { + SimpleObject = new SimpleObject() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Add(o => o.SimpleObject.IntegerList, 4); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(new List() { 1, 2, 3, 4 }, targetObject.SimpleObject.IntegerList); + } + + [Fact] + public void RemoveFromList() + { + // Arrange + var targetObject = new SimpleObject() + { + IntegerList = new List() { 1, 2, 3 } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Remove("IntegerList/2"); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(new List() { 1, 2 }, targetObject.IntegerList); + } + + [Theory] + [InlineData("3")] + [InlineData("-1")] + public void RemoveFromList_InvalidPosition(string position) + { + // Arrange + var targetObject = new SimpleObject() + { + IntegerList = new List() { 1, 2, 3 } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Remove("IntegerList/" + position); + + // Act + var exception = Assert.Throws(() => + { + patchDocument.ApplyTo(targetObject); + }); + + // Assert + Assert.Equal($"The index value provided by path segment '{position}' is out of bounds of the array size.", exception.Message); + } + + [Fact] + public void Remove_FromEndOfList() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObject() + { + SimpleObject = new SimpleObject() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Remove(o => o.SimpleObject.IntegerList); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(new List() { 1, 2 }, targetObject.SimpleObject.IntegerList); + } + + [Fact] + public void ReplaceFullList_WithCollection() + { + // Arrange + var targetObject = new SimpleObject() + { + IntegerList = new List() { 1, 2, 3 } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Replace("IntegerList", new Collection() { 4, 5, 6 }); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(new List() { 4, 5, 6 }, targetObject.IntegerList); + } + + [Fact] + public void Replace_AtEndOfList() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObject() + { + SimpleObject = new SimpleObject() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Replace(o => o.SimpleObject.IntegerList, 5); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(new List() { 1, 2, 5 }, targetObject.SimpleObject.IntegerList); + } + + [Fact] + public void Replace_InList_InvalidPosition() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObject() + { + SimpleObject = new SimpleObject() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Replace(o => o.SimpleObject.IntegerList, 5, -1); + + // Act + var exception = Assert.Throws(() => { patchDocument.ApplyTo(targetObject); }); + + // Assert + Assert.Equal("The index value provided by path segment '-1' is out of bounds of the array size.", exception.Message); + } + + [Fact] + public void CopyFromListToEndOfList() + { + // Arrange + var targetObject = new SimpleObject() + { + IntegerList = new List() { 1, 2, 3 } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Copy("IntegerList/0", "IntegerList/-"); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(new List() { 1, 2, 3, 1 }, targetObject.IntegerList); + } + + [Fact] + public void CopyFromListToNonList() + { + // Arrange + var targetObject = new SimpleObject() + { + IntegerList = new List() { 1, 2, 3 } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Copy("IntegerList/0", "IntegerValue"); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(1, targetObject.IntegerValue); + } + + [Fact] + public void MoveToEndOfList() + { + // Arrange + var targetObject = new SimpleObject() + { + IntegerValue = 5, + IntegerList = new List() { 1, 2, 3 } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Move("IntegerValue", "IntegerList/-"); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(0, targetObject.IntegerValue); + Assert.Equal(new List() { 1, 2, 3, 5 }, targetObject.IntegerList); + } + + [Fact] + public void Move_KeepsObjectReferenceInList() + { + // Arrange + var simpleObject1 = new SimpleObject() { IntegerValue = 1 }; + var simpleObject2 = new SimpleObject() { IntegerValue = 2 }; + var simpleObject3 = new SimpleObject() { IntegerValue = 3 }; + var targetObject = new SimpleObjectWithNestedObject() + { + SimpleObjectList = new List() { + simpleObject1, + simpleObject2, + simpleObject3 + } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Move(o => o.SimpleObjectList, 0, o => o.SimpleObjectList, 1); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(new List() { simpleObject2, simpleObject1, simpleObject3 }, targetObject.SimpleObjectList); + Assert.Equal(2, targetObject.SimpleObjectList[0].IntegerValue); + Assert.Equal(1, targetObject.SimpleObjectList[1].IntegerValue); + Assert.Same(simpleObject2, targetObject.SimpleObjectList[0]); + Assert.Same(simpleObject1, targetObject.SimpleObjectList[1]); + } + + [Fact] + public void MoveFromList_ToNonList_BetweenHierarchy() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObject() + { + SimpleObject = new SimpleObject() + { + IntegerList = new List() { 1, 2, 3 } + } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Move(o => o.SimpleObject.IntegerList, 0, o => o.IntegerValue); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(new List() { 2, 3 }, targetObject.SimpleObject.IntegerList); + Assert.Equal(1, targetObject.IntegerValue); + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/NestedObjectIntegrationTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/NestedObjectIntegrationTest.cs new file mode 100644 index 0000000000..92c0e7fb2d --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/NestedObjectIntegrationTest.cs @@ -0,0 +1,342 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Dynamic; +using Newtonsoft.Json; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch.IntegrationTests +{ + public class NestedObjectIntegrationTest + { + [Fact] + public void Replace_DTOWithNullCheck() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObjectWithNullCheck() + { + SimpleObjectWithNullCheck = new SimpleObjectWithNullCheck() + { + StringProperty = "A" + } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Replace(o => o.SimpleObjectWithNullCheck.StringProperty, "B"); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal("B", targetObject.SimpleObjectWithNullCheck.StringProperty); + } + + [Fact] + public void ReplaceNestedObject_WithSerialization() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObject() + { + IntegerValue = 1 + }; + + var newNested = new NestedObject() { StringProperty = "B" }; + var patchDocument = new JsonPatchDocument(); + patchDocument.Replace(o => o.NestedObject, newNested); + + var serialized = JsonConvert.SerializeObject(patchDocument); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(targetObject); + + // Assert + Assert.Equal("B", targetObject.NestedObject.StringProperty); + } + + [Fact] + public void TestStringProperty_InNestedObject() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObject() + { + NestedObject = new NestedObject() { StringProperty = "A"} + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Test(o => o.StringProperty, "A"); + + // Act + patchDocument.ApplyTo(targetObject.NestedObject); + + // Assert + Assert.Equal("A", targetObject.NestedObject.StringProperty); + } + + [Fact] + public void TestNestedObject() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObject() + { + NestedObject = new NestedObject() { StringProperty = "B"} + }; + + var testNested = new NestedObject() { StringProperty = "B" }; + var patchDocument = new JsonPatchDocument(); + patchDocument.Test(o => o.NestedObject, testNested); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal("B", targetObject.NestedObject.StringProperty); + } + + [Fact] + public void AddReplaces_ExistingStringProperty() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObject() + { + SimpleObject = new SimpleObject() + { + StringProperty = "A" + } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Add(o => o.SimpleObject.StringProperty, "B"); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal("B", targetObject.SimpleObject.StringProperty); + } + + [Fact] + public void AddNewProperty_ToExpandoOject_InTypedObject() + { + var targetObject = new NestedObject() + { + DynamicProperty = new ExpandoObject() + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Add("DynamicProperty/NewInt", 1); + + patchDocument.ApplyTo(targetObject); + + Assert.Equal(1, targetObject.DynamicProperty.NewInt); + } + + [Fact] + public void RemoveStringProperty() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObject() + { + SimpleObject = new SimpleObject() + { + StringProperty = "A" + } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Remove(o => o.SimpleObject.StringProperty); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Null(targetObject.SimpleObject.StringProperty); + } + + [Fact] + public void CopyStringProperty_ToAnotherStringProperty() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObject() + { + SimpleObject = new SimpleObject() + { + StringProperty = "A", + AnotherStringProperty = "B" + } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Copy(o => o.SimpleObject.StringProperty, o => o.SimpleObject.AnotherStringProperty); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal("A", targetObject.SimpleObject.AnotherStringProperty); + } + + [Fact] + public void Copy_DeepClonesObject() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObject() + { + SimpleObject = new SimpleObject() + { + StringProperty = "A", + AnotherStringProperty = "B" + }, + InheritedObject = new InheritedObject() + { + StringProperty = "C", + AnotherStringProperty = "D" + } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Copy(o => o.InheritedObject, o => o.SimpleObject); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal("C", targetObject.SimpleObject.StringProperty); + Assert.Equal("D", targetObject.SimpleObject.AnotherStringProperty); + Assert.Equal("C", targetObject.InheritedObject.StringProperty); + Assert.Equal("D", targetObject.InheritedObject.AnotherStringProperty); + Assert.NotSame(targetObject.SimpleObject.StringProperty, targetObject.InheritedObject.StringProperty); + } + + [Fact] + public void Copy_KeepsObjectType() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObject() + { + SimpleObject = new SimpleObject(), + InheritedObject = new InheritedObject() + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Copy(o => o.InheritedObject, o => o.SimpleObject); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(typeof(InheritedObject), targetObject.SimpleObject.GetType()); + } + + [Fact] + public void Copy_BreaksObjectReference() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObject() + { + SimpleObject = new SimpleObject(), + InheritedObject = new InheritedObject() + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Copy(o => o.InheritedObject, o => o.SimpleObject); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.NotSame(targetObject.SimpleObject, targetObject.InheritedObject); + } + + [Fact] + public void MoveIntegerValue_ToAnotherIntegerProperty() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObject() + { + SimpleObject = new SimpleObject() + { + IntegerValue = 2, + AnotherIntegerValue = 3 + } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Move(o => o.SimpleObject.IntegerValue, o => o.SimpleObject.AnotherIntegerValue); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(2, targetObject.SimpleObject.AnotherIntegerValue); + Assert.Equal(0, targetObject.SimpleObject.IntegerValue); + } + + [Fact] + public void Move_KeepsObjectReference() + { + // Arrange + var sDto = new SimpleObject() + { + StringProperty = "A", + AnotherStringProperty = "B" + }; + var iDto = new InheritedObject() + { + StringProperty = "C", + AnotherStringProperty = "D" + }; + var targetObject = new SimpleObjectWithNestedObject() + { + SimpleObject = sDto, + InheritedObject = iDto + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Move(o => o.InheritedObject, o => o.SimpleObject); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal("C", targetObject.SimpleObject.StringProperty); + Assert.Equal("D", targetObject.SimpleObject.AnotherStringProperty); + Assert.Same(iDto, targetObject.SimpleObject); + Assert.Null(targetObject.InheritedObject); + } + + private class SimpleObjectWithNullCheck + { + private string stringProperty; + + public string StringProperty + { + get + { + return stringProperty; + } + + set + { + if (value == null) + { + throw new ArgumentNullException(); + } + + stringProperty = value; + } + } + } + + private class SimpleObjectWithNestedObjectWithNullCheck + { + public SimpleObjectWithNullCheck SimpleObjectWithNullCheck { get; set; } + + public SimpleObjectWithNestedObjectWithNullCheck() + { + SimpleObjectWithNullCheck = new SimpleObjectWithNullCheck(); + } + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/SimpleObjectIntegrationTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/SimpleObjectIntegrationTest.cs new file mode 100644 index 0000000000..669c6d7af4 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/SimpleObjectIntegrationTest.cs @@ -0,0 +1,128 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch.IntegrationTests +{ + public class SimpleObjectIntegrationTest + { + [Fact] + public void TestDoubleValueProperty() + { + // Arrange + var targetObject = new SimpleObject() + { + DoubleValue = 9.8 + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Test("DoubleValue", 9.8); + + // Act & Assert + patchDocument.ApplyTo(targetObject); + } + + [Fact] + public void CopyStringProperty_ToAnotherStringProperty() + { + // Arrange + var targetObject = new SimpleObject() + { + StringProperty = "A", + AnotherStringProperty = "B" + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Copy("StringProperty", "AnotherStringProperty"); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal("A", targetObject.AnotherStringProperty); + } + + [Fact] + public void MoveIntegerProperty_ToAnotherIntegerProperty() + { + // Arrange + var targetObject = new SimpleObject() + { + IntegerValue = 2, + AnotherIntegerValue = 3 + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Move("IntegerValue", "AnotherIntegerValue"); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(2, targetObject.AnotherIntegerValue); + Assert.Equal(0, targetObject.IntegerValue); + } + + [Fact] + public void RemoveDecimalPropertyValue() + { + // Arrange + var targetObject = new SimpleObject() + { + DecimalValue = 9.8M + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Remove("DecimalValue"); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(0, targetObject.DecimalValue); + } + + [Fact] + public void ReplaceGuid() + { + // Arrange + var targetObject = new SimpleObject() + { + GuidValue = Guid.NewGuid() + }; + + var newGuid = Guid.NewGuid(); + var patchDocument = new JsonPatchDocument(); + patchDocument.Replace("GuidValue", newGuid); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(newGuid, targetObject.GuidValue); + } + + [Fact] + public void AddReplacesGuid() + { + // Arrange + var targetObject = new SimpleObject() + { + GuidValue = Guid.NewGuid() + }; + + var newGuid = Guid.NewGuid(); + var patchDocument = new JsonPatchDocument(); + patchDocument.Add("GuidValue", newGuid); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Equal(newGuid, targetObject.GuidValue); + } + + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/DictionaryAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/DictionaryAdapterTest.cs similarity index 91% rename from test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/DictionaryAdapterTest.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Internal/DictionaryAdapterTest.cs index d1d2216c2c..a0dcd82ab0 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/DictionaryAdapterTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/DictionaryAdapterTest.cs @@ -74,9 +74,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.False(getStatus); - Assert.Equal( - string.Format("The provided path segment '{0}' cannot be converted to the target type.", guidKey.ToString()), - message); + Assert.Equal($"The provided path segment '{guidKey.ToString()}' cannot be converted to the target type.", message); Assert.Null(outValue); } @@ -103,9 +101,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.False(getStatus); - Assert.Equal( - string.Format("The target location specified by path segment '{0}' was not found.", nameKey.ToUpper()), - message); + Assert.Equal("The target location specified by path segment 'NAME' was not found.", message); Assert.Null(outValue); } @@ -191,9 +187,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.False(replaceStatus); - Assert.Equal( - string.Format("The value '{0}' is invalid for target location.", "test"), - message); + Assert.Equal("The value 'test' is invalid for target location.", message); Assert.Equal(5, dictionary[guidKey]); } @@ -211,9 +205,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.False(replaceStatus); - Assert.Equal( - string.Format("The target location specified by path segment '{0}' was not found.", nameKey), - message); + Assert.Equal("The target location specified by path segment 'Name' was not found.", message); Assert.Empty(dictionary); } @@ -231,9 +223,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.False(removeStatus); - Assert.Equal( - string.Format("The target location specified by path segment '{0}' was not found.", nameKey), - message); + Assert.Equal("The target location specified by path segment 'Name' was not found.", message); Assert.Empty(dictionary); } @@ -280,13 +270,19 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { // Arrange var key = "Name"; - var dictionary = new Dictionary(); - dictionary[key] = "James"; - var dictionaryAdapter = new DictionaryAdapter(); + var dictionary = new Dictionary>(); + var value = new List() + { + "James", + 2, + new Customer("James", 25) + }; + dictionary[key] = value; + var dictionaryAdapter = new DictionaryAdapter>(); var resolver = new DefaultContractResolver(); // Act - var testStatus = dictionaryAdapter.TryTest(dictionary, key, resolver, "James", out var message); + var testStatus = dictionaryAdapter.TryTest(dictionary, key, resolver, value, out var message); //Assert Assert.True(testStatus); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/DynamicObjectAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/DynamicObjectAdapterTest.cs similarity index 97% rename from test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/DynamicObjectAdapterTest.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Internal/DynamicObjectAdapterTest.cs index 9ed9a51ed0..96b1aee935 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/DynamicObjectAdapterTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/DynamicObjectAdapterTest.cs @@ -233,15 +233,21 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { var adapter = new DynamicObjectAdapter(); dynamic target = new DynamicTestObject(); - target.NewProperty = "Joana"; + var value = new List() + { + "Joana", + 2, + new Customer("Joana", 25) + }; + target.NewProperty = value; var segment = "NewProperty"; var resolver = new DefaultContractResolver(); // Act - var testStatus = adapter.TryTest(target, segment, resolver, "Joana", out string errorMessage); + var testStatus = adapter.TryTest(target, segment, resolver, value, out string errorMessage); // Assert - Assert.Equal("Joana", target.NewProperty); + Assert.Equal(value, target.NewProperty); Assert.True(testStatus); Assert.True(string.IsNullOrEmpty(errorMessage), "Expected no error message"); } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/ListAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ListAdapterTest.cs similarity index 91% rename from test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/ListAdapterTest.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ListAdapterTest.cs index 25d8ae387b..f31e57541b 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/ListAdapterTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ListAdapterTest.cs @@ -24,11 +24,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.False(addStatus); - Assert.Equal( - string.Format( - "The type '{0}' which is an array is not supported for json patch operations as it has a fixed size.", - targetObject.GetType().FullName), - message); + Assert.Equal($"The type '{targetObject.GetType().FullName}' which is an array is not supported for json patch operations as it has a fixed size.", message); } [Fact] @@ -46,11 +42,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.False(addStatus); - Assert.Equal( - string.Format( - "The type '{0}' which is a non generic list is not supported for json patch operations. Only generic list types are supported.", - targetObject.GetType().FullName), - message); + Assert.Equal($"The type '{targetObject.GetType().FullName}' which is a non generic list is not supported for json patch operations. Only generic list types are supported.", message); } [Fact] @@ -88,9 +80,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.False(addStatus); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", position), - message); + Assert.Equal($"The index value provided by path segment '{position}' is out of bounds of the array size.", message); } [Theory] @@ -108,9 +98,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.False(addStatus); - Assert.Equal( - string.Format("The path segment '{0}' is invalid for an array index.", position), - message); + Assert.Equal($"The path segment '{position}' is invalid for an array index.", message); } public static TheoryData, List> AppendAtEndOfListData @@ -200,7 +188,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.False(addStatus); - Assert.Equal(string.Format("The value '{0}' is invalid for target location.", "James"), message); + Assert.Equal("The value 'James' is invalid for target location.", message); } public static TheoryData AddingDifferentComplexTypeWorksData @@ -255,8 +243,10 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.Equal(expected, targetObject); } - public static TheoryData AddingKeepsObjectReferenceData { - get { + public static TheoryData AddingKeepsObjectReferenceData + { + get + { var sDto1 = new SimpleObject(); var sDto2 = new SimpleObject(); var sDto3 = new SimpleObject(); @@ -324,9 +314,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.False(getStatus); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", position), - message); + Assert.Equal($"The index value provided by path segment '{position}' is out of bounds of the array size.", message); } [Theory] @@ -365,9 +353,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.False(removeStatus); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", position), - message); + Assert.Equal($"The index value provided by path segment '{position}' is out of bounds of the array size.", message); } [Theory] @@ -402,9 +388,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.False(replaceStatus); - Assert.Equal( - string.Format("The value '{0}' is invalid for target location.", "James"), - message); + Assert.Equal("The value 'James' is invalid for target location.", message); } [Fact] diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ObjectVisitorTest.cs similarity index 95% rename from test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ObjectVisitorTest.cs index 3384986c28..cb299cf0dc 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectVisitorTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ObjectVisitorTest.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.Collections.Generic; using System.Dynamic; using Newtonsoft.Json.Serialization; @@ -168,9 +167,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.False(visitStatus); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", position), - message); + Assert.Equal($"The index value provided by path segment '{position}' is out of bounds of the array size.", message); } [Theory] @@ -188,12 +185,9 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // Assert Assert.False(visitStatus); - Assert.Equal(string.Format( - "The path segment '{0}' is invalid for an array index.", position), - message); + Assert.Equal($"The path segment '{position}' is invalid for an array index.", message); } - // The adapter takes care of the responsibility of validating the final segment [Fact] public void Visit_DoesNotValidate_FinalPathSegment() { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ParsedPathTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ParsedPathTests.cs similarity index 91% rename from test/Microsoft.AspNetCore.JsonPatch.Test/ParsedPathTests.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ParsedPathTests.cs index 6b7c2e69cb..c23abcdb5e 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ParsedPathTests.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ParsedPathTests.cs @@ -2,10 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.AspNetCore.JsonPatch.Exceptions; -using Microsoft.AspNetCore.JsonPatch.Internal; using Xunit; -namespace Microsoft.AspNetCore.JsonPatch.Test +namespace Microsoft.AspNetCore.JsonPatch.Internal { public class ParsedPathTests { @@ -19,7 +18,10 @@ namespace Microsoft.AspNetCore.JsonPatch.Test [InlineData("~0~1foo", new string[] { "~/foo" })] public void ParsingValidPathShouldSucceed(string path, string[] expected) { + // Arrange & Act var parsedPath = new ParsedPath(path); + + // Assert Assert.Equal(expected, parsedPath.Segments); } @@ -30,6 +32,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Test [InlineData("foo~3bar")] public void PathWithInvalidEscapeSequenceShouldFail(string path) { + // Arrange, Act & Assert Assert.Throws(() => { var parsedPath = new ParsedPath(path); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/PocoAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/PocoAdapterTest.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/PocoAdapterTest.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/Internal/PocoAdapterTest.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentGetPathTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentGetPathTest.cs index 7d3331231c..266202c7a5 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentGetPathTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentGetPathTest.cs @@ -100,9 +100,7 @@ namespace Microsoft.AspNetCore.JsonPatch }); // Assert - Assert.Equal( - string.Format("The expression '(p.IntegerValue >= 4)' is not supported. Supported expressions include member access and indexer expressions."), - exception.Message); + Assert.Equal("The expression '(p.IntegerValue >= 4)' is not supported. Supported expressions include member access and indexer expressions.", exception.Message); } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs index 882e09ffe7..f5d6377989 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs @@ -1,9 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System.Collections.Generic; using System.Linq; -using System.Reflection; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using Xunit; @@ -13,263 +11,39 @@ namespace Microsoft.AspNetCore.JsonPatch public class JsonPatchDocumentJsonPropertyAttributeTest { [Fact] - public void Add_ToRoot_OfListOfObjects_AtEndOfList() + public void Add_RespectsJsonPropertyAttribute() { - var patchDoc = new JsonPatchDocument>(); - patchDoc.Add(p => p, new JsonPropertyObject()); + // Arrange + var patchDocument = new JsonPatchDocument(); - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = - JsonConvert.DeserializeObject>(serialized); + // Act + patchDocument.Add(p => p.Name, "John"); - // get path - var pathToCheck = deserialized.Operations.First().path; - Assert.Equal("/-", pathToCheck); - } - - [Fact] - public void Add_ToRoot_OfListOfObjects_AtGivenPosition() - { - var patchDoc = new JsonPatchDocument>(); - patchDoc.Add(p => p[3], new JsonPropertyObject()); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = - JsonConvert.DeserializeObject>(serialized); - - // get path - var pathToCheck = deserialized.Operations.First().path; - Assert.Equal("/3", pathToCheck); - } - - [Fact] - public void Add_WithExpression_RespectsJsonPropertyName_ForModelProperty() - { - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(p => p.Name, "John"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - // serialized value should have "AnotherName" as path - // deserialize to a JsonPatchDocument to check - var deserialized = - JsonConvert.DeserializeObject>(serialized); - - // get path - var pathToCheck = deserialized.Operations.First().path; + // Assert + var pathToCheck = patchDocument.Operations.First().path; Assert.Equal("/AnotherName", pathToCheck); } [Fact] - public void Add_WithExpressionOnStringProperty_FallsbackToPropertyName_WhenJsonPropertyName_IsEmpty() + public void Move_FallsbackToPropertyName_WhenJsonPropertyAttributeName_IsEmpty() { // Arrange - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(m => m.StringProperty, "Test"); - var serialized = JsonConvert.SerializeObject(patchDoc); + var patchDocument = new JsonPatchDocument(); // Act - var deserialized = - JsonConvert.DeserializeObject>(serialized); + patchDocument.Move(m => m.StringProperty, m => m.StringProperty2); // Assert - var pathToCheck = deserialized.Operations.First().path; - Assert.Equal("/StringProperty", pathToCheck); - } - - [Fact] - public void Add_WithExpressionOnArrayProperty_FallsbackToPropertyName_WhenJsonPropertyName_IsEmpty() - { - // Arrange - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(m => m.ArrayProperty, "James"); - var serialized = JsonConvert.SerializeObject(patchDoc); - - // Act - var deserialized = - JsonConvert.DeserializeObject>(serialized); - - // Assert - var pathToCheck = deserialized.Operations.First().path; - Assert.Equal("/ArrayProperty/-", pathToCheck); - } - - [Fact] - public void Add_WithExpression_RespectsJsonPropertyName_WhenApplyingToDifferentlyTypedClassWithPropertyMatchingJsonPropertyName() - { - var patchDocToSerialize = new JsonPatchDocument(); - patchDocToSerialize.Add(p => p.Name, "John"); - - // the patchdoc will deserialize to "anothername". We should thus be able to apply - // it to a class that HAS that other property name. - var doc = new JsonPropertyWithAnotherNameObject() - { - AnotherName = "InitialValue" - }; - - var serialized = JsonConvert.SerializeObject(patchDocToSerialize); - var deserialized = - JsonConvert.DeserializeObject> - (serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal("John", doc.AnotherName); - } - - [Fact] - public void Add_WithExpression_RespectsJsonPropertyName_WhenApplyingToSameTypedClassWithMatchingJsonPropertyName() - { - var patchDocToSerialize = new JsonPatchDocument(); - patchDocToSerialize.Add(p => p.Name, "John"); - - // the patchdoc will deserialize to "anothername". As JsonPropertyDTO has - // a JsonProperty signifying that "Name" should be deseriallized from "AnotherName", - // we should be able to apply the patchDoc. - - var doc = new JsonPropertyObject() - { - Name = "InitialValue" - }; - - var serialized = JsonConvert.SerializeObject(patchDocToSerialize); - var deserialized = - JsonConvert.DeserializeObject> - (serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal("John", doc.Name); - } - - [Fact] - public void Add_OnApplyFromJson_RespectsJsonPropertyNameOnJsonDocument() - { - var doc = new JsonPropertyObject() - { - Name = "InitialValue" - }; - - // serialization should serialize to "AnotherName" - var serialized = "[{\"value\":\"Kevin\",\"path\":\"/AnotherName\",\"op\":\"add\"}]"; - var deserialized = - JsonConvert.DeserializeObject>(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal("Kevin", doc.Name); - } - - [Fact] - public void Remove_OnApplyFromJson_RespectsJsonPropertyNameOnJsonDocument() - { - var doc = new JsonPropertyObject() - { - Name = "InitialValue" - }; - - // serialization should serialize to "AnotherName" - var serialized = "[{\"path\":\"/AnotherName\",\"op\":\"remove\"}]"; - var deserialized = - JsonConvert.DeserializeObject>(serialized); - - deserialized.ApplyTo(doc); - - Assert.Null(doc.Name); - } - - [Fact] - public void Add_OnApplyFromJson_RespectsInheritedJsonPropertyNameOnJsonDocument() - { - var doc = new JsonPropertyWithInheritanceObject() - { - Name = "InitialName" - }; - - // serialization should serialize to "AnotherName" - var serialized = "[{\"value\":\"Kevin\",\"path\":\"/AnotherName\",\"op\":\"add\"}]"; - var deserialized = - JsonConvert.DeserializeObject>(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal("Kevin", doc.Name); - } - - [Fact] - public void Add_WithExpression_RespectsJsonPropertyName_ForInheritedModelProperty() - { - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(p => p.Name, "John"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - // serialized value should have "AnotherName" as path - // deserialize to a JsonPatchDocument to check - var deserialized = - JsonConvert.DeserializeObject>(serialized); - - // get path - var pathToCheck = deserialized.Operations.First().path; - Assert.Equal("/AnotherName", pathToCheck); - } - - [Fact] - public void Add_OnApplyFromJson_EscapingHandledOnComplexJsonPropertyNameOnJsonDocument() - { - var doc = new JsonPropertyComplexNameObject() - { - FooSlashBars = "InitialName", - FooSlashTilde = new SimpleObject - { - StringProperty = "Initial Value" - } - }; - - // serialization should serialize to "AnotherName" - var serialized = "[{\"value\":\"Kevin\",\"path\":\"/foo~1bar~0\",\"op\":\"add\"},{\"value\":\"Final Value\",\"path\":\"/foo~1~0/StringProperty\",\"op\":\"replace\"}]"; - var deserialized = - JsonConvert.DeserializeObject>(serialized); - - deserialized.ApplyTo(doc); - - Assert.Equal("Kevin", doc.FooSlashBars); - Assert.Equal("Final Value", doc.FooSlashTilde.StringProperty); - } - - [Fact] - public void Move_WithExpression_FallsbackToPropertyName_WhenJsonPropertyName_IsEmpty() - { - // Arrange - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(m => m.StringProperty, m => m.StringProperty2); - var serialized = JsonConvert.SerializeObject(patchDoc); - - // Act - var deserialized = - JsonConvert.DeserializeObject>(serialized); - - // Assert - var fromPath = deserialized.Operations.First().from; + var fromPath = patchDocument.Operations.First().from; Assert.Equal("/StringProperty", fromPath); - var toPath = deserialized.Operations.First().path; + var toPath = patchDocument.Operations.First().path; Assert.Equal("/StringProperty2", toPath); } - [Fact] - public void Add_WithExpression_AndCustomContractResolver_UsesPropertyName_SetByContractResolver() + private class JsonPropertyObject { - // Arrange - var patchDoc = new JsonPatchDocument(); - patchDoc.ContractResolver = new CustomContractResolver(); - patchDoc.Add(m => m.SSN, "123-45-6789"); - var serialized = JsonConvert.SerializeObject(patchDoc); - - // Act - var deserialized = - JsonConvert.DeserializeObject>(serialized); - - // Assert - var path = deserialized.Operations.First().path; - Assert.Equal("/SocialSecurityNumber", path); + [JsonProperty("AnotherName")] + public string Name { get; set; } } private class JsonPropertyWithNoPropertyName @@ -286,20 +60,5 @@ namespace Microsoft.AspNetCore.JsonPatch [JsonProperty] public string SSN { get; set; } } - - private class CustomContractResolver : DefaultContractResolver - { - protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) - { - var jsonProperty = base.CreateProperty(member, memberSerialization); - - if (jsonProperty.PropertyName == "SSN") - { - jsonProperty.PropertyName = "SocialSecurityNumber"; - } - - return jsonProperty; - } - } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs index d754e8da5b..6b44b6696c 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs @@ -1,55 +1,180 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.AspNetCore.JsonPatch.Exceptions; using Newtonsoft.Json; using Xunit; -namespace Microsoft.AspNetCore.JsonPatch.Test +namespace Microsoft.AspNetCore.JsonPatch { public class JsonPatchDocumentTest { [Fact] - public void InvalidOperation_ThrowsException_CallsIntoLogErrorAction() + public void InvalidPathAtBeginningShouldThrowException() { // Arrange - var operationName = "foo"; - var serialized = "[{\"value\":\"John\",\"path\":\"/Name\",\"op\":\"" + operationName + "\"}]"; - var jsonPatchDocument = JsonConvert.DeserializeObject>(serialized); - var model = new Customer(); - var expectedErrorMessage = $"Invalid JsonPatch operation '{operationName}'."; - string actualErrorMessage = null; + var patchDocument = new JsonPatchDocument(); // Act - jsonPatchDocument.ApplyTo(model, (jsonPatchError) => + var exception = Assert.Throws(() => { - actualErrorMessage = jsonPatchError.ErrorMessage; + patchDocument.Add("//NewInt", 1); }); // Assert - Assert.Equal(expectedErrorMessage, actualErrorMessage); + Assert.Equal( + "The provided string '//NewInt' is an invalid path.", + exception.Message); } [Fact] - public void InvalidOperation_NoLogErrorAction_ThrowsJsonPatchException() + public void InvalidPathAtEndShouldThrowException() { // Arrange - var operationName = "foo"; - var serialized = "[{\"value\":\"John\",\"path\":\"/Name\",\"op\":\"" + operationName + "\"}]"; - var jsonPatchDocument = JsonConvert.DeserializeObject>(serialized); - var model = new Customer(); - var expectedErrorMessage = $"Invalid JsonPatch operation '{operationName}'."; + var patchDocument = new JsonPatchDocument(); // Act - var jsonPatchException = Assert.Throws(() => jsonPatchDocument.ApplyTo(model)); + var exception = Assert.Throws(() => + { + patchDocument.Add("NewInt//", 1); + }); // Assert - Assert.Equal(expectedErrorMessage, jsonPatchException.Message); + Assert.Equal( + "The provided string 'NewInt//' is an invalid path.", + exception.Message); } - private class Customer + [Fact] + public void InvalidPathWithDotShouldThrowException() { - public string Name { get; set; } + // Arrange + var patchDocument = new JsonPatchDocument(); + + // Act + var exception = Assert.Throws(() => + { + patchDocument.Add("NewInt.Test", 1); + }); + + // Assert + Assert.Equal( + "The provided string 'NewInt.Test' is an invalid path.", + exception.Message); + } + + [Fact] + public void NonGenericPatchDocToGenericMustSerialize() + { + // Arrange + var targetObject = new SimpleObject() + { + StringProperty = "A", + AnotherStringProperty = "B" + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Copy("StringProperty", "AnotherStringProperty"); + + var serialized = JsonConvert.SerializeObject(patchDocument); + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Act + deserialized.ApplyTo(targetObject); + + // Assert + Assert.Equal("A", targetObject.AnotherStringProperty); + } + + [Fact] + public void GenericPatchDocToNonGenericMustSerialize() + { + // Arrange + var targetObject = new SimpleObject() + { + StringProperty = "A", + AnotherStringProperty = "B" + }; + + var patchDocTyped = new JsonPatchDocument(); + patchDocTyped.Copy(o => o.StringProperty, o => o.AnotherStringProperty); + + var patchDocUntyped = new JsonPatchDocument(); + patchDocUntyped.Copy("StringProperty", "AnotherStringProperty"); + + var serializedTyped = JsonConvert.SerializeObject(patchDocTyped); + var serializedUntyped = JsonConvert.SerializeObject(patchDocUntyped); + var deserialized = JsonConvert.DeserializeObject(serializedTyped); + + // Act + deserialized.ApplyTo(targetObject); + + // Assert + Assert.Equal("A", targetObject.AnotherStringProperty); + } + + [Fact] + public void Deserialization_Successful_ForValidJsonPatchDocument() + { + // Arrange + var doc = new SimpleObject() + { + StringProperty = "A", + DecimalValue = 10, + DoubleValue = 10, + FloatValue = 10, + IntegerValue = 10 + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Replace(o => o.StringProperty, "B"); + patchDocument.Replace(o => o.DecimalValue, 12); + patchDocument.Replace(o => o.DoubleValue, 12); + patchDocument.Replace(o => o.FloatValue, 12); + patchDocument.Replace(o => o.IntegerValue, 12); + + // default: no envelope + var serialized = JsonConvert.SerializeObject(patchDocument); + + // Act + var deserialized = JsonConvert.DeserializeObject>(serialized); + + // Assert + Assert.IsType>(deserialized); + } + + [Fact] + public void Deserialization_Fails_ForInvalidJsonPatchDocument() + { + // Arrange + var serialized = "{\"Operations\": [{ \"op\": \"replace\", \"path\": \"/title\", \"value\": \"New Title\"}]}"; + + // Act + var exception = Assert.Throws(() => + { + var deserialized + = JsonConvert.DeserializeObject(serialized); + }); + + // Assert + Assert.Equal("The JSON patch document was malformed and could not be parsed.", exception.Message); + } + + [Fact] + public void Deserialization_Fails_ForInvalidTypedJsonPatchDocument() + { + // Arrange + var serialized = "{\"Operations\": [{ \"op\": \"replace\", \"path\": \"/title\", \"value\": \"New Title\"}]}"; + + // Act + var exception = Assert.Throws(() => + { + var deserialized + = JsonConvert.DeserializeObject>(serialized); + }); + + // Assert + Assert.Equal("The JSON patch document was malformed and could not be parsed.", exception.Message); } } -} +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyComplexNameObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyComplexNameObject.cs deleted file mode 100644 index a39aa8e30c..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyComplexNameObject.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.JsonPatch -{ - public class JsonPropertyComplexNameObject - { - [JsonProperty("foo/bar~")] - public string FooSlashBars { get; set; } - - [JsonProperty("foo/~")] - public SimpleObject FooSlashTilde { get; set; } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyObject.cs deleted file mode 100644 index 245ae6bb65..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyObject.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.JsonPatch -{ - public class JsonPropertyObject - { - [JsonProperty("AnotherName")] - public string Name { get; set; } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithAnotherNameObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithAnotherNameObject.cs deleted file mode 100644 index 4581a4826d..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithAnotherNameObject.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.JsonPatch -{ - public class JsonPropertyWithAnotherNameObject - { - public string AnotherName { get; set; } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithInheritanceObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithInheritanceObject.cs deleted file mode 100644 index 935ef275ad..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPropertyWithInheritanceObject.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Newtonsoft.Json; - -namespace Microsoft.AspNetCore.JsonPatch -{ - public class JsonPropertyWithInheritanceObject : JsonPropertyWithInheritanceBaseObject - { - public override string Name { get; set; } - } - - public abstract class JsonPropertyWithInheritanceBaseObject - { - [JsonProperty("AnotherName")] - public abstract string Name { get; set; } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObject.cs deleted file mode 100644 index 8f0927297e..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObject.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.JsonPatch -{ - public class NestedObject - { - public string StringProperty { get; set; } - } -} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs deleted file mode 100644 index a0b5bd7e3f..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/NestedObjectTests.cs +++ /dev/null @@ -1,2272 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using System.Collections.ObjectModel; -using Microsoft.AspNetCore.JsonPatch.Exceptions; -using Newtonsoft.Json; -using Xunit; - -namespace Microsoft.AspNetCore.JsonPatch -{ - public class NestedObjectTests - { - [Fact] - public void ReplacePropertyInNestedObject() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - IntegerValue = 1 - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.NestedObject.StringProperty, "B"); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal("B", doc.NestedObject.StringProperty); - } - - [Fact] - public void ReplacePropertyInNestedObjectWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - IntegerValue = 1 - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.NestedObject.StringProperty, "B"); - - // serialize & deserialize - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal("B", doc.NestedObject.StringProperty); - } - - [Fact] - public void ReplaceNestedObject() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - IntegerValue = 1 - }; - - var newNested = new NestedObject() { StringProperty = "B" }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.NestedObject, newNested); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal("B", doc.NestedObject.StringProperty); - } - - [Fact] - public void ReplaceNestedObjectWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - IntegerValue = 1 - }; - - var newNested = new NestedObject() { StringProperty = "B" }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.NestedObject, newNested); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal("B", doc.NestedObject.StringProperty); - } - - [Fact] - public void AddResultsInReplace() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - StringProperty = "A" - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleObject.StringProperty, "B"); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal("B", doc.SimpleObject.StringProperty); - } - - [Fact] - public void AddResultsInReplaceWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - StringProperty = "A" - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleObject.StringProperty, "B"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal("B", doc.SimpleObject.StringProperty); - } - - [Fact] - public void AddToList() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleObject.IntegerList, 4, 0); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void AddToListWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleObject.IntegerList, 4, 0); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void AddToIntegerIList() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerIList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => (List)o.SimpleObject.IntegerIList, 4, 0); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleObject.IntegerIList); - } - - [Fact] - public void AddToIntegerIListWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerIList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => (List)o.SimpleObject.IntegerIList, 4, 0); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleObject.IntegerIList); - } - - [Fact] - public void AddToNestedIntegerIList() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObjectIList = new List - { - new SimpleObject - { - IntegerIList = new List() { 1, 2, 3 } - } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => (List)o.SimpleObjectIList[0].IntegerIList, 4, 0); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleObjectIList[0].IntegerIList); - } - - [Fact] - public void AddToNestedIntegerIListWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObjectIList = new List - { - new SimpleObject - { - IntegerIList = new List() { 1, 2, 3 } - } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => (List)o.SimpleObjectIList[0].IntegerIList, 4, 0); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.SimpleObjectIList[0].IntegerIList); - } - - [Fact] - public void AddToComplextTypeListSpecifyIndex() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObjectList = new List() - { - new SimpleObject - { - StringProperty = "String1" - }, - new SimpleObject - { - StringProperty = "String2" - } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleObjectList[0].StringProperty, "ChangedString1"); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal("ChangedString1", doc.SimpleObjectList[0].StringProperty); - } - - [Fact] - public void AddToComplextTypeListSpecifyIndexWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObjectList = new List() - { - new SimpleObject - { - StringProperty = "String1" - }, - new SimpleObject - { - StringProperty = "String2" - } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleObjectList[0].StringProperty, "ChangedString1"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal("ChangedString1", doc.SimpleObjectList[0].StringProperty); - } - - [Fact] - public void AddToListInvalidPositionTooLarge() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleObject.IntegerList, 4, 4); - - // Act & Assert - var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "4"), - exception.Message); - - } - - [Fact] - public void AddToListInvalidPositionTooLargeWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleObject.IntegerList, 4, 4); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act & Assert - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "4"), - exception.Message); - } - - [Fact] - public void AddToListInvalidPositionTooLarge_LogsError() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleObject.IntegerList, 4, 4); - - var logger = new TestErrorLogger(); - - patchDoc.ApplyTo(doc, logger.LogErrorMessage); - - - //Assert - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "4"), - logger.ErrorMessage); - - } - - [Fact] - public void AddToListInvalidPositionTooSmall() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleObject.IntegerList, 4, -1); - - // Act & Assert - var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - exception.Message); - } - - [Fact] - public void AddToListInvalidPositionTooSmallWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleObject.IntegerList, 4, -1); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act & Assert - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - exception.Message); - } - - [Fact] - public void AddToListInvalidPositionTooSmall_LogsError() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleObject.IntegerList, 4, -1); - - var logger = new TestErrorLogger(); - - - patchDoc.ApplyTo(doc, logger.LogErrorMessage); - - - //Assert - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - logger.ErrorMessage); - } - - [Fact] - public void AddToListAppend() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleObject.IntegerList, 4); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2, 3, 4 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void AddToListAppendWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleObject.IntegerList, 4); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2, 3, 4 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void Remove() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - StringProperty = "A" - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleObject.StringProperty); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Null(doc.SimpleObject.StringProperty); - } - - [Fact] - public void RemoveWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - StringProperty = "A" - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleObject.StringProperty); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Null(doc.SimpleObject.StringProperty); - } - - [Fact] - public void RemoveFromList() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleObject.IntegerList, 2); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void RemoveFromListWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleObject.IntegerList, 2); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void RemoveFromListInvalidPositionTooLarge() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleObject.IntegerList, 3); - - // Act & Assert - var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), - exception.Message); - } - - [Fact] - public void RemoveFromListInvalidPositionTooLargeWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleObject.IntegerList, 3); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act & Assert - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), - exception.Message); - } - - [Fact] - public void RemoveFromListInvalidPositionTooLarge_LogsError() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleObject.IntegerList, 3); - - var logger = new TestErrorLogger(); - - patchDoc.ApplyTo(doc, logger.LogErrorMessage); - - // Assert - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), - logger.ErrorMessage); - } - - [Fact] - public void RemoveFromListInvalidPositionTooSmall() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleObject.IntegerList, -1); - - // Act & Assert - var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - exception.Message); - } - - [Fact] - public void RemoveFromListInvalidPositionTooSmallWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleObject.IntegerList, -1); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act & Assert - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - exception.Message); - } - - [Fact] - public void RemoveFromListInvalidPositionTooSmall_LogsError() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleObject.IntegerList, -1); - - var logger = new TestErrorLogger(); - - - patchDoc.ApplyTo(doc, logger.LogErrorMessage); - - // Assert - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - logger.ErrorMessage); - } - - [Fact] - public void RemoveFromEndOfList() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleObject.IntegerList); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void RemoveFromEndOfListWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.SimpleObject.IntegerList); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void Replace() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - StringProperty = "A", - DecimalValue = 10 - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleObject.StringProperty, "B"); - patchDoc.Replace(o => o.SimpleObject.DecimalValue, 12); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal("B", doc.SimpleObject.StringProperty); - Assert.Equal(12, doc.SimpleObject.DecimalValue); - } - - [Fact] - public void Replace_DTOWithNullCheck() - { - // Arrange - var doc = new SimpleObjectWithNestedObjectWithNullCheck() - { - SimpleObjectWithNullCheck = new SimpleObjectWithNullCheck() - { - StringProperty = "A" - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleObjectWithNullCheck.StringProperty, "B"); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal("B", doc.SimpleObjectWithNullCheck.StringProperty); - } - - [Fact] - public void ReplaceWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - StringProperty = "A", - DecimalValue = 10 - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleObject.StringProperty, "B"); - patchDoc.Replace(o => o.SimpleObject.DecimalValue, 12); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal("B", doc.SimpleObject.StringProperty); - Assert.Equal(12, doc.SimpleObject.DecimalValue); - } - - [Fact] - public void SerializationTests() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - StringProperty = "A", - DecimalValue = 10, - DoubleValue = 10, - FloatValue = 10, - IntegerValue = 10 - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleObject.StringProperty, "B"); - patchDoc.Replace(o => o.SimpleObject.DecimalValue, 12); - patchDoc.Replace(o => o.SimpleObject.DoubleValue, 12); - patchDoc.Replace(o => o.SimpleObject.FloatValue, 12); - patchDoc.Replace(o => o.SimpleObject.IntegerValue, 12); - - // serialize & deserialize - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserizalized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserizalized.ApplyTo(doc); - - // Assert - Assert.Equal("B", doc.SimpleObject.StringProperty); - Assert.Equal(12, doc.SimpleObject.DecimalValue); - Assert.Equal(12, doc.SimpleObject.DoubleValue); - Assert.Equal(12, doc.SimpleObject.FloatValue); - Assert.Equal(12, doc.SimpleObject.IntegerValue); - } - - [Fact] - public void ReplaceInList() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleObject.IntegerList, 5, 0); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 5, 2, 3 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void ReplaceInListWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleObject.IntegerList, 5, 0); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 5, 2, 3 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void ReplaceFullList() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleObject.IntegerList, new List() { 4, 5, 6 }); - - // Act - patchDoc.ApplyTo(doc); - - // Arrange - Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void ReplaceFullListWithSerialiation() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleObject.IntegerList, new List() { 4, 5, 6 }); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void ReplaceFullListFromEnumerable() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace>(o => o.SimpleObject.IntegerList, new List() { 4, 5, 6 }); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void ReplaceFullListFromEnumerableWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace>(o => o.SimpleObject.IntegerList, new List() { 4, 5, 6 }); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void ReplaceFullListWithCollection() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace>(o => o.SimpleObject.IntegerList, new Collection() { 4, 5, 6 }); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void ReplaceFullListWithCollectionWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace>(o => o.SimpleObject.IntegerList, new Collection() { 4, 5, 6 }); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 5, 6 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void ReplaceAtEndOfList() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleObject.IntegerList, 5); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2, 5 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void ReplaceAtEndOfListWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleObject.IntegerList, 5); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2, 5 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void ReplaceInListInvalidInvalidPositionTooLarge() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleObject.IntegerList, 5, 3); - - // Act & Assert - var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), - exception.Message); - } - - [Fact] - public void ReplaceInListInvalidInvalidPositionTooLargeWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleObject.IntegerList, 5, 3); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act & Assert - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), - exception.Message); - } - - [Fact] - public void ReplaceInListInvalid_PositionTooLarge_LogsError() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleObject.IntegerList, 5, 3); - - var logger = new TestErrorLogger(); - - - patchDoc.ApplyTo(doc, logger.LogErrorMessage); - - - // Assert - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), - logger.ErrorMessage); - } - - [Fact] - public void ReplaceInListInvalidPositionTooSmall() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleObject.IntegerList, 5, -1); - - // Act & Assert - var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - exception.Message); - } - - [Fact] - public void ReplaceInListInvalidPositionTooSmallWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleObject.IntegerList, 5, -1); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act & Assert - var exception = Assert.Throws(() => { deserialized.ApplyTo(doc); }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - exception.Message); - } - - [Fact] - public void ReplaceInListInvalidPositionTooSmall_LogsError() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleObject.IntegerList, 5, -1); - - var logger = new TestErrorLogger(); - - - patchDoc.ApplyTo(doc, logger.LogErrorMessage); - - - // Assert - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - logger.ErrorMessage); - } - - [Fact] - public void Copy() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - StringProperty = "A", - AnotherStringProperty = "B" - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleObject.StringProperty, o => o.SimpleObject.AnotherStringProperty); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal("A", doc.SimpleObject.AnotherStringProperty); - } - - [Fact] - public void CopyWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - StringProperty = "A", - AnotherStringProperty = "B" - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleObject.StringProperty, o => o.SimpleObject.AnotherStringProperty); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal("A", doc.SimpleObject.AnotherStringProperty); - } - - [Fact] - public void CopyInList() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerList, 1); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 1, 2, 3 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void CopyInListWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerList, 1); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 1, 2, 3 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void CopyFromListToEndOfList() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerList); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2, 3, 1 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void CopyFromListToEndOfListWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerList); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2, 3, 1 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void CopyFromListToNonList() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerValue); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(1, doc.SimpleObject.IntegerValue); - } - - [Fact] - public void CopyFromListToNonListWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerValue); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(1, doc.SimpleObject.IntegerValue); - } - - [Fact] - public void CopyFromNonListToList() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleObject.IntegerValue, o => o.SimpleObject.IntegerList, 0); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void CopyFromNonListToListWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleObject.IntegerValue, o => o.SimpleObject.IntegerList, 0); - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void CopyToEndOfList() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleObject.IntegerValue, o => o.SimpleObject.IntegerList); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void CopyToEndOfListWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.SimpleObject.IntegerValue, o => o.SimpleObject.IntegerList); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void Copy_DeepClonesObject() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - StringProperty = "A", - AnotherStringProperty = "B" - }, - InheritedObject = new InheritedObject() - { - StringProperty = "C", - AnotherStringProperty = "D" - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.InheritedObject, o => o.SimpleObject); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal("C", doc.SimpleObject.StringProperty); - Assert.Equal("D", doc.SimpleObject.AnotherStringProperty); - Assert.Equal("C", doc.InheritedObject.StringProperty); - Assert.Equal("D", doc.InheritedObject.AnotherStringProperty); - Assert.NotSame(doc.SimpleObject.StringProperty, doc.InheritedObject.StringProperty); - } - - [Fact] - public void Copy_KeepsObjectType() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject(), - InheritedObject = new InheritedObject() - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.InheritedObject, o => o.SimpleObject); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(typeof(InheritedObject), doc.SimpleObject.GetType()); - } - - [Fact] - public void Copy_BreaksObjectReference() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject(), - InheritedObject = new InheritedObject() - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.InheritedObject, o => o.SimpleObject); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.NotSame(doc.SimpleObject, doc.InheritedObject); - } - - [Fact] - public void Move() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - StringProperty = "A", - AnotherStringProperty = "B" - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleObject.StringProperty, o => o.SimpleObject.AnotherStringProperty); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal("A", doc.SimpleObject.AnotherStringProperty); - Assert.Null(doc.SimpleObject.StringProperty); - } - - [Fact] - public void MoveWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - StringProperty = "A", - AnotherStringProperty = "B" - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleObject.StringProperty, o => o.SimpleObject.AnotherStringProperty); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal("A", doc.SimpleObject.AnotherStringProperty); - Assert.Null(doc.SimpleObject.StringProperty); - } - - [Fact] - public void Move_KeepsObjectReference() - { - // Arrange - var sDto = new SimpleObject() - { - StringProperty = "A", - AnotherStringProperty = "B" - }; - var iDto = new InheritedObject() - { - StringProperty = "C", - AnotherStringProperty = "D" - }; - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = sDto, - InheritedObject = iDto - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.InheritedObject, o => o.SimpleObject); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal("C", doc.SimpleObject.StringProperty); - Assert.Equal("D", doc.SimpleObject.AnotherStringProperty); - Assert.Same(iDto, doc.SimpleObject); - Assert.Null(doc.InheritedObject); - } - - [Fact] - public void Move_KeepsObjectReferenceWithSerialization() - { - // Arrange - var sDto = new SimpleObject() - { - StringProperty = "A", - AnotherStringProperty = "B" - }; - var iDto = new InheritedObject() - { - StringProperty = "C", - AnotherStringProperty = "D" - }; - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = sDto, - InheritedObject = iDto - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.InheritedObject, o => o.SimpleObject); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal("C", doc.SimpleObject.StringProperty); - Assert.Equal("D", doc.SimpleObject.AnotherStringProperty); - Assert.Same(iDto, doc.SimpleObject); - Assert.Null(doc.InheritedObject); - } - - [Fact] - public void MoveInList() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerList, 1); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 2, 1, 3 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void MoveInListWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerList, 1); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 2, 1, 3 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void Move_KeepsObjectReferenceInList() - { - // Arrange - var sDto1 = new SimpleObject() { IntegerValue = 1 }; - var sDto2 = new SimpleObject() { IntegerValue = 2 }; - var sDto3 = new SimpleObject() { IntegerValue = 3 }; - var doc = new SimpleObjectWithNestedObject() - { - SimpleObjectList = new List() { - sDto1, - sDto2, - sDto3 - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleObjectList, 0, o => o.SimpleObjectList, 1); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { sDto2, sDto1, sDto3 }, doc.SimpleObjectList); - Assert.Equal(2, doc.SimpleObjectList[0].IntegerValue); - Assert.Equal(1, doc.SimpleObjectList[1].IntegerValue); - Assert.Same(sDto2, doc.SimpleObjectList[0]); - Assert.Same(sDto1, doc.SimpleObjectList[1]); - } - - [Fact] - public void Move_KeepsObjectReferenceInListWithSerialization() - { - // Arrange - var sDto1 = new SimpleObject() { IntegerValue = 1 }; - var sDto2 = new SimpleObject() { IntegerValue = 2 }; - var sDto3 = new SimpleObject() { IntegerValue = 3 }; - var doc = new SimpleObjectWithNestedObject() - { - SimpleObjectList = new List() { - sDto1, - sDto2, - sDto3 - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleObjectList, 0, o => o.SimpleObjectList, 1); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { sDto2, sDto1, sDto3 }, doc.SimpleObjectList); - Assert.Equal(2, doc.SimpleObjectList[0].IntegerValue); - Assert.Equal(1, doc.SimpleObjectList[1].IntegerValue); - Assert.Same(sDto2, doc.SimpleObjectList[0]); - Assert.Same(sDto1, doc.SimpleObjectList[1]); - } - - [Fact] - public void MoveFromListToEndOfList() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerList); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 2, 3, 1 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void MoveFromListToEndOfListWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerList); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 2, 3, 1 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void MoveFomListToNonList() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerValue); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 2, 3 }, doc.SimpleObject.IntegerList); - Assert.Equal(1, doc.SimpleObject.IntegerValue); - } - - [Fact] - public void MoveFomListToNonListWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleObject.IntegerList, 0, o => o.SimpleObject.IntegerValue); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 2, 3 }, doc.SimpleObject.IntegerList); - Assert.Equal(1, doc.SimpleObject.IntegerValue); - } - - [Fact] - public void MoveFomListToNonListBetweenHierarchy() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleObject.IntegerList, 0, o => o.IntegerValue); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 2, 3 }, doc.SimpleObject.IntegerList); - Assert.Equal(1, doc.IntegerValue); - } - - [Fact] - public void MoveFomListToNonListBetweenHierarchyWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleObject.IntegerList, 0, o => o.IntegerValue); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 2, 3 }, doc.SimpleObject.IntegerList); - Assert.Equal(1, doc.IntegerValue); - } - - [Fact] - public void MoveFromNonListToList() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleObject.IntegerValue, o => o.SimpleObject.IntegerList, 0); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(0, doc.IntegerValue); - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void MoveFromNonListToListWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleObject.IntegerValue, o => o.SimpleObject.IntegerList, 0); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(0, doc.IntegerValue); - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void MoveToEndOfList() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleObject.IntegerValue, o => o.SimpleObject.IntegerList); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(0, doc.IntegerValue); - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleObject.IntegerList); - } - - [Fact] - public void MoveToEndOfListWithSerialization() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.SimpleObject.IntegerValue, o => o.SimpleObject.IntegerList); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(0, doc.IntegerValue); - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.SimpleObject.IntegerList); - } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs deleted file mode 100644 index c1d005e897..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/ObjectAdapterTests.cs +++ /dev/null @@ -1,2331 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using Microsoft.AspNetCore.JsonPatch.Exceptions; -using Newtonsoft.Json; -using Xunit; - -namespace Microsoft.AspNetCore.JsonPatch.Adapters -{ - public class ObjectAdapterTests - { - [Fact] - public void AddResultsShouldReplace() - { - // Arrange - var doc = new SimpleObject() - { - StringProperty = "A" - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.StringProperty, "B"); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal("B", doc.StringProperty); - } - - [Fact] - public void AddResultsShouldReplaceWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - StringProperty = "A" - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.StringProperty, "B"); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal("B", doc.StringProperty); - } - - [Fact] - public void AddToList() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.IntegerList, 4, 0); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void AddToListWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.IntegerList, 4, 0); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void AddToIntegerIList() - { - // Arrange - var doc = new SimpleObject() - { - IntegerIList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.IntegerIList, 4, 0); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerIList); - } - - [Fact] - public void AddToIntegerIListWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerIList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.IntegerIList, 4, 0); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerIList); - } - - [Fact] - public void AddToListInvalidPositionTooLarge() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.IntegerList, 4, 4); - - // Act & Assert - var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "4"), - exception.Message); - } - - [Fact] - public void AddToListInvalidPositionTooLargeWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.IntegerList, 4, 4); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act & Assert - var exception = Assert.Throws(() => { deserialized.ApplyTo(doc); }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "4"), - exception.Message); - } - - [Fact] - public void AddToListInvalidPositionTooLarge_LogsError() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.IntegerList, 4, 4); - - var logger = new TestErrorLogger(); - - patchDoc.ApplyTo(doc, logger.LogErrorMessage); - - - // Assert - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "4"), - logger.ErrorMessage); - } - - [Fact] - public void AddToListAtBeginning() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.IntegerList, 4, 0); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void AddToListAtBeginningWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.IntegerList, 4, 0); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void AddToListInvalidPositionTooSmall() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.IntegerList, 4, -1); - - // Act & Assert - var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - exception.Message); - } - - [Fact] - public void AddToListInvalidPositionTooSmallWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.IntegerList, 4, -1); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act & Assert - var exception = Assert.Throws(() => { deserialized.ApplyTo(doc); }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - exception.Message); - } - - [Fact] - public void AddToListInvalidPositionTooSmall_LogsError() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.IntegerList, 4, -1); - - var logger = new TestErrorLogger(); - - patchDoc.ApplyTo(doc, logger.LogErrorMessage); - - // Assert - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - logger.ErrorMessage); - } - - [Fact] - public void AddToListAppend() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.IntegerList, 4); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2, 3, 4 }, doc.IntegerList); - } - - [Fact] - public void AddToListAppendWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.IntegerList, 4); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2, 3, 4 }, doc.IntegerList); - } - - [Fact] - public void Remove() - { - // Arrange - var doc = new SimpleObject() - { - StringProperty = "A" - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.StringProperty); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Null(doc.StringProperty); - } - - [Fact] - public void RemoveWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - StringProperty = "A" - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.StringProperty); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Null(doc.StringProperty); - } - - [Fact] - public void RemoveFromList() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.IntegerList, 2); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2 }, doc.IntegerList); - } - - [Fact] - public void RemoveFromListWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.IntegerList, 2); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2 }, doc.IntegerList); - } - - [Fact] - public void RemoveFromListInvalidPositionTooLarge() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.IntegerList, 3); - - // Act & Assert - var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), - exception.Message); - } - - [Fact] - public void RemoveFromListInvalidPositionTooLargeWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.IntegerList, 3); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act & Assert - var exception = Assert.Throws(() => { deserialized.ApplyTo(doc); }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), - exception.Message); - } - - [Fact] - public void RemoveFromListInvalidPositionTooLarge_LogsError() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.IntegerList, 3); - - var logger = new TestErrorLogger(); - - patchDoc.ApplyTo(doc, logger.LogErrorMessage); - - - // Assert - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), - logger.ErrorMessage); - } - - [Fact] - public void RemoveFromListInvalidPositionTooSmall() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.IntegerList, -1); - - // Act & Assert - var exception = Assert.Throws(() => { patchDoc.ApplyTo(doc); }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - exception.Message); - } - - [Fact] - public void RemoveFromListInvalidPositionTooSmallWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.IntegerList, -1); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act & Assert - var exception = Assert.Throws(() => { deserialized.ApplyTo(doc); }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - exception.Message); - } - - [Fact] - public void RemoveFromListInvalidPositionTooSmall_LogsError() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.IntegerList, -1); - - var logger = new TestErrorLogger(); - - - patchDoc.ApplyTo(doc, logger.LogErrorMessage); - - - // Assert - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - logger.ErrorMessage); - } - - [Fact] - public void RemoveFromEndOfList() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.IntegerList); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2 }, doc.IntegerList); - } - - [Fact] - public void RemoveFromEndOfListWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.IntegerList); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2 }, doc.IntegerList); - } - - [Fact] - public void Replace() - { - // Arrange - var doc = new SimpleObject() - { - StringProperty = "A", - DecimalValue = 10 - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.StringProperty, "B"); - - patchDoc.Replace(o => o.DecimalValue, 12); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal("B", doc.StringProperty); - Assert.Equal(12, doc.DecimalValue); - } - - [Fact] - public void Replace_DTOWithNullCheck() - { - // Arrange - var doc = new SimpleObjectWithNullCheck() - { - StringProperty = "A", - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.StringProperty, "B"); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal("B", doc.StringProperty); - } - - [Fact] - public void ReplaceWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - StringProperty = "A", - DecimalValue = 10 - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.StringProperty, "B"); - - patchDoc.Replace(o => o.DecimalValue, 12); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal("B", doc.StringProperty); - Assert.Equal(12, doc.DecimalValue); - } - - [Fact] - public void SerializationMustNotIncudeEnvelope() - { - // Arrange - var doc = new SimpleObject() - { - StringProperty = "A", - DecimalValue = 10, - DoubleValue = 10, - FloatValue = 10, - IntegerValue = 10 - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.StringProperty, "B"); - patchDoc.Replace(o => o.DecimalValue, 12); - patchDoc.Replace(o => o.DoubleValue, 12); - patchDoc.Replace(o => o.FloatValue, 12); - patchDoc.Replace(o => o.IntegerValue, 12); - - // Act - var serialized = JsonConvert.SerializeObject(patchDoc); - - // Assert - Assert.DoesNotContain("operations", serialized); - Assert.DoesNotContain("Operations", serialized); - } - - [Fact] - public void Deserialization_Successful_ForValidJsonPatchDocument() - { - // Arrange - var doc = new SimpleObject() - { - StringProperty = "A", - DecimalValue = 10, - DoubleValue = 10, - FloatValue = 10, - IntegerValue = 10 - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.StringProperty, "B"); - patchDoc.Replace(o => o.DecimalValue, 12); - patchDoc.Replace(o => o.DoubleValue, 12); - patchDoc.Replace(o => o.FloatValue, 12); - patchDoc.Replace(o => o.IntegerValue, 12); - - // default: no envelope - var serialized = JsonConvert.SerializeObject(patchDoc); - - // Act - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Assert - Assert.IsType>(deserialized); - } - - [Fact] - public void Deserialization_Fails_ForInvalidJsonPatchDocument() - { - // Arrange - var serialized = "{\"Operations\": [{ \"op\": \"replace\", \"path\": \"/title\", \"value\": \"New Title\"}]}"; - - // Act & Assert - var exception = Assert.Throws(() => - { - var deserialized - = JsonConvert.DeserializeObject(serialized); - }); - - Assert.Equal("The JSON patch document was malformed and could not be parsed.", exception.Message); - } - - [Fact] - public void Deserialization_Fails_ForInvalidTypedJsonPatchDocument() - { - // Arrange - var serialized = "{\"Operations\": [{ \"op\": \"replace\", \"path\": \"/title\", \"value\": \"New Title\"}]}"; - - // Act & Assert - var exception = Assert.Throws(() => - { - var deserialized - = JsonConvert.DeserializeObject>(serialized); - }); - - Assert.Equal("The JSON patch document was malformed and could not be parsed.", exception.Message); - } - - [Fact] - public void SerializationTests() - { - // Arrange - var doc = new SimpleObject() - { - StringProperty = "A", - DecimalValue = 10, - DoubleValue = 10, - FloatValue = 10, - IntegerValue = 10 - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.StringProperty, "B"); - patchDoc.Replace(o => o.DecimalValue, 12); - patchDoc.Replace(o => o.DoubleValue, 12); - patchDoc.Replace(o => o.FloatValue, 12); - patchDoc.Replace(o => o.IntegerValue, 12); - - // serialize & deserialize - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserizalized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserizalized.ApplyTo(doc); - - // Assert - Assert.Equal("B", doc.StringProperty); - Assert.Equal(12, doc.DecimalValue); - Assert.Equal(12, doc.DoubleValue); - Assert.Equal(12, doc.FloatValue); - Assert.Equal(12, doc.IntegerValue); - } - - [Fact] - public void SerializeAndReplaceGuidTest() - { - // Arrange - var doc = new SimpleObject() - { - GuidValue = Guid.NewGuid() - }; - - var newGuid = Guid.NewGuid(); - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.GuidValue, newGuid); - - // serialize & deserialize - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserizalized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserizalized.ApplyTo(doc); - - // Assert - Assert.Equal(newGuid, doc.GuidValue); - } - - [Fact] - public void SerializeAndReplaceNestedObjectTest() - { - // Arrange - var doc = new SimpleObjectWithNestedObject() - { - SimpleObject = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - } - }; - - var newDTO = new SimpleObject() - { - DoubleValue = 1 - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.SimpleObject, newDTO); - - // serialize & deserialize - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(1, doc.SimpleObject.DoubleValue); - Assert.Equal(0, doc.SimpleObject.IntegerValue); - Assert.Null(doc.SimpleObject.IntegerList); - } - - [Fact] - public void ReplaceInList() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.IntegerList, 5, 0); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 5, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void ReplaceInListWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.IntegerList, 5, 0); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 5, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void ReplaceFullList() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace>(o => o.IntegerList, new List() { 4, 5, 6 }); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); - } - - [Fact] - public void ReplaceFullListWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace>(o => o.IntegerList, new List() { 4, 5, 6 }); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); - } - - [Fact] - public void ReplaceFullListFromEnumerable() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace>(o => o.IntegerList, new List() { 4, 5, 6 }); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); - } - - [Fact] - public void ReplaceFullListFromEnumerableWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace>(o => o.IntegerList, new List() { 4, 5, 6 }); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); - } - - [Fact] - public void ReplaceFullListWithCollection() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace>(o => o.IntegerList, new Collection() { 4, 5, 6 }); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); - } - - [Fact] - public void ReplaceFullListWithCollectionWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace>(o => o.IntegerList, new Collection() { 4, 5, 6 }); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 5, 6 }, doc.IntegerList); - } - - [Fact] - public void ReplaceAtEndOfList() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.IntegerList, 5); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2, 5 }, doc.IntegerList); - } - - [Fact] - public void ReplaceAtEndOfListWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.IntegerList, 5); - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2, 5 }, doc.IntegerList); - } - - [Fact] - public void ReplaceInListInvalidInvalidPositionTooLarge() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.IntegerList, 5, 3); - - // Act & Assert - var exception = Assert.Throws(() => - { - patchDoc.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), - exception.Message); - } - - [Fact] - public void ReplaceInListInvalidInvalidPositionTooLargeWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.IntegerList, 5, 3); - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act & Assert - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "3"), - exception.Message); - } - - [Fact] - public void ReplaceInListInvalidPositionTooSmall() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.IntegerList, 5, -1); - - // Act & Assert - var exception = Assert.Throws(() => - { - patchDoc.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - exception.Message); - } - - [Fact] - public void ReplaceInListInvalidPositionTooSmallWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Replace(o => o.IntegerList, 5, -1); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act & Assert - var exception = Assert.Throws(() => - { - deserialized.ApplyTo(doc); - }); - Assert.Equal( - string.Format("The index value provided by path segment '{0}' is out of bounds of the array size.", "-1"), - exception.Message); - } - - [Fact] - public void Copy() - { - // Arrange - var doc = new SimpleObject() - { - StringProperty = "A", - AnotherStringProperty = "B" - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.StringProperty, o => o.AnotherStringProperty); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal("A", doc.AnotherStringProperty); - } - - [Fact] - public void CopyWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - StringProperty = "A", - AnotherStringProperty = "B" - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.StringProperty, o => o.AnotherStringProperty); - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal("A", doc.AnotherStringProperty); - } - - [Fact] - public void CopyInList() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.IntegerList, 0, o => o.IntegerList, 1); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 1, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void CopyInListWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.IntegerList, 0, o => o.IntegerList, 1); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 1, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void CopyFromListToEndOfList() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.IntegerList, 0, o => o.IntegerList); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2, 3, 1 }, doc.IntegerList); - } - - [Fact] - public void CopyFromListToEndOfListWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.IntegerList, 0, o => o.IntegerList); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2, 3, 1 }, doc.IntegerList); - } - - [Fact] - public void CopyFromListToNonList() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.IntegerList, 0, o => o.IntegerValue); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(1, doc.IntegerValue); - } - - [Fact] - public void CopyFromListToNonListWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.IntegerList, 0, o => o.IntegerValue); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(1, doc.IntegerValue); - } - - [Fact] - public void CopyFromNonListToList() - { - // Arrange - var doc = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.IntegerValue, o => o.IntegerList, 0); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void CopyFromNonListToListWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.IntegerValue, o => o.IntegerList, 0); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void CopyToEndOfList() - { - // Arrange - var doc = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.IntegerValue, o => o.IntegerList); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.IntegerList); - } - - [Fact] - public void CopyToEndOfListWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Copy(o => o.IntegerValue, o => o.IntegerList); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.IntegerList); - } - - [Fact] - public void Move() - { - // Arrange - var doc = new SimpleObject() - { - StringProperty = "A", - AnotherStringProperty = "B" - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.StringProperty, o => o.AnotherStringProperty); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal("A", doc.AnotherStringProperty); - Assert.Null(doc.StringProperty); - } - - [Fact] - public void MoveWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - StringProperty = "A", - AnotherStringProperty = "B" - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.StringProperty, o => o.AnotherStringProperty); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal("A", doc.AnotherStringProperty); - Assert.Null(doc.StringProperty); - } - - [Fact] - public void MoveInList() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.IntegerList, 0, o => o.IntegerList, 1); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 2, 1, 3 }, doc.IntegerList); - } - - [Fact] - public void MoveInListWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.IntegerList, 0, o => o.IntegerList, 1); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 2, 1, 3 }, doc.IntegerList); - } - - [Fact] - public void MoveFromListToEndOfList() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.IntegerList, 0, o => o.IntegerList); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 2, 3, 1 }, doc.IntegerList); - } - - [Fact] - public void MoveFromListToEndOfListWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.IntegerList, 0, o => o.IntegerList); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 2, 3, 1 }, doc.IntegerList); - } - - [Fact] - public void MoveFomListToNonList() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.IntegerList, 0, o => o.IntegerValue); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 2, 3 }, doc.IntegerList); - Assert.Equal(1, doc.IntegerValue); - } - - [Fact] - public void MoveFomListToNonListWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.IntegerList, 0, o => o.IntegerValue); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 2, 3 }, doc.IntegerList); - Assert.Equal(1, doc.IntegerValue); - } - - [Fact] - public void MoveFromNonListToList() - { - // Arrange - var doc = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.IntegerValue, o => o.IntegerList, 0); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(0, doc.IntegerValue); - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void MoveFromNonListToListWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.IntegerValue, o => o.IntegerList, 0); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(0, doc.IntegerValue); - Assert.Equal(new List() { 5, 1, 2, 3 }, doc.IntegerList); - } - - [Fact] - public void MoveToEndOfList() - { - // Arrange - var doc = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.IntegerValue, o => o.IntegerList); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(0, doc.IntegerValue); - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.IntegerList); - } - - [Fact] - public void MoveToEndOfListWithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - IntegerValue = 5, - IntegerList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Move(o => o.IntegerValue, o => o.IntegerList); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Equal(0, doc.IntegerValue); - Assert.Equal(new List() { 1, 2, 3, 5 }, doc.IntegerList); - } - - private class Class6 - { - public IDictionary DictionaryOfStringToInteger { get; } = new Dictionary(); - } - - [Fact] - public void Add_WhenDictionary_ValueIsNonObject_Succeeds() - { - // Arrange - var model = new Class6(); - model.DictionaryOfStringToInteger["one"] = 1; - model.DictionaryOfStringToInteger["two"] = 2; - var patchDocument = new JsonPatchDocument(); - patchDocument.Add("/DictionaryOfStringToInteger/three", 3); - - // Act - patchDocument.ApplyTo(model); - - // Assert - Assert.Equal(3, model.DictionaryOfStringToInteger.Count); - Assert.Equal(1, model.DictionaryOfStringToInteger["one"]); - Assert.Equal(2, model.DictionaryOfStringToInteger["two"]); - Assert.Equal(3, model.DictionaryOfStringToInteger["three"]); - } - - [Fact] - public void Remove_WhenDictionary_ValueIsNonObject_Succeeds() - { - // Arrange - var model = new Class6(); - model.DictionaryOfStringToInteger["one"] = 1; - model.DictionaryOfStringToInteger["two"] = 2; - var patchDocument = new JsonPatchDocument(); - patchDocument.Remove("/DictionaryOfStringToInteger/two"); - - // Act - patchDocument.ApplyTo(model); - - // Assert - Assert.Equal(1, model.DictionaryOfStringToInteger.Count); - Assert.Equal(1, model.DictionaryOfStringToInteger["one"]); - } - - [Fact] - public void Replace_WhenDictionary_ValueIsNonObject_Succeeds() - { - // Arrange - var model = new Class6(); - model.DictionaryOfStringToInteger["one"] = 1; - model.DictionaryOfStringToInteger["two"] = 2; - var patchDocument = new JsonPatchDocument(); - patchDocument.Replace("/DictionaryOfStringToInteger/two", 20); - - // Act - patchDocument.ApplyTo(model); - - // Assert - Assert.Equal(2, model.DictionaryOfStringToInteger.Count); - Assert.Equal(1, model.DictionaryOfStringToInteger["one"]); - Assert.Equal(20, model.DictionaryOfStringToInteger["two"]); - } - - private class Customer - { - public string Name { get; set; } - public Address Address { get; set; } - } - - private class Address - { - public string City { get; set; } - } - - private class Class8 - { - public IDictionary DictionaryOfStringToCustomer { get; } = new Dictionary(); - } - - [Fact] - public void Replace_WhenDictionary_ValueAPocoType_Succeeds() - { - // Arrange - var key1 = "key1"; - var value1 = new Customer() { Name = "Jamesss" }; - var key2 = "key2"; - var value2 = new Customer() { Name = "Mike" }; - var model = new Class8(); - model.DictionaryOfStringToCustomer[key1] = value1; - model.DictionaryOfStringToCustomer[key2] = value2; - var patchDocument = new JsonPatchDocument(); - patchDocument.Replace($"/DictionaryOfStringToCustomer/{key1}/Name", "James"); - - // Act - patchDocument.ApplyTo(model); - - // Assert - Assert.Equal(2, model.DictionaryOfStringToCustomer.Count); - var actualValue1 = model.DictionaryOfStringToCustomer[key1]; - Assert.NotNull(actualValue1); - Assert.Equal("James", actualValue1.Name); - } - - [Fact] - public void Replace_WhenDictionary_ValueAPocoType_Succeeds_WithSerialization() - { - // Arrange - var key1 = "key1"; - var value1 = new Customer() { Name = "Jamesss" }; - var key2 = "key2"; - var value2 = new Customer() { Name = "Mike" }; - var model = new Class8(); - model.DictionaryOfStringToCustomer[key1] = value1; - model.DictionaryOfStringToCustomer[key2] = value2; - var patchDocument = new JsonPatchDocument(); - patchDocument.Replace($"/DictionaryOfStringToCustomer/{key1}/Name", "James"); - var serialized = JsonConvert.SerializeObject(patchDocument); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - patchDocument.ApplyTo(model); - - // Assert - Assert.Equal(2, model.DictionaryOfStringToCustomer.Count); - var actualValue1 = model.DictionaryOfStringToCustomer[key1]; - Assert.NotNull(actualValue1); - Assert.Equal("James", actualValue1.Name); - } - - [Fact] - public void Replace_WhenDictionary_ValueAPocoType_WithEscaping_Succeeds() - { - // Arrange - var key1 = "Foo/Name"; - var value1 = new Customer() { Name = "Jamesss" }; - var key2 = "Foo"; - var value2 = new Customer() { Name = "Mike" }; - var model = new Class8(); - model.DictionaryOfStringToCustomer[key1] = value1; - model.DictionaryOfStringToCustomer[key2] = value2; - var patchDocument = new JsonPatchDocument(); - patchDocument.Replace($"/DictionaryOfStringToCustomer/Foo~1Name/Name", "James"); - - // Act - patchDocument.ApplyTo(model); - - // Assert - Assert.Equal(2, model.DictionaryOfStringToCustomer.Count); - var actualValue1 = model.DictionaryOfStringToCustomer[key1]; - var actualValue2 = model.DictionaryOfStringToCustomer[key2]; - Assert.NotNull(actualValue1); - Assert.Equal("James", actualValue1.Name); - Assert.Equal("Mike", actualValue2.Name); - - } - - [Fact] - public void Replace_DeepNested_DictionaryValue_Succeeds() - { - // Arrange - var key1 = "key1"; - var value1 = new Customer() { Name = "Jamesss" }; - var key2 = "key2"; - var value2 = new Customer() { Name = "Mike" }; - var model = new Class8(); - model.DictionaryOfStringToCustomer[key1] = value1; - model.DictionaryOfStringToCustomer[key2] = value2; - var patchDocument = new JsonPatchDocument(); - patchDocument.Replace($"/DictionaryOfStringToCustomer/{key1}/Name", "James"); - - // Act - patchDocument.ApplyTo(model); - - // Assert - Assert.Equal(2, model.DictionaryOfStringToCustomer.Count); - var actualValue1 = model.DictionaryOfStringToCustomer[key1]; - Assert.NotNull(actualValue1); - Assert.Equal("James", actualValue1.Name); - } - - [Fact] - public void Replace_DeepNested_DictionaryValue_Succeeds_WithSerialization() - { - // Arrange - var key1 = "key1"; - var value1 = new Customer() { Name = "James", Address = new Address { City = "Redmond" } }; - var key2 = "key2"; - var value2 = new Customer() { Name = "Mike", Address = new Address { City = "Seattle" } }; - var model = new Class8(); - model.DictionaryOfStringToCustomer[key1] = value1; - model.DictionaryOfStringToCustomer[key2] = value2; - var patchDocument = new JsonPatchDocument(); - patchDocument.Replace($"/DictionaryOfStringToCustomer/{key1}/Address/City", "Bellevue"); - var serialized = JsonConvert.SerializeObject(patchDocument); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - patchDocument.ApplyTo(model); - - // Assert - Assert.Equal(2, model.DictionaryOfStringToCustomer.Count); - var actualValue1 = model.DictionaryOfStringToCustomer[key1]; - Assert.NotNull(actualValue1); - Assert.Equal("James", actualValue1.Name); - var address = actualValue1.Address; - Assert.NotNull(address); - Assert.Equal("Bellevue", address.City); - } - - class Class9 - { - public List StringList { get; set; } = new List(); - } - - [Fact] - public void AddToNonIntegerListAtEnd() - { - // Arrange - var model = new Class9() - { - StringList = new List() - }; - model.StringList.Add("string1"); - model.StringList.Add("string2"); - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("/StringList/0", "string3"); - - // Act - patchDoc.ApplyTo(model); - - // Assert - Assert.Equal(new List() { "string3", "string1", "string2" }, model.StringList); - } - - [Fact] - public void AddMember_OnPOCO_WithNullPropertyValue_ShouldAddPropertyValue() - { - // Arrange - var doc = new SimpleObject() - { - StringProperty = null - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.StringProperty, "B"); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal("B", doc.StringProperty); - } - - private class Class1 - { - public IDictionary USStates { get; set; } = new Dictionary(); - } - - [Fact] - public void AddMember_OnDictionaryProperty_ShouldAddKeyValueMember() - { - // Arrange - var expected = "Washington"; - var model = new Class1(); - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("/USStates/WA", expected); - - // Act - patchDoc.ApplyTo(model); - - // Assert - Assert.Equal(1, model.USStates.Count); - Assert.Equal(expected, model.USStates["WA"]); - } - - [Fact] - public void AddMember_OnDictionaryProperty_ShouldAddKeyValueMember_WithSerialization() - { - // Arrange - var expected = "Washington"; - var model = new Class1(); - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("/USStates/WA", expected); - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(model); - - // Assert - Assert.Equal(1, model.USStates.Count); - Assert.Equal(expected, model.USStates["WA"]); - } - - private class Class2 - { - public Class1 Class1Property { get; set; } = new Class1(); - } - - [Fact] - public void AddMember_OnDictionaryPropertyDeeplyNested_ShouldAddKeyValueMember() - { - // Arrange - var expected = "Washington"; - var model = new Class2(); - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("/Class1Property/USStates/WA", expected); - - // Act - patchDoc.ApplyTo(model); - - // Assert - Assert.Equal(1, model.Class1Property.USStates.Count); - Assert.Equal(expected, model.Class1Property.USStates["WA"]); - } - - [Fact] - public void AddMember_OnDictionaryPropertyDeeplyNested_ShouldAddKeyValueMember_WithSerialization() - { - // Arrange - var expected = "Washington"; - var model = new Class2(); - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("/Class1Property/USStates/WA", expected); - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(model); - - // Assert - Assert.Equal(1, model.Class1Property.USStates.Count); - Assert.Equal(expected, model.Class1Property.USStates["WA"]); - } - - [Fact] - public void AddMember_OnDictionaryObjectDirectly_ShouldAddKeyValueMember() - { - // Arrange - var expected = "Washington"; - var model = new Dictionary(); - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("/WA", expected); - - // Act - patchDoc.ApplyTo(model); - - // Assert - Assert.Single(model); - Assert.Equal(expected, model["WA"]); - } - - [Fact] - public void AddMember_OnDictionaryObjectDirectly_ShouldAddKeyValueMember_WithSerialization() - { - // Arrange - var expected = "Washington"; - var model = new Dictionary(); - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("/WA", expected); - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>>(serialized); - - // Act - deserialized.ApplyTo(model); - - // Assert - Assert.Single(model); - Assert.Equal(expected, model["WA"]); - } - - [Fact] - public void AddElement_ToListDirectly_ShouldAppendValue() - { - // Arrange - var model = new List() { 1, 2, 3 }; - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("/-", value: 4); - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>>(serialized); - - // Act - deserialized.ApplyTo(model); - - // Assert - Assert.Equal(new List() { 1, 2, 3, 4 }, model); - } - - [Fact] - public void AddElement_ToListDirectly_ShouldAppendValue_WithSerialization() - { - // Arrange - var model = new List() { 1, 2, 3 }; - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("/-", value: 4); - - // Act - patchDoc.ApplyTo(model); - - // Assert - Assert.Equal(new List() { 1, 2, 3, 4 }, model); - } - - [Fact] - public void AddElement_ToListDirectly_ShouldAddValue_AtSuppliedPosition() - { - // Arrange - var model = new List() { 1, 2, 3 }; - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("/0", value: 4); - - // Act - patchDoc.ApplyTo(model); - - // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, model); - } - - [Fact] - public void AddElement_ToListDirectly_ShouldAddValue_AtSuppliedPosition_WithSerialization() - { - // Arrange - var model = new List() { 1, 2, 3 }; - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("/0", value: 4); - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>>(serialized); - - // Act - deserialized.ApplyTo(model); - - // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, model); - } - - class ListOnDictionary - { - public IDictionary> NamesAndBadgeIds { get; set; } = new Dictionary>(); - } - - [Fact] - public void AddElement_ToList_OnDictionary_ShouldAddValue_AtSuppliedPosition() - { - // Arrange - var model = new ListOnDictionary(); - model.NamesAndBadgeIds["James"] = new List(); - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("/NamesAndBadgeIds/James/-", 200); - - // Act - patchDoc.ApplyTo(model); - - // Assert - var list = model.NamesAndBadgeIds["James"]; - Assert.NotNull(list); - Assert.Equal(new List() { 200 }, list); - } - - [Fact] - public void AddElement_ToList_OnPOCO_ShouldAddValue_AtSuppliedPosition() - { - // Arrange - var doc = new SimpleObject() - { - IntegerIList = new List() { 1, 2, 3 } - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.IntegerIList, 4, 0); - - // Act - patchDoc.ApplyTo(doc); - - // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, doc.IntegerIList); - } - - class Class3 - { - public SimpleObject SimpleObjectProperty { get; set; } = new SimpleObject(); - } - - [Fact] - public void AddElement_ToDeeplyNestedListProperty_OnPOCO_ShouldAddValue_AtSuppliedPosition() - { - // Arrange - var model = new Class3() - { - SimpleObjectProperty = new SimpleObject() - { - IntegerIList = new List() { 1, 2, 3 } - } - }; - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleObjectProperty.IntegerIList, value: 4, position: 0); - - // Act - patchDoc.ApplyTo(model); - - // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, model.SimpleObjectProperty.IntegerIList); - } - - [Fact] - public void AddElement_ToDeeplyNestedListProperty_OnPOCO_ShouldAddValue_AtSuppliedPosition_WithSerialization() - { - // Arrange - var model = new Class3() - { - SimpleObjectProperty = new SimpleObject() - { - IntegerIList = new List() { 1, 2, 3 } - } - }; - var patchDoc = new JsonPatchDocument(); - patchDoc.Add(o => o.SimpleObjectProperty.IntegerIList, value: 4, position: 0); - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(model); - - // Assert - Assert.Equal(new List() { 4, 1, 2, 3 }, model.SimpleObjectProperty.IntegerIList); - } - - class Class4 - { - public int IntegerProperty { get; set; } - } - - [Fact] - public void Remove_OnNonReferenceType_POCOProperty_ShouldSetDefaultValue() - { - // Arrange - var model = new Class4() - { - IntegerProperty = 10 - }; - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.IntegerProperty); - - // Act - patchDoc.ApplyTo(model); - - // Assert - Assert.Equal(0, model.IntegerProperty); - } - - [Fact] - public void Remove_OnNonReferenceType_POCOProperty_ShouldSetDefaultValue_WithSerialization() - { - // Arrange - var doc = new SimpleObject() - { - StringProperty = "A" - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Remove(o => o.StringProperty); - - var serialized = JsonConvert.SerializeObject(patchDoc); - var deserialized = JsonConvert.DeserializeObject>(serialized); - - // Act - deserialized.ApplyTo(doc); - - // Assert - Assert.Null(doc.StringProperty); - } - - class ClassWithPrivateProperties - { - public string Name { get; set; } - private int Age { get; set; } = 45; - } - - [Fact] - public void Add_OnPrivateProperties_FailesWithException() - { - // Arrange - var doc = new ClassWithPrivateProperties() - { - Name = "James" - }; - - // create patch - var patchDoc = new JsonPatchDocument(); - patchDoc.Add("/Age", 30); - - // Act & Assert - var exception = Assert.Throws(() => patchDoc.ApplyTo(doc)); - Assert.Equal( - string.Format("The target location specified by path segment '{0}' was not found.", "Age"), - exception.Message); - } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNestedObjectWithNullCheck.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNestedObjectWithNullCheck.cs deleted file mode 100644 index f2423700d8..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNestedObjectWithNullCheck.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.JsonPatch -{ - public class SimpleObjectWithNestedObjectWithNullCheck - { - public SimpleObjectWithNullCheck SimpleObjectWithNullCheck { get; set; } - - public SimpleObjectWithNestedObjectWithNullCheck() - { - SimpleObjectWithNullCheck = new SimpleObjectWithNullCheck(); - } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNullCheck.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNullCheck.cs deleted file mode 100644 index 83338c5a23..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNullCheck.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; - -namespace Microsoft.AspNetCore.JsonPatch -{ - public class SimpleObjectWithNullCheck - { - private string stringProperty; - - public string StringProperty - { - get - { - return stringProperty; - } - - set - { - if (value == null) - { - throw new ArgumentNullException(); - } - - stringProperty = value; - } - } - } -} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/Customer.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/Customer.cs new file mode 100644 index 0000000000..c8a5aa22b1 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/Customer.cs @@ -0,0 +1,17 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + internal class Customer + { + private string _name; + private int _age; + + public Customer(string name, int age) + { + _name = name; + _age = age; + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/DynamicTestObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/DynamicTestObject.cs similarity index 98% rename from test/Microsoft.AspNetCore.JsonPatch.Test/DynamicTestObject.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/DynamicTestObject.cs index 4268d5526c..94ecf1685d 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/DynamicTestObject.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/DynamicTestObject.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Dynamic; -namespace Microsoft.AspNetCore.JsonPatch.Internal +namespace Microsoft.AspNetCore.JsonPatch { public class DynamicTestObject : DynamicObject { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/InheritedObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/InheritedObject.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/InheritedObject.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/InheritedObject.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/NestedObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/NestedObject.cs similarity index 85% rename from test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/NestedObject.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/NestedObject.cs index 050ad3a3b4..1b42d0d7ef 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Dynamic/NestedObject.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/NestedObject.cs @@ -1,11 +1,11 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace Microsoft.AspNetCore.JsonPatch.Internal +namespace Microsoft.AspNetCore.JsonPatch { public class NestedObject { public string StringProperty { get; set; } public dynamic DynamicProperty { get; set; } } -} +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/SimpleObject.cs similarity index 86% rename from test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObject.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/SimpleObject.cs index 28a9570c2b..651a91bdcf 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObject.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/SimpleObject.cs @@ -8,9 +8,11 @@ namespace Microsoft.AspNetCore.JsonPatch { public class SimpleObject { + public List SimpleObjectList { get; set; } public List IntegerList { get; set; } public IList IntegerIList { get; set; } public int IntegerValue { get; set; } + public int AnotherIntegerValue { get; set; } public string StringProperty { get; set; } public string AnotherStringProperty { get; set; } public decimal DecimalValue { get; set; } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNestedObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/SimpleObjectWithNestedObject.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/SimpleObjectWithNestedObject.cs rename to test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/SimpleObjectWithNestedObject.cs From 1836201beecf81c3e2b4a50cc1666f5aa51f5786 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 31 Oct 2017 17:33:49 -0700 Subject: [PATCH 0606/1029] Pin tool and package versions to make build more repeatable --- .gitignore | 1 - Directory.Build.props | 6 +++--- Directory.Build.targets | 17 ++++------------ DotNetTools.sln | 2 +- NuGet.config | 1 + build/dependencies.props | 20 +++++++++++++++++++ build/repo.props | 10 +++++++--- korebuild-lock.txt | 2 ++ korebuild.json | 4 ++++ src/Directory.Build.props | 4 ++-- ...NetCore.DeveloperCertificates.Tools.csproj | 6 +++--- .../Microsoft.DotNet.Watcher.Tools.csproj | 4 ++-- ....Extensions.Caching.SqlConfig.Tools.csproj | 4 ++-- ...soft.Extensions.SecretManager.Tools.csproj | 6 +++--- test/Directory.Build.props | 12 +++++------ ...otNet.Watcher.Tools.FunctionalTests.csproj | 4 ++-- version.props | 10 ++++++++++ version.xml | 8 -------- 18 files changed, 72 insertions(+), 49 deletions(-) create mode 100644 build/dependencies.props create mode 100644 korebuild-lock.txt create mode 100644 korebuild.json create mode 100644 version.props delete mode 100644 version.xml diff --git a/.gitignore b/.gitignore index 44848d7813..591bacd6e1 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,3 @@ testWorkDir/ .idea/ .dotnet/ global.json -korebuild-lock.txt diff --git a/Directory.Build.props b/Directory.Build.props index a42c6f0597..1da295c3a6 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,6 @@ - - + + + Microsoft .NET @@ -9,7 +10,6 @@ $(MSBuildThisFileDirectory)build\Key.snk true true - $(VersionSuffix)-$(BuildNumber) true diff --git a/Directory.Build.targets b/Directory.Build.targets index bc118fd907..e83ff95e39 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,14 +1,5 @@ - - - - <_BootstrapperFile Condition=" $([MSBuild]::IsOSUnixLike()) ">build.sh - <_BootstrapperFile Condition="! $([MSBuild]::IsOSUnixLike()) ">build.cmd - <_BootstrapperError> - Package references have not been pinned. Run './$(_BootstrapperFile) /t:Pin'. - Also, you can run './$(_BootstrapperFile) /t:Restore' which will pin *and* restore packages. '$(_BootstrapperFile)' can be found in '$(MSBuildThisFileDirectory)'. - - - - - + + + $(MicrosoftNETCoreApp20PackageVersion) + diff --git a/DotNetTools.sln b/DotNetTools.sln index d3c6048370..5e9642e106 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -26,7 +26,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution NuGet.config = NuGet.config NuGetPackageVerifier.json = NuGetPackageVerifier.json README.md = README.md - version.xml = version.xml + version.props = version.props EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F5B382BC-258F-46E1-AC3D-10E5CCD55134}" diff --git a/NuGet.config b/NuGet.config index 20060c934e..4e8a1f6de1 100644 --- a/NuGet.config +++ b/NuGet.config @@ -3,6 +3,7 @@ + diff --git a/build/dependencies.props b/build/dependencies.props new file mode 100644 index 0000000000..0187c674d0 --- /dev/null +++ b/build/dependencies.props @@ -0,0 +1,20 @@ + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + + 2.1.0-preview1-15549 + 2.1.0-preview1-27478 + 2.1.0-preview1-27478 + 2.1.0-preview1-27478 + 2.1.0-preview1-27478 + 2.1.0-preview1-27478 + 2.0.0 + 15.3.0 + 4.4.0 + 4.4.0 + 2.3.0 + 2.3.0 + + + diff --git a/build/repo.props b/build/repo.props index a48caedc22..ade3bd71f7 100644 --- a/build/repo.props +++ b/build/repo.props @@ -1,7 +1,11 @@ - + - - + + + + Internal.AspNetCore.Universe.Lineup + https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json + diff --git a/korebuild-lock.txt b/korebuild-lock.txt new file mode 100644 index 0000000000..45463cc71e --- /dev/null +++ b/korebuild-lock.txt @@ -0,0 +1,2 @@ +version:2.1.0-preview1-15549 +commithash:f570e08585fec510dd60cd4bfe8795388b757a95 diff --git a/korebuild.json b/korebuild.json new file mode 100644 index 0000000000..bd5d51a51b --- /dev/null +++ b/korebuild.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", + "channel": "dev" +} diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 9d9a3de33a..4b89a431e7 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,7 +1,7 @@ - + - + diff --git a/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj b/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj index 438e88f121..36ba69485e 100644 --- a/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj +++ b/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj @@ -27,9 +27,9 @@ - - - + + + diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj index 443587cf07..294943581a 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj @@ -17,8 +17,8 @@ - - + + diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj index 61f55ddb17..f8ea155986 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj @@ -16,8 +16,8 @@ - - + + diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj index 261b94791f..3dc0507021 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj @@ -13,13 +13,13 @@ - + - - + + diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 82ba457f18..c79812719a 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -1,11 +1,11 @@ - + - - - - - + + + + + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj index d0bac72314..8d2c4713c8 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj @@ -17,8 +17,8 @@ - - + + diff --git a/version.props b/version.props new file mode 100644 index 0000000000..5c4a7c32d1 --- /dev/null +++ b/version.props @@ -0,0 +1,10 @@ + + + 2.1.0 + preview1 + $(VersionPrefix) + $(VersionPrefix)-$(VersionSuffix)-final + t000 + $(VersionSuffix)-$(BuildNumber) + + diff --git a/version.xml b/version.xml deleted file mode 100644 index 3c05022b7d..0000000000 --- a/version.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - dev - 2.1.0 - preview1 - - From d687617a356b9a875ea5b09163ef9d443b4256bb Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 1 Nov 2017 09:29:41 -0700 Subject: [PATCH 0607/1029] Pin tool and package versions to make builds more repeatable Part of aspnet/Universe#575 --- .gitignore | 1 - Directory.Build.props | 8 ++++---- Directory.Build.targets | 17 ++++------------- NuGet.config | 1 + build/dependencies.props | 18 ++++++++++++++++++ build/repo.props | 9 +++++---- korebuild-lock.txt | 2 ++ korebuild.json | 4 ++++ ...crosoft.AspNetCore.Html.Abstractions.csproj | 2 +- .../Microsoft.Extensions.WebEncoders.csproj | 6 +++--- test/Directory.Build.props | 10 +++++----- ...crosoft.Extensions.WebEncoders.Tests.csproj | 2 +- version.props | 10 ++++++++++ version.xml | 8 -------- 14 files changed, 58 insertions(+), 40 deletions(-) create mode 100644 build/dependencies.props create mode 100644 korebuild-lock.txt create mode 100644 korebuild.json create mode 100644 version.props delete mode 100644 version.xml diff --git a/.gitignore b/.gitignore index a7fdfd773b..6da3c6a3e9 100644 --- a/.gitignore +++ b/.gitignore @@ -38,4 +38,3 @@ node_modules .build/ .testPublish/ global.json -korebuild-lock.txt diff --git a/Directory.Build.props b/Directory.Build.props index 50b555b540..9db4d01587 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,6 @@ - - + + + https://github.com/aspnet/HtmlAbstractions @@ -8,12 +9,11 @@ $(MSBuildThisFileDirectory)build\Key.snk true true - $(VersionSuffix)-$(BuildNumber) true - + diff --git a/Directory.Build.targets b/Directory.Build.targets index bc118fd907..e83ff95e39 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,14 +1,5 @@ - - - - <_BootstrapperFile Condition=" $([MSBuild]::IsOSUnixLike()) ">build.sh - <_BootstrapperFile Condition="! $([MSBuild]::IsOSUnixLike()) ">build.cmd - <_BootstrapperError> - Package references have not been pinned. Run './$(_BootstrapperFile) /t:Pin'. - Also, you can run './$(_BootstrapperFile) /t:Restore' which will pin *and* restore packages. '$(_BootstrapperFile)' can be found in '$(MSBuildThisFileDirectory)'. - - - - - + + + $(MicrosoftNETCoreApp20PackageVersion) + diff --git a/NuGet.config b/NuGet.config index 20060c934e..4e8a1f6de1 100644 --- a/NuGet.config +++ b/NuGet.config @@ -3,6 +3,7 @@ + diff --git a/build/dependencies.props b/build/dependencies.props new file mode 100644 index 0000000000..410f1c8697 --- /dev/null +++ b/build/dependencies.props @@ -0,0 +1,18 @@ + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + + 2.1.0-preview1-15549 + 2.1.0-preview1-27488 + 2.1.0-preview1-27488 + 2.1.0-preview1-27488 + 2.1.0-preview1-27488 + 2.0.0 + 15.3.0 + 4.4.0 + 2.3.0 + 2.3.0 + + + diff --git a/build/repo.props b/build/repo.props index 13fe1c296a..b55e651b87 100644 --- a/build/repo.props +++ b/build/repo.props @@ -1,6 +1,7 @@  - - - - + + + Internal.AspNetCore.Universe.Lineup + https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json + diff --git a/korebuild-lock.txt b/korebuild-lock.txt new file mode 100644 index 0000000000..45463cc71e --- /dev/null +++ b/korebuild-lock.txt @@ -0,0 +1,2 @@ +version:2.1.0-preview1-15549 +commithash:f570e08585fec510dd60cd4bfe8795388b757a95 diff --git a/korebuild.json b/korebuild.json new file mode 100644 index 0000000000..bd5d51a51b --- /dev/null +++ b/korebuild.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", + "channel": "dev" +} diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj b/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj index 79e5ea01a5..271cc6c7fa 100755 --- a/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj +++ b/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj @@ -12,7 +12,7 @@ Microsoft.AspNetCore.Html.IHtmlContent - + diff --git a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj index cd0c144633..5e6b3392b5 100755 --- a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj +++ b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj @@ -11,9 +11,9 @@ - - - + + + diff --git a/test/Directory.Build.props b/test/Directory.Build.props index a728ed268e..80e7258054 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -1,10 +1,10 @@ - + - - - - + + + + diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj index c019c8b97e..f016febe5c 100755 --- a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj +++ b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj @@ -10,7 +10,7 @@ - + diff --git a/version.props b/version.props new file mode 100644 index 0000000000..5c4a7c32d1 --- /dev/null +++ b/version.props @@ -0,0 +1,10 @@ + + + 2.1.0 + preview1 + $(VersionPrefix) + $(VersionPrefix)-$(VersionSuffix)-final + t000 + $(VersionSuffix)-$(BuildNumber) + + diff --git a/version.xml b/version.xml deleted file mode 100644 index 3c05022b7d..0000000000 --- a/version.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - dev - 2.1.0 - preview1 - - From 478c640a68bc9e91c25ee5edd81363c67d98c6e0 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 1 Nov 2017 15:11:36 -0700 Subject: [PATCH 0608/1029] Pin tool and package versions to make builds more repeatable Part of aspnet/Universe#575 --- .gitignore | 1 - Directory.Build.props | 6 +++--- Directory.Build.targets | 17 ++++------------- build/dependencies.props | 19 +++++++++++++++++++ build/repo.props | 11 ++++++----- korebuild-lock.txt | 2 ++ korebuild.json | 4 ++++ src/Directory.Build.props | 2 +- .../Microsoft.AspNetCore.JsonPatch.csproj | 6 +++--- test/Directory.Build.props | 10 +++++----- ...Microsoft.AspNetCore.JsonPatch.Test.csproj | 6 +++--- version.props | 10 ++++++++++ version.xml | 8 -------- 13 files changed, 60 insertions(+), 42 deletions(-) create mode 100644 build/dependencies.props create mode 100644 korebuild-lock.txt create mode 100644 korebuild.json create mode 100644 version.props delete mode 100644 version.xml diff --git a/.gitignore b/.gitignore index 24d990294f..2e8ec28064 100644 --- a/.gitignore +++ b/.gitignore @@ -37,4 +37,3 @@ node_modules *launchSettings.json *.orig global.json -korebuild-lock.txt diff --git a/Directory.Build.props b/Directory.Build.props index fb7dfae923..442db60e74 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,6 @@ - - + + + Microsoft ASP.NET Core @@ -9,7 +10,6 @@ $(MSBuildThisFileDirectory)build\Key.snk true true - $(VersionSuffix)-$(BuildNumber) true diff --git a/Directory.Build.targets b/Directory.Build.targets index 9989b1046b..e83ff95e39 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,14 +1,5 @@ - - - - <_BootstrapperFile Condition=" $([MSBuild]::IsOSUnixLike()) ">build.sh - <_BootstrapperFile Condition="! $([MSBuild]::IsOSUnixLike()) ">build.cmd - <_BootstrapperError> - Package references have not been pinned. Run './$(_BootstrapperFile) /t:Pin'. - Also, you can run './$(_BootstrapperFile) /t:Restore' which will pin *and* restore packages. '$(_BootstrapperFile)' can be found in '$(MSBuildThisFileDirectory)'. - - - - - + + + $(MicrosoftNETCoreApp20PackageVersion) + diff --git a/build/dependencies.props b/build/dependencies.props new file mode 100644 index 0000000000..ba20d698d6 --- /dev/null +++ b/build/dependencies.props @@ -0,0 +1,19 @@ + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + + 2.1.0-preview1-15550 + 2.1.0-preview1-27497 + 4.4.0 + 2.1.0-preview1-27497 + 2.0.0 + 15.3.0 + 4.7.49 + 10.0.1 + 0.7.0 + 2.3.0 + 2.3.0 + + + diff --git a/build/repo.props b/build/repo.props index c5d91e8a2c..b55e651b87 100644 --- a/build/repo.props +++ b/build/repo.props @@ -1,6 +1,7 @@ - - - - - + + + + Internal.AspNetCore.Universe.Lineup + https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json + diff --git a/korebuild-lock.txt b/korebuild-lock.txt new file mode 100644 index 0000000000..36d8056037 --- /dev/null +++ b/korebuild-lock.txt @@ -0,0 +1,2 @@ +version:2.1.0-preview1-15550 +commithash:0dd080d0d87b4d1966ec0af9961dc8bacc04f84f diff --git a/korebuild.json b/korebuild.json new file mode 100644 index 0000000000..bd5d51a51b --- /dev/null +++ b/korebuild.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", + "channel": "dev" +} diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 5236edee58..4b89a431e7 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -2,6 +2,6 @@ - + diff --git a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj index a364de22ef..9bd08214f6 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj +++ b/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj @@ -9,9 +9,9 @@ - - - + + + diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 31ed7dd07c..b10972fadd 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -2,10 +2,10 @@ - - - - - + + + + + diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj index 6d7b403a79..241271d58f 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj @@ -1,4 +1,4 @@ - + netcoreapp2.0;net461 @@ -10,8 +10,8 @@ - - + + diff --git a/version.props b/version.props new file mode 100644 index 0000000000..5c4a7c32d1 --- /dev/null +++ b/version.props @@ -0,0 +1,10 @@ + + + 2.1.0 + preview1 + $(VersionPrefix) + $(VersionPrefix)-$(VersionSuffix)-final + t000 + $(VersionSuffix)-$(BuildNumber) + + diff --git a/version.xml b/version.xml deleted file mode 100644 index 3c05022b7d..0000000000 --- a/version.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - dev - 2.1.0 - preview1 - - From 70c8133fce523b6eb42f39cc4da78e9ac11e99dc Mon Sep 17 00:00:00 2001 From: arerlend <30675661+arerlend@users.noreply.github.com> Date: Tue, 7 Nov 2017 11:24:52 -0800 Subject: [PATCH 0609/1029] allow paths that contain '.' (#125) * allow paths that contain '.' * remove InvalidPathWithDotShouldThrowException test --- .../Internal/PathHelpers.cs | 2 +- .../JsonPatchDocumentTest.cs | 20 +------------------ 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/PathHelpers.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/PathHelpers.cs index 7ef8fe7baf..d46314c148 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/PathHelpers.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/PathHelpers.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal // absolutely necessary, but it allows us to already catch mistakes // on creation of the patch document rather than on execute. - if (path.Contains(".") || path.Contains("//") || path.Contains(" ") || path.Contains("\\")) + if (path.Contains("//") || path.Contains(" ") || path.Contains("\\")) { throw new JsonPatchException(Resources.FormatInvalidValueForPath(path), null); } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs index 6b44b6696c..197e514cee 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs @@ -45,24 +45,6 @@ namespace Microsoft.AspNetCore.JsonPatch exception.Message); } - [Fact] - public void InvalidPathWithDotShouldThrowException() - { - // Arrange - var patchDocument = new JsonPatchDocument(); - - // Act - var exception = Assert.Throws(() => - { - patchDocument.Add("NewInt.Test", 1); - }); - - // Assert - Assert.Equal( - "The provided string 'NewInt.Test' is an invalid path.", - exception.Message); - } - [Fact] public void NonGenericPatchDocToGenericMustSerialize() { @@ -177,4 +159,4 @@ namespace Microsoft.AspNetCore.JsonPatch Assert.Equal("The JSON patch document was malformed and could not be parsed.", exception.Message); } } -} \ No newline at end of file +} From 1cc289cf1dbdc67d1bff112f8c349c5dfba8d9d9 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 13 Nov 2017 08:49:25 -0800 Subject: [PATCH 0610/1029] Update the dotnet-watch samples to 2.0.0 [ci skip] --- samples/dotnet-watch/Directory.Build.props | 2 ++ samples/dotnet-watch/Directory.Build.targets | 2 ++ .../dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj | 2 +- .../WatchJavascriptFiles/WatchJavascriptFiles.csproj | 4 ++-- .../WatchMultipleProjects/{watch.proj => watch.csproj} | 6 +++--- 5 files changed, 10 insertions(+), 6 deletions(-) create mode 100644 samples/dotnet-watch/Directory.Build.props create mode 100644 samples/dotnet-watch/Directory.Build.targets rename samples/dotnet-watch/WatchMultipleProjects/{watch.proj => watch.csproj} (80%) diff --git a/samples/dotnet-watch/Directory.Build.props b/samples/dotnet-watch/Directory.Build.props new file mode 100644 index 0000000000..76c9003a6b --- /dev/null +++ b/samples/dotnet-watch/Directory.Build.props @@ -0,0 +1,2 @@ + + diff --git a/samples/dotnet-watch/Directory.Build.targets b/samples/dotnet-watch/Directory.Build.targets new file mode 100644 index 0000000000..76c9003a6b --- /dev/null +++ b/samples/dotnet-watch/Directory.Build.targets @@ -0,0 +1,2 @@ + + diff --git a/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj b/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj index 1a5ab09de4..39dea69c5f 100644 --- a/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj +++ b/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj @@ -4,7 +4,7 @@ - + diff --git a/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj b/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj index 3b2818d532..f45eb26ccf 100755 --- a/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj +++ b/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj @@ -10,8 +10,8 @@ - - + + diff --git a/samples/dotnet-watch/WatchMultipleProjects/watch.proj b/samples/dotnet-watch/WatchMultipleProjects/watch.csproj similarity index 80% rename from samples/dotnet-watch/WatchMultipleProjects/watch.proj rename to samples/dotnet-watch/WatchMultipleProjects/watch.csproj index c66bcda4c7..d34686cbbc 100644 --- a/samples/dotnet-watch/WatchMultipleProjects/watch.proj +++ b/samples/dotnet-watch/WatchMultipleProjects/watch.csproj @@ -1,10 +1,11 @@ - + netcoreapp2.0 + false - + @@ -15,5 +16,4 @@ - From eac0e2d03b168271488db6f3cb0212a1cfb4c1c1 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Fri, 10 Nov 2017 12:45:58 -0800 Subject: [PATCH 0611/1029] Add support for detecting when the user cancels the trust prompt and a mode to check for the validity and trust of existing certificates --- build/dependencies.props | 12 ++--- .../Program.cs | 50 ++++++++++++++++++- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 0187c674d0..15bc58988f 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,14 +1,14 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 2.1.0-preview1-15549 - 2.1.0-preview1-27478 - 2.1.0-preview1-27478 - 2.1.0-preview1-27478 - 2.1.0-preview1-27478 - 2.1.0-preview1-27478 + 2.1.0-preview1-27561 + 2.1.0-preview1-27560 + 2.1.0-preview1-27560 + 2.1.0-preview1-27560 + 2.1.0-preview1-27560 2.0.0 15.3.0 4.4.0 diff --git a/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Program.cs b/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Program.cs index f07f7bbe3e..7fbd5993cf 100644 --- a/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Program.cs +++ b/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Program.cs @@ -2,12 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; -using System.Text.RegularExpressions; using Microsoft.AspNetCore.Certificates.Generation; using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Tools.Internal; @@ -22,6 +20,9 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools private const int ErrorSavingTheCertificate = 2; private const int ErrorExportingTheCertificate = 3; private const int ErrorTrustingTheCertificate = 4; + private const int ErrorUserCancelledTrustPrompt = 5; + private const int ErrorNoValidCertificateFound = 6; + private const int ErrorCertificateNotTrusted = 7; public static readonly TimeSpan HttpsCertificateValidity = TimeSpan.FromDays(365); @@ -44,6 +45,11 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools "Password to use when exporting the certificate with the private key into a pfx file", CommandOptionType.SingleValue); + var check = c.Option( + "-c|--check", + "Check for the existence of the certificate but do not perform any action", + CommandOptionType.NoValue); + CommandOption trust = null; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { @@ -65,6 +71,10 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools c.OnExecute(() => { var reporter = new ConsoleReporter(PhysicalConsole.Singleton, verbose.HasValue(), quiet.HasValue()); + if (check.HasValue()) + { + return CheckHttpsCertificate(check, trust, reporter); + } return EnsureHttpsCertificate(exportPath, password, trust, reporter); }); }); @@ -85,6 +95,39 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools } } + private static int CheckHttpsCertificate(CommandOption check, CommandOption trust, IReporter reporter) + { + var now = DateTimeOffset.Now; + var certificateManager = new CertificateManager(); + var certificates = certificateManager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: true); + if (certificates.Count == 0) + { + reporter.Verbose("No valid certificate found."); + return ErrorNoValidCertificateFound; + } + else + { + reporter.Verbose("A valid certificate was found."); + } + + if (trust != null && trust.HasValue()) + { + var trustedCertificates = certificateManager.ListCertificates(CertificatePurpose.HTTPS, StoreName.Root, StoreLocation.CurrentUser, isValid: true, requireExportable: false); + if (!certificates.Any(c => certificateManager.IsTrusted(c))) + { + reporter.Verbose($@"The following certificates were found, but none of them is trusted: +{string.Join(Environment.NewLine, certificates.Select(c => $"{c.Subject} - {c.Thumbprint}"))}"); + return ErrorCertificateNotTrusted; + } + else + { + reporter.Verbose("A trusted certificate was found."); + } + } + + return Success; + } + private static int EnsureHttpsCertificate(CommandOption exportPath, CommandOption password, CommandOption trust, IReporter reporter) { var now = DateTimeOffset.Now; @@ -135,6 +178,9 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools case EnsureCertificateResult.FailedToTrustTheCertificate: reporter.Warn("There was an error trusting HTTPS developer certificate."); return ErrorTrustingTheCertificate; + case EnsureCertificateResult.UserCancelledTrustStep: + reporter.Warn("The user cancelled the trust step."); + return ErrorUserCancelledTrustPrompt; default: reporter.Error("Something went wrong. The HTTPS developer certificate could not be created."); return CriticalError; From 42d3bdb82d0a241259e079aec06c79e3873cd3c1 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 13 Nov 2017 15:19:26 -0800 Subject: [PATCH 0612/1029] Update samples and tests to target netcoreapp2.1 --- Directory.Build.props | 4 ++++ korebuild-lock.txt | 4 ++-- test/Directory.Build.props | 7 +++++++ .../Microsoft.AspNetCore.Html.Abstractions.Test.csproj | 3 +-- .../Microsoft.Extensions.WebEncoders.Tests.csproj | 3 +-- 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 9db4d01587..ffc398567e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,4 +1,8 @@  + + diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 45463cc71e..95f4613014 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15549 -commithash:f570e08585fec510dd60cd4bfe8795388b757a95 +version:2.1.0-preview1-15567 +commithash:903e3104807b1bb8cddd28bdef205b1e2dc021d1 diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 80e7258054..0b706cbca5 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -1,6 +1,13 @@ + + netcoreapp2.1 + $(DeveloperBuildTestTfms) + netcoreapp2.1;netcoreapp2.0 + $(StandardTestTfms);net461 + + diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj index f899e1a699..1577693497 100755 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj +++ b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj @@ -1,8 +1,7 @@  - netcoreapp2.0;net461 - netcoreapp2.0 + $(StandardTestTfms) diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj index f016febe5c..247ccd19b3 100755 --- a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj +++ b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj @@ -1,8 +1,7 @@  - netcoreapp2.0;net461 - netcoreapp2.0 + $(StandardTestTfms) From 39db8585c1327d9ff50de3d73ef471e76a536d19 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 10 Nov 2017 10:19:50 -0800 Subject: [PATCH 0613/1029] Target netcoreapp2.1 in tests and samples --- Directory.Build.props | 4 ++++ korebuild-lock.txt | 4 ++-- test/Directory.Build.props | 7 +++++++ .../Microsoft.AspNetCore.JsonPatch.Test.csproj | 3 +-- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 442db60e74..2843f64536 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,4 +1,8 @@  + + diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 36d8056037..07a4d73a83 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15550 -commithash:0dd080d0d87b4d1966ec0af9961dc8bacc04f84f +version:2.1.0-preview1-15564 +commithash:1f3f14382764e06b7e691e5ee89d12a280249284 diff --git a/test/Directory.Build.props b/test/Directory.Build.props index b10972fadd..98685a5e13 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -1,6 +1,13 @@ + + netcoreapp2.1 + $(DeveloperBuildTestTfms) + $(StandardTestTfms);netcoreapp2.0 + $(StandardTestTfms);net461 + + diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj index 241271d58f..ce1d92802d 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj @@ -1,8 +1,7 @@ - netcoreapp2.0;net461 - netcoreapp2.0 + $(StandardTestTfms) From 6c4427cde5f05c64d792062036a7312a0edae309 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Wed, 15 Nov 2017 11:42:49 -0800 Subject: [PATCH 0614/1029] Added a package for generating HTTPS Certificates on CLI first run scenarios --- DotNetTools.sln | 11 +++++++++-- NuGetPackageVerifier.json | 13 ++++++++++--- build/dependencies.props | 10 +++++----- .../CertificateGenerator.cs | 15 +++++++++++++++ ....AspNetCore.DeveloperCertificates.XPlat.csproj | 15 +++++++++++++++ 5 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/CertificateGenerator.cs create mode 100644 src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj diff --git a/DotNetTools.sln b/DotNetTools.sln index 5e9642e106..95b7b67009 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26927.1 +VisualStudioVersion = 15.0.27110.0 MinimumVisualStudioVersion = 15.0.26730.03 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66517987-2A5A-4330-B130-207039378FD4}" ProjectSection(SolutionItems) = preProject @@ -44,7 +44,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Watcher.To EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Caching.SqlConfig.Tools", "src\Microsoft.Extensions.Caching.SqlConfig.Tools\Microsoft.Extensions.Caching.SqlConfig.Tools.csproj", "{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.DeveloperCertificates.Tools", "src\Microsoft.AspNetCore.DeveloperCertificates.Tools\Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj", "{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DeveloperCertificates.Tools", "src\Microsoft.AspNetCore.DeveloperCertificates.Tools\Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj", "{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.DeveloperCertificates.XPlat", "src\Microsoft.AspNetCore.DeveloperCertificates.XPlat\Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj", "{96E71881-1465-44F5-B4B7-DF9B370FFD02}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -80,6 +82,10 @@ Global {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Debug|Any CPU.Build.0 = Debug|Any CPU {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Release|Any CPU.ActiveCfg = Release|Any CPU {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Release|Any CPU.Build.0 = Release|Any CPU + {96E71881-1465-44F5-B4B7-DF9B370FFD02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {96E71881-1465-44F5-B4B7-DF9B370FFD02}.Debug|Any CPU.Build.0 = Debug|Any CPU + {96E71881-1465-44F5-B4B7-DF9B370FFD02}.Release|Any CPU.ActiveCfg = Release|Any CPU + {96E71881-1465-44F5-B4B7-DF9B370FFD02}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -92,6 +98,7 @@ Global {8A2E6961-6B12-4A8E-8215-3E7301D52EAC} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {53F3B53D-303A-4DAA-9C38-4F55195FA5B9} = {66517987-2A5A-4330-B130-207039378FD4} {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8} = {66517987-2A5A-4330-B130-207039378FD4} + {96E71881-1465-44F5-B4B7-DF9B370FFD02} = {66517987-2A5A-4330-B130-207039378FD4} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {57C07F14-2EAC-44FF-A277-B9221B4B2BF7} diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index d5e919176f..c279df4745 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -20,9 +20,16 @@ ] }, "Microsoft.AspNetCore.DeveloperCertificates.Tools": { - "packageTypes": [ - "DotnetCliTool" - ] + "packageTypes": [ + "DotnetCliTool" + ] + }, + "Microsoft.AspNetCore.DeveloperCertificates.XPlat": { + "Exclusions": { + "DOC_MISSING": { + "lib/netcoreapp2.0/Microsoft.AspNetCore.DeveloperCertificates.XPlat.dll": "Enter justification" + } + } } } }, diff --git a/build/dependencies.props b/build/dependencies.props index 15bc58988f..c31590c1ac 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,11 +4,11 @@ 2.1.0-preview1-15549 - 2.1.0-preview1-27561 - 2.1.0-preview1-27560 - 2.1.0-preview1-27560 - 2.1.0-preview1-27560 - 2.1.0-preview1-27560 + 2.1.0-preview1-27595 + 2.1.0-preview1-27595 + 2.1.0-preview1-27595 + 2.1.0-preview1-27595 + 2.1.0-preview1-27595 2.0.0 15.3.0 4.4.0 diff --git a/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/CertificateGenerator.cs b/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/CertificateGenerator.cs new file mode 100644 index 0000000000..d3f58eae35 --- /dev/null +++ b/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/CertificateGenerator.cs @@ -0,0 +1,15 @@ +using System; +using Microsoft.AspNetCore.Certificates.Generation; + +namespace Microsoft.AspNetCore.DeveloperCertificates.XPlat +{ + public static class CertificateGenerator + { + public static void GenerateAspNetHttpsCertificate() + { + var manager = new CertificateManager(); + var now = DateTimeOffset.Now; + manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1)); + } + } +} diff --git a/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj b/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj new file mode 100644 index 0000000000..04bf6946c9 --- /dev/null +++ b/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj @@ -0,0 +1,15 @@ + + + + netcoreapp2.0 + Package for the CLI first run experience. + $(DefineConstants);XPLAT + aspnet;cli + false + + + + + + + From 382cfa8e074bfbef884ea5f5a7e1add5e661258a Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 17 Nov 2017 13:00:24 -0800 Subject: [PATCH 0615/1029] Use MicrosoftNETCoreApp21PackageVersion to determine the runtime framework in netcoreapp2.1 --- Directory.Build.targets | 1 + build/dependencies.props | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Directory.Build.targets b/Directory.Build.targets index e83ff95e39..894b1d0cf8 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,5 +1,6 @@  $(MicrosoftNETCoreApp20PackageVersion) + $(MicrosoftNETCoreApp21PackageVersion) diff --git a/build/dependencies.props b/build/dependencies.props index c31590c1ac..72cc8468e4 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,4 +1,4 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) @@ -10,6 +10,7 @@ 2.1.0-preview1-27595 2.1.0-preview1-27595 2.0.0 + 2.1.0-preview1-25907-02 15.3.0 4.4.0 4.4.0 From 330960460cf4c7718f54dedaf4ca63a46a2fec7d Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 17 Nov 2017 13:00:25 -0800 Subject: [PATCH 0616/1029] Use MicrosoftNETCoreApp21PackageVersion to determine the runtime framework in netcoreapp2.1 --- Directory.Build.targets | 1 + build/dependencies.props | 1 + 2 files changed, 2 insertions(+) diff --git a/Directory.Build.targets b/Directory.Build.targets index e83ff95e39..894b1d0cf8 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,5 +1,6 @@  $(MicrosoftNETCoreApp20PackageVersion) + $(MicrosoftNETCoreApp21PackageVersion) diff --git a/build/dependencies.props b/build/dependencies.props index 410f1c8697..fa9a01ce97 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -9,6 +9,7 @@ 2.1.0-preview1-27488 2.1.0-preview1-27488 2.0.0 + 2.1.0-preview1-25907-02 15.3.0 4.4.0 2.3.0 From bccd5a1244637eed3f23d86367c2ac146e6a7576 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 17 Nov 2017 13:00:25 -0800 Subject: [PATCH 0617/1029] Use MicrosoftNETCoreApp21PackageVersion to determine the runtime framework in netcoreapp2.1 --- Directory.Build.targets | 1 + build/dependencies.props | 1 + 2 files changed, 2 insertions(+) diff --git a/Directory.Build.targets b/Directory.Build.targets index e83ff95e39..894b1d0cf8 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,5 +1,6 @@  $(MicrosoftNETCoreApp20PackageVersion) + $(MicrosoftNETCoreApp21PackageVersion) diff --git a/build/dependencies.props b/build/dependencies.props index ba20d698d6..3072c1d6e4 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -8,6 +8,7 @@ 4.4.0 2.1.0-preview1-27497 2.0.0 + 2.1.0-preview1-25907-02 15.3.0 4.7.49 10.0.1 From bd725635c7b03c6d840c5bee0ef3e9bf3de3653f Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 20 Nov 2017 12:15:49 -0800 Subject: [PATCH 0618/1029] Use MSBuild to set NuGet feeds instead of NuGet.config --- Directory.Build.props | 1 + NuGet.config | 4 +--- build/sources.props | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 build/sources.props diff --git a/Directory.Build.props b/Directory.Build.props index 1da295c3a6..29ae42a346 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,7 @@  + Microsoft .NET diff --git a/NuGet.config b/NuGet.config index 4e8a1f6de1..e32bddfd51 100644 --- a/NuGet.config +++ b/NuGet.config @@ -2,8 +2,6 @@ - - - + diff --git a/build/sources.props b/build/sources.props new file mode 100644 index 0000000000..c03f3ddb60 --- /dev/null +++ b/build/sources.props @@ -0,0 +1,16 @@ + + + + + $(DotNetRestoreSources) + + $(RestoreSources); + https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json; + https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; + + + $(RestoreSources); + https://api.nuget.org/v3/index.json; + + + From dc095b1f4d5e2c1a03a2dc1de98f5b0883ef65d4 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 20 Nov 2017 12:15:56 -0800 Subject: [PATCH 0619/1029] Use MSBuild to set NuGet feeds instead of NuGet.config --- Directory.Build.props | 1 + NuGet.config | 4 +--- build/sources.props | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 build/sources.props diff --git a/Directory.Build.props b/Directory.Build.props index ffc398567e..b7176c688d 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -5,6 +5,7 @@ + https://github.com/aspnet/HtmlAbstractions diff --git a/NuGet.config b/NuGet.config index 4e8a1f6de1..e32bddfd51 100644 --- a/NuGet.config +++ b/NuGet.config @@ -2,8 +2,6 @@ - - - + diff --git a/build/sources.props b/build/sources.props new file mode 100644 index 0000000000..c03f3ddb60 --- /dev/null +++ b/build/sources.props @@ -0,0 +1,16 @@ + + + + + $(DotNetRestoreSources) + + $(RestoreSources); + https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json; + https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; + + + $(RestoreSources); + https://api.nuget.org/v3/index.json; + + + From 0d4e34e0a1d66e87df2bc580320de93d215d093b Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 20 Nov 2017 12:18:17 -0800 Subject: [PATCH 0620/1029] Use MSBuild to set NuGet feeds instead of NuGet.config --- Directory.Build.props | 1 + NuGet.config | 4 +--- build/sources.props | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 build/sources.props diff --git a/Directory.Build.props b/Directory.Build.props index 2843f64536..88b93729bb 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -5,6 +5,7 @@ + Microsoft ASP.NET Core diff --git a/NuGet.config b/NuGet.config index 4e8a1f6de1..e32bddfd51 100644 --- a/NuGet.config +++ b/NuGet.config @@ -2,8 +2,6 @@ - - - + diff --git a/build/sources.props b/build/sources.props new file mode 100644 index 0000000000..c03f3ddb60 --- /dev/null +++ b/build/sources.props @@ -0,0 +1,16 @@ + + + + + $(DotNetRestoreSources) + + $(RestoreSources); + https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json; + https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; + + + $(RestoreSources); + https://api.nuget.org/v3/index.json; + + + From 4ecabacc7642431bc7d1529e46e07354cf6a870f Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 21 Nov 2017 14:16:39 -0800 Subject: [PATCH 0621/1029] Create an initial implementation of the secret manager for VS (#355) --- DotNetTools.sln | 60 ++++- build/VSIX.props | 9 + build/VSIX.targets | 86 +++++++ build/dependencies.props | 13 +- build/repo.targets | 10 + build/sources.props | 3 +- korebuild-lock.txt | 4 +- korebuild.json | 14 +- .../Key.snk | Bin 0 -> 596 bytes ...lStudio.SecretManager.TestExtension.csproj | 149 ++++++++++++ .../NotifyPropertyChanged.cs | 18 ++ .../ProjectViewModel.cs | 20 ++ .../Properties/AssemblyInfo.cs | 33 +++ .../RelayCommand.cs | 44 ++++ .../Resources/SecretManagerTestCommand.png | Bin 0 -> 1172 bytes .../Resources/SecretManagerTestPackage.ico | Bin 0 -> 428446 bytes .../SecretManagerTestCommand.cs | 100 ++++++++ .../SecretManagerTestControl.xaml | 87 +++++++ .../SecretManagerTestControl.xaml.cs | 37 +++ .../SecretManagerTestPackage.cs | 27 +++ .../SecretManagerTestPackage.vsct | 83 +++++++ .../SecretManagerTestWindow.cs | 31 +++ .../SecretManagerViewModel.cs | 214 ++++++++++++++++++ .../VSPackage.resx | 140 ++++++++++++ .../app.config | 27 +++ .../source.extension.vsixmanifest | 21 ++ ...icrosoft.VisualStudio.SecretManager.csproj | 106 +++++++++ .../ProjectLocalSecretsManager.cs | 148 ++++++++++++ .../Properties/AssemblyInfo.cs | 16 ++ .../Resources.Designer.cs | 140 ++++++++++++ .../Resources.resx | 146 ++++++++++++ .../SecretManagerFactory.cs | 37 +++ .../SecretStore.cs | 169 ++++++++++++++ .../Sources/ConfigurationPath.cs | 79 +++++++ .../Sources/JsonConfigurationFileParser.cs | 120 ++++++++++ .../Sources/PathHelper.cs | 57 +++++ .../source.extension.vsixmanifest | 21 ++ version.props | 3 + 38 files changed, 2260 insertions(+), 12 deletions(-) create mode 100644 build/VSIX.props create mode 100644 build/VSIX.targets create mode 100644 build/repo.targets create mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Key.snk create mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Microsoft.VisualStudio.SecretManager.TestExtension.csproj create mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/NotifyPropertyChanged.cs create mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/ProjectViewModel.cs create mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Properties/AssemblyInfo.cs create mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/RelayCommand.cs create mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Resources/SecretManagerTestCommand.png create mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Resources/SecretManagerTestPackage.ico create mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestCommand.cs create mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestControl.xaml create mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestControl.xaml.cs create mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestPackage.cs create mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestPackage.vsct create mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestWindow.cs create mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerViewModel.cs create mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/VSPackage.resx create mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/app.config create mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/source.extension.vsixmanifest create mode 100644 tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj create mode 100644 tooling/Microsoft.VisualStudio.SecretManager/ProjectLocalSecretsManager.cs create mode 100644 tooling/Microsoft.VisualStudio.SecretManager/Properties/AssemblyInfo.cs create mode 100644 tooling/Microsoft.VisualStudio.SecretManager/Resources.Designer.cs create mode 100644 tooling/Microsoft.VisualStudio.SecretManager/Resources.resx create mode 100644 tooling/Microsoft.VisualStudio.SecretManager/SecretManagerFactory.cs create mode 100644 tooling/Microsoft.VisualStudio.SecretManager/SecretStore.cs create mode 100644 tooling/Microsoft.VisualStudio.SecretManager/Sources/ConfigurationPath.cs create mode 100644 tooling/Microsoft.VisualStudio.SecretManager/Sources/JsonConfigurationFileParser.cs create mode 100644 tooling/Microsoft.VisualStudio.SecretManager/Sources/PathHelper.cs create mode 100644 tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest diff --git a/DotNetTools.sln b/DotNetTools.sln index 95b7b67009..302f0e2f5d 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27110.0 +VisualStudioVersion = 15.0.27120.0 MinimumVisualStudioVersion = 15.0.26730.03 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66517987-2A5A-4330-B130-207039378FD4}" ProjectSection(SolutionItems) = preProject @@ -20,12 +20,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution build.ps1 = build.ps1 build.sh = build.sh CONTRIBUTING.md = CONTRIBUTING.md + build\dependencies.props = build\dependencies.props Directory.Build.props = Directory.Build.props Directory.Build.targets = Directory.Build.targets LICENSE.txt = LICENSE.txt NuGet.config = NuGet.config NuGetPackageVerifier.json = NuGetPackageVerifier.json README.md = README.md + build\sources.props = build\sources.props version.props = version.props EndProjectSection EndProject @@ -46,46 +48,98 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Cachin EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DeveloperCertificates.Tools", "src\Microsoft.AspNetCore.DeveloperCertificates.Tools\Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj", "{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.DeveloperCertificates.XPlat", "src\Microsoft.AspNetCore.DeveloperCertificates.XPlat\Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj", "{96E71881-1465-44F5-B4B7-DF9B370FFD02}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.VisualStudio.SecretManager", "tooling\Microsoft.VisualStudio.SecretManager\Microsoft.VisualStudio.SecretManager.csproj", "{5E117F2E-7152-447F-BF47-59F759EEF3A7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tooling", "tooling", "{62826851-7D74-4F1E-B7D1-12553B789CD8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.VisualStudio.SecretManager.TestExtension", "tooling\Microsoft.VisualStudio.SecretManager.TestExtension\Microsoft.VisualStudio.SecretManager.TestExtension.csproj", "{965F8820-F809-4081-9090-1AEC903F291B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DeveloperCertificates.XPlat", "src\Microsoft.AspNetCore.DeveloperCertificates.XPlat\Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj", "{96E71881-1465-44F5-B4B7-DF9B370FFD02}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + DebugNoVSIX|Any CPU = DebugNoVSIX|Any CPU Release|Any CPU = Release|Any CPU + ReleaseNoVSIX|Any CPU = ReleaseNoVSIX|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU + {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Release|Any CPU.ActiveCfg = Release|Any CPU {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Release|Any CPU.Build.0 = Release|Any CPU + {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU + {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU {16BADE2F-1184-4518-8A70-B68A19D0805B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {16BADE2F-1184-4518-8A70-B68A19D0805B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {16BADE2F-1184-4518-8A70-B68A19D0805B}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU + {16BADE2F-1184-4518-8A70-B68A19D0805B}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU {16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.ActiveCfg = Release|Any CPU {16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.Build.0 = Release|Any CPU + {16BADE2F-1184-4518-8A70-B68A19D0805B}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU + {16BADE2F-1184-4518-8A70-B68A19D0805B}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU + {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.ActiveCfg = Release|Any CPU {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.Build.0 = Release|Any CPU + {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU + {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU {7B331122-83B1-4F08-A119-DC846959844C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7B331122-83B1-4F08-A119-DC846959844C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B331122-83B1-4F08-A119-DC846959844C}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU + {7B331122-83B1-4F08-A119-DC846959844C}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU {7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.ActiveCfg = Release|Any CPU {7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.Build.0 = Release|Any CPU + {7B331122-83B1-4F08-A119-DC846959844C}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU + {7B331122-83B1-4F08-A119-DC846959844C}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU + {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Release|Any CPU.ActiveCfg = Release|Any CPU {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Release|Any CPU.Build.0 = Release|Any CPU + {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU + {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU + {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.ActiveCfg = Release|Any CPU {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.Build.0 = Release|Any CPU + {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU + {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU + {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Release|Any CPU.ActiveCfg = Release|Any CPU {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Release|Any CPU.Build.0 = Release|Any CPU + {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU + {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU + {5E117F2E-7152-447F-BF47-59F759EEF3A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5E117F2E-7152-447F-BF47-59F759EEF3A7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5E117F2E-7152-447F-BF47-59F759EEF3A7}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU + {5E117F2E-7152-447F-BF47-59F759EEF3A7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5E117F2E-7152-447F-BF47-59F759EEF3A7}.Release|Any CPU.Build.0 = Release|Any CPU + {5E117F2E-7152-447F-BF47-59F759EEF3A7}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU + {965F8820-F809-4081-9090-1AEC903F291B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {965F8820-F809-4081-9090-1AEC903F291B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {965F8820-F809-4081-9090-1AEC903F291B}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU + {965F8820-F809-4081-9090-1AEC903F291B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {965F8820-F809-4081-9090-1AEC903F291B}.Release|Any CPU.Build.0 = Release|Any CPU + {965F8820-F809-4081-9090-1AEC903F291B}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU {96E71881-1465-44F5-B4B7-DF9B370FFD02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {96E71881-1465-44F5-B4B7-DF9B370FFD02}.Debug|Any CPU.Build.0 = Debug|Any CPU + {96E71881-1465-44F5-B4B7-DF9B370FFD02}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU + {96E71881-1465-44F5-B4B7-DF9B370FFD02}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU {96E71881-1465-44F5-B4B7-DF9B370FFD02}.Release|Any CPU.ActiveCfg = Release|Any CPU {96E71881-1465-44F5-B4B7-DF9B370FFD02}.Release|Any CPU.Build.0 = Release|Any CPU + {96E71881-1465-44F5-B4B7-DF9B370FFD02}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU + {96E71881-1465-44F5-B4B7-DF9B370FFD02}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -98,6 +152,8 @@ Global {8A2E6961-6B12-4A8E-8215-3E7301D52EAC} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} {53F3B53D-303A-4DAA-9C38-4F55195FA5B9} = {66517987-2A5A-4330-B130-207039378FD4} {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8} = {66517987-2A5A-4330-B130-207039378FD4} + {5E117F2E-7152-447F-BF47-59F759EEF3A7} = {62826851-7D74-4F1E-B7D1-12553B789CD8} + {965F8820-F809-4081-9090-1AEC903F291B} = {62826851-7D74-4F1E-B7D1-12553B789CD8} {96E71881-1465-44F5-B4B7-DF9B370FFD02} = {66517987-2A5A-4330-B130-207039378FD4} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/build/VSIX.props b/build/VSIX.props new file mode 100644 index 0000000000..9640955a99 --- /dev/null +++ b/build/VSIX.props @@ -0,0 +1,9 @@ + + + + + + diff --git a/build/VSIX.targets b/build/VSIX.targets new file mode 100644 index 0000000000..e679e98e42 --- /dev/null +++ b/build/VSIX.targets @@ -0,0 +1,86 @@ + + + true + $(RestoreDependsOn);RestoreVSIX + $(PackageDependsOn);PackageVSIX + Microsoft.VisualStudio.SecretManager + $(RepositoryRoot)tooling\$(VSIXName)\$(VSIXName).csproj + $(BuildDir)$(VSIXName).vsix + $(ArtifactsDir)msbuild\ + + + + + + + + + $(MSBuildArtifactsDir)vsix-restore.rsp + + + + + + + + + + + + + + + + + + + + + + $(MSBuildArtifactsDir)vsix.log + $(MSBuildArtifactsDir)vsix-build.rsp + + + + + + + + + + + + + + + diff --git a/build/dependencies.props b/build/dependencies.props index 72cc8468e4..87f9d17fce 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,18 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15549 - 2.1.0-preview1-27595 - 2.1.0-preview1-27595 - 2.1.0-preview1-27595 - 2.1.0-preview1-27595 - 2.1.0-preview1-27595 + 2.1.0-preview1-15573 + 2.1.0-preview1-27644 + 2.1.0-preview1-27644 + 2.1.0-preview1-27644 + 2.1.0-preview1-27644 + 2.1.0-preview1-27644 2.0.0 2.1.0-preview1-25907-02 15.3.0 4.4.0 4.4.0 + 9.0.1 2.3.0 2.3.0 diff --git a/build/repo.targets b/build/repo.targets new file mode 100644 index 0000000000..1183428580 --- /dev/null +++ b/build/repo.targets @@ -0,0 +1,10 @@ + + + + + + + Configuration=$(Configuration)NoVSIX + + + diff --git a/build/sources.props b/build/sources.props index c03f3ddb60..77203a6622 100644 --- a/build/sources.props +++ b/build/sources.props @@ -1,4 +1,4 @@ - + @@ -7,6 +7,7 @@ $(RestoreSources); https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json; https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; + https://vside.myget.org/F/vssdk/api/v3/index.json; $(RestoreSources); diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 45463cc71e..e255811551 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15549 -commithash:f570e08585fec510dd60cd4bfe8795388b757a95 +version:2.1.0-preview1-15573 +commithash:82cb53a8578610baf96ef33142797c68bae68c81 diff --git a/korebuild.json b/korebuild.json index bd5d51a51b..0a2e713c08 100644 --- a/korebuild.json +++ b/korebuild.json @@ -1,4 +1,16 @@ { "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev" + "channel": "dev", + "toolsets": { + "visualstudio": { + "required": [ + "windows" + ], + "includePrerelease": true, + "minVersion": "15.4", + "requiredWorkloads": [ + "Microsoft.VisualStudio.Component.VSSDK" + ] + } + } } diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Key.snk b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Key.snk new file mode 100644 index 0000000000000000000000000000000000000000..2181a1627bf841f91b220de8258de4591629d169 GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098eLAD9Hsv)-@LYruqYXoq*$CbcyqhF9_ zJNINE4KwxCc=zqW)Jwkn`UV}^Y(IMBUm{xgCv_L2E)Wkc$U2dxKX7}>;DDK-YyBR0 zv=7PjBU$b1ek&UiLnaZH0)Abxi^KRk>d3t73-A?lyM6?EoG?NRqitAMj2X3Z%u&|E zrwKH+r+S(9p=O{cvKd2`xM2&?bvfd7`75k&O%+r%^Y9Y((vA%FwT9CHDc1YIm z?bKQ;eA=^ehw|6kYCr#+^U@%^KVmW;jWR>>>52Qp(#(u)JQMZntn)LxTf^YaEopg% zSwCw!kXHvf`Yi5*iHA|n^xZiW`Vs!)erHg)_=wmuq`=R*E1(2vKuV7Aqfi;Z_JV}) zocdzFRoQ|X~Wz-;7of>%3oHo1{Tr@ar%xdF&hy6Cdrd z#Vr5nWd2vx^_sX>r<(q0{qfHrRw{Oq(R~1V%Y)_)X+3Kn8cf$)`f?|$rnz~wob0mw z!!?6FA|Ksdn;(hg$rFCTIa5M7;@1K!FJEr&5h+UyX% i)<83a5xbDB8Z + + + 15.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + False + False + False + True + True + ..\..\build\Key.snk + True + + + + + + + Debug + AnyCPU + 2.0 + {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {965F8820-F809-4081-9090-1AEC903F291B} + Library + Properties + Microsoft.VisualStudio.SecretManager.TestExtension + Microsoft.VisualStudio.SecretManager.TestExtension + v4.6.1 + true + true + true + true + true + false + Program + $(DevEnvDir)devenv.exe + /rootsuffix Exp + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + SecretManagerTestControl.xaml + + + + + + + Designer + + + + + + + + + Designer + MSBuild:Compile + + + + + + + + False + + + + + + + + + + + + + + + + + + + 7.10.6071 + + + + + + 11.0.61030 + + + 12.0.30110 + + + 15.0.26606 + + + 8.0.50727 + + + 9.0.30729 + + + + 4.4.0 + + + + + + + Menus.ctmenu + + + + + true + VSPackage + + + + + + diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/NotifyPropertyChanged.cs b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/NotifyPropertyChanged.cs new file mode 100644 index 0000000000..720593d469 --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/NotifyPropertyChanged.cs @@ -0,0 +1,18 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace Microsoft.VisualStudio.SecretManager.TestExtension +{ + public abstract class NotifyPropertyChanged : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + + protected void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } +} diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/ProjectViewModel.cs b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/ProjectViewModel.cs new file mode 100644 index 0000000000..f667db5267 --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/ProjectViewModel.cs @@ -0,0 +1,20 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; +using Microsoft.VisualStudio.ProjectSystem; + +namespace Microsoft.VisualStudio.SecretManager.TestExtension +{ + public class ProjectViewModel : NotifyPropertyChanged + { + public ProjectViewModel(UnconfiguredProject project) + { + Project = project; + } + + internal UnconfiguredProject Project { get; } + + public string ProjectName => Path.GetFileNameWithoutExtension(Project.FullPath); + } +} diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Properties/AssemblyInfo.cs b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..9999a9ba7e --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Microsoft.VisualStudio.SecretManager.TestExtension")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Microsoft.VisualStudio.SecretManager.TestExtension")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/RelayCommand.cs b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/RelayCommand.cs new file mode 100644 index 0000000000..e12b2bd622 --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/RelayCommand.cs @@ -0,0 +1,44 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Windows.Input; + +namespace Microsoft.VisualStudio.SecretManager.TestExtension +{ + public class RelayCommand : ICommand + { + readonly Action _execute = null; + readonly Predicate _canExecute = null; + + public RelayCommand(Action execute) + : this(execute, null) + { + } + + public RelayCommand(Action execute, Predicate canExecute) + { + if (execute == null) + throw new ArgumentNullException("execute"); + + _execute = execute; + _canExecute = canExecute; + } + + public bool CanExecute(object parameter) + { + return _canExecute == null ? true : _canExecute((T)parameter); + } + + public event EventHandler CanExecuteChanged + { + add { CommandManager.RequerySuggested += value; } + remove { CommandManager.RequerySuggested -= value; } + } + + public void Execute(object parameter) + { + _execute((T)parameter); + } + } +} diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Resources/SecretManagerTestCommand.png b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Resources/SecretManagerTestCommand.png new file mode 100644 index 0000000000000000000000000000000000000000..b22d975cbf00eda60e37587614e0677d0bfb525d GIT binary patch literal 1172 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

N3mPu2mM3; zmKw3j9OIw0-7>d1d|TrK z{X_qjJhtX<%)e!BbNG(smuiRpp?^yrr}8s(y=885_)g6~wjTP2{w;YNSe5YKQ)ze@h;x@-ub4Wo~o$PR&2I9{Pv=EqNT{pS9gG zw>f-U;{*Le|CT(q=5NfuWo~o$j^&qXhyI~|OCG24Gj+XXZgcof%|Est`iK54c^u=P zwcRqeIec5=1N}q)mOQrRZ_K}CZgcpK<(F!Q{-J+M9;fm%b-iV7bNEipKeitFhyE>j z9OIw0-7>d1d|TrK{X_qjJhtX<%)e!BbNG(smuiRpp?^yrr}8s(y=885_)g6~wjTP2 z{w;YNSe5YKQ)ze@h;x@-ub4Wo~o$PR&2I z9{Pv=EqNT{pS9gGw>f-U;{*Le|CT(q=5NfuWo~o$j^&qXhyI~|OCG24Gj+XXZgcof z%|Est`iK54c^u=PwcRqeIec5=1N}q)mOQrRZ_K}CZgcpK<(F!Q{-J+M9;fm%b-iV7 zbNEipKeitFhyE>j9OIw0-7>d1d|TrK{X_qjJhtX<%)e!BbNG(smuiRpp?^yrr}8s( zy=885_)g6~wjTP2{w;YNSe5YKQ)ze@h;x z@-ub4Wo~o$PR&2I9{Pv=EqNT{pS9gGw>f-U;{*Le|CT(q=5NfuWo~o$j^&qXhyI~| zOCG24Gj+XXZgcof%|Est`iK54c^u=PwcRqeIec5=1N}q)mOQrRZ_K}CZgcpK<(F!Q z{-J+M9;fm%b-iV7bNEipKeitFhyE>j9OIw0-7>d1d|TrK{X_qjJhtX<%)e!BbNG(s zmuiRpp?^yrr}8s(y=885_)g6~wjTP2{w;YNSe5YKQ)ze@h;x@-ub4Wo~o$PR&2I9{Pv=EqNT{pS9gGw>f-U;{*Le|CT(q=5Nfu zWo~o$j^&qXhyI~|OCG24Gj+XXZgcof%|Est`d_yGWA%gm!44Qq#{l|={-K}g`dK@6 z&_DFQb`B%{>E{>p5B)f9)Jb{L{}b=pXurex~bZ?bt#8(Er*wjQFRY zU(i4F5B*Hn&)Ttr{-OW1a~SbYKfj=V=pXu-uAjAI2mM3;Yv(ZHpMHKp|Ik15GhIJx z#}4|3{@2c7#6SJ~g8rd@=x4fq){Y(Y5B;y5!-#+S`33z$|Ip8L{j423=pXuDJBJbf z^z#e)hyJ0T>H1kacF;fczjh8I{^{oz^bh?*KhyQIcI=>k=zr}TM*P#yFX$iohkmB( zXYJTQ|Iq*1IgI$HpI^{F^bh?^*U#FqgZ`JT|2h5}6P9}%S|66V&EeY`KjWBx63o5Oc3zf?Q)5B*#6IF+BN>n(Ge!*^=_vGveD^l!=I82_y8mbuO0+ZrF} zANsfCu{D2V{w;Hx!*?vdR6Fz!{af-lm7l5WEpwa0cWVBz_0T``Z^`2r|E%qnxy|9* z8XxE%`nTkSLRtnHS$ z&EeY`ALt+Yx8$)ke`EeFbDP6=EWcDc^bh@8@;H^Bsp~Cso5Oc%{;~DYKlE?O;~4*} z?UuRC;oBM?=pXvGWBx63o5Oc3zf?Q)5B*#6IF+BN>n(Ge!*^=_vGveD^l!=I z82_y8mbuO0+ZrF}ANsfCu{D2V{w;Hx!*?vdR6Fz!{af-lm7l5WEpwa0cWVBz_0T`` zZ^`2r|E%qnxy|9*8XxE%`nTkSLRtnHS$&EeY`ALt+Yx8$)ke`EeFbDP6=EWcDc^bh@8@;H^Bsp~Cso5Oc% z{;~DYKlE?O;~4*}?UuRC;oBM?=pXvGWBx63o5Oc3zf?Q)5B*#6IF+BN>n(Ge z!*^=_vGveD^l!=I82_y8mbuO0+ZrF}ANsfCu{D2V{w;Hx!*?vdR6Fz!{af-lm7l5W zEpwa0cWVBz_0T``Z^`2r|E%qnxy|9*8XxE%`nTkSLRtnHS$&EeY`ALt+Yx8$)ke`EeFbDP6=EWcDc^bh@8 z@;H^Bsp~Cso5Oc%{;~DYKlE?O;~4*}?UuRC;oBM?=pXvGWBx63o5Oc3zf?Q) z5B*#6IF+BN>n(Ge!*^=_vGveD^l!=I82_y8mbuO0+ZrF}ANsfCu{D2V{w;Hx!*?vd zR6Fz!{af-lm7l5WEpwa0cWVBz_0T``Z^`2r|E%qnxy|9*8XxE%`nTku2rQLI2SI+BuB)r=MTY zKlBg%OxMrav4j4h|Fv@%@lQX$pnvEe`kAhuwPOeUL;q{%FyfznenJ1xKlC$QKWoPh z`iK74&SAtq{rrOdp?~OSx_;J<9rT~3{~Y)o!pFOJ?{<$KJ;LA4e~_mACr_U2-oJmp zJ46kavS+d4uccr(R~#QceAvBw`4YNM)V+M)fA#9s(VhV-mVYsq?v}6*-t*Jm>!s%9 z^|9UyK>y4B41xE2TiwfZ;Mnd3p#SCSAMg3|YM;-7W4afB{+FkJyyqWA_pE@#_Im;7e?I-=J^ylP zpU;3b-wQzh_WH+r{^is?>z~^--U~qgw))3={&8rZ&w#bv3qb!i`p0|zap|7*&+S_7 z1=g(pA+aCgclYp~|DgQ)1jqh23J!TMFhm=dea_t4$9sPJo=<1s+qZA=w+h_fDmc`= zz-8CBmfzgEr~UAr-)jHavuDlU(|G#yDb4_Q2H;*mQ)}MwxwVh?{8sn$+4teYhr5f5 zi$?#{=g-7waW9Zp?X9=Db&vP_uI^dep?h5#V>?>h3$&`u)0x1@jh%ulNYo(1;fhk7a=%}FhqLC)ai}l6=f`6L!S9*^}@5j;aDHry@19Ut8u*N59cDk z?+<@*1+3y83u2_!aJ%2n8=?uuhMe@Pt3EE+GxUBaAmKqQF#(VxSzJ+u- z_L*M@e;UKH!09!}asFy`=^M}euK;~}S=xwuZ{EDw;dAJC4o-RIr_~bA0>|S|&s~VS z8m4oM=Qs!Eh;zsu^jVb7Q~Zp2oQo;X{Ipu&436VY+g+Ppj)OJPTao{k>nW6s^bB`unVb|eN5*uyT*^Dk6*UW2bRzLv|3)4XMwoCkEwi^UE|4;$1lU@1A5Oo z1jcKB7Kr=%VY;3&>kxcQ-E*y<59WC0r(wIcXMwoCpQ7gJYc$?0eS9sS59WO4r`2rf z&jN9OKV82$S8DuO^7xWJAI$yCPpi{Xp9SLnKBs!~`qH?xEnm~d~m2|ep+1)`799k_tq+%$G^s{C66EK^T8pX`Dyi-`&l6F@8{9w zA$HL?w&d}-J|8UMnV(h%>t}(uzdwW;54Werv!#z)eLl$j%#SOZ3r~w@fw;ftDjj#5 zi=%V;$^H2t_cK3cR8CBCJqyJBJy!>*i*Rsz>k5Xi~jxqJ=%e31K@pN4PFykpM-aeuE>0pqC% zH=R?qx2jC181dKQTLdkuArTOg2&%X9njKOa~<^V9IonJdMP`+E&(jL(Tc zPF~ODi#{LZ+-oS_x%SK*f3CQO_!){7=B*EbA@#qEbB0#xGUh%cr=j>@-sM1G2q!Mf zoUs+VEO`&fV=Ok9fB6s?!jrYmnOd#2<~t ziNFv}EqzXE<(8h`koZzDzQS02)jWz0i-%Xn}N1eT1z5KddnvBJb6)*(Kv@_}C7_yx1>{z;3q-8))>*Sz!l08Uo-4^nvq1QwPpZoDVo3a6aIC&=A1+fb#+8 zgQgDLKj3`8`GE5Q=Yxg-&IgxCidO^ zoX7nkKkKokIkB95JMu^U*Tn51vHJXu^+WuB@ZiC2O)rT_EN9=2{P*?0rrJ}isQ)h= z419ja`rtqKFZHA8|L31R?#8?{KRiCh7tQ5$vX$}2IPcrX@IP0)9Dgo<$bX*mFIT-# z|LXoS7oOlh`0sPTKi^}0od3h`e{$&+=O4~L;y^Aw`P!#`O!K}S`X8=;*6q^Tx$3{P zyg44^KhOOS5g?GJc=m zu|D_@{!9KaKiAUA_+y;+?PK`AR6LMBKL7h1@cA99?c29W`7>4#E>JGFIlsQv%`>ez$NTKrvxZYopFYikK?)ZL zANMk^IpzQG;ltg<#YK}p^%<8O?N~1K)!f<2IN!W^v&&VdP<**GMKMyW9JkVT&ILDz z-tWG5FBlq2POU!DVQj5P4ry?$`7V4VIq zonOzNKQH+_l()3T_u==)oQ0$z+Plx6@7wh$C(3Q;Ie6;kZr$rg_flgf8`W-zKKwIJ z^BL0^^PBe6e0bv&JLPaHYdz-Lt-tSH-@DgjeaJJ<`J(uLs9)4CU!k**G?RnhV{#77 zbumuX2gT1hdhNHaPp^)R=34VRl;4;!7xO56$Q<4E3*L|VzMZ%|C%-w4sjZ8Bus-TM zNk`2&M1A*)YRg;uz3bnf8n4y5I*-S${h^Mv!)tHsv5djlXq`5n#>pqmX>gN1mUQjn zJawy`GEs;Dp4)x#BIIHV%_hVJyTjy1K zvaMSFdnB8S>iT;9_c`uWe+R?;J&e-e{w~FDg`4aCKE!Uj+0x(T**0VH92cG8vmi6AFSpHE+GDy|K0=e z@BV#_p+5&A^)Pi^Zv3alF?Ai{2Y*Nl;7|FUp8Wnb700RTpkL^BN&1!VtJc@K`EMPs z^pE(v`jz-tU+2bu>N!4j9pdluXDW_U*8zXvPiGYPgZt+c9)Lf2_+x#)ApPe)|D}KH zYsBAu|FXtg`cK7QtZ)7;;`Qs-qkg_f#>Ln4^AzMu+eeI#etsg>mp_XY`&k~2ZA?o( z2mG8@QvA6v*YX-ri)j1~@89Rb{N>A+<%7LSr@6Fe&(As$))ez8)5-OTKabt(2lwji&DZp^`NZiMA40!R zLqAX1mp}O=-=VdzAZ z9|}j<55+*SG+1+-Lt3})zI%P|UQHaX&%VnVGrtH!QFGdtUgdnU(VP+dxIZMuA#+>| zQGSWoeNBbA@UyegPZr5)(nYh>Ky0))V&DTCN9@6bda}&%5qFI7Zj*+wOeh{zE>l{dKdwOYQFDoc`lS^mAIL?seb2nxE5( zsK?_0^TDKbAqBsdvcG&U$aT&61(SD!Y|piy^uzwww7>RzNai+V-jw`@_@!8e%)|cG z`^*^r4Z-y?<1cxhay^BADf`K_Yux|X`G@?&|GgT??IAc#;r|f76w8o#Q}&m6rd(tH zVefy86Srgkb^<*I=zHE0d;jHqsiog7oLX~Q>-*wwEX=)W==#>KEDR#n*mIYiRBLf!nFmoR3g_ zzUKw?KD_r2?)ovUVS8VD;r`?2)~|E-0?WAKjA<_j_w+yTALp^7qLo&{Ox~ z=M?v^x(nsY<;8gpYNZ=mFS)8+(_C%6|9;Es<=B$fbIg5hU;KUR*w(jRVnu7@*pk + /// Command ID. + /// + public const int CommandId = 0x0100; + + ///

+ /// Command menu group (command set GUID). + /// + public static readonly Guid CommandSet = new Guid("e415a3f4-f2a8-4834-b7f7-f89844b2505c"); + + /// + /// VS Package that provides this command, not null. + /// + private readonly Package package; + + /// + /// Initializes a new instance of the class. + /// Adds our command handlers for menu (commands must exist in the command table file) + /// + /// Owner package, not null. + private SecretManagerTestCommand(Package package) + { + if (package == null) + { + throw new ArgumentNullException("package"); + } + + this.package = package; + + OleMenuCommandService commandService = this.ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService; + if (commandService != null) + { + var menuCommandID = new CommandID(CommandSet, CommandId); + var menuItem = new MenuCommand(this.ShowToolWindow, menuCommandID); + commandService.AddCommand(menuItem); + } + } + + /// + /// Gets the instance of the command. + /// + public static SecretManagerTestCommand Instance + { + get; + private set; + } + + /// + /// Gets the service provider from the owner package. + /// + private IServiceProvider ServiceProvider + { + get + { + return this.package; + } + } + + /// + /// Initializes the singleton instance of the command. + /// + /// Owner package, not null. + public static void Initialize(Package package) + { + Instance = new SecretManagerTestCommand(package); + } + + /// + /// Shows the tool window when the menu item is clicked. + /// + /// The event sender. + /// The event args. + private void ShowToolWindow(object sender, EventArgs e) + { + // Get the instance number 0 of this tool window. This window is single instance so this instance + // is actually the only one. + // The last flag is set to true so that if the tool window does not exists it will be created. + ToolWindowPane window = this.package.FindToolWindow(typeof(SecretManagerTestWindow), 0, true); + if ((null == window) || (null == window.Frame)) + { + throw new NotSupportedException("Cannot create tool window"); + } + + IVsWindowFrame windowFrame = (IVsWindowFrame)window.Frame; + Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(windowFrame.Show()); + } + } +} diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestControl.xaml b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestControl.xaml new file mode 100644 index 0000000000..201144b7e1 --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestControl.xaml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestControl.xaml.cs b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestControl.xaml.cs new file mode 100644 index 0000000000..b39c208ddf --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestControl.xaml.cs @@ -0,0 +1,37 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.VisualStudio.SecretManager.TestExtension +{ + using System.Diagnostics.CodeAnalysis; + using System.Windows; + using System.Windows.Controls; + + /// + /// Interaction logic for SecretManagerTestControl. + /// + public partial class SecretManagerTestControl : UserControl + { + /// + /// Initializes a new instance of the class. + /// + public SecretManagerTestControl() + { + this.InitializeComponent(); + } + + /// + /// Handles click on the button by displaying a message box. + /// + /// The event sender. + /// The event args. + [SuppressMessage("Microsoft.Globalization", "CA1300:SpecifyMessageBoxOptions", Justification = "Sample code")] + [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:ElementMustBeginWithUpperCaseLetter", Justification = "Default event handler naming pattern")] + private void button1_Click(object sender, RoutedEventArgs e) + { + MessageBox.Show( + string.Format(System.Globalization.CultureInfo.CurrentUICulture, "Invoked '{0}'", this.ToString()), + "SecretManagerTest"); + } + } +} diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestPackage.cs b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestPackage.cs new file mode 100644 index 0000000000..ada842d9cb --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestPackage.cs @@ -0,0 +1,27 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using Microsoft.VisualStudio.Shell; + +namespace Microsoft.VisualStudio.SecretManager.TestExtension +{ + [PackageRegistration(UseManagedResourcesOnly = true)] + [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] // Info on this package for Help/About + [ProvideMenuResource("Menus.ctmenu", 1)] + [ProvideToolWindow(typeof(SecretManagerTestWindow))] + [Guid(SecretManagerTestPackage.PackageGuidString)] + [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "pkgdef, VS and vsixmanifest are valid VS terms")] + public sealed class SecretManagerTestPackage : Package + { + public const string PackageGuidString = "7b771e3e-f599-4fde-95a9-e35019e705f7"; + + protected override void Initialize() + { + SecretManagerTestCommand.Initialize(this); + base.Initialize(); + } + } +} diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestPackage.vsct b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestPackage.vsct new file mode 100644 index 0000000000..554ae60164 --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestPackage.vsct @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestWindow.cs b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestWindow.cs new file mode 100644 index 0000000000..240a8fb935 --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestWindow.cs @@ -0,0 +1,31 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Runtime.InteropServices; +using Microsoft.VisualStudio.ComponentModelHost; +using Microsoft.VisualStudio.ProjectSystem; +using Microsoft.VisualStudio.Shell; + +namespace Microsoft.VisualStudio.SecretManager.TestExtension +{ + [Guid("6afffd63-17b6-4ef2-b515-fee22d767631")] + public class SecretManagerTestWindow : ToolWindowPane + { + public SecretManagerTestWindow() + : base(null) + { + this.Caption = "SecretManager Test Window"; + this.Content = new SecretManagerTestControl(); + } + + protected override void Initialize() + { + base.Initialize(); + + var component = (IComponentModel)GetService(typeof(SComponentModel)); + var projectService = component.GetService().GetProjectService(); + ((SecretManagerTestControl)Content).DataContext = new SecretManagerViewModel(projectService); + } + } +} diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerViewModel.cs b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerViewModel.cs new file mode 100644 index 0000000000..3a4d5cbf61 --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerViewModel.cs @@ -0,0 +1,214 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using System.Windows; +using Microsoft.VisualStudio.ProjectSystem; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.VisualStudio.Threading; +using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider; +using Task = System.Threading.Tasks.Task; + +namespace Microsoft.VisualStudio.SecretManager.TestExtension +{ + public class SecretManagerViewModel : NotifyPropertyChanged + { + private readonly IProjectService _projectService; + private readonly Random _rand; + private string _error; + private bool _isLoaded; + private ProjectViewModel _selectedProject; + + public SecretManagerViewModel(IProjectService projectService) + { + _projectService = projectService; + + RefreshCommand = new RelayCommand(Refresh, RefreshIsEnabled); + AddCommand = new RelayCommand(Add, IsProjectLoaded); + SaveCommand = new RelayCommand(Save, IsProjectLoaded); + Refresh(null); + _rand = new Random(); + } + + public RelayCommand RefreshCommand { get; } + + public RelayCommand AddCommand { get; } + public RelayCommand SaveCommand { get; } + + public ObservableCollection Projects { get; } = new ObservableCollection(); + + public ProjectViewModel SelectedProject + { + get => _selectedProject; + set + { + if (value == _selectedProject) + { + return; + } + + _selectedProject = value; + OnSelectedProjectChanged(); + OnPropertyChanged(); + } + } + + public bool IsLoaded + { + get => _isLoaded; + set + { + if (value == _isLoaded) + { + return; + } + + _isLoaded = value; + OnPropertyChanged(); + } + } + + public string Error + { + get => _error; + set + { + if (value == _error) + { + return; + } + + _error = value; + OnPropertyChanged(); + OnPropertyChanged(nameof(ErrorVisibility)); + } + } + + public Visibility ErrorVisibility => Error == null ? Visibility.Collapsed : Visibility.Visible; + + public ObservableCollection> Secrets { get; } = new ObservableCollection>(); + + private bool RefreshIsEnabled(object obj) => IsLoaded || SelectedProject == null; + + private void Refresh(object obj) + { + Projects.Clear(); + + foreach (var project in _projectService.LoadedUnconfiguredProjects) + { + Projects.Add(new ProjectViewModel(project)); + } + } + + private bool IsProjectLoaded(object obj) => IsLoaded && SelectedProject != null; + + private void Add(object obj) + { + Secrets.Add(new KeyValuePair("NewKey" + _rand.Next(10_000), "My new totally random and secret test value")); + } + + private async void Save(object obj) + { + Exception exception; + + try + { + IOleServiceProvider oleServices; + var project = (IVsProject)_selectedProject.Project.Services.HostObject; + Marshal.ThrowExceptionForHR(project.GetItemContext((uint)VSConstants.VSITEMID.Root, out oleServices)); + var services = new ServiceProvider(oleServices); + + var projectSecrets = (IVsProjectSecrets)services.GetService(typeof(SVsProjectLocalSecrets)); + await TaskScheduler.Default; + + if (projectSecrets == null) + { + exception = null; + } + else + { + foreach (var secret in Secrets) + { + await projectSecrets.SetSecretAsync(secret.Key, secret.Value).ConfigureAwait(false); + } + + exception = null; + } + } + catch (Exception ex) + { + exception = ex; + } + + if (exception != null) + { + Error = exception.ToString(); + } + } + + private async void OnSelectedProjectChanged() + { + Secrets.Clear(); + IsLoaded = false; + + if (_selectedProject == null) + { + return; + } + + KeyValuePair[] results; + Exception exception; + + try + { + IOleServiceProvider oleServices; + var project = (IVsProject)_selectedProject.Project.Services.HostObject; + Marshal.ThrowExceptionForHR(project.GetItemContext((uint)VSConstants.VSITEMID.Root, out oleServices)); + var services = new ServiceProvider(oleServices); + + var projectSecrets = (IVsProjectSecrets)services.GetService(typeof(SVsProjectLocalSecrets)); + await TaskScheduler.Default; + + if (projectSecrets == null) + { + results = null; + exception = null; + } + else + { + var secrets = await projectSecrets.GetSecretsAsync().ConfigureAwait(false); + + results = secrets.ToArray(); + exception = null; + } + } + catch (Exception ex) + { + results = null; + exception = ex; + } + + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + + if (exception != null) + { + Error = exception.ToString(); + } + else if (results != null) + { + for (var i = 0; i < results.Length; i++) + { + Secrets.Add(results[i]); + } + } + + IsLoaded = true; + } + } +} diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/VSPackage.resx b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/VSPackage.resx new file mode 100644 index 0000000000..ca1c752309 --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/VSPackage.resx @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + SecretManagerTest Extension + + + SecretManagerTest Visual Studio Extension Detailed Info + + + Resources\SecretManagerTestPackage.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/app.config b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/app.config new file mode 100644 index 0000000000..4bac29887b --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/app.config @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/source.extension.vsixmanifest b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/source.extension.vsixmanifest new file mode 100644 index 0000000000..3b8e971651 --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/source.extension.vsixmanifest @@ -0,0 +1,21 @@ + + + + + Microsoft.VisualStudio.SecretManager.TestExtension + A test extension for Microsoft.VisualStudio.TestExtension + + + + + + + + + + + + + + + diff --git a/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj b/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj new file mode 100644 index 0000000000..bfd99e46b7 --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj @@ -0,0 +1,106 @@ + + + + 15.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + False + False + False + True + True + ..\..\build\Key.snk + True + + + + + + + Debug + AnyCPU + 2.0 + {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {5E117F2E-7152-447F-BF47-59F759EEF3A7} + Library + Properties + Microsoft.VisualStudio.SecretManager + Microsoft.VisualStudio.SecretManager + v4.6.1 + true + true + true + true + true + false + Program + $(DevEnvDir)devenv.exe + /rootsuffix Exp + + + true + full + false + bin\Debug\ + TRACE;DEBUG;EXTENSION_DEVELOPER_MODE + prompt + 4 + latest + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + latest + + + + + + + + + + + + + + Designer + + + + + + + + + + + + + + + + + + + + + + + + + + + Designer + + + + + + diff --git a/tooling/Microsoft.VisualStudio.SecretManager/ProjectLocalSecretsManager.cs b/tooling/Microsoft.VisualStudio.SecretManager/ProjectLocalSecretsManager.cs new file mode 100644 index 0000000000..e516a85ffb --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager/ProjectLocalSecretsManager.cs @@ -0,0 +1,148 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.ProjectSystem.Properties; +using Microsoft.VisualStudio.Threading; +using Task = System.Threading.Tasks.Task; + +namespace Microsoft.VisualStudio.SecretManager +{ + /// + /// Provides an thread-safe access the secrets.json file based on the UserSecretsId property in a configured project. + /// + internal class ProjectLocalSecretsManager : Shell.IVsProjectSecrets, Shell.SVsProjectLocalSecrets + { + private const string UserSecretsPropertyName = "UserSecretsId"; + + private readonly AsyncSemaphore _semaphore; + private readonly IProjectPropertiesProvider _propertiesProvider; + private readonly Lazy _services; + + public ProjectLocalSecretsManager(IProjectPropertiesProvider propertiesProvider, Lazy serviceProvider) + { + _propertiesProvider = propertiesProvider ?? throw new ArgumentNullException(nameof(propertiesProvider)); + _services = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); + _semaphore = new AsyncSemaphore(1); + } + + public string SanitizeName(string name) => name; + + public IReadOnlyCollection GetInvalidCharactersFrom(string name) => Array.Empty(); + + public async Task AddSecretAsync(string name, string value, CancellationToken cancellationToken = default) + { + EnsureKeyNameIsValid(name); + await TaskScheduler.Default; + + using (await _semaphore.EnterAsync(cancellationToken)) + using (var store = await GetOrCreateStoreAsync(cancellationToken)) + { + if (store.ContainsKey(name)) + { + throw new ArgumentException(Resources.Error_SecretAlreadyExists, nameof(name)); + } + + store.Set(name, value); + await store.SaveAsync(cancellationToken); + } + } + + public async Task SetSecretAsync(string name, string value, CancellationToken cancellationToken = default) + { + EnsureKeyNameIsValid(name); + await TaskScheduler.Default; + + using (await _semaphore.EnterAsync(cancellationToken)) + using (var store = await GetOrCreateStoreAsync(cancellationToken)) + { + store.Set(name, value); + await store.SaveAsync(cancellationToken); + } + } + + public async Task GetSecretAsync(string name, CancellationToken cancellationToken = default) + { + EnsureKeyNameIsValid(name); + await TaskScheduler.Default; + + using (await _semaphore.EnterAsync(cancellationToken)) + using (var store = await GetOrCreateStoreAsync(cancellationToken)) + { + return store.Get(name); + } + } + + public async Task> GetSecretNamesAsync(CancellationToken cancellationToken = default) + { + await TaskScheduler.Default; + + using (await _semaphore.EnterAsync(cancellationToken)) + using (var store = await GetOrCreateStoreAsync(cancellationToken)) + { + return store.ReadOnlyKeys; + } + } + + + public async Task> GetSecretsAsync(CancellationToken cancellationToken = default) + { + await TaskScheduler.Default; + + using (await _semaphore.EnterAsync(cancellationToken)) + using (var store = await GetOrCreateStoreAsync(cancellationToken)) + { + return store.Values; + } + } + + public async Task RemoveSecretAsync(string name, CancellationToken cancellationToken = default) + { + EnsureKeyNameIsValid(name); + await TaskScheduler.Default; + + using (await _semaphore.EnterAsync(cancellationToken)) + using (var store = await GetOrCreateStoreAsync(cancellationToken)) + { + if (store.Remove(name)) + { + await store.SaveAsync(cancellationToken); + return true; + } + + return false; + } + } + + private void EnsureKeyNameIsValid(string name) + { + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + + if (name.Length == 0) + { + throw new ArgumentException(nameof(name)); + } + } + + private async Task GetOrCreateStoreAsync(CancellationToken cancellationToken) + { + var userSecretsId = await _propertiesProvider.GetCommonProperties().GetEvaluatedPropertyValueAsync(UserSecretsPropertyName); + + if (string.IsNullOrEmpty(userSecretsId)) + { + userSecretsId = Guid.NewGuid().ToString(); + await _propertiesProvider.GetCommonProperties().SetPropertyValueAsync(UserSecretsPropertyName, userSecretsId); + } + + var store = new SecretStore(userSecretsId); + await store.LoadAsync(cancellationToken); + return store; + } + } +} diff --git a/tooling/Microsoft.VisualStudio.SecretManager/Properties/AssemblyInfo.cs b/tooling/Microsoft.VisualStudio.SecretManager/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..56a9841165 --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Reflection; +using Microsoft.VisualStudio.Shell; + +// required for VS to generate the pkgdef +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: ProvideCodeBase(CodeBase = @"$PackageFolder$\Microsoft.VisualStudio.SecretManager.dll")] +[assembly: ProvideBindingRedirection( + AssemblyName = "Microsoft.VisualStudio.SecretManager", + GenerateCodeBase = true, + PublicKeyToken = "adb9793829ddae60", + OldVersionLowerBound = "0.0.0.0", + OldVersionUpperBound = "1.0.0.0", + NewVersion = "1.0.0.0")] diff --git a/tooling/Microsoft.VisualStudio.SecretManager/Resources.Designer.cs b/tooling/Microsoft.VisualStudio.SecretManager/Resources.Designer.cs new file mode 100644 index 0000000000..bd79af4b8c --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager/Resources.Designer.cs @@ -0,0 +1,140 @@ +// +namespace Microsoft.VisualStudio.SecretManager +{ + using System.Globalization; + using System.Reflection; + using System.Resources; + + internal static class Resources + { + private static readonly ResourceManager _resourceManager + = new ResourceManager("Microsoft.VisualStudio.SecretManager.Resources", typeof(Resources).GetTypeInfo().Assembly); + + /// + /// A secret with this name already exists. + /// + internal static string Error_SecretAlreadyExists + { + get => GetString("Error_SecretAlreadyExists"); + } + + /// + /// Value cannot be null or an empty string. + /// + internal static string Common_StringNullOrEmpty + { + get => GetString("Common_StringNullOrEmpty"); + } + + /// + /// Value cannot be null or an empty string. + /// + internal static string FormatCommon_StringNullOrEmpty() + => GetString("Common_StringNullOrEmpty"); + + /// + /// Invalid character '{0}' found in the user secrets ID at index '{1}'. + /// + internal static string Error_Invalid_Character_In_UserSecrets_Id + { + get => GetString("Error_Invalid_Character_In_UserSecrets_Id"); + } + + /// + /// Invalid character '{0}' found in the user secrets ID at index '{1}'. + /// + internal static string FormatError_Invalid_Character_In_UserSecrets_Id(object p0, object p1) + => string.Format(CultureInfo.CurrentCulture, GetString("Error_Invalid_Character_In_UserSecrets_Id"), p0, p1); + + /// + /// Could not find 'UserSecretsIdAttribute' on assembly '{0}'. + /// Check that the project for '{0}' has set the 'UserSecretsId' build property. + /// If the 'UserSecretsId' property is already set then add a reference to the Microsoft.Extensions.Configuration.UserSecrets package. + /// + internal static string Error_Missing_UserSecretsIdAttribute + { + get => GetString("Error_Missing_UserSecretsIdAttribute"); + } + + /// + /// Could not find 'UserSecretsIdAttribute' on assembly '{0}'. + /// Check that the project for '{0}' has set the 'UserSecretsId' build property. + /// If the 'UserSecretsId' property is already set then add a reference to the Microsoft.Extensions.Configuration.UserSecrets package. + /// + internal static string FormatError_Missing_UserSecretsIdAttribute(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("Error_Missing_UserSecretsIdAttribute"), p0); + + /// + /// File path must be a non-empty string. + /// + internal static string Error_InvalidFilePath + { + get => GetString("Error_InvalidFilePath"); + } + + /// + /// File path must be a non-empty string. + /// + internal static string FormatError_InvalidFilePath() + => GetString("Error_InvalidFilePath"); + + /// + /// Could not parse the JSON file. Error on line number '{0}': '{1}'. + /// + internal static string Error_JSONParseError + { + get => GetString("Error_JSONParseError"); + } + + /// + /// Could not parse the JSON file. Error on line number '{0}': '{1}'. + /// + internal static string FormatError_JSONParseError(object p0, object p1) + => string.Format(CultureInfo.CurrentCulture, GetString("Error_JSONParseError"), p0, p1); + + /// + /// A duplicate key '{0}' was found. + /// + internal static string Error_KeyIsDuplicated + { + get => GetString("Error_KeyIsDuplicated"); + } + + /// + /// A duplicate key '{0}' was found. + /// + internal static string FormatError_KeyIsDuplicated(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("Error_KeyIsDuplicated"), p0); + + /// + /// Unsupported JSON token '{0}' was found. Path '{1}', line {2} position {3}. + /// + internal static string Error_UnsupportedJSONToken + { + get => GetString("Error_UnsupportedJSONToken"); + } + + /// + /// Unsupported JSON token '{0}' was found. Path '{1}', line {2} position {3}. + /// + internal static string FormatError_UnsupportedJSONToken(object p0, object p1, object p2, object p3) + => string.Format(CultureInfo.CurrentCulture, GetString("Error_UnsupportedJSONToken"), p0, p1, p2, p3); + + private static string GetString(string name, params string[] formatterNames) + { + var value = _resourceManager.GetString(name); + + System.Diagnostics.Debug.Assert(value != null); + + if (formatterNames != null) + { + for (var i = 0; i < formatterNames.Length; i++) + { + value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); + } + } + + return value; + } + } +} diff --git a/tooling/Microsoft.VisualStudio.SecretManager/Resources.resx b/tooling/Microsoft.VisualStudio.SecretManager/Resources.resx new file mode 100644 index 0000000000..1057cd7926 --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager/Resources.resx @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + File path must be a non-empty string. + + + Could not parse the JSON file. Error on line number '{0}': '{1}'. + + + A duplicate key '{0}' was found. + + + Unsupported JSON token '{0}' was found. Path '{1}', line {2} position {3}. + + + Value cannot be null or an empty string. + + + Invalid character '{0}' found in the user secrets ID at index '{1}'. + + + Could not find 'UserSecretsIdAttribute' on assembly '{0}'. +Check that the project for '{0}' has set the 'UserSecretsId' build property. +If the 'UserSecretsId' property is already set then add a reference to the Microsoft.Extensions.Configuration.UserSecrets package. + + + A secret with this name already exists. + + \ No newline at end of file diff --git a/tooling/Microsoft.VisualStudio.SecretManager/SecretManagerFactory.cs b/tooling/Microsoft.VisualStudio.SecretManager/SecretManagerFactory.cs new file mode 100644 index 0000000000..b37212e23b --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager/SecretManagerFactory.cs @@ -0,0 +1,37 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.ComponentModel.Composition; +using Microsoft.VisualStudio.ProjectSystem; +using Microsoft.VisualStudio.Shell; + +namespace Microsoft.VisualStudio.SecretManager +{ + internal class SecretManagerFactory + { + // This is capability is set in Microsoft.Extensions.Configuration.UserSecrets + private const string CapabilityName = "LocalUserSecrets"; + + private readonly Lazy _secretManager; + private readonly UnconfiguredProject _project; + + [ImportingConstructor] + public SecretManagerFactory(UnconfiguredProject project, SVsServiceProvider vsServiceProvider) + { + _project = project; + + var serviceProvider = new Lazy(() => vsServiceProvider); + + _secretManager = new Lazy(() => + { + var propertiesProvider = _project.Services.ActiveConfiguredProjectProvider.ActiveConfiguredProject.Services.ProjectPropertiesProvider; + return new ProjectLocalSecretsManager(propertiesProvider, serviceProvider); + }); + } + + [ExportVsProfferedProjectService(typeof(SVsProjectLocalSecrets))] + [AppliesTo(CapabilityName)] + public SVsProjectLocalSecrets ProjectLocalSecretsManager => _secretManager.Value; + } +} diff --git a/tooling/Microsoft.VisualStudio.SecretManager/SecretStore.cs b/tooling/Microsoft.VisualStudio.SecretManager/SecretStore.cs new file mode 100644 index 0000000000..ee10d5069c --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager/SecretStore.cs @@ -0,0 +1,169 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration.Json; +using Microsoft.Extensions.Configuration.UserSecrets; +using Microsoft.VisualStudio.Threading; +using Newtonsoft.Json.Linq; +using Task = System.Threading.Tasks.Task; + +namespace Microsoft.VisualStudio.SecretManager +{ + /// + /// Provides read and write access to the secrets.json file for local user secrets. + /// This is not thread-safe. + /// This object is meant to have a short lifetime. + /// When calling , this will overwrite the secrets.json file. It does not check for concurrency issues if another process has edited this file. + /// + internal class SecretStore : IDisposable + { + private Dictionary _secrets; + private string _fileDir; + private string _filePath; + private bool _isDirty; + private volatile bool _disposed; + + public SecretStore(string userSecretsId) + { + _filePath = PathHelper.GetSecretsPathFromSecretsId(userSecretsId); + _fileDir = Path.GetDirectoryName(_filePath); + } + + public IReadOnlyCollection ReadOnlyKeys + { + get + { + EnsureNotDisposed(); + return _secrets.Keys; + } + } + + public IReadOnlyDictionary Values + { + get + { + EnsureNotDisposed(); + + return _secrets; + } + } + + public bool ContainsKey(string key) + { + EnsureNotDisposed(); + + return _secrets.ContainsKey(key); + } + + public string Get(string name) + { + EnsureNotDisposed(); + + return _secrets[name]; + } + + public void Set(string key, string value) + { + EnsureNotDisposed(); + + _isDirty = true; + _secrets[key] = value; + } + + public bool Remove(string key) + { + EnsureNotDisposed(); + _isDirty = true; + return _secrets.Remove(key); + } + + public async Task LoadAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + await TaskScheduler.Default; + + EnsureNotDisposed(); + + string text = null; + + if (File.Exists(_filePath)) + { + text = File.ReadAllText(_filePath); + } + + _secrets = DeserializeJson(text); + } + + public async Task SaveAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + await TaskScheduler.Default; + + EnsureNotDisposed(); + + if (!_isDirty) + { + return; + } + + Directory.CreateDirectory(_fileDir); + File.WriteAllText(_filePath, Stringify(_secrets), Encoding.UTF8); + + _isDirty = false; + } + + private void EnsureNotDisposed() + { + if (_disposed) + { + throw new ObjectDisposedException(nameof(SecretStore)); + } + } + + private static string Stringify(Dictionary secrets) + { + var contents = new JObject(); + if (secrets != null) + { + foreach (var secret in secrets) + { + contents[secret.Key] = secret.Value; + } + } + + return contents.ToString(); + } + + private static Dictionary DeserializeJson(string text) + { + if (string.IsNullOrEmpty(text)) + { + return new Dictionary(StringComparer.OrdinalIgnoreCase); + } + + using (var stream = new MemoryStream()) + { + var bytes = Encoding.UTF8.GetBytes(text); + stream.Write(bytes, 0, bytes.Length); + stream.Position = 0; + + // might throw FormatException if JSON is malformed. + var data = JsonConfigurationFileParser.Parse(stream); + + return new Dictionary(data, StringComparer.OrdinalIgnoreCase); + } + } + + public void Dispose() + { + if (_disposed) return; + _disposed = true; + } + } +} diff --git a/tooling/Microsoft.VisualStudio.SecretManager/Sources/ConfigurationPath.cs b/tooling/Microsoft.VisualStudio.SecretManager/Sources/ConfigurationPath.cs new file mode 100644 index 0000000000..d4f277e0d1 --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager/Sources/ConfigurationPath.cs @@ -0,0 +1,79 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; + +namespace Microsoft.Extensions.Configuration +{ + /// + /// Utility methods and constants for manipulating Configuration paths + /// + internal static class ConfigurationPath + { + /// + /// The delimiter ":" used to separate individual keys in a path. + /// + public static readonly string KeyDelimiter = ":"; + + /// + /// Combines path segments into one path. + /// + /// The path segments to combine. + /// The combined path. + public static string Combine(params string[] pathSegments) + { + if (pathSegments == null) + { + throw new ArgumentNullException(nameof(pathSegments)); + } + return string.Join(KeyDelimiter, pathSegments); + } + + /// + /// Combines path segments into one path. + /// + /// The path segments to combine. + /// The combined path. + public static string Combine(IEnumerable pathSegments) + { + if (pathSegments == null) + { + throw new ArgumentNullException(nameof(pathSegments)); + } + return string.Join(KeyDelimiter, pathSegments); + } + + /// + /// Extracts the last path segment from the path. + /// + /// The path. + /// The last path segment of the path. + public static string GetSectionKey(string path) + { + if (string.IsNullOrEmpty(path)) + { + return path; + } + + var lastDelimiterIndex = path.LastIndexOf(KeyDelimiter, StringComparison.OrdinalIgnoreCase); + return lastDelimiterIndex == -1 ? path : path.Substring(lastDelimiterIndex + 1); + } + + /// + /// Extracts the path corresponding to the parent node for a given path. + /// + /// The path. + /// The original path minus the last individual segment found in it. Null if the original path corresponds to a top level node. + public static string GetParentPath(string path) + { + if (string.IsNullOrEmpty(path)) + { + return null; + } + + var lastDelimiterIndex = path.LastIndexOf(KeyDelimiter, StringComparison.OrdinalIgnoreCase); + return lastDelimiterIndex == -1 ? null : path.Substring(0, lastDelimiterIndex); + } + } +} diff --git a/tooling/Microsoft.VisualStudio.SecretManager/Sources/JsonConfigurationFileParser.cs b/tooling/Microsoft.VisualStudio.SecretManager/Sources/JsonConfigurationFileParser.cs new file mode 100644 index 0000000000..1cc65407c5 --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager/Sources/JsonConfigurationFileParser.cs @@ -0,0 +1,120 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using Microsoft.VisualStudio.SecretManager; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Microsoft.Extensions.Configuration.Json +{ + internal class JsonConfigurationFileParser + { + private JsonConfigurationFileParser() { } + + private readonly IDictionary _data = new SortedDictionary(StringComparer.OrdinalIgnoreCase); + private readonly Stack _context = new Stack(); + private string _currentPath; + + private JsonTextReader _reader; + + public static IDictionary Parse(Stream input) + => new JsonConfigurationFileParser().ParseStream(input); + + private IDictionary ParseStream(Stream input) + { + _data.Clear(); + _reader = new JsonTextReader(new StreamReader(input)); + _reader.DateParseHandling = DateParseHandling.None; + + var jsonConfig = JObject.Load(_reader); + + VisitJObject(jsonConfig); + + return _data; + } + + private void VisitJObject(JObject jObject) + { + foreach (var property in jObject.Properties()) + { + EnterContext(property.Name); + VisitProperty(property); + ExitContext(); + } + } + + private void VisitProperty(JProperty property) + { + VisitToken(property.Value); + } + + private void VisitToken(JToken token) + { + switch (token.Type) + { + case JTokenType.Object: + VisitJObject(token.Value()); + break; + + case JTokenType.Array: + VisitArray(token.Value()); + break; + + case JTokenType.Integer: + case JTokenType.Float: + case JTokenType.String: + case JTokenType.Boolean: + case JTokenType.Bytes: + case JTokenType.Raw: + case JTokenType.Null: + VisitPrimitive(token.Value()); + break; + + default: + throw new FormatException(Resources.FormatError_UnsupportedJSONToken( + _reader.TokenType, + _reader.Path, + _reader.LineNumber, + _reader.LinePosition)); + } + } + + private void VisitArray(JArray array) + { + for (int index = 0; index < array.Count; index++) + { + EnterContext(index.ToString()); + VisitToken(array[index]); + ExitContext(); + } + } + + private void VisitPrimitive(JValue data) + { + var key = _currentPath; + + if (_data.ContainsKey(key)) + { + throw new FormatException(Resources.FormatError_KeyIsDuplicated(key)); + } + _data[key] = data.ToString(CultureInfo.InvariantCulture); + } + + private void EnterContext(string context) + { + _context.Push(context); + _currentPath = ConfigurationPath.Combine(_context.Reverse()); + } + + private void ExitContext() + { + _context.Pop(); + _currentPath = ConfigurationPath.Combine(_context.Reverse()); + } + } +} diff --git a/tooling/Microsoft.VisualStudio.SecretManager/Sources/PathHelper.cs b/tooling/Microsoft.VisualStudio.SecretManager/Sources/PathHelper.cs new file mode 100644 index 0000000000..ae135cb5c4 --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager/Sources/PathHelper.cs @@ -0,0 +1,57 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using Microsoft.VisualStudio.SecretManager; + +namespace Microsoft.Extensions.Configuration.UserSecrets +{ + /// + /// Provides paths for user secrets configuration files. + /// + internal class PathHelper + { + internal const string SecretsFileName = "secrets.json"; + + /// + /// + /// Returns the path to the JSON file that stores user secrets. + /// + /// + /// This uses the current user profile to locate the secrets file on disk in a location outside of source control. + /// + /// + /// The user secret ID. + /// The full path to the secret file. + public static string GetSecretsPathFromSecretsId(string userSecretsId) + { + if (string.IsNullOrEmpty(userSecretsId)) + { + throw new ArgumentException(Resources.Common_StringNullOrEmpty, nameof(userSecretsId)); + } + + var badCharIndex = userSecretsId.IndexOfAny(Path.GetInvalidFileNameChars()); + if (badCharIndex != -1) + { + throw new InvalidOperationException( + string.Format( + Resources.Error_Invalid_Character_In_UserSecrets_Id, + userSecretsId[badCharIndex], + badCharIndex)); + } + + var root = Environment.GetEnvironmentVariable("APPDATA") ?? // On Windows it goes to %APPDATA%\Microsoft\UserSecrets\ + Environment.GetEnvironmentVariable("HOME"); // On Mac/Linux it goes to ~/.microsoft/usersecrets/ + + if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("APPDATA"))) + { + return Path.Combine(root, "Microsoft", "UserSecrets", userSecretsId, SecretsFileName); + } + else + { + return Path.Combine(root, ".microsoft", "usersecrets", userSecretsId, SecretsFileName); + } + } + } +} diff --git a/tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest b/tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest new file mode 100644 index 0000000000..643914b606 --- /dev/null +++ b/tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest @@ -0,0 +1,21 @@ + + + + + Microsoft.VisualStudio.SecretManager + Enables IVsProjectSecrets for ASP.NET Core projects that use Microsoft.Extensions.Configuration.UserSecrets. + + + + + + + + + + + + + + + diff --git a/version.props b/version.props index 5c4a7c32d1..4884e87b9e 100644 --- a/version.props +++ b/version.props @@ -1,9 +1,12 @@ 2.1.0 + 15.6 preview1 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final + $(VsixVersion).$(BuildNumber) + $(VsixVersion).999999 t000 $(VersionSuffix)-$(BuildNumber) From 5841ab1065d740e25214611f60e5ee3bedbbcee5 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 21 Nov 2017 15:40:13 -0800 Subject: [PATCH 0622/1029] Set minimum VS version to 15.0.26730.03 --- korebuild.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/korebuild.json b/korebuild.json index 0a2e713c08..4d59ad132a 100644 --- a/korebuild.json +++ b/korebuild.json @@ -7,7 +7,7 @@ "windows" ], "includePrerelease": true, - "minVersion": "15.4", + "minVersion": "15.0.26730.03", "requiredWorkloads": [ "Microsoft.VisualStudio.Component.VSSDK" ] From f6341853de7e6f305d3f47756a0d63f01b8cc1e1 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 21 Nov 2017 15:47:50 -0800 Subject: [PATCH 0623/1029] Replace aspnetcore-ci-dev feed with aspnetcore-dev --- build/dependencies.props | 12 ++++++------ build/repo.props | 2 +- build/sources.props | 2 +- korebuild-lock.txt | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index fa9a01ce97..9b84aca3eb 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,13 +1,13 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15549 - 2.1.0-preview1-27488 - 2.1.0-preview1-27488 - 2.1.0-preview1-27488 - 2.1.0-preview1-27488 + 2.1.0-preview1-15576 + 2.1.0-preview1-27644 + 2.1.0-preview1-27644 + 2.1.0-preview1-27644 + 2.1.0-preview1-27644 2.0.0 2.1.0-preview1-25907-02 15.3.0 diff --git a/build/repo.props b/build/repo.props index b55e651b87..07c5f08325 100644 --- a/build/repo.props +++ b/build/repo.props @@ -2,6 +2,6 @@ Internal.AspNetCore.Universe.Lineup - https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json + https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json diff --git a/build/sources.props b/build/sources.props index c03f3ddb60..9feff29d09 100644 --- a/build/sources.props +++ b/build/sources.props @@ -5,7 +5,7 @@ $(DotNetRestoreSources) $(RestoreSources); - https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json; + https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 95f4613014..1a99066b7c 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15567 -commithash:903e3104807b1bb8cddd28bdef205b1e2dc021d1 +version:2.1.0-preview1-15576 +commithash:2f3856d2ba4f659fcb9253215b83946a06794a27 From b5906870fdf158abfdaaef30eb89c6c68503cc84 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 21 Nov 2017 15:48:09 -0800 Subject: [PATCH 0624/1029] Replace aspnetcore-ci-dev feed with aspnetcore-dev --- build/dependencies.props | 8 ++++---- build/repo.props | 2 +- build/sources.props | 2 +- korebuild-lock.txt | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 3072c1d6e4..34524aaba3 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,12 +1,12 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15550 - 2.1.0-preview1-27497 + 2.1.0-preview1-15576 + 2.1.0-preview1-27644 4.4.0 - 2.1.0-preview1-27497 + 2.1.0-preview1-27644 2.0.0 2.1.0-preview1-25907-02 15.3.0 diff --git a/build/repo.props b/build/repo.props index b55e651b87..07c5f08325 100644 --- a/build/repo.props +++ b/build/repo.props @@ -2,6 +2,6 @@ Internal.AspNetCore.Universe.Lineup - https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json + https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json diff --git a/build/sources.props b/build/sources.props index c03f3ddb60..9feff29d09 100644 --- a/build/sources.props +++ b/build/sources.props @@ -5,7 +5,7 @@ $(DotNetRestoreSources) $(RestoreSources); - https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json; + https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 07a4d73a83..1a99066b7c 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15564 -commithash:1f3f14382764e06b7e691e5ee89d12a280249284 +version:2.1.0-preview1-15576 +commithash:2f3856d2ba4f659fcb9253215b83946a06794a27 From e07a19446b03076af6f57bb263d8831867de5509 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 21 Nov 2017 16:27:06 -0800 Subject: [PATCH 0625/1029] Replace aspnetcore-ci-dev feed with aspnetcore-dev --- build/dependencies.props | 4 ++-- build/repo.props | 2 +- build/sources.props | 4 ++-- korebuild-lock.txt | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 87f9d17fce..856e2d84a7 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,9 +1,9 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15573 + 2.1.0-preview1-15576 2.1.0-preview1-27644 2.1.0-preview1-27644 2.1.0-preview1-27644 diff --git a/build/repo.props b/build/repo.props index ade3bd71f7..5d7e17594c 100644 --- a/build/repo.props +++ b/build/repo.props @@ -6,6 +6,6 @@ Internal.AspNetCore.Universe.Lineup - https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json + https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json diff --git a/build/sources.props b/build/sources.props index 77203a6622..903de4e87b 100644 --- a/build/sources.props +++ b/build/sources.props @@ -1,11 +1,11 @@ - + $(DotNetRestoreSources) $(RestoreSources); - https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json; + https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; https://vside.myget.org/F/vssdk/api/v3/index.json; diff --git a/korebuild-lock.txt b/korebuild-lock.txt index e255811551..3e3fb6bbb8 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15573 -commithash:82cb53a8578610baf96ef33142797c68bae68c81 +version:2.1.0-preview1-15576 +commithash:2f3856d2ba4f659fcb9253215b83946a06794a27 From e36ed0f011fce87c163974aeba3ea5b4169471bc Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 29 Nov 2017 14:09:25 -0800 Subject: [PATCH 0626/1029] Specify runtime versions to install --- build/repo.props | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/build/repo.props b/build/repo.props index 5d7e17594c..7e2917edef 100644 --- a/build/repo.props +++ b/build/repo.props @@ -1,11 +1,15 @@  + + + + - Internal.AspNetCore.Universe.Lineup https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json + From b9867d21b35cd653730eacb6ebc56c94f618372a Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 29 Nov 2017 14:09:26 -0800 Subject: [PATCH 0627/1029] Specify runtime versions to install --- build/repo.props | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/build/repo.props b/build/repo.props index 07c5f08325..78b0ce5879 100644 --- a/build/repo.props +++ b/build/repo.props @@ -1,7 +1,14 @@  + + Internal.AspNetCore.Universe.Lineup https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json + + + + + From fe4d3c7ea9ceff78e3347d3ee40b99a12dcc9631 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 29 Nov 2017 14:09:27 -0800 Subject: [PATCH 0628/1029] Specify runtime versions to install --- build/repo.props | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/build/repo.props b/build/repo.props index 07c5f08325..78b0ce5879 100644 --- a/build/repo.props +++ b/build/repo.props @@ -1,7 +1,14 @@  + + Internal.AspNetCore.Universe.Lineup https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json + + + + + From 62a1d5c1769e0bbb6bc6ac99fd9ee97e165f540b Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Fri, 1 Dec 2017 10:23:41 -0800 Subject: [PATCH 0629/1029] Update bootstrappers --- run.ps1 | 17 +++++++++++------ run.sh | 30 +++++++++++++++++++----------- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/run.ps1 b/run.ps1 index 49c2899856..27dcf848f8 100644 --- a/run.ps1 +++ b/run.ps1 @@ -29,6 +29,9 @@ Updates KoreBuild to the latest version even if a lock file is present. .PARAMETER ConfigFile The path to the configuration file that stores values. Defaults to korebuild.json. +.PARAMETER ToolsSourceSuffix +The Suffix to append to the end of the ToolsSource. Useful for query strings in blob stores. + .PARAMETER Arguments Arguments to be passed to the command @@ -51,7 +54,7 @@ Example config file: #> [CmdletBinding(PositionalBinding = $false)] param( - [Parameter(Mandatory=$true, Position = 0)] + [Parameter(Mandatory = $true, Position = 0)] [string]$Command, [string]$Path = $PSScriptRoot, [Alias('c')] @@ -63,6 +66,7 @@ param( [Alias('u')] [switch]$Update, [string]$ConfigFile, + [string]$ToolsSourceSuffix, [Parameter(ValueFromRemainingArguments = $true)] [string[]]$Arguments ) @@ -79,7 +83,7 @@ function Get-KoreBuild { $lockFile = Join-Path $Path 'korebuild-lock.txt' if (!(Test-Path $lockFile) -or $Update) { - Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile + Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile $ToolsSourceSuffix } $version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1 @@ -96,7 +100,7 @@ function Get-KoreBuild { try { $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip" - Get-RemoteFile $remotePath $tmpfile + Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) { # Use built-in commands where possible as they are cross-plat compatible Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath @@ -124,7 +128,7 @@ function Join-Paths([string]$path, [string[]]$childPaths) { return $path } -function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) { +function Get-RemoteFile([string]$RemotePath, [string]$LocalPath, [string]$RemoteSuffix) { if ($RemotePath -notlike 'http*') { Copy-Item $RemotePath $LocalPath return @@ -134,7 +138,7 @@ function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) { while ($retries -gt 0) { $retries -= 1 try { - Invoke-WebRequest -UseBasicParsing -Uri $RemotePath -OutFile $LocalPath + Invoke-WebRequest -UseBasicParsing -Uri $($RemotePath + $RemoteSuffix) -OutFile $LocalPath return } catch { @@ -161,7 +165,8 @@ if (Test-Path $ConfigFile) { if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel } if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource} } - } catch { + } + catch { Write-Warning "$ConfigFile could not be read. Its settings will be ignored." Write-Warning $Error[0] } diff --git a/run.sh b/run.sh index c278423acc..834961fc3a 100755 --- a/run.sh +++ b/run.sh @@ -17,6 +17,7 @@ update=false repo_path="$DIR" channel='' tools_source='' +tools_source_suffix='' # # Functions @@ -29,13 +30,14 @@ __usage() { echo " ... Arguments passed to the command. Variable number of arguments allowed." echo "" echo "Options:" - echo " --verbose Show verbose output." - echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." - echo " --config-file The path to the configuration file that stores values. Defaults to korebuild.json." - echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." - echo " --path The directory to build. Defaults to the directory containing the script." - echo " -s|--tools-source|-ToolsSource The base url where build tools can be downloaded. Overrides the value from the config file." - echo " -u|--update Update to the latest KoreBuild even if the lock file is present." + echo " --verbose Show verbose output." + echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." + echo " --config-file The path to the configuration file that stores values. Defaults to korebuild.json." + echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." + echo " --path The directory to build. Defaults to the directory containing the script." + echo " -s|--tools-source|-ToolsSource The base url where build tools can be downloaded. Overrides the value from the config file." + echo " --tools-source-suffix|-ToolsSourceSuffix The suffix to append to tools-source. Useful for query strings." + echo " -u|--update Update to the latest KoreBuild even if the lock file is present." echo "" echo "Description:" echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." @@ -50,7 +52,7 @@ get_korebuild() { local version local lock_file="$repo_path/korebuild-lock.txt" if [ ! -f "$lock_file" ] || [ "$update" = true ]; then - __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" + __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" "$tools_source_suffix" fi version="$(grep 'version:*' -m 1 "$lock_file")" if [[ "$version" == '' ]]; then @@ -66,7 +68,7 @@ get_korebuild() { local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" tmpfile="$(mktemp)" echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" - if __get_remote_file "$remote_path" "$tmpfile"; then + if __get_remote_file "$remote_path" "$tmpfile" "$tools_source_suffix"; then unzip -q -d "$korebuild_path" "$tmpfile" fi rm "$tmpfile" || true @@ -98,6 +100,7 @@ __machine_has() { __get_remote_file() { local remote_path=$1 local local_path=$2 + local remote_path_suffix=$3 if [[ "$remote_path" != 'http'* ]]; then cp "$remote_path" "$local_path" @@ -106,14 +109,14 @@ __get_remote_file() { local failed=false if __machine_has wget; then - wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true + wget --tries 10 --quiet -O "$local_path" "${remote_path}${remote_path_suffix}" || failed=true else failed=true fi if [ "$failed" = true ] && __machine_has curl; then failed=false - curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true + curl --retry 10 -sSL -f --create-dirs -o "$local_path" "${remote_path}${remote_path_suffix}" || failed=true fi if [ "$failed" = true ]; then @@ -164,6 +167,11 @@ while [[ $# -gt 0 ]]; do tools_source="${1:-}" [ -z "$tools_source" ] && __usage ;; + --tools-source-suffix|-ToolsSourceSuffix) + shift + tools_source_suffix="${1:-}" + [ -z "$tools_source_suffix" ] && __usage + ;; -u|--update|-Update) update=true ;; From a928adee30db55c591eaece34de7fddd2e9ab834 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Fri, 1 Dec 2017 10:24:45 -0800 Subject: [PATCH 0630/1029] Update bootstrappers --- run.ps1 | 17 +++++++++++------ run.sh | 30 +++++++++++++++++++----------- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/run.ps1 b/run.ps1 index 49c2899856..27dcf848f8 100644 --- a/run.ps1 +++ b/run.ps1 @@ -29,6 +29,9 @@ Updates KoreBuild to the latest version even if a lock file is present. .PARAMETER ConfigFile The path to the configuration file that stores values. Defaults to korebuild.json. +.PARAMETER ToolsSourceSuffix +The Suffix to append to the end of the ToolsSource. Useful for query strings in blob stores. + .PARAMETER Arguments Arguments to be passed to the command @@ -51,7 +54,7 @@ Example config file: #> [CmdletBinding(PositionalBinding = $false)] param( - [Parameter(Mandatory=$true, Position = 0)] + [Parameter(Mandatory = $true, Position = 0)] [string]$Command, [string]$Path = $PSScriptRoot, [Alias('c')] @@ -63,6 +66,7 @@ param( [Alias('u')] [switch]$Update, [string]$ConfigFile, + [string]$ToolsSourceSuffix, [Parameter(ValueFromRemainingArguments = $true)] [string[]]$Arguments ) @@ -79,7 +83,7 @@ function Get-KoreBuild { $lockFile = Join-Path $Path 'korebuild-lock.txt' if (!(Test-Path $lockFile) -or $Update) { - Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile + Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile $ToolsSourceSuffix } $version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1 @@ -96,7 +100,7 @@ function Get-KoreBuild { try { $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip" - Get-RemoteFile $remotePath $tmpfile + Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) { # Use built-in commands where possible as they are cross-plat compatible Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath @@ -124,7 +128,7 @@ function Join-Paths([string]$path, [string[]]$childPaths) { return $path } -function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) { +function Get-RemoteFile([string]$RemotePath, [string]$LocalPath, [string]$RemoteSuffix) { if ($RemotePath -notlike 'http*') { Copy-Item $RemotePath $LocalPath return @@ -134,7 +138,7 @@ function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) { while ($retries -gt 0) { $retries -= 1 try { - Invoke-WebRequest -UseBasicParsing -Uri $RemotePath -OutFile $LocalPath + Invoke-WebRequest -UseBasicParsing -Uri $($RemotePath + $RemoteSuffix) -OutFile $LocalPath return } catch { @@ -161,7 +165,8 @@ if (Test-Path $ConfigFile) { if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel } if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource} } - } catch { + } + catch { Write-Warning "$ConfigFile could not be read. Its settings will be ignored." Write-Warning $Error[0] } diff --git a/run.sh b/run.sh index c278423acc..834961fc3a 100755 --- a/run.sh +++ b/run.sh @@ -17,6 +17,7 @@ update=false repo_path="$DIR" channel='' tools_source='' +tools_source_suffix='' # # Functions @@ -29,13 +30,14 @@ __usage() { echo " ... Arguments passed to the command. Variable number of arguments allowed." echo "" echo "Options:" - echo " --verbose Show verbose output." - echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." - echo " --config-file The path to the configuration file that stores values. Defaults to korebuild.json." - echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." - echo " --path The directory to build. Defaults to the directory containing the script." - echo " -s|--tools-source|-ToolsSource The base url where build tools can be downloaded. Overrides the value from the config file." - echo " -u|--update Update to the latest KoreBuild even if the lock file is present." + echo " --verbose Show verbose output." + echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." + echo " --config-file The path to the configuration file that stores values. Defaults to korebuild.json." + echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." + echo " --path The directory to build. Defaults to the directory containing the script." + echo " -s|--tools-source|-ToolsSource The base url where build tools can be downloaded. Overrides the value from the config file." + echo " --tools-source-suffix|-ToolsSourceSuffix The suffix to append to tools-source. Useful for query strings." + echo " -u|--update Update to the latest KoreBuild even if the lock file is present." echo "" echo "Description:" echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." @@ -50,7 +52,7 @@ get_korebuild() { local version local lock_file="$repo_path/korebuild-lock.txt" if [ ! -f "$lock_file" ] || [ "$update" = true ]; then - __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" + __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" "$tools_source_suffix" fi version="$(grep 'version:*' -m 1 "$lock_file")" if [[ "$version" == '' ]]; then @@ -66,7 +68,7 @@ get_korebuild() { local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" tmpfile="$(mktemp)" echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" - if __get_remote_file "$remote_path" "$tmpfile"; then + if __get_remote_file "$remote_path" "$tmpfile" "$tools_source_suffix"; then unzip -q -d "$korebuild_path" "$tmpfile" fi rm "$tmpfile" || true @@ -98,6 +100,7 @@ __machine_has() { __get_remote_file() { local remote_path=$1 local local_path=$2 + local remote_path_suffix=$3 if [[ "$remote_path" != 'http'* ]]; then cp "$remote_path" "$local_path" @@ -106,14 +109,14 @@ __get_remote_file() { local failed=false if __machine_has wget; then - wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true + wget --tries 10 --quiet -O "$local_path" "${remote_path}${remote_path_suffix}" || failed=true else failed=true fi if [ "$failed" = true ] && __machine_has curl; then failed=false - curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true + curl --retry 10 -sSL -f --create-dirs -o "$local_path" "${remote_path}${remote_path_suffix}" || failed=true fi if [ "$failed" = true ]; then @@ -164,6 +167,11 @@ while [[ $# -gt 0 ]]; do tools_source="${1:-}" [ -z "$tools_source" ] && __usage ;; + --tools-source-suffix|-ToolsSourceSuffix) + shift + tools_source_suffix="${1:-}" + [ -z "$tools_source_suffix" ] && __usage + ;; -u|--update|-Update) update=true ;; From 03130b55f4c89fe80a980ba5e34fd74a1fe4435e Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Fri, 1 Dec 2017 10:22:53 -0800 Subject: [PATCH 0631/1029] Update bootstrappers --- run.ps1 | 17 +++++++++++------ run.sh | 30 +++++++++++++++++++----------- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/run.ps1 b/run.ps1 index 49c2899856..27dcf848f8 100644 --- a/run.ps1 +++ b/run.ps1 @@ -29,6 +29,9 @@ Updates KoreBuild to the latest version even if a lock file is present. .PARAMETER ConfigFile The path to the configuration file that stores values. Defaults to korebuild.json. +.PARAMETER ToolsSourceSuffix +The Suffix to append to the end of the ToolsSource. Useful for query strings in blob stores. + .PARAMETER Arguments Arguments to be passed to the command @@ -51,7 +54,7 @@ Example config file: #> [CmdletBinding(PositionalBinding = $false)] param( - [Parameter(Mandatory=$true, Position = 0)] + [Parameter(Mandatory = $true, Position = 0)] [string]$Command, [string]$Path = $PSScriptRoot, [Alias('c')] @@ -63,6 +66,7 @@ param( [Alias('u')] [switch]$Update, [string]$ConfigFile, + [string]$ToolsSourceSuffix, [Parameter(ValueFromRemainingArguments = $true)] [string[]]$Arguments ) @@ -79,7 +83,7 @@ function Get-KoreBuild { $lockFile = Join-Path $Path 'korebuild-lock.txt' if (!(Test-Path $lockFile) -or $Update) { - Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile + Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile $ToolsSourceSuffix } $version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1 @@ -96,7 +100,7 @@ function Get-KoreBuild { try { $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip" - Get-RemoteFile $remotePath $tmpfile + Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) { # Use built-in commands where possible as they are cross-plat compatible Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath @@ -124,7 +128,7 @@ function Join-Paths([string]$path, [string[]]$childPaths) { return $path } -function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) { +function Get-RemoteFile([string]$RemotePath, [string]$LocalPath, [string]$RemoteSuffix) { if ($RemotePath -notlike 'http*') { Copy-Item $RemotePath $LocalPath return @@ -134,7 +138,7 @@ function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) { while ($retries -gt 0) { $retries -= 1 try { - Invoke-WebRequest -UseBasicParsing -Uri $RemotePath -OutFile $LocalPath + Invoke-WebRequest -UseBasicParsing -Uri $($RemotePath + $RemoteSuffix) -OutFile $LocalPath return } catch { @@ -161,7 +165,8 @@ if (Test-Path $ConfigFile) { if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel } if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource} } - } catch { + } + catch { Write-Warning "$ConfigFile could not be read. Its settings will be ignored." Write-Warning $Error[0] } diff --git a/run.sh b/run.sh index c278423acc..834961fc3a 100755 --- a/run.sh +++ b/run.sh @@ -17,6 +17,7 @@ update=false repo_path="$DIR" channel='' tools_source='' +tools_source_suffix='' # # Functions @@ -29,13 +30,14 @@ __usage() { echo " ... Arguments passed to the command. Variable number of arguments allowed." echo "" echo "Options:" - echo " --verbose Show verbose output." - echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." - echo " --config-file The path to the configuration file that stores values. Defaults to korebuild.json." - echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." - echo " --path The directory to build. Defaults to the directory containing the script." - echo " -s|--tools-source|-ToolsSource The base url where build tools can be downloaded. Overrides the value from the config file." - echo " -u|--update Update to the latest KoreBuild even if the lock file is present." + echo " --verbose Show verbose output." + echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." + echo " --config-file The path to the configuration file that stores values. Defaults to korebuild.json." + echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." + echo " --path The directory to build. Defaults to the directory containing the script." + echo " -s|--tools-source|-ToolsSource The base url where build tools can be downloaded. Overrides the value from the config file." + echo " --tools-source-suffix|-ToolsSourceSuffix The suffix to append to tools-source. Useful for query strings." + echo " -u|--update Update to the latest KoreBuild even if the lock file is present." echo "" echo "Description:" echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." @@ -50,7 +52,7 @@ get_korebuild() { local version local lock_file="$repo_path/korebuild-lock.txt" if [ ! -f "$lock_file" ] || [ "$update" = true ]; then - __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" + __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" "$tools_source_suffix" fi version="$(grep 'version:*' -m 1 "$lock_file")" if [[ "$version" == '' ]]; then @@ -66,7 +68,7 @@ get_korebuild() { local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" tmpfile="$(mktemp)" echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" - if __get_remote_file "$remote_path" "$tmpfile"; then + if __get_remote_file "$remote_path" "$tmpfile" "$tools_source_suffix"; then unzip -q -d "$korebuild_path" "$tmpfile" fi rm "$tmpfile" || true @@ -98,6 +100,7 @@ __machine_has() { __get_remote_file() { local remote_path=$1 local local_path=$2 + local remote_path_suffix=$3 if [[ "$remote_path" != 'http'* ]]; then cp "$remote_path" "$local_path" @@ -106,14 +109,14 @@ __get_remote_file() { local failed=false if __machine_has wget; then - wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true + wget --tries 10 --quiet -O "$local_path" "${remote_path}${remote_path_suffix}" || failed=true else failed=true fi if [ "$failed" = true ] && __machine_has curl; then failed=false - curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true + curl --retry 10 -sSL -f --create-dirs -o "$local_path" "${remote_path}${remote_path_suffix}" || failed=true fi if [ "$failed" = true ]; then @@ -164,6 +167,11 @@ while [[ $# -gt 0 ]]; do tools_source="${1:-}" [ -z "$tools_source" ] && __usage ;; + --tools-source-suffix|-ToolsSourceSuffix) + shift + tools_source_suffix="${1:-}" + [ -z "$tools_source_suffix" ] && __usage + ;; -u|--update|-Update) update=true ;; From b434d49304c7239122032ead27631d06ed101fe2 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 10 Dec 2017 12:26:15 -0800 Subject: [PATCH 0632/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 22 +++++++++++----------- korebuild-lock.txt | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 856e2d84a7..9c732c970d 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,20 +3,20 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15576 - 2.1.0-preview1-27644 - 2.1.0-preview1-27644 - 2.1.0-preview1-27644 - 2.1.0-preview1-27644 - 2.1.0-preview1-27644 + 2.1.0-preview1-15618 + 2.1.0-preview1-27773 + 2.1.0-preview1-27773 + 2.1.0-preview1-27773 + 2.1.0-preview1-27773 + 2.1.0-preview1-27773 2.0.0 - 2.1.0-preview1-25907-02 + 2.1.0-preview1-25915-01 15.3.0 - 4.4.0 - 4.4.0 + 4.5.0-preview1-25914-04 + 4.5.0-preview1-25914-04 9.0.1 - 2.3.0 - 2.3.0 + 2.3.1 + 2.3.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 3e3fb6bbb8..c4715de5c1 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15576 -commithash:2f3856d2ba4f659fcb9253215b83946a06794a27 +version:2.1.0-preview1-15618 +commithash:00ce1383114015fe89b221146036e59e6bc11219 From 1760bab38fc7e601b9165f6dc60268b3739b7863 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 10 Dec 2017 12:48:34 -0800 Subject: [PATCH 0633/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 9b84aca3eb..00ce6f22db 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15576 - 2.1.0-preview1-27644 - 2.1.0-preview1-27644 - 2.1.0-preview1-27644 - 2.1.0-preview1-27644 + 2.1.0-preview1-15618 + 2.1.0-preview1-27773 + 2.1.0-preview1-27773 + 2.1.0-preview1-27773 + 2.1.0-preview1-27773 2.0.0 - 2.1.0-preview1-25907-02 + 2.1.0-preview1-25915-01 15.3.0 - 4.4.0 - 2.3.0 - 2.3.0 + 4.5.0-preview1-25914-04 + 2.3.1 + 2.3.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 1a99066b7c..e7cce93009 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15576 -commithash:2f3856d2ba4f659fcb9253215b83946a06794a27 +version:2.1.0-preview1-15618 +commithash:00ce1383114015fe89b221146036e59e6bc11219 From 84194387a22ae103166fe5d59a0b30f335f616fb Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 10 Dec 2017 13:01:26 -0800 Subject: [PATCH 0634/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 16 ++++++++-------- korebuild-lock.txt | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 34524aaba3..1808025509 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,18 +3,18 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15576 - 2.1.0-preview1-27644 - 4.4.0 - 2.1.0-preview1-27644 + 2.1.0-preview1-15618 + 2.1.0-preview1-27773 + 4.5.0-preview1-25914-04 + 2.1.0-preview1-27773 2.0.0 - 2.1.0-preview1-25907-02 + 2.1.0-preview1-25915-01 15.3.0 4.7.49 10.0.1 - 0.7.0 - 2.3.0 - 2.3.0 + 0.8.0 + 2.3.1 + 2.3.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 1a99066b7c..e7cce93009 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15576 -commithash:2f3856d2ba4f659fcb9253215b83946a06794a27 +version:2.1.0-preview1-15618 +commithash:00ce1383114015fe89b221146036e59e6bc11219 From 1f3f010f873f22bfdaa23d6855ad3750a4058dfc Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 12 Dec 2017 14:37:42 -0800 Subject: [PATCH 0635/1029] Upgrade CLI tools to .NET Core 2.1 --- Directory.Build.props | 4 ++++ Directory.Build.targets | 1 - NuGetPackageVerifier.json | 2 +- .../LaunchAnyCommand/LaunchAnyCommand.csproj | 2 +- .../WatchJavascriptFiles.csproj | 2 +- .../WatchMultipleProjects/Test/Test.csproj | 2 +- .../WatchMultipleProjects/Web/Web.csproj | 2 +- .../WatchMultipleProjects/watch.csproj | 2 +- ...pNetCore.DeveloperCertificates.Tools.csproj | 2 +- ...pNetCore.DeveloperCertificates.XPlat.csproj | 3 +-- .../Microsoft.DotNet.Watcher.Tools.csproj | 2 +- ...t.Extensions.Caching.SqlConfig.Tools.csproj | 2 +- ...osoft.Extensions.SecretManager.Tools.csproj | 2 +- .../FileWatcherTests.cs | 18 ++++++++++++------ ...DotNet.Watcher.Tools.FunctionalTests.csproj | 2 +- .../AppWithDeps/AppWithDeps.csproj | 2 +- .../GlobbingApp/GlobbingApp.csproj | 2 +- .../KitchenSink/KitchenSink.csproj | 2 +- .../TestProjects/NoDepsApp/NoDepsApp.csproj | 2 +- ...Microsoft.DotNet.Watcher.Tools.Tests.csproj | 2 +- .../MsBuildFileSetFactoryTest.cs | 10 ++++------ ...Extensions.SecretManager.Tools.Tests.csproj | 2 +- .../UserSecretsTestFixture.cs | 2 +- 23 files changed, 39 insertions(+), 33 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 29ae42a346..1afa691c5f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,4 +1,8 @@  + + diff --git a/Directory.Build.targets b/Directory.Build.targets index 894b1d0cf8..c3d61be3b4 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,6 +1,5 @@  - $(MicrosoftNETCoreApp20PackageVersion) $(MicrosoftNETCoreApp21PackageVersion) diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index c279df4745..6979dfba80 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -27,7 +27,7 @@ "Microsoft.AspNetCore.DeveloperCertificates.XPlat": { "Exclusions": { "DOC_MISSING": { - "lib/netcoreapp2.0/Microsoft.AspNetCore.DeveloperCertificates.XPlat.dll": "Enter justification" + "lib/netcoreapp2.1/Microsoft.AspNetCore.DeveloperCertificates.XPlat.dll": "Docs not required to shipoob package" } } } diff --git a/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj b/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj index 39dea69c5f..96438bfa81 100644 --- a/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj +++ b/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj @@ -1,6 +1,6 @@ - netcoreapp2.0 + netcoreapp2.1 diff --git a/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj b/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj index f45eb26ccf..65fd51d8d7 100755 --- a/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj +++ b/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj @@ -1,7 +1,7 @@ - netcoreapp2.0 + netcoreapp2.1 diff --git a/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj b/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj index 694a96f3f9..0ffd10766a 100755 --- a/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj +++ b/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj @@ -1,7 +1,7 @@ - netcoreapp2.0 + netcoreapp2.1 diff --git a/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj b/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj index 0bc2f3e71b..ec2a93ed3a 100755 --- a/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj +++ b/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj @@ -1,7 +1,7 @@ - netcoreapp2.0 + netcoreapp2.1 diff --git a/samples/dotnet-watch/WatchMultipleProjects/watch.csproj b/samples/dotnet-watch/WatchMultipleProjects/watch.csproj index d34686cbbc..b0ab41a539 100644 --- a/samples/dotnet-watch/WatchMultipleProjects/watch.csproj +++ b/samples/dotnet-watch/WatchMultipleProjects/watch.csproj @@ -1,6 +1,6 @@ - netcoreapp2.0 + netcoreapp2.1 false diff --git a/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj b/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj index 36ba69485e..c2fd9283f1 100644 --- a/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj +++ b/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj @@ -1,7 +1,7 @@ - netcoreapp2.0 + netcoreapp2.1 dotnet-developercertificates exe Command line tool to generate certificates used in ASP.NET Core during development. diff --git a/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj b/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj index 04bf6946c9..81c90a297c 100644 --- a/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj +++ b/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj @@ -1,11 +1,10 @@ - netcoreapp2.0 + netcoreapp2.1 Package for the CLI first run experience. $(DefineConstants);XPLAT aspnet;cli - false diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj index 294943581a..5c79f6f652 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj +++ b/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj @@ -1,7 +1,7 @@  - netcoreapp2.0 + netcoreapp2.1 dotnet-watch exe Command line tool to watch for source file changes during development and restart the dotnet command. diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj index f8ea155986..d3ce82febe 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj +++ b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj @@ -1,7 +1,7 @@  - netcoreapp2.0 + netcoreapp2.1 dotnet-sql-cache exe Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching. diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj index 3dc0507021..ef8adb296f 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj +++ b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj @@ -1,7 +1,7 @@  - netcoreapp2.0 + netcoreapp2.1 dotnet-user-secrets exe Command line tool to manage user secrets for Microsoft.Extensions.Configuration. diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs index 4df16166a0..9f1cc132bc 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs @@ -292,16 +292,16 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { changedEv.Set(); } - catch(ObjectDisposedException) + catch (ObjectDisposedException) { // There's a known race condition here: // even though we tell the watcher to stop raising events and we unsubscribe the handler - // there might be in-flight events that will still process. Since we dispose the reset + // there might be in-flight events that will still process. Since we dispose the reset // event, this code will fail if the handler executes after Dispose happens. There's no // better way to guard against it than catch because we cannot check if the object is // disposed nor can we check if there are any in-flight events. // This is actually a known issue in the corefx file watcher. It can trigger multiple - // times for the same item. + // times for the same item. } }; @@ -316,8 +316,10 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests var testFileFullPath = Path.Combine(dir, "foo1"); File.WriteAllText(testFileFullPath, string.Empty); Assert.True(changedEv.WaitOne(DefaultTimeout)); - Assert.Equal(testFileFullPath, filesChanged.Single()); + var fileChanged = Assert.Single(filesChanged); + Assert.Equal(testFileFullPath, fileChanged); filesChanged.Clear(); + changedEv.Reset(); // On Unix the file write time is in 1s increments; // if we don't wait, there's a chance that the polling @@ -327,8 +329,10 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests testFileFullPath = Path.Combine(dir, "foo2"); File.WriteAllText(testFileFullPath, string.Empty); Assert.True(changedEv.WaitOne(DefaultTimeout)); - Assert.Equal(testFileFullPath, filesChanged.Single()); + fileChanged = Assert.Single(filesChanged); + Assert.Equal(testFileFullPath, fileChanged); filesChanged.Clear(); + changedEv.Reset(); // On Unix the file write time is in 1s increments; // if we don't wait, there's a chance that the polling @@ -340,6 +344,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests Assert.True(changedEv.WaitOne(DefaultTimeout)); Assert.Equal(testFileFullPath, filesChanged.Single()); filesChanged.Clear(); + changedEv.Reset(); // On Unix the file write time is in 1s increments; // if we don't wait, there's a chance that the polling @@ -348,7 +353,8 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests File.WriteAllText(testFileFullPath, string.Empty); Assert.True(changedEv.WaitOne(DefaultTimeout)); - Assert.Equal(testFileFullPath, filesChanged.Single()); + fileChanged = Assert.Single(filesChanged); + Assert.Equal(testFileFullPath, fileChanged); watcher.EnableRaisingEvents = false; watcher.OnFileChange -= handler; diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj index 8d2c4713c8..06434ae064 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj @@ -1,7 +1,7 @@  - netcoreapp2.0 + netcoreapp2.1 $(DefaultItemExcludes);TestProjects\**\* diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj index 3a4f75ddc6..76d7446452 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj @@ -1,7 +1,7 @@ - netcoreapp2.0 + netcoreapp2.1 exe diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj index d18211405e..60645a49da 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj @@ -1,7 +1,7 @@  - netcoreapp2.0 + netcoreapp2.1 exe false diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj index aeb186ac39..699071e138 100755 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj @@ -9,7 +9,7 @@ Exe - netcoreapp2.0 + netcoreapp2.1 diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj index 161a1c9290..86e88b8b95 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj @@ -1,7 +1,7 @@  - netcoreapp2.0 + netcoreapp2.1 exe diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj index c005f40d88..0ace1e9148 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj @@ -1,7 +1,7 @@  - netcoreapp2.0 + netcoreapp2.1 diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs b/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs index dde03d31ab..572b021f80 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.Testing; using Microsoft.DotNet.Watcher.Internal; using Microsoft.Extensions.Tools.Internal; using Xunit; @@ -274,12 +275,9 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests private async Task GetFileSet(MsBuildFileSetFactory filesetFactory) { _tempDir.Create(); - var createTask = filesetFactory.CreateAsync(CancellationToken.None); - var finished = await Task.WhenAny(createTask, Task.Delay(TimeSpan.FromSeconds(10))); - - Assert.Same(createTask, finished); - Assert.NotNull(createTask.Result); - return createTask.Result; + return await filesetFactory + .CreateAsync(CancellationToken.None) + .TimeoutAfter(TimeSpan.FromSeconds(30)); } public void Dispose() diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj index 67ace090c0..cd5d68d140 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj @@ -1,7 +1,7 @@  - netcoreapp2.0 + netcoreapp2.1 diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs b/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs index 36a9e524ae..14e62805bc 100644 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs +++ b/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs @@ -35,7 +35,7 @@ namespace Microsoft.Extensions.Configuration.UserSecrets.Tests private const string ProjectTemplate = @" Exe - netcoreapp2.0 + netcoreapp2.1 {0} false From 2aaed280542978b61fb6fcc3d982eb092730d6ae Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 12 Dec 2017 15:56:48 -0800 Subject: [PATCH 0636/1029] Rename dotnet-developercertificates to dotnet-dev-certs (#371) --- .../Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj b/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj index c2fd9283f1..53cc86f701 100644 --- a/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj +++ b/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj @@ -2,7 +2,7 @@ netcoreapp2.1 - dotnet-developercertificates + dotnet-dev-certs exe Command line tool to generate certificates used in ASP.NET Core during development. Microsoft.AspNetCore.DeveloperCertificates.Tools From 62ed760da8a3c90e30677daa047038edec4794df Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Wed, 13 Dec 2017 20:31:51 +0000 Subject: [PATCH 0637/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 9c732c970d..6d05b05caf 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15618 - 2.1.0-preview1-27773 - 2.1.0-preview1-27773 - 2.1.0-preview1-27773 - 2.1.0-preview1-27773 - 2.1.0-preview1-27773 + 2.1.0-preview1-15626 + 2.1.0-preview1-27807 + 2.1.0-preview1-27807 + 2.1.0-preview1-27807 + 2.1.0-preview1-27807 + 2.1.0-preview1-27807 2.0.0 - 2.1.0-preview1-25915-01 + 2.1.0-preview1-26008-01 15.3.0 - 4.5.0-preview1-25914-04 - 4.5.0-preview1-25914-04 + 4.5.0-preview1-26006-06 + 4.5.0-preview1-26006-06 9.0.1 2.3.1 2.3.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index c4715de5c1..8203150442 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15618 -commithash:00ce1383114015fe89b221146036e59e6bc11219 +version:2.1.0-preview1-15626 +commithash:fd6410e9c90c428bc01238372303ad09cb9ec889 From d3c71cce948c400c40c26f818b2bec177ba9827c Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Wed, 13 Dec 2017 20:49:48 +0000 Subject: [PATCH 0638/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 00ce6f22db..9333aa7bd3 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,15 +3,15 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15618 - 2.1.0-preview1-27773 - 2.1.0-preview1-27773 - 2.1.0-preview1-27773 - 2.1.0-preview1-27773 + 2.1.0-preview1-15626 + 2.1.0-preview1-27807 + 2.1.0-preview1-27807 + 2.1.0-preview1-27807 + 2.1.0-preview1-27807 2.0.0 - 2.1.0-preview1-25915-01 + 2.1.0-preview1-26008-01 15.3.0 - 4.5.0-preview1-25914-04 + 4.5.0-preview1-26006-06 2.3.1 2.3.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index e7cce93009..8d52a6128c 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15618 -commithash:00ce1383114015fe89b221146036e59e6bc11219 +version:2.1.0-preview1-15626 +commithash:fd6410e9c90c428bc01238372303ad09cb9ec889 From 77de59903060c225b31ee8fb1ef0885d13a6cdf9 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Wed, 13 Dec 2017 21:01:02 +0000 Subject: [PATCH 0639/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 1808025509..2e1d5008e8 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15618 - 2.1.0-preview1-27773 - 4.5.0-preview1-25914-04 - 2.1.0-preview1-27773 + 2.1.0-preview1-15626 + 2.1.0-preview1-27807 + 4.5.0-preview1-26006-06 + 2.1.0-preview1-27807 2.0.0 - 2.1.0-preview1-25915-01 + 2.1.0-preview1-26008-01 15.3.0 4.7.49 10.0.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index e7cce93009..8d52a6128c 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15618 -commithash:00ce1383114015fe89b221146036e59e6bc11219 +version:2.1.0-preview1-15626 +commithash:fd6410e9c90c428bc01238372303ad09cb9ec889 From 1d427b4065d2dcb421b161b3c1abe4dd29796639 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 17 Dec 2017 12:35:17 -0800 Subject: [PATCH 0640/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 2e1d5008e8..ab34d96520 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,11 +4,11 @@ 2.1.0-preview1-15626 - 2.1.0-preview1-27807 - 4.5.0-preview1-26006-06 - 2.1.0-preview1-27807 + 2.1.0-preview1-27838 + 4.5.0-preview1-26014-03 + 2.1.0-preview1-27838 2.0.0 - 2.1.0-preview1-26008-01 + 2.1.0-preview1-26015-01 15.3.0 4.7.49 10.0.1 From 888e4e0724f136b8b944544fadf2c46576cbd5e1 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Mon, 18 Dec 2017 16:44:45 -0800 Subject: [PATCH 0641/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 6d05b05caf..f10c6259ec 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,16 +4,16 @@ 2.1.0-preview1-15626 - 2.1.0-preview1-27807 - 2.1.0-preview1-27807 - 2.1.0-preview1-27807 - 2.1.0-preview1-27807 - 2.1.0-preview1-27807 + 2.1.0-preview1-27849 + 2.1.0-preview1-27849 + 2.1.0-preview1-27849 + 2.1.0-preview1-27849 + 2.1.0-preview1-27849 2.0.0 - 2.1.0-preview1-26008-01 + 2.1.0-preview1-26016-05 15.3.0 - 4.5.0-preview1-26006-06 - 4.5.0-preview1-26006-06 + 4.5.0-preview1-26016-05 + 4.5.0-preview1-26016-05 9.0.1 2.3.1 2.3.1 From d3fa87c6c5fd0e362d758da44c6423283a9e7145 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Mon, 18 Dec 2017 17:04:20 -0800 Subject: [PATCH 0642/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 9333aa7bd3..766fe3e033 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,14 +4,14 @@ 2.1.0-preview1-15626 - 2.1.0-preview1-27807 - 2.1.0-preview1-27807 - 2.1.0-preview1-27807 - 2.1.0-preview1-27807 + 2.1.0-preview1-27849 + 2.1.0-preview1-27849 + 2.1.0-preview1-27849 + 2.1.0-preview1-27849 2.0.0 - 2.1.0-preview1-26008-01 + 2.1.0-preview1-26016-05 15.3.0 - 4.5.0-preview1-26006-06 + 4.5.0-preview1-26016-05 2.3.1 2.3.1 From a0316af7b207cb94372db1ab727b97ea720651e8 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Mon, 18 Dec 2017 17:15:24 -0800 Subject: [PATCH 0643/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index ab34d96520..06cca20623 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,11 +4,11 @@ 2.1.0-preview1-15626 - 2.1.0-preview1-27838 - 4.5.0-preview1-26014-03 - 2.1.0-preview1-27838 + 2.1.0-preview1-27849 + 4.5.0-preview1-26016-05 + 2.1.0-preview1-27849 2.0.0 - 2.1.0-preview1-26015-01 + 2.1.0-preview1-26016-05 15.3.0 4.7.49 10.0.1 From aac7ad71e1b5520d5147704e02b19669ce1ff873 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 20 Dec 2017 11:29:46 -0800 Subject: [PATCH 0644/1029] Update dependencies and add the VSIX to the bill of materials --- build/VSIX.targets | 21 +++++++++++++++------ build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/build/VSIX.targets b/build/VSIX.targets index e679e98e42..b066b0a8de 100644 --- a/build/VSIX.targets +++ b/build/VSIX.targets @@ -3,10 +3,10 @@ true $(RestoreDependsOn);RestoreVSIX $(PackageDependsOn);PackageVSIX + $(GetArtifactInfoDependsOn);GetVSIXArtifactInfo Microsoft.VisualStudio.SecretManager $(RepositoryRoot)tooling\$(VSIXName)\$(VSIXName).csproj $(BuildDir)$(VSIXName).vsix - $(ArtifactsDir)msbuild\ + + + + VsixPackage + $(PackageVersion) + + + + - $(MSBuildArtifactsDir)vsix-restore.rsp + $(LogOutputDir)vsix-restore.rsp @@ -37,7 +46,7 @@ - + - $(MSBuildArtifactsDir)vsix.log - $(MSBuildArtifactsDir)vsix-build.rsp + $(LogOutputDir)vsix.log + $(LogOutputDir)vsix-build.rsp @@ -72,7 +81,7 @@ /p:PackageReferencePropsPath=$(MSBuildThisFileDirectory)VSIX.props;" /> - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15626 - 2.1.0-preview1-27849 - 2.1.0-preview1-27849 - 2.1.0-preview1-27849 - 2.1.0-preview1-27849 - 2.1.0-preview1-27849 + 2.1.0-preview1-15639 + 2.1.0-preview1-27871 + 2.1.0-preview1-27871 + 2.1.0-preview1-27871 + 2.1.0-preview1-27871 + 2.1.0-preview1-27871 2.0.0 2.1.0-preview1-26016-05 15.3.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 8203150442..51ae52c049 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15626 -commithash:fd6410e9c90c428bc01238372303ad09cb9ec889 +version:2.1.0-preview1-15639 +commithash:231066d459f3c86a94b5bdcd197a3c2e4992a7ff From 57fc6833fe95f4be0053939eac70d4e99e10ff00 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 20 Dec 2017 12:54:47 -0800 Subject: [PATCH 0645/1029] Mark the SecretManager VSIX as IsProductComponent=true - Update extension to be per-machine, and make installation folder more-specific - Update the VSIX identity - Set the artifact category as shipoob --- build/VSIX.targets | 11 +++++++++++ build/repo.props | 1 + .../Microsoft.VisualStudio.SecretManager.csproj | 6 ++++++ .../source.extension.vsixmanifest | 7 ++++--- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/build/VSIX.targets b/build/VSIX.targets index b066b0a8de..d343689ae6 100644 --- a/build/VSIX.targets +++ b/build/VSIX.targets @@ -7,6 +7,8 @@ Microsoft.VisualStudio.SecretManager $(RepositoryRoot)tooling\$(VSIXName)\$(VSIXName).csproj $(BuildDir)$(VSIXName).vsix + $(BuildDir)$(VSIXName).json + shipoob VsixPackage $(PackageVersion) + $(VSIXArtifactCategory) + $(VSIXName) + + + + JsonFile + $(VSIXArtifactCategory) + $(VSIXName).json + $(VSIXName) diff --git a/build/repo.props b/build/repo.props index 7e2917edef..1be3632130 100644 --- a/build/repo.props +++ b/build/repo.props @@ -6,6 +6,7 @@ + Internal.AspNetCore.Universe.Lineup diff --git a/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj b/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj index bfd99e46b7..dfe6fa36bd 100644 --- a/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj +++ b/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj @@ -3,6 +3,12 @@ 15.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + CommonExtensions + Microsoft\ASP.NET Core\UserSecrets + true + False False False diff --git a/tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest b/tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest index 643914b606..7edf1295e0 100644 --- a/tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest +++ b/tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest @@ -1,11 +1,12 @@ - - Microsoft.VisualStudio.SecretManager + + ASP.NET Core User Secrets Extension + Microsoft.VisualStudio.SecretManager Enables IVsProjectSecrets for ASP.NET Core projects that use Microsoft.Extensions.Configuration.UserSecrets. - + From 3c20e7c45beb5d45547b549964a3da83b2e8303e Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 20 Dec 2017 13:50:53 -0800 Subject: [PATCH 0646/1029] Update the artifact type for the JSON manifest file [ci skip] --- build/VSIX.targets | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/VSIX.targets b/build/VSIX.targets index d343689ae6..a22b83f020 100644 --- a/build/VSIX.targets +++ b/build/VSIX.targets @@ -26,9 +26,9 @@ - JsonFile + VsixPackageManifestFile $(VSIXArtifactCategory) - $(VSIXName).json + $(VSIXName).vsix $(VSIXName) From d81f23e1599cd7c464ae51c3d5605c37b0421450 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 28 Dec 2017 15:45:45 -0800 Subject: [PATCH 0647/1029] Update to build tools 2.1.0-preview1-15651 --- Directory.Build.props | 1 + build/VSIX.targets | 3 +++ korebuild-lock.txt | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 1afa691c5f..29d623306f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -15,6 +15,7 @@ $(MSBuildThisFileDirectory)build\Key.snk true true + Microsoft true diff --git a/build/VSIX.targets b/build/VSIX.targets index a22b83f020..eade7e4414 100644 --- a/build/VSIX.targets +++ b/build/VSIX.targets @@ -31,6 +31,9 @@ $(VSIXName).vsix $(VSIXName) + + + diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 51ae52c049..09bd77accb 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15639 -commithash:231066d459f3c86a94b5bdcd197a3c2e4992a7ff +version:2.1.0-preview1-15651 +commithash:ebf2365121c2c6a6a0fbfa9b0f37bb5effc89323 From 261b27b70027871143540af10a5cba57ce07ff97 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 29 Dec 2017 08:41:21 -0800 Subject: [PATCH 0648/1029] Port CLI tools to be dotnet global tools - Rename package IDs to dotnet-watch, dotnet-user-secrets, and dotnet-sql-cache - Change packaging layout to support dotnet-install-tool - Change package metadata to DotnetTool - Drop support for DotNetCliToolReference (those will continue to be available under previous package ID's) - Rename project files and folders --- .gitignore | 1 + DotNetTools.sln | 14 ++--- NuGetPackageVerifier.json | 51 +++++++++++++++---- README.md | 39 +++++++------- build/VSIX.targets | 4 +- .../LaunchAnyCommand/LaunchAnyCommand.csproj | 2 - .../dotnet-watch/LaunchAnyCommand/README.md | 1 - samples/dotnet-watch/README.md | 2 +- .../WatchJavascriptFiles/README.md | 1 - .../WatchJavascriptFiles.csproj | 1 - .../WatchMultipleProjects/README.md | 3 +- .../WatchMultipleProjects/watch.csproj | 2 - src/Directory.Build.props | 9 ++++ src/Directory.Build.targets | 6 +++ src/DotnetTool.props | 16 ++++++ .../prefercliruntime | 0 ...NetCore.DeveloperCertificates.XPlat.csproj | 3 ++ .../prefercliruntime | 0 ....Extensions.Caching.SqlConfig.Tools.csproj | 23 --------- .../prefercliruntime | 0 ...soft.Extensions.SecretManager.Tools.csproj | 25 --------- .../prefercliruntime | 0 src/PackGlobalTool.targets | 18 +++++++ src/dotnet-dev-certs/DotnetToolSettings.xml | 6 +++ .../Program.cs | 4 +- .../dotnet-dev-certs.csproj} | 10 +--- src/dotnet-dev-certs/dotnet-dev-certs.nuspec | 26 ++++++++++ src/dotnet-sql-cache/DotnetToolSettings.xml | 6 +++ .../Program.cs | 0 .../README.md | 8 ++- .../SqlQueries.cs | 2 +- src/dotnet-sql-cache/dotnet-sql-cache.csproj | 30 +++++++++++ src/dotnet-sql-cache/dotnet-sql-cache.nuspec | 26 ++++++++++ .../CommandLineOptions.cs | 8 +-- .../DotnetToolSettings.xml | 6 +++ .../Internal/ClearCommand.cs | 0 .../Internal/CommandContext.cs | 0 .../Internal/ICommand.cs | 0 .../Internal/ListCommand.cs | 0 .../Internal/MsBuildProjectFinder.cs | 0 .../Internal/ProjectIdResolver.cs | 5 +- .../ReadableJsonConfigurationSource.cs | 0 .../Internal/RemoveCommand.cs | 0 .../Internal/SecretsStore.cs | 0 .../Internal/SetCommand.cs | 0 .../Program.cs | 0 .../Properties/AssemblyInfo.cs | 0 .../Properties/Resources.Designer.cs | 0 .../README.md | 8 ++- .../Resources.resx | 0 .../assets}/SecretManager.targets | 0 .../dotnet-user-secrets.csproj | 40 +++++++++++++++ .../dotnet-user-secrets.nuspec | 26 ++++++++++ .../CommandLineOptions.cs | 0 .../DotNetWatcher.cs | 0 src/dotnet-watch/DotnetToolSettings.xml | 6 +++ .../IFileSet.cs | 0 .../IFileSetFactory.cs | 0 .../Internal/FileSet.cs | 0 .../Internal/FileSetWatcher.cs | 0 .../Internal/FileWatcher.cs | 0 .../Internal/FileWatcher/DotnetFileWatcher.cs | 0 .../FileWatcher/FileWatcherFactory.cs | 4 +- .../FileWatcher/IFileSystemWatcher.cs | 0 .../FileWatcher/PollingFileWatcher.cs | 0 .../Internal/MsBuildFileSetFactory.cs | 5 +- .../Internal/MsBuildProjectFinder.cs | 0 .../Internal/OutputCapture.cs | 0 .../Internal/OutputSink.cs | 0 .../Internal/ProcessRunner.cs | 0 .../PrefixConsoleReporter.cs | 0 .../ProcessSpec.cs | 0 .../Program.cs | 0 .../Properties/AssemblyInfo.cs | 0 .../Properties/Resources.Designer.cs | 0 .../README.md | 8 ++- .../Resources.resx | 0 .../assets}/DotNetWatch.targets | 0 .../dotnet-watch.csproj} | 9 ++-- src/dotnet-watch/dotnet-watch.nuspec | 26 ++++++++++ ...icrosoft.DotNet.Watcher.Tools.Tests.csproj | 16 ------ ...xtensions.SecretManager.Tools.Tests.csproj | 16 ------ .../MsBuildProjectFinderTest.cs | 0 .../SecretManagerTests.cs | 0 .../SetCommandTest.cs | 0 .../TemporaryFileProvider.cs | 0 .../UserSecretsTestFixture.cs | 0 .../dotnet-user-secrets.Tests.csproj | 17 +++++++ .../AppWithDepsTests.cs | 0 .../AwaitableProcess.cs | 0 .../DotNetWatcherTests.cs | 0 .../FileWatcherTests.cs | 0 .../GlobbingAppTests.cs | 0 .../NoDepsAppTests.cs | 0 .../Scenario/ProjectToolScenario.cs | 37 ++------------ .../Scenario/WatchableApp.cs | 8 +-- .../AppWithDeps/AppWithDeps.csproj | 0 .../TestProjects/AppWithDeps/Program.cs | 0 .../TestProjects/Dependency/Dependency.csproj | 0 .../TestProjects/Dependency/Foo.cs | 0 .../GlobbingApp/GlobbingApp.csproj | 0 .../TestProjects/GlobbingApp/Program.cs | 0 .../TestProjects/GlobbingApp/exclude/Baz.cs | 0 .../TestProjects/GlobbingApp/include/Foo.cs | 0 .../KitchenSink/KitchenSink.csproj | 0 .../TestProjects/KitchenSink/Program.cs | 0 .../TestProjects/NoDepsApp/NoDepsApp.csproj | 0 .../TestProjects/NoDepsApp/Program.cs | 0 .../dotnet-watch.FunctionalTests.csproj} | 12 +++-- .../AssertEx.cs | 0 .../CommandLineOptionsTests.cs | 0 .../ConsoleReporterTests.cs | 0 .../MsBuildFileSetFactoryTest.cs | 0 .../ProgramTests.cs | 0 .../Utilities/TemporaryCSharpProject.cs | 0 .../Utilities/TemporaryDirectory.cs | 0 .../Utilities/TestProjectGraph.cs | 0 .../dotnet-watch.Tests.csproj | 16 ++++++ 118 files changed, 401 insertions(+), 211 deletions(-) create mode 100644 src/Directory.Build.targets create mode 100644 src/DotnetTool.props delete mode 100644 src/Microsoft.AspNetCore.DeveloperCertificates.Tools/prefercliruntime delete mode 100644 src/Microsoft.DotNet.Watcher.Tools/prefercliruntime delete mode 100644 src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj delete mode 100644 src/Microsoft.Extensions.Caching.SqlConfig.Tools/prefercliruntime delete mode 100644 src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj delete mode 100644 src/Microsoft.Extensions.SecretManager.Tools/prefercliruntime create mode 100644 src/PackGlobalTool.targets create mode 100644 src/dotnet-dev-certs/DotnetToolSettings.xml rename src/{Microsoft.AspNetCore.DeveloperCertificates.Tools => dotnet-dev-certs}/Program.cs (99%) rename src/{Microsoft.AspNetCore.DeveloperCertificates.Tools/Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj => dotnet-dev-certs/dotnet-dev-certs.csproj} (82%) create mode 100644 src/dotnet-dev-certs/dotnet-dev-certs.nuspec create mode 100644 src/dotnet-sql-cache/DotnetToolSettings.xml rename src/{Microsoft.Extensions.Caching.SqlConfig.Tools => dotnet-sql-cache}/Program.cs (100%) rename src/{Microsoft.Extensions.Caching.SqlConfig.Tools => dotnet-sql-cache}/README.md (54%) rename src/{Microsoft.Extensions.Caching.SqlConfig.Tools => dotnet-sql-cache}/SqlQueries.cs (98%) create mode 100644 src/dotnet-sql-cache/dotnet-sql-cache.csproj create mode 100644 src/dotnet-sql-cache/dotnet-sql-cache.nuspec rename src/{Microsoft.Extensions.SecretManager.Tools => dotnet-user-secrets}/CommandLineOptions.cs (94%) create mode 100644 src/dotnet-user-secrets/DotnetToolSettings.xml rename src/{Microsoft.Extensions.SecretManager.Tools => dotnet-user-secrets}/Internal/ClearCommand.cs (100%) rename src/{Microsoft.Extensions.SecretManager.Tools => dotnet-user-secrets}/Internal/CommandContext.cs (100%) rename src/{Microsoft.Extensions.SecretManager.Tools => dotnet-user-secrets}/Internal/ICommand.cs (100%) rename src/{Microsoft.Extensions.SecretManager.Tools => dotnet-user-secrets}/Internal/ListCommand.cs (100%) rename src/{Microsoft.Extensions.SecretManager.Tools => dotnet-user-secrets}/Internal/MsBuildProjectFinder.cs (100%) rename src/{Microsoft.Extensions.SecretManager.Tools => dotnet-user-secrets}/Internal/ProjectIdResolver.cs (93%) rename src/{Microsoft.Extensions.SecretManager.Tools => dotnet-user-secrets}/Internal/ReadableJsonConfigurationSource.cs (100%) rename src/{Microsoft.Extensions.SecretManager.Tools => dotnet-user-secrets}/Internal/RemoveCommand.cs (100%) rename src/{Microsoft.Extensions.SecretManager.Tools => dotnet-user-secrets}/Internal/SecretsStore.cs (100%) rename src/{Microsoft.Extensions.SecretManager.Tools => dotnet-user-secrets}/Internal/SetCommand.cs (100%) rename src/{Microsoft.Extensions.SecretManager.Tools => dotnet-user-secrets}/Program.cs (100%) rename src/{Microsoft.Extensions.SecretManager.Tools => dotnet-user-secrets}/Properties/AssemblyInfo.cs (100%) rename src/{Microsoft.Extensions.SecretManager.Tools => dotnet-user-secrets}/Properties/Resources.Designer.cs (100%) rename src/{Microsoft.Extensions.SecretManager.Tools => dotnet-user-secrets}/README.md (51%) rename src/{Microsoft.Extensions.SecretManager.Tools => dotnet-user-secrets}/Resources.resx (100%) rename src/{Microsoft.Extensions.SecretManager.Tools/toolassets => dotnet-user-secrets/assets}/SecretManager.targets (100%) create mode 100644 src/dotnet-user-secrets/dotnet-user-secrets.csproj create mode 100644 src/dotnet-user-secrets/dotnet-user-secrets.nuspec rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/CommandLineOptions.cs (100%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/DotNetWatcher.cs (100%) create mode 100644 src/dotnet-watch/DotnetToolSettings.xml rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/IFileSet.cs (100%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/IFileSetFactory.cs (100%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/Internal/FileSet.cs (100%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/Internal/FileSetWatcher.cs (100%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/Internal/FileWatcher.cs (100%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/Internal/FileWatcher/DotnetFileWatcher.cs (100%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/Internal/FileWatcher/FileWatcherFactory.cs (86%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/Internal/FileWatcher/IFileSystemWatcher.cs (100%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/Internal/FileWatcher/PollingFileWatcher.cs (100%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/Internal/MsBuildFileSetFactory.cs (96%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/Internal/MsBuildProjectFinder.cs (100%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/Internal/OutputCapture.cs (100%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/Internal/OutputSink.cs (100%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/Internal/ProcessRunner.cs (100%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/PrefixConsoleReporter.cs (100%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/ProcessSpec.cs (100%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/Program.cs (100%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/Properties/AssemblyInfo.cs (100%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/Properties/Resources.Designer.cs (100%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/README.md (94%) rename src/{Microsoft.DotNet.Watcher.Tools => dotnet-watch}/Resources.resx (100%) rename src/{Microsoft.DotNet.Watcher.Tools/toolassets => dotnet-watch/assets}/DotNetWatch.targets (100%) rename src/{Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj => dotnet-watch/dotnet-watch.csproj} (65%) create mode 100644 src/dotnet-watch/dotnet-watch.nuspec delete mode 100644 test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj delete mode 100644 test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj rename test/{Microsoft.Extensions.SecretManager.Tools.Tests => dotnet-user-secrets.Tests}/MsBuildProjectFinderTest.cs (100%) rename test/{Microsoft.Extensions.SecretManager.Tools.Tests => dotnet-user-secrets.Tests}/SecretManagerTests.cs (100%) rename test/{Microsoft.Extensions.SecretManager.Tools.Tests => dotnet-user-secrets.Tests}/SetCommandTest.cs (100%) rename test/{Microsoft.Extensions.SecretManager.Tools.Tests => dotnet-user-secrets.Tests}/TemporaryFileProvider.cs (100%) rename test/{Microsoft.Extensions.SecretManager.Tools.Tests => dotnet-user-secrets.Tests}/UserSecretsTestFixture.cs (100%) create mode 100644 test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => dotnet-watch.FunctionalTests}/AppWithDepsTests.cs (100%) rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => dotnet-watch.FunctionalTests}/AwaitableProcess.cs (100%) rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => dotnet-watch.FunctionalTests}/DotNetWatcherTests.cs (100%) rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => dotnet-watch.FunctionalTests}/FileWatcherTests.cs (100%) rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => dotnet-watch.FunctionalTests}/GlobbingAppTests.cs (100%) rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => dotnet-watch.FunctionalTests}/NoDepsAppTests.cs (100%) rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => dotnet-watch.FunctionalTests}/Scenario/ProjectToolScenario.cs (80%) rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => dotnet-watch.FunctionalTests}/Scenario/WatchableApp.cs (96%) rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => dotnet-watch.FunctionalTests}/TestProjects/AppWithDeps/AppWithDeps.csproj (100%) rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => dotnet-watch.FunctionalTests}/TestProjects/AppWithDeps/Program.cs (100%) rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => dotnet-watch.FunctionalTests}/TestProjects/Dependency/Dependency.csproj (100%) rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => dotnet-watch.FunctionalTests}/TestProjects/Dependency/Foo.cs (100%) rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => dotnet-watch.FunctionalTests}/TestProjects/GlobbingApp/GlobbingApp.csproj (100%) rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => dotnet-watch.FunctionalTests}/TestProjects/GlobbingApp/Program.cs (100%) rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => dotnet-watch.FunctionalTests}/TestProjects/GlobbingApp/exclude/Baz.cs (100%) rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => dotnet-watch.FunctionalTests}/TestProjects/GlobbingApp/include/Foo.cs (100%) rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => dotnet-watch.FunctionalTests}/TestProjects/KitchenSink/KitchenSink.csproj (100%) mode change 100755 => 100644 rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => dotnet-watch.FunctionalTests}/TestProjects/KitchenSink/Program.cs (100%) mode change 100755 => 100644 rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => dotnet-watch.FunctionalTests}/TestProjects/NoDepsApp/NoDepsApp.csproj (100%) rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests => dotnet-watch.FunctionalTests}/TestProjects/NoDepsApp/Program.cs (100%) rename test/{Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj => dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj} (66%) rename test/{Microsoft.DotNet.Watcher.Tools.Tests => dotnet-watch.Tests}/AssertEx.cs (100%) rename test/{Microsoft.DotNet.Watcher.Tools.Tests => dotnet-watch.Tests}/CommandLineOptionsTests.cs (100%) rename test/{Microsoft.DotNet.Watcher.Tools.Tests => dotnet-watch.Tests}/ConsoleReporterTests.cs (100%) rename test/{Microsoft.DotNet.Watcher.Tools.Tests => dotnet-watch.Tests}/MsBuildFileSetFactoryTest.cs (100%) rename test/{Microsoft.DotNet.Watcher.Tools.Tests => dotnet-watch.Tests}/ProgramTests.cs (100%) rename test/{Microsoft.DotNet.Watcher.Tools.Tests => dotnet-watch.Tests}/Utilities/TemporaryCSharpProject.cs (100%) rename test/{Microsoft.DotNet.Watcher.Tools.Tests => dotnet-watch.Tests}/Utilities/TemporaryDirectory.cs (100%) rename test/{Microsoft.DotNet.Watcher.Tools.Tests => dotnet-watch.Tests}/Utilities/TestProjectGraph.cs (100%) create mode 100644 test/dotnet-watch.Tests/dotnet-watch.Tests.csproj diff --git a/.gitignore b/.gitignore index 591bacd6e1..ddc5e01720 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ testWorkDir/ .idea/ .dotnet/ global.json +*.binlog diff --git a/DotNetTools.sln b/DotNetTools.sln index 302f0e2f5d..82fefe40d0 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -7,7 +7,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66517987-2A5 src\Directory.Build.props = src\Directory.Build.props EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Watcher.Tools", "src\Microsoft.DotNet.Watcher.Tools\Microsoft.DotNet.Watcher.Tools.csproj", "{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-watch", "src\dotnet-watch\dotnet-watch.csproj", "{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8321E0D1-9A47-4D2F-AED8-3AE636D44E35}" ProjectSection(SolutionItems) = preProject @@ -36,17 +36,17 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F5B382BC-2 test\Directory.Build.props = test\Directory.Build.props EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Watcher.Tools.FunctionalTests", "test\Microsoft.DotNet.Watcher.Tools.FunctionalTests\Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj", "{16BADE2F-1184-4518-8A70-B68A19D0805B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-watch.FunctionalTests", "test\dotnet-watch.FunctionalTests\dotnet-watch.FunctionalTests.csproj", "{16BADE2F-1184-4518-8A70-B68A19D0805B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.SecretManager.Tools", "src\Microsoft.Extensions.SecretManager.Tools\Microsoft.Extensions.SecretManager.Tools.csproj", "{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-user-secrets", "src\dotnet-user-secrets\dotnet-user-secrets.csproj", "{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.SecretManager.Tools.Tests", "test\Microsoft.Extensions.SecretManager.Tools.Tests\Microsoft.Extensions.SecretManager.Tools.Tests.csproj", "{7B331122-83B1-4F08-A119-DC846959844C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-user-secrets.Tests", "test\dotnet-user-secrets.Tests\dotnet-user-secrets.Tests.csproj", "{7B331122-83B1-4F08-A119-DC846959844C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Watcher.Tools.Tests", "test\Microsoft.DotNet.Watcher.Tools.Tests\Microsoft.DotNet.Watcher.Tools.Tests.csproj", "{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-watch.Tests", "test\dotnet-watch.Tests\dotnet-watch.Tests.csproj", "{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Caching.SqlConfig.Tools", "src\Microsoft.Extensions.Caching.SqlConfig.Tools\Microsoft.Extensions.Caching.SqlConfig.Tools.csproj", "{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-sql-cache", "src\dotnet-sql-cache\dotnet-sql-cache.csproj", "{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DeveloperCertificates.Tools", "src\Microsoft.AspNetCore.DeveloperCertificates.Tools\Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj", "{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-dev-certs", "src\dotnet-dev-certs\dotnet-dev-certs.csproj", "{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.VisualStudio.SecretManager", "tooling\Microsoft.VisualStudio.SecretManager\Microsoft.VisualStudio.SecretManager.csproj", "{5E117F2E-7152-447F-BF47-59F759EEF3A7}" EndProject diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index 6979dfba80..171ae87771 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -4,24 +4,55 @@ "AdxVerificationCompositeRule" ], "packages": { - "Microsoft.DotNet.Watcher.Tools": { + "dotnet-watch": { "packageTypes": [ - "DotnetCliTool" + "DotnetTool" ] }, - "Microsoft.Extensions.Caching.SqlConfig.Tools": { + "dotnet-sql-cache": { "packageTypes": [ - "DotnetCliTool" - ] + "DotnetTool" + ], + "Exclusions": { + "WRONG_PUBLICKEYTOKEN": { + "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + }, + "ASSEMBLY_INFORMATIONAL_VERSION_MISMATCH": { + "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + } + } }, - "Microsoft.Extensions.SecretManager.Tools": { + "dotnet-user-secrets": { "packageTypes": [ - "DotnetCliTool" - ] + "DotnetTool" + ], + "Exclusions": { + "NEUTRAL_RESOURCES_LANGUAGE": { + "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + }, + "SERVICING_ATTRIBUTE": { + "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg." + }, + "VERSION_INFORMATIONALVERSION": { + "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg." + }, + "WRONG_PUBLICKEYTOKEN": { + "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + }, + "ASSEMBLY_INFORMATIONAL_VERSION_MISMATCH": { + "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg." + } + } }, - "Microsoft.AspNetCore.DeveloperCertificates.Tools": { + "dotnet-dev-certs": { "packageTypes": [ - "DotnetCliTool" + "DotnetTool" ] }, "Microsoft.AspNetCore.DeveloperCertificates.XPlat": { diff --git a/README.md b/README.md index c007157a78..111174914c 100644 --- a/README.md +++ b/README.md @@ -10,33 +10,36 @@ This project is part of ASP.NET Core. You can find samples, documentation and ge The repository contains command-line tools for the .NET Core CLI. Follow the links below for more details on each tool. - - [dotnet-watch](src/Microsoft.DotNet.Watcher.Tools/) (Microsoft.DotNet.Watcher.Tools) - - [dotnet-user-secrets](src/Microsoft.Extensions.SecretManager.Tools/) (Microsoft.Extensions.SecretManager.Tools) - - [dotnet-sql-cache](src/Microsoft.Extensions.Caching.SqlConfig.Tools/) (Microsoft.Extensions.Caching.SqlConfig.Tools) + - [dotnet-watch](src/dotnet-watch/) + - [dotnet-user-secrets](src/dotnet-user-secrets/) + - [dotnet-sql-cache](src/dotnet-sql-cache/) (dotnet-sql-cache) + - [dotnet-dev-certs](src/dotnet-dev-certs/) (dotnet-dev-certs) ## How to Install -Install tools by editing your \*.csproj file and adding a `DotNetCliToolReference` with the package name and version. +Install tools using the .NET Core command-line. + +``` +dotnet install tool dotnet-watch +dotnet install tool dotnet-user-secrets +dotnet install tool dotnet-dev-certs +dotnet install tool dotnet-sql-cache -```xml - - - - - ``` -Then, from command line, change directories to your project and run the following commands: +## Usage + +The command line tools can be invoked as a new verb hanging off `dotnet`. ```sh -# Location of MyProject.csproj which includes DotNetCliToolReference's -cd C:\Source\MyProject\ - -# Download tools into the project -dotnet restore - -# Execute tools dotnet watch dotnet user-secrets dotnet sql-cache +dotnet dev-certs +``` + +Add `--help` to see more details. For example, + +``` +dotnet watch --help ``` diff --git a/build/VSIX.targets b/build/VSIX.targets index eade7e4414..83ab88c4f6 100644 --- a/build/VSIX.targets +++ b/build/VSIX.targets @@ -1,4 +1,4 @@ - + true $(RestoreDependsOn);RestoreVSIX @@ -32,7 +32,7 @@ $(VSIXName) - + diff --git a/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj b/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj index 96438bfa81..1dc6efedd6 100644 --- a/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj +++ b/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj @@ -4,8 +4,6 @@ - - diff --git a/samples/dotnet-watch/LaunchAnyCommand/README.md b/samples/dotnet-watch/LaunchAnyCommand/README.md index 698d69225d..fa52f4073e 100644 --- a/samples/dotnet-watch/LaunchAnyCommand/README.md +++ b/samples/dotnet-watch/LaunchAnyCommand/README.md @@ -11,7 +11,6 @@ Launch any command with dotnet-watch Open a terminal to the directory containing this project. ``` -dotnet restore dotnet watch msbuild /t:RunMyNpmCommand ``` diff --git a/samples/dotnet-watch/README.md b/samples/dotnet-watch/README.md index 467a552f7e..5988ab77ba 100644 --- a/samples/dotnet-watch/README.md +++ b/samples/dotnet-watch/README.md @@ -2,4 +2,4 @@ dotnet-watch samples ==================== The samples in this folder show some ways to customize dotnet-watch. For full details on -available settings and configuration, see the [README for the Microsoft.DotNet.Watcher.Tools](../../src/Microsoft.DotNet.Watcher.Tools/README.md) project. +available settings and configuration, see the [README for the dotnet-watch](../../src/dotnet-watch/README.md) project. diff --git a/samples/dotnet-watch/WatchJavascriptFiles/README.md b/samples/dotnet-watch/WatchJavascriptFiles/README.md index dc98940cd7..3b0a148cd0 100644 --- a/samples/dotnet-watch/WatchJavascriptFiles/README.md +++ b/samples/dotnet-watch/WatchJavascriptFiles/README.md @@ -10,7 +10,6 @@ Install .NET Core command line. Open a terminal to the directory containing this project. ``` -dotnet restore dotnet watch run ``` diff --git a/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj b/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj index 65fd51d8d7..008b0322e6 100755 --- a/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj +++ b/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj @@ -11,7 +11,6 @@ - diff --git a/samples/dotnet-watch/WatchMultipleProjects/README.md b/samples/dotnet-watch/WatchMultipleProjects/README.md index 2c01233d36..46d7a7904c 100644 --- a/samples/dotnet-watch/WatchMultipleProjects/README.md +++ b/samples/dotnet-watch/WatchMultipleProjects/README.md @@ -10,8 +10,7 @@ Install .NET Core command line. Open a terminal to the directory containing this project. ``` -dotnet restore watch.proj -dotnet watch msbuild watch.proj /t:TestAndRun +dotnet watch msbuild /t:TestAndRun ``` The "TestAndRun" target in watch.proj will execute "dotnet test" on Test.csproj and then launch the website by calling "dotnet run" on Web.csproj. diff --git a/samples/dotnet-watch/WatchMultipleProjects/watch.csproj b/samples/dotnet-watch/WatchMultipleProjects/watch.csproj index b0ab41a539..d890295d39 100644 --- a/samples/dotnet-watch/WatchMultipleProjects/watch.csproj +++ b/samples/dotnet-watch/WatchMultipleProjects/watch.csproj @@ -5,8 +5,6 @@ - - diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 4b89a431e7..7129734857 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,6 +1,15 @@ + + + false + + + false + + + diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets new file mode 100644 index 0000000000..6d04f45f89 --- /dev/null +++ b/src/Directory.Build.targets @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/DotnetTool.props b/src/DotnetTool.props new file mode 100644 index 0000000000..04fc17a28b --- /dev/null +++ b/src/DotnetTool.props @@ -0,0 +1,16 @@ + + + $(MSBuildProjectDirectory)\$(MSBuildProjectName).nuspec + + true + + ship + Microsoft + false + false + + + + + + diff --git a/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/prefercliruntime b/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/prefercliruntime deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj b/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj index 81c90a297c..a8e6fe928a 100644 --- a/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj +++ b/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj @@ -5,6 +5,9 @@ Package for the CLI first run experience. $(DefineConstants);XPLAT aspnet;cli + + shipoob + Microsoft diff --git a/src/Microsoft.DotNet.Watcher.Tools/prefercliruntime b/src/Microsoft.DotNet.Watcher.Tools/prefercliruntime deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj deleted file mode 100644 index d3ce82febe..0000000000 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - netcoreapp2.1 - dotnet-sql-cache - exe - Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching. - Microsoft.Extensions.Caching.SqlConfig.Tools - cache;distributedcache;sqlserver - DotnetCliTool - - - - - - - - - - - - - diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/prefercliruntime b/src/Microsoft.Extensions.Caching.SqlConfig.Tools/prefercliruntime deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj b/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj deleted file mode 100644 index ef8adb296f..0000000000 --- a/src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.csproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - netcoreapp2.1 - dotnet-user-secrets - exe - Command line tool to manage user secrets for Microsoft.Extensions.Configuration. - Microsoft.Extensions.SecretManager.Tools - configuration;secrets;usersecrets - DotnetCliTool - false - - - - - - - - - - - - - - diff --git a/src/Microsoft.Extensions.SecretManager.Tools/prefercliruntime b/src/Microsoft.Extensions.SecretManager.Tools/prefercliruntime deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/PackGlobalTool.targets b/src/PackGlobalTool.targets new file mode 100644 index 0000000000..5f498664c8 --- /dev/null +++ b/src/PackGlobalTool.targets @@ -0,0 +1,18 @@ + + + + + publishDir=$(PublishDir); + version=$(PackageVersion); + licenseUrl=$(PackageLicenseUrl); + projectUrl=$(PackageProjectUrl); + iconUrl=$(PackageIconUrl); + serviceable=$(Serviceable); + copyright=$(Copyright); + description=$(Description); + repositoryUrl=$(RepositoryUrl); + targetframework=$(TargetFramework); + + + + diff --git a/src/dotnet-dev-certs/DotnetToolSettings.xml b/src/dotnet-dev-certs/DotnetToolSettings.xml new file mode 100644 index 0000000000..dbc7a5b6d9 --- /dev/null +++ b/src/dotnet-dev-certs/DotnetToolSettings.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Program.cs b/src/dotnet-dev-certs/Program.cs similarity index 99% rename from src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Program.cs rename to src/dotnet-dev-certs/Program.cs index 7fbd5993cf..d1d5cfabaf 100644 --- a/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Program.cs +++ b/src/dotnet-dev-certs/Program.cs @@ -12,7 +12,7 @@ using Microsoft.Extensions.Tools.Internal; namespace Microsoft.AspNetCore.DeveloperCertificates.Tools { - class Program + internal class Program { private const int CriticalError = -1; private const int Success = 0; @@ -32,7 +32,7 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools { var app = new CommandLineApplication { - Name = "dotnet-developercertificates" + Name = "dotnet-dev-certs" }; app.Command("https", c => diff --git a/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj b/src/dotnet-dev-certs/dotnet-dev-certs.csproj similarity index 82% rename from src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj rename to src/dotnet-dev-certs/dotnet-dev-certs.csproj index 53cc86f701..8c4d039c02 100644 --- a/src/Microsoft.AspNetCore.DeveloperCertificates.Tools/Microsoft.AspNetCore.DeveloperCertificates.Tools.csproj +++ b/src/dotnet-dev-certs/dotnet-dev-certs.csproj @@ -2,12 +2,10 @@ netcoreapp2.1 - dotnet-dev-certs exe Command line tool to generate certificates used in ASP.NET Core during development. - Microsoft.AspNetCore.DeveloperCertificates.Tools - dotnet;developercertificates - DotnetCliTool + DotnetTool + Microsoft.AspNetCore.DeveloperCertificates.Tools @@ -22,10 +20,6 @@ - - - - diff --git a/src/dotnet-dev-certs/dotnet-dev-certs.nuspec b/src/dotnet-dev-certs/dotnet-dev-certs.nuspec new file mode 100644 index 0000000000..7c063e6e29 --- /dev/null +++ b/src/dotnet-dev-certs/dotnet-dev-certs.nuspec @@ -0,0 +1,26 @@ + + + + dotnet-dev-certs + dotnet developercertificates + $version$ + Microsoft + Microsoft + $licenseUrl$ + $projectUrl$ + $iconUrl$ + $description$ + $copyright$ + true + $serviceable$ + + + + + + + + + + + diff --git a/src/dotnet-sql-cache/DotnetToolSettings.xml b/src/dotnet-sql-cache/DotnetToolSettings.xml new file mode 100644 index 0000000000..2619964f0e --- /dev/null +++ b/src/dotnet-sql-cache/DotnetToolSettings.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs b/src/dotnet-sql-cache/Program.cs similarity index 100% rename from src/Microsoft.Extensions.Caching.SqlConfig.Tools/Program.cs rename to src/dotnet-sql-cache/Program.cs diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/README.md b/src/dotnet-sql-cache/README.md similarity index 54% rename from src/Microsoft.Extensions.Caching.SqlConfig.Tools/README.md rename to src/dotnet-sql-cache/README.md index dae4ad333e..05f7153882 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/README.md +++ b/src/dotnet-sql-cache/README.md @@ -5,12 +5,10 @@ dotnet-sql-cache ### How To Install -Install `Microsoft.Extensions.Caching.SqlConfig.Tools` as a `DotNetCliToolReference` to your project. +From the command-line, execute: -```xml - - - +``` +dotnet install tool dotnet-sql-cache ``` ### How To Use diff --git a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/SqlQueries.cs b/src/dotnet-sql-cache/SqlQueries.cs similarity index 98% rename from src/Microsoft.Extensions.Caching.SqlConfig.Tools/SqlQueries.cs rename to src/dotnet-sql-cache/SqlQueries.cs index c8ae6f8284..7b9c73a990 100644 --- a/src/Microsoft.Extensions.Caching.SqlConfig.Tools/SqlQueries.cs +++ b/src/dotnet-sql-cache/SqlQueries.cs @@ -8,7 +8,7 @@ namespace Microsoft.Extensions.Caching.SqlConfig.Tools internal class SqlQueries { private const string CreateTableFormat = "CREATE TABLE {0}(" + - // Maximum size of primary key column is 900 bytes (898 bytes from key + 2 additional bytes used by the + // Maximum size of primary key column is 900 bytes (898 bytes from key + 2 additional bytes used by the // Sql Server). In the case where the key is greater than 898 bytes, then it gets truncated. // - Add collation to the key column to make it case-sensitive "Id nvarchar(449) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, " + diff --git a/src/dotnet-sql-cache/dotnet-sql-cache.csproj b/src/dotnet-sql-cache/dotnet-sql-cache.csproj new file mode 100644 index 0000000000..1bd0904ab5 --- /dev/null +++ b/src/dotnet-sql-cache/dotnet-sql-cache.csproj @@ -0,0 +1,30 @@ + + + + netcoreapp2.1 + exe + Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching. + DotnetTool + tools/$(TargetFramework)/any/ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/dotnet-sql-cache/dotnet-sql-cache.nuspec b/src/dotnet-sql-cache/dotnet-sql-cache.nuspec new file mode 100644 index 0000000000..3c198fc163 --- /dev/null +++ b/src/dotnet-sql-cache/dotnet-sql-cache.nuspec @@ -0,0 +1,26 @@ + + + + dotnet-sql-cache + cache distributedcache sqlserver + $version$ + Microsoft + Microsoft + $licenseUrl$ + $projectUrl$ + $iconUrl$ + $description$ + $copyright$ + true + $serviceable$ + + + + + + + + + + + diff --git a/src/Microsoft.Extensions.SecretManager.Tools/CommandLineOptions.cs b/src/dotnet-user-secrets/CommandLineOptions.cs similarity index 94% rename from src/Microsoft.Extensions.SecretManager.Tools/CommandLineOptions.cs rename to src/dotnet-user-secrets/CommandLineOptions.cs index ff888f9e8b..6ce543cc00 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/CommandLineOptions.cs +++ b/src/dotnet-user-secrets/CommandLineOptions.cs @@ -33,15 +33,15 @@ namespace Microsoft.Extensions.SecretManager.Tools var optionVerbose = app.VerboseOption(); - var optionProject = app.Option("-p|--project ", "Path to project, default is current directory", + var optionProject = app.Option("-p|--project ", "Path to project. Defaults to searching the current directory.", CommandOptionType.SingleValue, inherited: true); - var optionConfig = app.Option("-c|--configuration ", $"The project configuration to use. Defaults to 'Debug'", + var optionConfig = app.Option("-c|--configuration ", $"The project configuration to use. Defaults to 'Debug'.", CommandOptionType.SingleValue, inherited: true); // the escape hatch if project evaluation fails, or if users want to alter a secret store other than the one // in the current project - var optionId = app.Option("--id", "The user secret id to use.", + var optionId = app.Option("--id", "The user secret ID to use.", CommandOptionType.SingleValue, inherited: true); var options = new CommandLineOptions(); @@ -69,4 +69,4 @@ namespace Microsoft.Extensions.SecretManager.Tools return options; } } -} \ No newline at end of file +} diff --git a/src/dotnet-user-secrets/DotnetToolSettings.xml b/src/dotnet-user-secrets/DotnetToolSettings.xml new file mode 100644 index 0000000000..0de9f13c31 --- /dev/null +++ b/src/dotnet-user-secrets/DotnetToolSettings.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ClearCommand.cs b/src/dotnet-user-secrets/Internal/ClearCommand.cs similarity index 100% rename from src/Microsoft.Extensions.SecretManager.Tools/Internal/ClearCommand.cs rename to src/dotnet-user-secrets/Internal/ClearCommand.cs diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandContext.cs b/src/dotnet-user-secrets/Internal/CommandContext.cs similarity index 100% rename from src/Microsoft.Extensions.SecretManager.Tools/Internal/CommandContext.cs rename to src/dotnet-user-secrets/Internal/CommandContext.cs diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ICommand.cs b/src/dotnet-user-secrets/Internal/ICommand.cs similarity index 100% rename from src/Microsoft.Extensions.SecretManager.Tools/Internal/ICommand.cs rename to src/dotnet-user-secrets/Internal/ICommand.cs diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ListCommand.cs b/src/dotnet-user-secrets/Internal/ListCommand.cs similarity index 100% rename from src/Microsoft.Extensions.SecretManager.Tools/Internal/ListCommand.cs rename to src/dotnet-user-secrets/Internal/ListCommand.cs diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/MsBuildProjectFinder.cs b/src/dotnet-user-secrets/Internal/MsBuildProjectFinder.cs similarity index 100% rename from src/Microsoft.Extensions.SecretManager.Tools/Internal/MsBuildProjectFinder.cs rename to src/dotnet-user-secrets/Internal/MsBuildProjectFinder.cs diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs b/src/dotnet-user-secrets/Internal/ProjectIdResolver.cs similarity index 93% rename from src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs rename to src/dotnet-user-secrets/Internal/ProjectIdResolver.cs index 66d08b008b..da5111ca51 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ProjectIdResolver.cs +++ b/src/dotnet-user-secrets/Internal/ProjectIdResolver.cs @@ -91,11 +91,10 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal var assemblyDir = Path.GetDirectoryName(typeof(ProjectIdResolver).Assembly.Location); var searchPaths = new[] { + Path.Combine(AppContext.BaseDirectory, "assets"), + Path.Combine(assemblyDir, "assets"), AppContext.BaseDirectory, assemblyDir, - Path.Combine(assemblyDir, "../../toolassets"), // from nuget cache - Path.Combine(assemblyDir, "toolassets"), // from local build - Path.Combine(AppContext.BaseDirectory, "../../toolassets"), // relative to packaged deps.json }; var targetPath = searchPaths.Select(p => Path.Combine(p, "SecretManager.targets")).FirstOrDefault(File.Exists); diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/ReadableJsonConfigurationSource.cs b/src/dotnet-user-secrets/Internal/ReadableJsonConfigurationSource.cs similarity index 100% rename from src/Microsoft.Extensions.SecretManager.Tools/Internal/ReadableJsonConfigurationSource.cs rename to src/dotnet-user-secrets/Internal/ReadableJsonConfigurationSource.cs diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs b/src/dotnet-user-secrets/Internal/RemoveCommand.cs similarity index 100% rename from src/Microsoft.Extensions.SecretManager.Tools/Internal/RemoveCommand.cs rename to src/dotnet-user-secrets/Internal/RemoveCommand.cs diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs b/src/dotnet-user-secrets/Internal/SecretsStore.cs similarity index 100% rename from src/Microsoft.Extensions.SecretManager.Tools/Internal/SecretsStore.cs rename to src/dotnet-user-secrets/Internal/SecretsStore.cs diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs b/src/dotnet-user-secrets/Internal/SetCommand.cs similarity index 100% rename from src/Microsoft.Extensions.SecretManager.Tools/Internal/SetCommand.cs rename to src/dotnet-user-secrets/Internal/SetCommand.cs diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Program.cs b/src/dotnet-user-secrets/Program.cs similarity index 100% rename from src/Microsoft.Extensions.SecretManager.Tools/Program.cs rename to src/dotnet-user-secrets/Program.cs diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Properties/AssemblyInfo.cs b/src/dotnet-user-secrets/Properties/AssemblyInfo.cs similarity index 100% rename from src/Microsoft.Extensions.SecretManager.Tools/Properties/AssemblyInfo.cs rename to src/dotnet-user-secrets/Properties/AssemblyInfo.cs diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs b/src/dotnet-user-secrets/Properties/Resources.Designer.cs similarity index 100% rename from src/Microsoft.Extensions.SecretManager.Tools/Properties/Resources.Designer.cs rename to src/dotnet-user-secrets/Properties/Resources.Designer.cs diff --git a/src/Microsoft.Extensions.SecretManager.Tools/README.md b/src/dotnet-user-secrets/README.md similarity index 51% rename from src/Microsoft.Extensions.SecretManager.Tools/README.md rename to src/dotnet-user-secrets/README.md index f23371dc30..33d9e0cae0 100644 --- a/src/Microsoft.Extensions.SecretManager.Tools/README.md +++ b/src/dotnet-user-secrets/README.md @@ -5,12 +5,10 @@ dotnet-user-secrets ### How To Install -Install `Microsoft.Extensions.SecretManager.Tools` as a `DotNetCliToolReference` to your project. +From the command-line, execute: -```xml - - - +``` +dotnet install tool dotnet-user-secrets ``` ### How To Use diff --git a/src/Microsoft.Extensions.SecretManager.Tools/Resources.resx b/src/dotnet-user-secrets/Resources.resx similarity index 100% rename from src/Microsoft.Extensions.SecretManager.Tools/Resources.resx rename to src/dotnet-user-secrets/Resources.resx diff --git a/src/Microsoft.Extensions.SecretManager.Tools/toolassets/SecretManager.targets b/src/dotnet-user-secrets/assets/SecretManager.targets similarity index 100% rename from src/Microsoft.Extensions.SecretManager.Tools/toolassets/SecretManager.targets rename to src/dotnet-user-secrets/assets/SecretManager.targets diff --git a/src/dotnet-user-secrets/dotnet-user-secrets.csproj b/src/dotnet-user-secrets/dotnet-user-secrets.csproj new file mode 100644 index 0000000000..d979f1a355 --- /dev/null +++ b/src/dotnet-user-secrets/dotnet-user-secrets.csproj @@ -0,0 +1,40 @@ + + + + netcoreapp2.1 + exe + Command line tool to manage user secrets for Microsoft.Extensions.Configuration. + DotnetTool + false + Microsoft.Extensions.SecretManager.Tools + tools/$(TargetFramework)/any/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/dotnet-user-secrets/dotnet-user-secrets.nuspec b/src/dotnet-user-secrets/dotnet-user-secrets.nuspec new file mode 100644 index 0000000000..145ec4233b --- /dev/null +++ b/src/dotnet-user-secrets/dotnet-user-secrets.nuspec @@ -0,0 +1,26 @@ + + + + dotnet-user-secrets + configuration secrets usersecrets + $version$ + Microsoft + Microsoft + $licenseUrl$ + $projectUrl$ + $iconUrl$ + $description$ + $copyright$ + true + $serviceable$ + + + + + + + + + + + diff --git a/src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs b/src/dotnet-watch/CommandLineOptions.cs similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/CommandLineOptions.cs rename to src/dotnet-watch/CommandLineOptions.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs b/src/dotnet-watch/DotNetWatcher.cs similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/DotNetWatcher.cs rename to src/dotnet-watch/DotNetWatcher.cs diff --git a/src/dotnet-watch/DotnetToolSettings.xml b/src/dotnet-watch/DotnetToolSettings.xml new file mode 100644 index 0000000000..7e9a7f40d4 --- /dev/null +++ b/src/dotnet-watch/DotnetToolSettings.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/Microsoft.DotNet.Watcher.Tools/IFileSet.cs b/src/dotnet-watch/IFileSet.cs similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/IFileSet.cs rename to src/dotnet-watch/IFileSet.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/IFileSetFactory.cs b/src/dotnet-watch/IFileSetFactory.cs similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/IFileSetFactory.cs rename to src/dotnet-watch/IFileSetFactory.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSet.cs b/src/dotnet-watch/Internal/FileSet.cs similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/Internal/FileSet.cs rename to src/dotnet-watch/Internal/FileSet.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileSetWatcher.cs b/src/dotnet-watch/Internal/FileSetWatcher.cs similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/Internal/FileSetWatcher.cs rename to src/dotnet-watch/Internal/FileSetWatcher.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher.cs b/src/dotnet-watch/Internal/FileWatcher.cs similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher.cs rename to src/dotnet-watch/Internal/FileWatcher.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/DotnetFileWatcher.cs b/src/dotnet-watch/Internal/FileWatcher/DotnetFileWatcher.cs similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/DotnetFileWatcher.cs rename to src/dotnet-watch/Internal/FileWatcher/DotnetFileWatcher.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/FileWatcherFactory.cs b/src/dotnet-watch/Internal/FileWatcher/FileWatcherFactory.cs similarity index 86% rename from src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/FileWatcherFactory.cs rename to src/dotnet-watch/Internal/FileWatcher/FileWatcherFactory.cs index cbb1c12a74..9c91176ec1 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/FileWatcherFactory.cs +++ b/src/dotnet-watch/Internal/FileWatcher/FileWatcherFactory.cs @@ -12,8 +12,8 @@ namespace Microsoft.DotNet.Watcher.Internal public static IFileSystemWatcher CreateWatcher(string watchedDirectory, bool usePollingWatcher) { - return usePollingWatcher ? - new PollingFileWatcher(watchedDirectory) : + return usePollingWatcher ? + new PollingFileWatcher(watchedDirectory) : new DotnetFileWatcher(watchedDirectory) as IFileSystemWatcher; } } diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/IFileSystemWatcher.cs b/src/dotnet-watch/Internal/FileWatcher/IFileSystemWatcher.cs similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/IFileSystemWatcher.cs rename to src/dotnet-watch/Internal/FileWatcher/IFileSystemWatcher.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs b/src/dotnet-watch/Internal/FileWatcher/PollingFileWatcher.cs similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/Internal/FileWatcher/PollingFileWatcher.cs rename to src/dotnet-watch/Internal/FileWatcher/PollingFileWatcher.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs b/src/dotnet-watch/Internal/MsBuildFileSetFactory.cs similarity index 96% rename from src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs rename to src/dotnet-watch/Internal/MsBuildFileSetFactory.cs index 837881c907..3cdf453067 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildFileSetFactory.cs +++ b/src/dotnet-watch/Internal/MsBuildFileSetFactory.cs @@ -170,11 +170,10 @@ namespace Microsoft.DotNet.Watcher.Internal var assemblyDir = Path.GetDirectoryName(typeof(MsBuildFileSetFactory).Assembly.Location); var searchPaths = new[] { + Path.Combine(AppContext.BaseDirectory, "assets"), + Path.Combine(assemblyDir, "assets"), AppContext.BaseDirectory, assemblyDir, - Path.Combine(assemblyDir, "../../toolassets"), // from nuget cache - Path.Combine(assemblyDir, "toolassets"), // from local build - Path.Combine(AppContext.BaseDirectory, "../../toolassets"), // relative to packaged deps.json }; var targetPath = searchPaths.Select(p => Path.Combine(p, WatchTargetsFileName)).FirstOrDefault(File.Exists); diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildProjectFinder.cs b/src/dotnet-watch/Internal/MsBuildProjectFinder.cs similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/Internal/MsBuildProjectFinder.cs rename to src/dotnet-watch/Internal/MsBuildProjectFinder.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/OutputCapture.cs b/src/dotnet-watch/Internal/OutputCapture.cs similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/Internal/OutputCapture.cs rename to src/dotnet-watch/Internal/OutputCapture.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/OutputSink.cs b/src/dotnet-watch/Internal/OutputSink.cs similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/Internal/OutputSink.cs rename to src/dotnet-watch/Internal/OutputSink.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs b/src/dotnet-watch/Internal/ProcessRunner.cs similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs rename to src/dotnet-watch/Internal/ProcessRunner.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/PrefixConsoleReporter.cs b/src/dotnet-watch/PrefixConsoleReporter.cs similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/PrefixConsoleReporter.cs rename to src/dotnet-watch/PrefixConsoleReporter.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/ProcessSpec.cs b/src/dotnet-watch/ProcessSpec.cs similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/ProcessSpec.cs rename to src/dotnet-watch/ProcessSpec.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/dotnet-watch/Program.cs similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/Program.cs rename to src/dotnet-watch/Program.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs b/src/dotnet-watch/Properties/AssemblyInfo.cs similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/Properties/AssemblyInfo.cs rename to src/dotnet-watch/Properties/AssemblyInfo.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/Properties/Resources.Designer.cs b/src/dotnet-watch/Properties/Resources.Designer.cs similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/Properties/Resources.Designer.cs rename to src/dotnet-watch/Properties/Resources.Designer.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/README.md b/src/dotnet-watch/README.md similarity index 94% rename from src/Microsoft.DotNet.Watcher.Tools/README.md rename to src/dotnet-watch/README.md index dafbcde2e3..8fb0db78db 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/README.md +++ b/src/dotnet-watch/README.md @@ -4,12 +4,10 @@ dotnet-watch ### How To Install -Install `Microsoft.DotNet.Watcher.Tools` as a `DotNetCliToolReference` to your project. +From the command-line, execute: -```xml - - - +``` +dotnet install tool dotnet-watch ``` ### How To Use diff --git a/src/Microsoft.DotNet.Watcher.Tools/Resources.resx b/src/dotnet-watch/Resources.resx similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/Resources.resx rename to src/dotnet-watch/Resources.resx diff --git a/src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatch.targets b/src/dotnet-watch/assets/DotNetWatch.targets similarity index 100% rename from src/Microsoft.DotNet.Watcher.Tools/toolassets/DotNetWatch.targets rename to src/dotnet-watch/assets/DotNetWatch.targets diff --git a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj b/src/dotnet-watch/dotnet-watch.csproj similarity index 65% rename from src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj rename to src/dotnet-watch/dotnet-watch.csproj index 5c79f6f652..19db471fe7 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.csproj +++ b/src/dotnet-watch/dotnet-watch.csproj @@ -2,18 +2,15 @@ netcoreapp2.1 - dotnet-watch exe Command line tool to watch for source file changes during development and restart the dotnet command. - Microsoft.DotNet.Watcher.Tools - dotnet;watch - DotnetCliTool + DotnetTool + Microsoft.DotNet.Watcher.Tools - - + diff --git a/src/dotnet-watch/dotnet-watch.nuspec b/src/dotnet-watch/dotnet-watch.nuspec new file mode 100644 index 0000000000..53c4447f94 --- /dev/null +++ b/src/dotnet-watch/dotnet-watch.nuspec @@ -0,0 +1,26 @@ + + + + dotnet-watch + dotnet watch + $version$ + Microsoft + Microsoft + $licenseUrl$ + $projectUrl$ + $iconUrl$ + $description$ + $copyright$ + true + $serviceable$ + + + + + + + + + + + diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj b/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj deleted file mode 100644 index 0ace1e9148..0000000000 --- a/test/Microsoft.DotNet.Watcher.Tools.Tests/Microsoft.DotNet.Watcher.Tools.Tests.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - netcoreapp2.1 - - - - - - - - - - - - diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj b/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj deleted file mode 100644 index cd5d68d140..0000000000 --- a/test/Microsoft.Extensions.SecretManager.Tools.Tests/Microsoft.Extensions.SecretManager.Tools.Tests.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - netcoreapp2.1 - - - - - - - - - - - - diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/MsBuildProjectFinderTest.cs b/test/dotnet-user-secrets.Tests/MsBuildProjectFinderTest.cs similarity index 100% rename from test/Microsoft.Extensions.SecretManager.Tools.Tests/MsBuildProjectFinderTest.cs rename to test/dotnet-user-secrets.Tests/MsBuildProjectFinderTest.cs diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs b/test/dotnet-user-secrets.Tests/SecretManagerTests.cs similarity index 100% rename from test/Microsoft.Extensions.SecretManager.Tools.Tests/SecretManagerTests.cs rename to test/dotnet-user-secrets.Tests/SecretManagerTests.cs diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs b/test/dotnet-user-secrets.Tests/SetCommandTest.cs similarity index 100% rename from test/Microsoft.Extensions.SecretManager.Tools.Tests/SetCommandTest.cs rename to test/dotnet-user-secrets.Tests/SetCommandTest.cs diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/TemporaryFileProvider.cs b/test/dotnet-user-secrets.Tests/TemporaryFileProvider.cs similarity index 100% rename from test/Microsoft.Extensions.SecretManager.Tools.Tests/TemporaryFileProvider.cs rename to test/dotnet-user-secrets.Tests/TemporaryFileProvider.cs diff --git a/test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs b/test/dotnet-user-secrets.Tests/UserSecretsTestFixture.cs similarity index 100% rename from test/Microsoft.Extensions.SecretManager.Tools.Tests/UserSecretsTestFixture.cs rename to test/dotnet-user-secrets.Tests/UserSecretsTestFixture.cs diff --git a/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj b/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj new file mode 100644 index 0000000000..360e9301cf --- /dev/null +++ b/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj @@ -0,0 +1,17 @@ + + + + netcoreapp2.1 + Microsoft.Extensions.SecretManager.Tools.Tests + + + + + + + + + + + + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs b/test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AppWithDepsTests.cs rename to test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs b/test/dotnet-watch.FunctionalTests/AwaitableProcess.cs similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/AwaitableProcess.cs rename to test/dotnet-watch.FunctionalTests/AwaitableProcess.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/DotNetWatcherTests.cs b/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/DotNetWatcherTests.cs rename to test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs b/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/FileWatcherTests.cs rename to test/dotnet-watch.FunctionalTests/FileWatcherTests.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs b/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/GlobbingAppTests.cs rename to test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/NoDepsAppTests.cs rename to test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs similarity index 80% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs rename to test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs index e212b51086..dc90313fab 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -39,6 +39,8 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public string WorkFolder { get; } + public string DotNetWatchPath { get; } = Path.Combine(AppContext.BaseDirectory, "tool", "dotnet-watch.dll"); + public void AddTestProjectFolder(string projectName) { var srcFolder = Path.Combine(TestProjectSourceRoot, projectName); @@ -150,39 +152,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests File.Copy(nugetConfigFilePath, tempNugetConfigFile); } - public IEnumerable GetDotnetWatchArguments() - { - // this launches a new .NET Core process using the runtime of the current test app - // and the version of dotnet-watch that this test app is compiled against - var thisAssembly = Path.GetFileNameWithoutExtension(GetType().GetTypeInfo().Assembly.Location); - - var args = new List - { - "exec", - "--depsfile", - Path.Combine(AppContext.BaseDirectory, thisAssembly + ".deps.json"), - "--runtimeconfig", - Path.Combine(AppContext.BaseDirectory, thisAssembly + ".runtimeconfig.json") - }; - - if (AppContext.GetData("FX_DEPS_FILE") is string currentFxVersion) - { - // This overrides the version of shared fx in the runtimeconfig.json file. - // Tests do this to ensure dotnet-watch is executing on the version of Microsoft.NETCore.App - // used by the current test project. The test project can target multiple version of - // netcoreapp1.x in order to ensure the tool runs when it is lifted to higher netcore versions - // due to inclusion of the 'prefercliruntime' file in our nupkg. - - var version = new FileInfo(currentFxVersion).Directory.Name; - args.Add("--fx-version"); - args.Add(version); - } - - args.Add(Path.Combine(AppContext.BaseDirectory, "dotnet-watch.dll")); - - return args; - } - private static string FindNugetConfig() { var currentDirPath = AppContext.BaseDirectory; @@ -216,4 +185,4 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } } } -} \ No newline at end of file +} diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs b/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs similarity index 96% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs rename to test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs index d204d5159a..88c322b382 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs +++ b/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs @@ -69,9 +69,11 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests throw new InvalidOperationException($"Call {nameof(PrepareAsync)} first"); } - var args = Scenario - .GetDotnetWatchArguments() - .Concat(arguments); + var args = new List + { + Scenario.DotNetWatchPath, + }; + args.AddRange(arguments); var spec = new ProcessSpec { diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj b/test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj rename to test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/Program.cs b/test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/Program.cs similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/AppWithDeps/Program.cs rename to test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/Program.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj b/test/dotnet-watch.FunctionalTests/TestProjects/Dependency/Dependency.csproj similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Dependency.csproj rename to test/dotnet-watch.FunctionalTests/TestProjects/Dependency/Dependency.csproj diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Foo.cs b/test/dotnet-watch.FunctionalTests/TestProjects/Dependency/Foo.cs similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/Dependency/Foo.cs rename to test/dotnet-watch.FunctionalTests/TestProjects/Dependency/Foo.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj b/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj rename to test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/Program.cs b/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/Program.cs similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/Program.cs rename to test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/Program.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/exclude/Baz.cs b/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/exclude/Baz.cs similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/exclude/Baz.cs rename to test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/exclude/Baz.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/include/Foo.cs b/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/include/Foo.cs similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/GlobbingApp/include/Foo.cs rename to test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/include/Foo.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj b/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj old mode 100755 new mode 100644 similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj rename to test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/Program.cs b/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/Program.cs old mode 100755 new mode 100644 similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/Program.cs rename to test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/Program.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj b/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj rename to test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/Program.cs b/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/Program.cs similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/NoDepsApp/Program.cs rename to test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/Program.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj b/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj similarity index 66% rename from test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj rename to test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj index 06434ae064..04d8118bc1 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Microsoft.DotNet.Watcher.Tools.FunctionalTests.csproj +++ b/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj @@ -3,17 +3,17 @@ netcoreapp2.1 $(DefaultItemExcludes);TestProjects\**\* + Microsoft.DotNet.Watcher.Tools.FunctionalTests - - - + + @@ -25,4 +25,10 @@ + + + + diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs b/test/dotnet-watch.Tests/AssertEx.cs similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.Tests/AssertEx.cs rename to test/dotnet-watch.Tests/AssertEx.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs b/test/dotnet-watch.Tests/CommandLineOptionsTests.cs similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.Tests/CommandLineOptionsTests.cs rename to test/dotnet-watch.Tests/CommandLineOptionsTests.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/ConsoleReporterTests.cs b/test/dotnet-watch.Tests/ConsoleReporterTests.cs similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.Tests/ConsoleReporterTests.cs rename to test/dotnet-watch.Tests/ConsoleReporterTests.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs b/test/dotnet-watch.Tests/MsBuildFileSetFactoryTest.cs similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.Tests/MsBuildFileSetFactoryTest.cs rename to test/dotnet-watch.Tests/MsBuildFileSetFactoryTest.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/ProgramTests.cs b/test/dotnet-watch.Tests/ProgramTests.cs similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.Tests/ProgramTests.cs rename to test/dotnet-watch.Tests/ProgramTests.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryCSharpProject.cs b/test/dotnet-watch.Tests/Utilities/TemporaryCSharpProject.cs similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryCSharpProject.cs rename to test/dotnet-watch.Tests/Utilities/TemporaryCSharpProject.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryDirectory.cs b/test/dotnet-watch.Tests/Utilities/TemporaryDirectory.cs similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TemporaryDirectory.cs rename to test/dotnet-watch.Tests/Utilities/TemporaryDirectory.cs diff --git a/test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TestProjectGraph.cs b/test/dotnet-watch.Tests/Utilities/TestProjectGraph.cs similarity index 100% rename from test/Microsoft.DotNet.Watcher.Tools.Tests/Utilities/TestProjectGraph.cs rename to test/dotnet-watch.Tests/Utilities/TestProjectGraph.cs diff --git a/test/dotnet-watch.Tests/dotnet-watch.Tests.csproj b/test/dotnet-watch.Tests/dotnet-watch.Tests.csproj new file mode 100644 index 0000000000..ce5349ad3e --- /dev/null +++ b/test/dotnet-watch.Tests/dotnet-watch.Tests.csproj @@ -0,0 +1,16 @@ + + + + netcoreapp2.1 + Microsoft.DotNet.Watcher.Tools.Tests + + + + + + + + + + + From 7934d538e2ab3875985dba782c03f5e8fa977d8d Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 31 Dec 2017 20:46:14 +0000 Subject: [PATCH 0649/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 1a6ed69d4b..f73f04b017 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15639 - 2.1.0-preview1-27871 - 2.1.0-preview1-27871 - 2.1.0-preview1-27871 - 2.1.0-preview1-27871 - 2.1.0-preview1-27871 + 2.1.0-preview1-15651 + 2.1.0-preview1-27942 + 2.1.0-preview1-27942 + 2.1.0-preview1-27942 + 2.1.0-preview1-27942 + 2.1.0-preview1-27942 2.0.0 2.1.0-preview1-26016-05 15.3.0 From 48cc16eadc2e58190fdf8100cdec1653da08a6d8 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 31 Dec 2017 21:05:44 +0000 Subject: [PATCH 0650/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 766fe3e033..e5e9ff8abf 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,11 +3,11 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15626 - 2.1.0-preview1-27849 - 2.1.0-preview1-27849 - 2.1.0-preview1-27849 - 2.1.0-preview1-27849 + 2.1.0-preview1-15651 + 2.1.0-preview1-27942 + 2.1.0-preview1-27942 + 2.1.0-preview1-27942 + 2.1.0-preview1-27942 2.0.0 2.1.0-preview1-26016-05 15.3.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 8d52a6128c..7c2e97aa79 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15626 -commithash:fd6410e9c90c428bc01238372303ad09cb9ec889 +version:2.1.0-preview1-15651 +commithash:ebf2365121c2c6a6a0fbfa9b0f37bb5effc89323 From a7589fbd7d132b02efb553e8a3c339559c1dfe44 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 31 Dec 2017 21:18:01 +0000 Subject: [PATCH 0651/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 6 +++--- korebuild-lock.txt | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 06cca20623..71f186007d 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15626 - 2.1.0-preview1-27849 + 2.1.0-preview1-15651 + 2.1.0-preview1-27942 4.5.0-preview1-26016-05 - 2.1.0-preview1-27849 + 2.1.0-preview1-27942 2.0.0 2.1.0-preview1-26016-05 15.3.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 8d52a6128c..7c2e97aa79 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15626 -commithash:fd6410e9c90c428bc01238372303ad09cb9ec889 +version:2.1.0-preview1-15651 +commithash:ebf2365121c2c6a6a0fbfa9b0f37bb5effc89323 From 721e8ac93921ee5655f4208f620a19e1edc23b81 Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Tue, 2 Jan 2018 14:25:50 -0800 Subject: [PATCH 0652/1029] Create ISSUE_TEMPLATE.md --- .github/ISSUE_TEMPLATE.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000000..101a084f0a --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,3 @@ +THIS ISSUE TRACKER IS CLOSED - please log new issues here: https://github.com/aspnet/Home/issues + +For information about this change, see https://github.com/aspnet/Announcements/issues/283 From 6a1046d3b9bfc53baf74127b21f8310516cf5e32 Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Tue, 2 Jan 2018 14:34:07 -0800 Subject: [PATCH 0653/1029] Create ISSUE_TEMPLATE.md --- .github/ISSUE_TEMPLATE.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000000..101a084f0a --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,3 @@ +THIS ISSUE TRACKER IS CLOSED - please log new issues here: https://github.com/aspnet/Home/issues + +For information about this change, see https://github.com/aspnet/Announcements/issues/283 From b7e29773337096bed5b602869b5d0d3e4e3f15b2 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 4 Jan 2018 00:51:33 +0000 Subject: [PATCH 0654/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index f73f04b017..58794885bc 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,11 +4,11 @@ 2.1.0-preview1-15651 - 2.1.0-preview1-27942 - 2.1.0-preview1-27942 - 2.1.0-preview1-27942 - 2.1.0-preview1-27942 - 2.1.0-preview1-27942 + 2.1.0-preview1-27965 + 2.1.0-preview1-27965 + 2.1.0-preview1-27965 + 2.1.0-preview1-27965 + 2.1.0-preview1-27965 2.0.0 2.1.0-preview1-26016-05 15.3.0 From 0f65354175f9cfdcd48c37902a1bd6311d8a278e Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 4 Jan 2018 01:12:22 +0000 Subject: [PATCH 0655/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index e5e9ff8abf..c5a5bf4ea0 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,10 +4,10 @@ 2.1.0-preview1-15651 - 2.1.0-preview1-27942 - 2.1.0-preview1-27942 - 2.1.0-preview1-27942 - 2.1.0-preview1-27942 + 2.1.0-preview1-27965 + 2.1.0-preview1-27965 + 2.1.0-preview1-27965 + 2.1.0-preview1-27965 2.0.0 2.1.0-preview1-26016-05 15.3.0 From add34207364e4eb8a918ee46af8ddef1f430f7cb Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 4 Jan 2018 01:24:28 +0000 Subject: [PATCH 0656/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 71f186007d..8ebfd2751f 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,9 +4,9 @@ 2.1.0-preview1-15651 - 2.1.0-preview1-27942 + 2.1.0-preview1-27965 4.5.0-preview1-26016-05 - 2.1.0-preview1-27942 + 2.1.0-preview1-27965 2.0.0 2.1.0-preview1-26016-05 15.3.0 From 9f5b1aa18a689ea92f04012078943aa594e8a446 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Sat, 6 Jan 2018 12:25:23 -0800 Subject: [PATCH 0657/1029] Update README to indicate dotnet-install is for prerelease versions of the CLI [ci skip] Close #375 --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 111174914c..47681c659e 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,9 @@ The repository contains command-line tools for the .NET Core CLI. Follow the lin ## How to Install +:warning: These instructions currently require a prerelease version of the [.NET Core SDK](https://github.com/dotnet/cli). +For stable, released versions of the tools, see [these instructions](https://github.com/aspnet/DotNetTools/tree/release/2.0.0#how-to-install). + Install tools using the .NET Core command-line. ``` @@ -24,7 +27,6 @@ dotnet install tool dotnet-watch dotnet install tool dotnet-user-secrets dotnet install tool dotnet-dev-certs dotnet install tool dotnet-sql-cache - ``` ## Usage From 3746bf4286db95096849e2b064069ef24616d026 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sat, 6 Jan 2018 14:44:10 -0800 Subject: [PATCH 0658/1029] Update dependencies.props [auto-updated: dependencies] --- korebuild-lock.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 7c2e97aa79..2146d006d7 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15651 -commithash:ebf2365121c2c6a6a0fbfa9b0f37bb5effc89323 +version:2.1.0-preview1-15661 +commithash:c9349d4c8a495d3085d9b879214d80f2f45e2193 From 8f09923324ec5f9f9f58adf43e414edf978874c1 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sat, 6 Jan 2018 14:57:37 -0800 Subject: [PATCH 0659/1029] Update dependencies.props [auto-updated: dependencies] --- korebuild-lock.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 7c2e97aa79..2146d006d7 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15651 -commithash:ebf2365121c2c6a6a0fbfa9b0f37bb5effc89323 +version:2.1.0-preview1-15661 +commithash:c9349d4c8a495d3085d9b879214d80f2f45e2193 From 74229e57db589fac3d836e424966692629037d89 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Tue, 9 Jan 2018 11:10:29 -0800 Subject: [PATCH 0660/1029] Fix FunctionalTests on fresh system --- .gitignore | 1 + .../Scenario/ProjectToolScenario.cs | 7 +++-- .../dotnet-watch.FunctionalTests.csproj | 26 +++++++++++++++++++ .../MsBuildFileSetFactoryTest.cs | 25 +++++++++--------- .../Utilities/TemporaryDirectory.cs | 2 +- 5 files changed, 46 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index ddc5e01720..78ed833761 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,4 @@ testWorkDir/ .dotnet/ global.json *.binlog +test/dotnet-watch.FunctionalTests/TestProjects/NuGet.config \ No newline at end of file diff --git a/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs index dc90313fab..a11310c6e9 100644 --- a/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -35,7 +35,10 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests CreateTestDirectory(); } - public string TempFolder { get; } = Path.Combine(Path.GetDirectoryName(FindNugetConfig()), "testWorkDir", Guid.NewGuid().ToString("N")); + + public static string TestWorkFolder { get; } = Path.Combine(AppContext.BaseDirectory, "testWorkDir"); + + public string TempFolder { get; } = Path.Combine(TestWorkFolder, Guid.NewGuid().ToString("N")); public string WorkFolder { get; } @@ -154,7 +157,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests private static string FindNugetConfig() { - var currentDirPath = AppContext.BaseDirectory; + var currentDirPath = TestWorkFolder; string nugetConfigFile; while (true) diff --git a/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj b/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj index 04d8118bc1..5d97fcca6f 100644 --- a/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj +++ b/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj @@ -21,6 +21,32 @@ + + + $(MSBuildThisFileDirectory)/TestProjects/NuGet.config + + + + + + + + + + + + + + + + + + + diff --git a/test/dotnet-watch.Tests/MsBuildFileSetFactoryTest.cs b/test/dotnet-watch.Tests/MsBuildFileSetFactoryTest.cs index 572b021f80..c34111b239 100644 --- a/test/dotnet-watch.Tests/MsBuildFileSetFactoryTest.cs +++ b/test/dotnet-watch.Tests/MsBuildFileSetFactoryTest.cs @@ -83,6 +83,7 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests .SubDir("src") .SubDir("Project1") .WithCSharpProject("Project1", out var target) + .WithProperty("BaseIntermediateOutputPath", "obj") .WithTargetFrameworks("netcoreapp1.0") .Dir() .WithFile("Program.cs") @@ -111,18 +112,18 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests [Fact] public async Task MultiTfm() { - _tempDir - .SubDir("src") - .SubDir("Project1") - .WithCSharpProject("Project1", out var target) - .WithTargetFrameworks("netcoreapp1.0", "net451") - .WithProperty("EnableDefaultCompileItems", "false") - .WithItem("Compile", "Class1.netcore.cs", "'$(TargetFramework)'=='netcoreapp1.0'") - .WithItem("Compile", "Class1.desktop.cs", "'$(TargetFramework)'=='net451'") - .Dir() - .WithFile("Class1.netcore.cs") - .WithFile("Class1.desktop.cs") - .WithFile("Class1.notincluded.cs"); + _tempDir + .SubDir("src") + .SubDir("Project1") + .WithCSharpProject("Project1", out var target) + .WithTargetFrameworks("netcoreapp1.0", "net451") + .WithProperty("EnableDefaultCompileItems", "false") + .WithItem("Compile", "Class1.netcore.cs", "'$(TargetFramework)'=='netcoreapp1.0'") + .WithItem("Compile", "Class1.desktop.cs", "'$(TargetFramework)'=='net451'") + .Dir() + .WithFile("Class1.netcore.cs") + .WithFile("Class1.desktop.cs") + .WithFile("Class1.notincluded.cs"); var fileset = await GetFileSet(target); diff --git a/test/dotnet-watch.Tests/Utilities/TemporaryDirectory.cs b/test/dotnet-watch.Tests/Utilities/TemporaryDirectory.cs index 26f36ec5f0..692899817e 100644 --- a/test/dotnet-watch.Tests/Utilities/TemporaryDirectory.cs +++ b/test/dotnet-watch.Tests/Utilities/TemporaryDirectory.cs @@ -104,4 +104,4 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests } } } -} \ No newline at end of file +} From a036fa6bf4ef5f1e5dc16ead54a519748cdf385a Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Thu, 4 Jan 2018 14:24:58 -0800 Subject: [PATCH 0661/1029] Add support for cleaning certificates on the machine to the dev-certs tool --- build/dependencies.props | 16 ++++----- src/dotnet-dev-certs/Program.cs | 63 +++++++++++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 58794885bc..bc74981c7b 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,16 +4,16 @@ 2.1.0-preview1-15651 - 2.1.0-preview1-27965 - 2.1.0-preview1-27965 - 2.1.0-preview1-27965 - 2.1.0-preview1-27965 - 2.1.0-preview1-27965 + 2.1.0-preview1-27997 + 2.1.0-preview1-27997 + 2.1.0-preview1-27997 + 2.1.0-preview1-27997 + 2.1.0-preview1-27997 2.0.0 - 2.1.0-preview1-26016-05 + 2.1.0-preview1-26102-01 15.3.0 - 4.5.0-preview1-26016-05 - 4.5.0-preview1-26016-05 + 4.5.0-preview1-26102-01 + 4.5.0-preview1-26102-01 9.0.1 2.3.1 2.3.1 diff --git a/src/dotnet-dev-certs/Program.cs b/src/dotnet-dev-certs/Program.cs index d1d5cfabaf..cda4f906c6 100644 --- a/src/dotnet-dev-certs/Program.cs +++ b/src/dotnet-dev-certs/Program.cs @@ -23,6 +23,7 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools private const int ErrorUserCancelledTrustPrompt = 5; private const int ErrorNoValidCertificateFound = 6; private const int ErrorCertificateNotTrusted = 7; + private const int ErrorCleaningUpCertificates = 8; public static readonly TimeSpan HttpsCertificateValidity = TimeSpan.FromDays(365); @@ -50,6 +51,11 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools "Check for the existence of the certificate but do not perform any action", CommandOptionType.NoValue); + var clean = c.Option( + "--clean", + "Cleans all HTTPS development certificates from the machine.", + CommandOptionType.NoValue); + CommandOption trust = null; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { @@ -71,10 +77,25 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools c.OnExecute(() => { var reporter = new ConsoleReporter(PhysicalConsole.Singleton, verbose.HasValue(), quiet.HasValue()); + if ((clean.HasValue() && (exportPath.HasValue() || password.HasValue() || trust?.HasValue() == true)) || + (check.HasValue() && (exportPath.HasValue() || password.HasValue() || clean.HasValue()))) + { + reporter.Error(@"Incompatible set of flags. Sample usages +'dotnet dev-certs https --clean' +'dotnet dev-certs https --check --trust' +'dotnet dev-certs https -ep ./certificate.pfx -p password --trust'"); + } + if (check.HasValue()) { - return CheckHttpsCertificate(check, trust, reporter); + return CheckHttpsCertificate(trust, reporter); } + + if (clean.HasValue()) + { + return CleanHttpsCertificates(reporter); + } + return EnsureHttpsCertificate(exportPath, password, trust, reporter); }); }); @@ -95,7 +116,36 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools } } - private static int CheckHttpsCertificate(CommandOption check, CommandOption trust, IReporter reporter) + private static int CleanHttpsCertificates(IReporter reporter) + { + var manager = new CertificateManager(); + try + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + reporter.Output("Cleaning HTTPS development certificates from the machine. A prompt might get " + + "displayed to confirm the removal of some of the certificates."); + } + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + reporter.Output("Cleaning HTTPS development certificates from the machine. This operation might " + + "require elevated privileges. If that is the case, a prompt for credentials will be displayed."); + } + + manager.CleanupHttpsCertificates(); + reporter.Verbose("HTTPS development certificates successfully removed from the machine."); + return Success; + } + catch(Exception e) + { + reporter.Error("There was an error trying to clean HTTPS development certificates on this machine."); + reporter.Error(e.Message); + + return ErrorCleaningUpCertificates; + } + } + + private static int CheckHttpsCertificate(CommandOption trust, IReporter reporter) { var now = DateTimeOffset.Now; var certificateManager = new CertificateManager(); @@ -112,7 +162,8 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools if (trust != null && trust.HasValue()) { - var trustedCertificates = certificateManager.ListCertificates(CertificatePurpose.HTTPS, StoreName.Root, StoreLocation.CurrentUser, isValid: true, requireExportable: false); + var store = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? StoreName.My : StoreName.Root; + var trustedCertificates = certificateManager.ListCertificates(CertificatePurpose.HTTPS, store, StoreLocation.CurrentUser, isValid: true); if (!certificates.Any(c => certificateManager.IsTrusted(c))) { reporter.Verbose($@"The following certificates were found, but none of them is trusted: @@ -142,6 +193,12 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools "on the system keychain."); } + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && trust?.HasValue() == true) + { + reporter.Warn("Trusting the HTTPS development certificate was requested. A confirmation prompt will be displayed " + + "if the certificate was not previously trusted. Click yes on the prompt to trust the certificate."); + } + var result = manager.EnsureAspNetCoreHttpsDevelopmentCertificate( now, now.Add(HttpsCertificateValidity), From d4adf148190e15d61d8c9242b56f88c07b24824b Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 12 Jan 2018 12:17:27 -0800 Subject: [PATCH 0662/1029] Update exclusions for nuget package verifier --- NuGetPackageVerifier.json | 15 +++++++++++++-- korebuild-lock.txt | 4 ++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index 171ae87771..b471106339 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -22,7 +22,11 @@ "tools/netcoreapp2.1/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_INFORMATIONAL_VERSION_MISMATCH": { - "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." } } }, @@ -46,7 +50,14 @@ "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_INFORMATIONAL_VERSION_MISMATCH": { - "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + }, + "ASSEMBLY_FILE_VERSION_MISMATCH": { + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + }, + "ASSEMBLY_VERSION_MISMATCH": { + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." } } }, diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 09bd77accb..db31b63687 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15651 -commithash:ebf2365121c2c6a6a0fbfa9b0f37bb5effc89323 +version:2.1.0-preview1-15670 +commithash:49176144e03c3015d83b21e3f1d0ce093c05ecc3 From e53e74c6a65963eb913950405607fe055522189d Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 17 Jan 2018 10:22:12 -0800 Subject: [PATCH 0663/1029] Fix broken link in readme [ci skip] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 47681c659e..7e245fe013 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ The repository contains command-line tools for the .NET Core CLI. Follow the lin ## How to Install :warning: These instructions currently require a prerelease version of the [.NET Core SDK](https://github.com/dotnet/cli). -For stable, released versions of the tools, see [these instructions](https://github.com/aspnet/DotNetTools/tree/release/2.0.0#how-to-install). +For stable, released versions of the tools, see [these instructions](https://github.com/aspnet/DotNetTools/tree/release/2.0#how-to-install). Install tools using the .NET Core command-line. From c6aa71ddc46244eca1677583b807bd203f304bb5 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 23 Jan 2018 15:30:45 -0800 Subject: [PATCH 0664/1029] Branching for 2.1.0-preview1 --- build/dependencies.props | 18 +++++++++--------- build/repo.props | 4 ++-- build/sources.props | 4 ++-- korebuild-lock.txt | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index bc74981c7b..35ddc13904 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15651 - 2.1.0-preview1-27997 - 2.1.0-preview1-27997 - 2.1.0-preview1-27997 - 2.1.0-preview1-27997 - 2.1.0-preview1-27997 + 2.1.0-preview1-15679 + 2.1.0-preview1-28153 + 2.1.0-preview1-28153 + 2.1.0-preview1-28153 + 2.1.0-preview1-28153 + 2.1.0-preview1-28153 2.0.0 - 2.1.0-preview1-26102-01 + 2.1.0-preview1-26115-03 15.3.0 - 4.5.0-preview1-26102-01 - 4.5.0-preview1-26102-01 + 4.5.0-preview1-26112-01 + 4.5.0-preview1-26112-01 9.0.1 2.3.1 2.3.1 diff --git a/build/repo.props b/build/repo.props index 1be3632130..91a4b29fcf 100644 --- a/build/repo.props +++ b/build/repo.props @@ -1,4 +1,4 @@ - + @@ -10,7 +10,7 @@ Internal.AspNetCore.Universe.Lineup - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json + https://dotnet.myget.org/F/aspnetcore-release/api/v3/index.json diff --git a/build/sources.props b/build/sources.props index 903de4e87b..c523a08884 100644 --- a/build/sources.props +++ b/build/sources.props @@ -1,11 +1,11 @@ - + $(DotNetRestoreSources) $(RestoreSources); - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; + https://dotnet.myget.org/F/aspnetcore-release/api/v3/index.json; https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; https://vside.myget.org/F/vssdk/api/v3/index.json; diff --git a/korebuild-lock.txt b/korebuild-lock.txt index db31b63687..0518052b1b 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15670 -commithash:49176144e03c3015d83b21e3f1d0ce093c05ecc3 +version:2.1.0-preview1-15679 +commithash:5347461137cb45a77ddcc0b55b2478092de43338 From d208eca57fdd0af1e2a638eb2feed891dc8aa146 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 23 Jan 2018 15:31:08 -0800 Subject: [PATCH 0665/1029] Branching for 2.1.0-preview1 --- build/dependencies.props | 14 +++++++------- build/repo.props | 4 ++-- build/sources.props | 4 ++-- korebuild-lock.txt | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index c5a5bf4ea0..aacad395d0 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,15 +3,15 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15651 - 2.1.0-preview1-27965 - 2.1.0-preview1-27965 - 2.1.0-preview1-27965 - 2.1.0-preview1-27965 + 2.1.0-preview1-15679 + 2.1.0-preview1-28153 + 2.1.0-preview1-28153 + 2.1.0-preview1-28153 + 2.1.0-preview1-28153 2.0.0 - 2.1.0-preview1-26016-05 + 2.1.0-preview1-26115-03 15.3.0 - 4.5.0-preview1-26016-05 + 4.5.0-preview1-26112-01 2.3.1 2.3.1 diff --git a/build/repo.props b/build/repo.props index 78b0ce5879..d94ff7d00d 100644 --- a/build/repo.props +++ b/build/repo.props @@ -1,10 +1,10 @@ - + Internal.AspNetCore.Universe.Lineup - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json + https://dotnet.myget.org/F/aspnetcore-release/api/v3/index.json diff --git a/build/sources.props b/build/sources.props index 9feff29d09..5d66393335 100644 --- a/build/sources.props +++ b/build/sources.props @@ -1,11 +1,11 @@ - + $(DotNetRestoreSources) $(RestoreSources); - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; + https://dotnet.myget.org/F/aspnetcore-release/api/v3/index.json; https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 2146d006d7..a474bc0e35 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15661 -commithash:c9349d4c8a495d3085d9b879214d80f2f45e2193 +version:2.1.0-preview1-15679 +commithash:5347461137cb45a77ddcc0b55b2478092de43338 From eafe3e7aa39c4023883394d4fbab16131d190295 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 23 Jan 2018 15:31:40 -0800 Subject: [PATCH 0666/1029] Branching for 2.1.0-preview1 --- build/dependencies.props | 10 +++++----- build/repo.props | 4 ++-- build/sources.props | 4 ++-- korebuild-lock.txt | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 8ebfd2751f..5382af18d5 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15651 - 2.1.0-preview1-27965 - 4.5.0-preview1-26016-05 - 2.1.0-preview1-27965 + 2.1.0-preview1-15679 + 2.1.0-preview1-28153 + 4.5.0-preview1-26112-01 + 2.1.0-preview1-28153 2.0.0 - 2.1.0-preview1-26016-05 + 2.1.0-preview1-26115-03 15.3.0 4.7.49 10.0.1 diff --git a/build/repo.props b/build/repo.props index 78b0ce5879..d94ff7d00d 100644 --- a/build/repo.props +++ b/build/repo.props @@ -1,10 +1,10 @@ - + Internal.AspNetCore.Universe.Lineup - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json + https://dotnet.myget.org/F/aspnetcore-release/api/v3/index.json diff --git a/build/sources.props b/build/sources.props index 9feff29d09..5d66393335 100644 --- a/build/sources.props +++ b/build/sources.props @@ -1,11 +1,11 @@ - + $(DotNetRestoreSources) $(RestoreSources); - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; + https://dotnet.myget.org/F/aspnetcore-release/api/v3/index.json; https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 2146d006d7..a474bc0e35 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15661 -commithash:c9349d4c8a495d3085d9b879214d80f2f45e2193 +version:2.1.0-preview1-15679 +commithash:5347461137cb45a77ddcc0b55b2478092de43338 From da8675306bf0ede6f13c3cefcc58d8898db536e8 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 24 Jan 2018 09:48:04 -0800 Subject: [PATCH 0667/1029] Do not include debug symbols in the secret manager vsix --- .../Microsoft.VisualStudio.SecretManager.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj b/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj index dfe6fa36bd..9c3fed86b6 100644 --- a/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj +++ b/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj @@ -34,7 +34,7 @@ v4.6.1 true true - true + false true true false From 26c76a2f17c590ab21651d32eabe25f968b682eb Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 24 Jan 2018 15:00:27 -0800 Subject: [PATCH 0668/1029] Updating version to preview2 --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 5c4a7c32d1..370d5ababd 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ 2.1.0 - preview1 + preview2 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From 8fb433d276a2ce76e706cf26391abb0c02fa24a5 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 24 Jan 2018 15:00:28 -0800 Subject: [PATCH 0669/1029] Updating version to preview2 --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 5c4a7c32d1..370d5ababd 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ 2.1.0 - preview1 + preview2 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From af8d61395f0aa052dbde8a053c8198982587013f Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 24 Jan 2018 16:09:20 -0800 Subject: [PATCH 0670/1029] React to changes in package layout requirements for global CLI tools (#385) --- .appveyor.yml | 4 +- .travis.yml | 4 +- NuGetPackageVerifier.json | 40 +++++++++---------- README.md | 8 ++-- build/dependencies.props | 3 +- korebuild-lock.txt | 4 +- src/DotnetTool.props | 2 +- src/PackGlobalTool.targets | 1 + src/dotnet-dev-certs/README.md | 16 ++++++++ src/dotnet-dev-certs/dotnet-dev-certs.nuspec | 9 +++-- src/dotnet-sql-cache/README.md | 2 +- src/dotnet-sql-cache/dotnet-sql-cache.csproj | 2 +- src/dotnet-sql-cache/dotnet-sql-cache.nuspec | 9 +++-- src/dotnet-user-secrets/README.md | 2 +- .../dotnet-user-secrets.csproj | 2 +- .../dotnet-user-secrets.nuspec | 9 +++-- src/dotnet-watch/README.md | 2 +- src/dotnet-watch/dotnet-watch.nuspec | 9 +++-- 18 files changed, 77 insertions(+), 51 deletions(-) create mode 100644 src/dotnet-dev-certs/README.md diff --git a/.appveyor.yml b/.appveyor.yml index 6ee7cf4664..bc0f3e7285 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -2,10 +2,8 @@ init: - git config --global core.autocrlf true branches: only: - - master - - release - - /^rel\/.*/ - dev + - /^release\/.*/ - /^(.*\/)?ci-.*$/ build_script: - ps: .\run.ps1 default-build diff --git a/.travis.yml b/.travis.yml index fb3f3a84c2..e8c0bc04ea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,10 +16,8 @@ addons: - libunwind8 branches: only: - - master - - release - dev - - /^rel\/.*/ + - /^release\/.*/ - /^(.*\/)?ci-.*$/ before_install: - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; fi diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index b471106339..f0c02acf43 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -15,18 +15,18 @@ ], "Exclusions": { "WRONG_PUBLICKEYTOKEN": { - "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/any/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_INFORMATIONAL_VERSION_MISMATCH": { - "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/any/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." } } }, @@ -36,28 +36,28 @@ ], "Exclusions": { "NEUTRAL_RESOURCES_LANGUAGE": { - "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/any/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." }, "SERVICING_ATTRIBUTE": { - "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/any/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg." }, "VERSION_INFORMATIONALVERSION": { - "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/any/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg." }, "WRONG_PUBLICKEYTOKEN": { - "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/any/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_INFORMATIONAL_VERSION_MISMATCH": { - "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/any/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_FILE_VERSION_MISMATCH": { - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_VERSION_MISMATCH": { - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." } } }, diff --git a/README.md b/README.md index 7e245fe013..65998d0c54 100644 --- a/README.md +++ b/README.md @@ -23,10 +23,10 @@ For stable, released versions of the tools, see [these instructions](https://git Install tools using the .NET Core command-line. ``` -dotnet install tool dotnet-watch -dotnet install tool dotnet-user-secrets -dotnet install tool dotnet-dev-certs -dotnet install tool dotnet-sql-cache +dotnet install tool --global dotnet-watch +dotnet install tool --global dotnet-user-secrets +dotnet install tool --global dotnet-dev-certs +dotnet install tool --global dotnet-sql-cache ``` ## Usage diff --git a/build/dependencies.props b/build/dependencies.props index 35ddc13904..bc7916c4e3 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,7 +3,7 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15679 + 2.1.0-preview1-15681 2.1.0-preview1-28153 2.1.0-preview1-28153 2.1.0-preview1-28153 @@ -11,6 +11,7 @@ 2.1.0-preview1-28153 2.0.0 2.1.0-preview1-26115-03 + 2.1.0-preview1-26112-01 15.3.0 4.5.0-preview1-26112-01 4.5.0-preview1-26112-01 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 0518052b1b..ad4b437219 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15679 -commithash:5347461137cb45a77ddcc0b55b2478092de43338 +version:2.1.0-preview1-15681 +commithash:409cab8f55191829e70f2f8e307196fd6a427b4c diff --git a/src/DotnetTool.props b/src/DotnetTool.props index 04fc17a28b..75eca8d65f 100644 --- a/src/DotnetTool.props +++ b/src/DotnetTool.props @@ -11,6 +11,6 @@ - + diff --git a/src/PackGlobalTool.targets b/src/PackGlobalTool.targets index 5f498664c8..ed75c775b7 100644 --- a/src/PackGlobalTool.targets +++ b/src/PackGlobalTool.targets @@ -12,6 +12,7 @@ description=$(Description); repositoryUrl=$(RepositoryUrl); targetframework=$(TargetFramework); + MicrosoftNETCorePlatformsPackageVersion=$(MicrosoftNETCorePlatformsPackageVersion); diff --git a/src/dotnet-dev-certs/README.md b/src/dotnet-dev-certs/README.md new file mode 100644 index 0000000000..4e8aaea714 --- /dev/null +++ b/src/dotnet-dev-certs/README.md @@ -0,0 +1,16 @@ +dotnet-dev-certs +================ + +`dotnet-dev-certs` is a command line tool to generate certificates used in ASP.NET Core during development. + +### How To Install + +From the command-line, execute: + +``` +dotnet install tool --global dotnet-dev-certs +``` + +### How To Use + +Run `dotnet dev-certs --help` for more information about usage. diff --git a/src/dotnet-dev-certs/dotnet-dev-certs.nuspec b/src/dotnet-dev-certs/dotnet-dev-certs.nuspec index 7c063e6e29..e8dce16395 100644 --- a/src/dotnet-dev-certs/dotnet-dev-certs.nuspec +++ b/src/dotnet-dev-certs/dotnet-dev-certs.nuspec @@ -17,10 +17,13 @@ - + + + + - - + + diff --git a/src/dotnet-sql-cache/README.md b/src/dotnet-sql-cache/README.md index 05f7153882..9c8ca25653 100644 --- a/src/dotnet-sql-cache/README.md +++ b/src/dotnet-sql-cache/README.md @@ -8,7 +8,7 @@ dotnet-sql-cache From the command-line, execute: ``` -dotnet install tool dotnet-sql-cache +dotnet install tool --global dotnet-sql-cache ``` ### How To Use diff --git a/src/dotnet-sql-cache/dotnet-sql-cache.csproj b/src/dotnet-sql-cache/dotnet-sql-cache.csproj index 1bd0904ab5..8b7a58f538 100644 --- a/src/dotnet-sql-cache/dotnet-sql-cache.csproj +++ b/src/dotnet-sql-cache/dotnet-sql-cache.csproj @@ -5,7 +5,7 @@ exe Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching. DotnetTool - tools/$(TargetFramework)/any/ + tools/any/any/ diff --git a/src/dotnet-sql-cache/dotnet-sql-cache.nuspec b/src/dotnet-sql-cache/dotnet-sql-cache.nuspec index 3c198fc163..a2498a00d2 100644 --- a/src/dotnet-sql-cache/dotnet-sql-cache.nuspec +++ b/src/dotnet-sql-cache/dotnet-sql-cache.nuspec @@ -17,10 +17,13 @@ - + + + + - - + + diff --git a/src/dotnet-user-secrets/README.md b/src/dotnet-user-secrets/README.md index 33d9e0cae0..50e4fbdb06 100644 --- a/src/dotnet-user-secrets/README.md +++ b/src/dotnet-user-secrets/README.md @@ -8,7 +8,7 @@ dotnet-user-secrets From the command-line, execute: ``` -dotnet install tool dotnet-user-secrets +dotnet install tool --global dotnet-user-secrets ``` ### How To Use diff --git a/src/dotnet-user-secrets/dotnet-user-secrets.csproj b/src/dotnet-user-secrets/dotnet-user-secrets.csproj index d979f1a355..9f578a0c36 100644 --- a/src/dotnet-user-secrets/dotnet-user-secrets.csproj +++ b/src/dotnet-user-secrets/dotnet-user-secrets.csproj @@ -7,7 +7,7 @@ DotnetTool false Microsoft.Extensions.SecretManager.Tools - tools/$(TargetFramework)/any/ + tools/any/any/ diff --git a/src/dotnet-user-secrets/dotnet-user-secrets.nuspec b/src/dotnet-user-secrets/dotnet-user-secrets.nuspec index 145ec4233b..fdd3fb95d5 100644 --- a/src/dotnet-user-secrets/dotnet-user-secrets.nuspec +++ b/src/dotnet-user-secrets/dotnet-user-secrets.nuspec @@ -17,10 +17,13 @@ - + + + + - - + + diff --git a/src/dotnet-watch/README.md b/src/dotnet-watch/README.md index 8fb0db78db..37725d97d4 100644 --- a/src/dotnet-watch/README.md +++ b/src/dotnet-watch/README.md @@ -7,7 +7,7 @@ dotnet-watch From the command-line, execute: ``` -dotnet install tool dotnet-watch +dotnet install tool --global dotnet-watch ``` ### How To Use diff --git a/src/dotnet-watch/dotnet-watch.nuspec b/src/dotnet-watch/dotnet-watch.nuspec index 53c4447f94..5a748260c1 100644 --- a/src/dotnet-watch/dotnet-watch.nuspec +++ b/src/dotnet-watch/dotnet-watch.nuspec @@ -17,10 +17,13 @@ - + + + + - - + + From f86bad971a63984b9af7375cacc8afbfaafaf231 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Wed, 24 Jan 2018 15:47:41 -0800 Subject: [PATCH 0671/1029] Preview2 --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 4884e87b9e..e271613fcc 100644 --- a/version.props +++ b/version.props @@ -2,7 +2,7 @@ 2.1.0 15.6 - preview1 + preview2 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final $(VsixVersion).$(BuildNumber) From 52c688c4cdc8bc5065c0ea05865664a47c0dc371 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 31 Jan 2018 15:01:11 -0800 Subject: [PATCH 0672/1029] Update dependencies.props to 2.1.0-preview-28193, build tools to 2.1.0-preview1-1010 [ci skip] Scripted changes: - updated travis and appveyor.yml files to only build dev, ci, and release branches - updated dependencies.props - updated korebuild-lock.txt - updated korebuild.json to release/2.1 channel --- .appveyor.yml | 14 +++++++------- .travis.yml | 22 ++++++++++++---------- build/dependencies.props | 20 ++++++++++---------- korebuild-lock.txt | 4 ++-- korebuild.json | 4 ++-- 5 files changed, 33 insertions(+), 31 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index bc0f3e7285..4eea96ab69 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,17 +1,17 @@ init: - - git config --global core.autocrlf true +- git config --global core.autocrlf true branches: only: - - dev - - /^release\/.*/ - - /^(.*\/)?ci-.*$/ + - dev + - /^release\/.*$/ + - /^(.*\/)?ci-.*$/ build_script: - - ps: .\run.ps1 default-build +- ps: .\run.ps1 default-build clone_depth: 1 environment: global: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: 1 -test: off -deploy: off +test: 'off' +deploy: 'off' os: Visual Studio 2017 diff --git a/.travis.yml b/.travis.yml index e8c0bc04ea..64bdbb4441 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,23 +3,25 @@ sudo: false dist: trusty env: global: - - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - - DOTNET_CLI_TELEMETRY_OPTOUT: 1 + - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + - DOTNET_CLI_TELEMETRY_OPTOUT: 1 mono: none os: - - linux - - osx +- linux +- osx osx_image: xcode8.2 addons: apt: packages: - - libunwind8 + - libunwind8 branches: only: - - dev - - /^release\/.*/ - - /^(.*\/)?ci-.*$/ + - dev + - /^release\/.*$/ + - /^(.*\/)?ci-.*$/ before_install: - - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; fi +- if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s + /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib + /usr/local/lib/; fi script: - - ./build.sh +- ./build.sh diff --git a/build/dependencies.props b/build/dependencies.props index bc7916c4e3..ede9bb247a 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,18 +3,18 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15681 - 2.1.0-preview1-28153 - 2.1.0-preview1-28153 - 2.1.0-preview1-28153 - 2.1.0-preview1-28153 - 2.1.0-preview1-28153 + 2.1.0-preview1-1010 + 2.1.0-preview1-28193 + 2.1.0-preview1-28193 + 2.1.0-preview1-28193 + 2.1.0-preview1-28193 + 2.1.0-preview1-28193 2.0.0 - 2.1.0-preview1-26115-03 - 2.1.0-preview1-26112-01 + 2.1.0-preview1-26122-01 + 2.1.0-preview1-26119-06 15.3.0 - 4.5.0-preview1-26112-01 - 4.5.0-preview1-26112-01 + 4.5.0-preview1-26119-06 + 4.5.0-preview1-26119-06 9.0.1 2.3.1 2.3.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index ad4b437219..851bfbf203 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15681 -commithash:409cab8f55191829e70f2f8e307196fd6a427b4c +version:2.1.0-preview1-1010 +commithash:75ca924dfbd673c38841025b04c4dcd93b84f56d diff --git a/korebuild.json b/korebuild.json index 4d59ad132a..196a3ca537 100644 --- a/korebuild.json +++ b/korebuild.json @@ -1,6 +1,6 @@ { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev", + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.1/tools/korebuild.schema.json", + "channel": "release/2.1", "toolsets": { "visualstudio": { "required": [ From a7219e0c5cdc1de5cf6f5871b3f2b89b9d7e5040 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 31 Jan 2018 15:01:11 -0800 Subject: [PATCH 0673/1029] Update dependencies.props to 2.1.0-preview-28193, build tools to 2.1.0-preview1-1010 [ci skip] Scripted changes: - updated travis and appveyor.yml files to only build dev, ci, and release branches - updated dependencies.props - updated korebuild-lock.txt - updated korebuild.json to release/2.1 channel --- .appveyor.yml | 15 +++++++-------- .travis.yml | 23 ++++++++++++----------- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- korebuild.json | 4 ++-- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 46038786c9..4eea96ab69 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,18 +1,17 @@ init: - - git config --global core.autocrlf true +- git config --global core.autocrlf true branches: only: - - master - - release - - dev - - /^(.*\/)?ci-.*$/ + - dev + - /^release\/.*$/ + - /^(.*\/)?ci-.*$/ build_script: - - ps: .\run.ps1 default-build +- ps: .\run.ps1 default-build clone_depth: 1 environment: global: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: 1 -test: off -deploy: off +test: 'off' +deploy: 'off' os: Visual Studio 2017 diff --git a/.travis.yml b/.travis.yml index b10be14215..64bdbb4441 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,24 +3,25 @@ sudo: false dist: trusty env: global: - - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - - DOTNET_CLI_TELEMETRY_OPTOUT: 1 + - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + - DOTNET_CLI_TELEMETRY_OPTOUT: 1 mono: none os: - - linux - - osx +- linux +- osx osx_image: xcode8.2 addons: apt: packages: - - libunwind8 + - libunwind8 branches: only: - - master - - release - - dev - - /^(.*\/)?ci-.*$/ + - dev + - /^release\/.*$/ + - /^(.*\/)?ci-.*$/ before_install: - - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; fi +- if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s + /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib + /usr/local/lib/; fi script: - - ./build.sh +- ./build.sh diff --git a/build/dependencies.props b/build/dependencies.props index aacad395d0..a3badf6fc0 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,15 +3,15 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15679 - 2.1.0-preview1-28153 - 2.1.0-preview1-28153 - 2.1.0-preview1-28153 - 2.1.0-preview1-28153 + 2.1.0-preview1-1010 + 2.1.0-preview1-28193 + 2.1.0-preview1-28193 + 2.1.0-preview1-28193 + 2.1.0-preview1-28193 2.0.0 - 2.1.0-preview1-26115-03 + 2.1.0-preview1-26122-01 15.3.0 - 4.5.0-preview1-26112-01 + 4.5.0-preview1-26119-06 2.3.1 2.3.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index a474bc0e35..851bfbf203 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15679 -commithash:5347461137cb45a77ddcc0b55b2478092de43338 +version:2.1.0-preview1-1010 +commithash:75ca924dfbd673c38841025b04c4dcd93b84f56d diff --git a/korebuild.json b/korebuild.json index bd5d51a51b..678d8bb948 100644 --- a/korebuild.json +++ b/korebuild.json @@ -1,4 +1,4 @@ { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev" + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.1/tools/korebuild.schema.json", + "channel": "release/2.1" } From 829db1aae540b51ac3b5e369ae8b13863e63ef73 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 31 Jan 2018 15:01:12 -0800 Subject: [PATCH 0674/1029] Update dependencies.props to 2.1.0-preview-28193, build tools to 2.1.0-preview1-1010 [ci skip] Scripted changes: - updated travis and appveyor.yml files to only build dev, ci, and release branches - updated dependencies.props - updated korebuild-lock.txt - updated korebuild.json to release/2.1 channel --- .appveyor.yml | 15 +++++++-------- .travis.yml | 23 ++++++++++++----------- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- korebuild.json | 4 ++-- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 46038786c9..4eea96ab69 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,18 +1,17 @@ init: - - git config --global core.autocrlf true +- git config --global core.autocrlf true branches: only: - - master - - release - - dev - - /^(.*\/)?ci-.*$/ + - dev + - /^release\/.*$/ + - /^(.*\/)?ci-.*$/ build_script: - - ps: .\run.ps1 default-build +- ps: .\run.ps1 default-build clone_depth: 1 environment: global: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: 1 -test: off -deploy: off +test: 'off' +deploy: 'off' os: Visual Studio 2017 diff --git a/.travis.yml b/.travis.yml index b10be14215..64bdbb4441 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,24 +3,25 @@ sudo: false dist: trusty env: global: - - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - - DOTNET_CLI_TELEMETRY_OPTOUT: 1 + - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + - DOTNET_CLI_TELEMETRY_OPTOUT: 1 mono: none os: - - linux - - osx +- linux +- osx osx_image: xcode8.2 addons: apt: packages: - - libunwind8 + - libunwind8 branches: only: - - master - - release - - dev - - /^(.*\/)?ci-.*$/ + - dev + - /^release\/.*$/ + - /^(.*\/)?ci-.*$/ before_install: - - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; fi +- if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s + /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib + /usr/local/lib/; fi script: - - ./build.sh +- ./build.sh diff --git a/build/dependencies.props b/build/dependencies.props index 5382af18d5..9c5ea2b351 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15679 - 2.1.0-preview1-28153 - 4.5.0-preview1-26112-01 - 2.1.0-preview1-28153 + 2.1.0-preview1-1010 + 2.1.0-preview1-28193 + 4.5.0-preview1-26119-06 + 2.1.0-preview1-28193 2.0.0 - 2.1.0-preview1-26115-03 + 2.1.0-preview1-26122-01 15.3.0 4.7.49 10.0.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index a474bc0e35..851bfbf203 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15679 -commithash:5347461137cb45a77ddcc0b55b2478092de43338 +version:2.1.0-preview1-1010 +commithash:75ca924dfbd673c38841025b04c4dcd93b84f56d diff --git a/korebuild.json b/korebuild.json index bd5d51a51b..678d8bb948 100644 --- a/korebuild.json +++ b/korebuild.json @@ -1,4 +1,4 @@ { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev" + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.1/tools/korebuild.schema.json", + "channel": "release/2.1" } From e792400c311d2cebd70ea3d45baaca08b21cdad4 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 1 Feb 2018 03:08:57 +0000 Subject: [PATCH 0675/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 20 ++++++++++---------- korebuild-lock.txt | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 07ad0f4023..62c46ee86a 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,18 +3,18 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15681 - 2.1.0-preview1-27997 - 2.1.0-preview1-27997 - 2.1.0-preview1-27997 - 2.1.0-preview1-27997 - 2.1.0-preview1-27997 + 2.1.0-preview2-15692 + 2.1.0-preview2-28215 + 2.1.0-preview2-28215 + 2.1.0-preview2-28215 + 2.1.0-preview2-28215 + 2.1.0-preview2-28215 2.0.0 - 2.1.0-preview1-26102-01 - 2.1.0-preview1-26102-01 + 2.1.0-preview2-26130-04 + 2.1.0-preview2-26130-01 15.3.0 - 4.5.0-preview1-26102-01 - 4.5.0-preview1-26102-01 + 4.5.0-preview2-26130-01 + 4.5.0-preview2-26130-01 9.0.1 2.3.1 2.3.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index ad4b437219..c76ae7f9e1 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15681 -commithash:409cab8f55191829e70f2f8e307196fd6a427b4c +version:2.1.0-preview2-15692 +commithash:5d9f445ce3f8492451a6f461df7e739bbed6a7f8 From 22c2797d84e091221767ccb4cb50cad470695f44 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 1 Feb 2018 03:29:53 +0000 Subject: [PATCH 0676/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index c5a5bf4ea0..c1e4d6ef27 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,15 +3,15 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15651 - 2.1.0-preview1-27965 - 2.1.0-preview1-27965 - 2.1.0-preview1-27965 - 2.1.0-preview1-27965 + 2.1.0-preview2-15692 + 2.1.0-preview2-28215 + 2.1.0-preview2-28215 + 2.1.0-preview2-28215 + 2.1.0-preview2-28215 2.0.0 - 2.1.0-preview1-26016-05 + 2.1.0-preview2-26130-04 15.3.0 - 4.5.0-preview1-26016-05 + 4.5.0-preview2-26130-01 2.3.1 2.3.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 2146d006d7..232cb858c2 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15661 -commithash:c9349d4c8a495d3085d9b879214d80f2f45e2193 +version:2.1.0-preview2-15692 +commithash:5d9f445ce3f8492451a6f461df7e739bbed6a7f8 From 9bdbac7049d530e1f25f6b95ec8c78c04d3b1702 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 1 Feb 2018 03:42:02 +0000 Subject: [PATCH 0677/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 8ebfd2751f..4aa9e9db7f 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview1-15651 - 2.1.0-preview1-27965 - 4.5.0-preview1-26016-05 - 2.1.0-preview1-27965 + 2.1.0-preview2-15692 + 2.1.0-preview2-28215 + 4.5.0-preview2-26130-01 + 2.1.0-preview2-28215 2.0.0 - 2.1.0-preview1-26016-05 + 2.1.0-preview2-26130-04 15.3.0 4.7.49 10.0.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 2146d006d7..232cb858c2 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview1-15661 -commithash:c9349d4c8a495d3085d9b879214d80f2f45e2193 +version:2.1.0-preview2-15692 +commithash:5d9f445ce3f8492451a6f461df7e739bbed6a7f8 From 01aa75eb2995a5d3ec19c91d2ac3ffcf9b54db59 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sat, 3 Feb 2018 02:41:47 +0000 Subject: [PATCH 0678/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 62c46ee86a..75ee314c0e 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15692 - 2.1.0-preview2-28215 - 2.1.0-preview2-28215 - 2.1.0-preview2-28215 - 2.1.0-preview2-28215 - 2.1.0-preview2-28215 + 2.1.0-preview2-15694 + 2.1.0-preview2-30020 + 2.1.0-preview2-30020 + 2.1.0-preview2-30020 + 2.1.0-preview2-30020 + 2.1.0-preview2-30020 2.0.0 2.1.0-preview2-26130-04 2.1.0-preview2-26130-01 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index c76ae7f9e1..7213174ac6 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15692 -commithash:5d9f445ce3f8492451a6f461df7e739bbed6a7f8 +version:2.1.0-preview2-15694 +commithash:f61af02b48e89592c9aadb7ebaebe84228666c3b From 0b4285caa28f7ec84ebf02f79036845b0af3509a Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sat, 3 Feb 2018 02:46:03 +0000 Subject: [PATCH 0679/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index c1e4d6ef27..b9e0d540c9 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,11 +3,11 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15692 - 2.1.0-preview2-28215 - 2.1.0-preview2-28215 - 2.1.0-preview2-28215 - 2.1.0-preview2-28215 + 2.1.0-preview2-15694 + 2.1.0-preview2-30020 + 2.1.0-preview2-30020 + 2.1.0-preview2-30020 + 2.1.0-preview2-30020 2.0.0 2.1.0-preview2-26130-04 15.3.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 232cb858c2..6f294ef0e6 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15692 -commithash:5d9f445ce3f8492451a6f461df7e739bbed6a7f8 +version:2.1.0-preview2-15694 +commithash:f61af02b48e89592c9aadb7ebaebe84228666c3b From a063328ba2c7eab3427dddb068547a99d07ee11b Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sat, 3 Feb 2018 02:51:35 +0000 Subject: [PATCH 0680/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 6 +++--- korebuild-lock.txt | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 4aa9e9db7f..875796c3b7 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15692 - 2.1.0-preview2-28215 + 2.1.0-preview2-15694 + 2.1.0-preview2-30020 4.5.0-preview2-26130-01 - 2.1.0-preview2-28215 + 2.1.0-preview2-30020 2.0.0 2.1.0-preview2-26130-04 15.3.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 232cb858c2..6f294ef0e6 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15692 -commithash:5d9f445ce3f8492451a6f461df7e739bbed6a7f8 +version:2.1.0-preview2-15694 +commithash:f61af02b48e89592c9aadb7ebaebe84228666c3b From 3f03428b0cd9104b35405a49a59c434763303bb1 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 8 Feb 2018 12:24:36 -0800 Subject: [PATCH 0681/1029] Include symbols in build output for the VSIX project, and update vsixmanifest dependency version --- build/VSIX.targets | 10 ++++++++++ .../Microsoft.VisualStudio.SecretManager.csproj | 9 +++++++-- .../source.extension.vsixmanifest | 2 +- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/build/VSIX.targets b/build/VSIX.targets index 83ab88c4f6..687fd72b24 100644 --- a/build/VSIX.targets +++ b/build/VSIX.targets @@ -8,6 +8,7 @@ $(RepositoryRoot)tooling\$(VSIXName)\$(VSIXName).csproj $(BuildDir)$(VSIXName).vsix $(BuildDir)$(VSIXName).json + $(BuildDir)$(VSIXName).pdb shipoob @@ -32,8 +33,16 @@ $(VSIXName) + + SymbolsFile + $(VSIXArtifactCategory) + $(VSIXName).vsix + full + + + @@ -92,6 +101,7 @@ /p:DeployExtension=false; /p:TargetVSIXContainer=$(VSIXOutputPath); /p:Configuration=$(Configuration); + /p:SymbolsPublishDir=$(BuildDir); /p:PackageReferencePropsPath=$(MSBuildThisFileDirectory)VSIX.props;" /> diff --git a/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj b/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj index 9c3fed86b6..b178075251 100644 --- a/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj +++ b/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj @@ -37,7 +37,7 @@ false true true - false + true Program $(DevEnvDir)devenv.exe /rootsuffix Exp @@ -53,7 +53,8 @@ latest - pdbonly + true + full true bin\Release\ TRACE @@ -109,4 +110,8 @@ + + + + diff --git a/tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest b/tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest index 7edf1295e0..37bb50c5da 100644 --- a/tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest +++ b/tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest @@ -14,7 +14,7 @@ - + From a64672d6e9b1ddcf394b8ae0259a2b1086d2b96c Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 9 Feb 2018 09:56:40 -0800 Subject: [PATCH 0682/1029] Ensure publish directory is cleaned when /t:Clean is executed [ci skip] --- src/Directory.Build.targets | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index 6d04f45f89..9dd4a760bf 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -3,4 +3,8 @@ + + + + From 52249d6038339a493739c8bc82eebfad7ae2c81b Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Fri, 9 Feb 2018 11:43:03 -0800 Subject: [PATCH 0683/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index b9e0d540c9..3636a35d79 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,11 +3,11 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15694 - 2.1.0-preview2-30020 - 2.1.0-preview2-30020 - 2.1.0-preview2-30020 - 2.1.0-preview2-30020 + 2.1.0-preview2-15698 + 2.1.0-preview2-30066 + 2.1.0-preview2-30066 + 2.1.0-preview2-30066 + 2.1.0-preview2-30066 2.0.0 2.1.0-preview2-26130-04 15.3.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 6f294ef0e6..3e2b56b91b 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15694 -commithash:f61af02b48e89592c9aadb7ebaebe84228666c3b +version:2.1.0-preview2-15698 +commithash:7216e5068cb1957e09d45fcbe58a744dd5c2de73 From 6d0dfc114552ab09b1dd1afac133ae5107b7d32d Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Fri, 9 Feb 2018 11:48:21 -0800 Subject: [PATCH 0684/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 6 +++--- korebuild-lock.txt | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 875796c3b7..399130aab9 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15694 - 2.1.0-preview2-30020 + 2.1.0-preview2-15698 + 2.1.0-preview2-30066 4.5.0-preview2-26130-01 - 2.1.0-preview2-30020 + 2.1.0-preview2-30066 2.0.0 2.1.0-preview2-26130-04 15.3.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 6f294ef0e6..3e2b56b91b 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15694 -commithash:f61af02b48e89592c9aadb7ebaebe84228666c3b +version:2.1.0-preview2-15698 +commithash:7216e5068cb1957e09d45fcbe58a744dd5c2de73 From f14799c4ae7becf77d39cb553caff8c28289848b Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 11 Feb 2018 12:20:11 -0800 Subject: [PATCH 0685/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 75ee314c0e..555f37af6b 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15694 - 2.1.0-preview2-30020 - 2.1.0-preview2-30020 - 2.1.0-preview2-30020 - 2.1.0-preview2-30020 - 2.1.0-preview2-30020 + 2.1.0-preview2-15698 + 2.1.0-preview2-30077 + 2.1.0-preview2-30077 + 2.1.0-preview2-30077 + 2.1.0-preview2-30077 + 2.1.0-preview2-30077 2.0.0 2.1.0-preview2-26130-04 2.1.0-preview2-26130-01 @@ -17,7 +17,7 @@ 4.5.0-preview2-26130-01 9.0.1 2.3.1 - 2.3.1 + 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 7213174ac6..c6125ba391 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15694 -commithash:f61af02b48e89592c9aadb7ebaebe84228666c3b +version:2.1.0-preview2-15698 +commithash:7216e5068cb1957e09d45fcbe58a744dd5c2de73 From fbfafa06ce20d5a236c284e5a6bdaecc1fa1cea7 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 11 Feb 2018 12:24:21 -0800 Subject: [PATCH 0686/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 3636a35d79..e01cfca7d0 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,16 +4,16 @@ 2.1.0-preview2-15698 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 - 2.1.0-preview2-30066 + 2.1.0-preview2-30077 + 2.1.0-preview2-30077 + 2.1.0-preview2-30077 + 2.1.0-preview2-30077 2.0.0 2.1.0-preview2-26130-04 15.3.0 4.5.0-preview2-26130-01 2.3.1 - 2.3.1 + 2.4.0-beta.1.build3945 From 55169b1c92400bfbe1347ccf7d6e6379c244af19 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 11 Feb 2018 12:29:38 -0800 Subject: [PATCH 0687/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 399130aab9..31af71a3d5 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,9 +4,9 @@ 2.1.0-preview2-15698 - 2.1.0-preview2-30066 + 2.1.0-preview2-30077 4.5.0-preview2-26130-01 - 2.1.0-preview2-30066 + 2.1.0-preview2-30077 2.0.0 2.1.0-preview2-26130-04 15.3.0 @@ -14,7 +14,7 @@ 10.0.1 0.8.0 2.3.1 - 2.3.1 + 2.4.0-beta.1.build3945 From d51a6951c7e40a0dc6a8eb8f2a47f2517a1cb275 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 12 Feb 2018 12:29:13 -0800 Subject: [PATCH 0688/1029] Add more logging for flaky tests on CI (#393) --- .../AwaitableProcess.cs | 16 +++++++++++++--- .../DotNetWatcherTests.cs | 2 +- .../GlobbingAppTests.cs | 3 +-- .../Scenario/WatchableApp.cs | 9 ++++----- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/test/dotnet-watch.FunctionalTests/AwaitableProcess.cs b/test/dotnet-watch.FunctionalTests/AwaitableProcess.cs index 1700845d5e..25a0189315 100644 --- a/test/dotnet-watch.FunctionalTests/AwaitableProcess.cs +++ b/test/dotnet-watch.FunctionalTests/AwaitableProcess.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; +using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.Internal; using Microsoft.Extensions.CommandLineUtils; using Xunit.Abstractions; @@ -61,10 +62,19 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests _logger.WriteLine($"{DateTime.Now}: process start: '{_process.StartInfo.FileName} {_process.StartInfo.Arguments}'"); } - public Task GetOutputLineAsync(string message) - => GetOutputLineAsync(m => message == m); + public async Task GetOutputLineAsync(string message, TimeSpan timeout) + { + _logger.WriteLine($"Waiting for output line [msg == '{message}']. Will wait for {timeout.TotalSeconds} sec."); + return await GetOutputLineAsync(m => message == m).TimeoutAfter(timeout); + } - public async Task GetOutputLineAsync(Predicate predicate) + public async Task GetOutputLineStartsWithAsync(string message, TimeSpan timeout) + { + _logger.WriteLine($"Waiting for output line [msg.StartsWith('{message}')]. Will wait for {timeout.TotalSeconds} sec."); + return await GetOutputLineAsync(m => m.StartsWith(message)).TimeoutAfter(timeout); + } + + private async Task GetOutputLineAsync(Predicate predicate) { while (!_source.Completion.IsCompleted) { diff --git a/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs b/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs index 368c55a202..d0dc735247 100644 --- a/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs +++ b/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs @@ -25,7 +25,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests await _app.StartWatcherAsync(); const string messagePrefix = "DOTNET_WATCH = "; - var message = await _app.Process.GetOutputLineAsync(m => m.StartsWith(messagePrefix)); + var message = await _app.Process.GetOutputLineStartsWithAsync(messagePrefix, TimeSpan.FromMinutes(2)); var envValue = message.Substring(messagePrefix.Length); Assert.Equal("1", envValue); } diff --git a/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs b/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs index 4e958f71f5..71b5d068bf 100644 --- a/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs +++ b/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs @@ -5,7 +5,6 @@ using System; using System.IO; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing; using Microsoft.DotNet.Watcher.Tools.Tests; using Xunit; using Xunit.Abstractions; @@ -129,7 +128,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public async Task GetCompiledAppDefinedTypes() { - var definedTypesMessage = await Process.GetOutputLineAsync(m => m.StartsWith("Defined types = ")).TimeoutAfter(TimeSpan.FromSeconds(30)); + var definedTypesMessage = await Process.GetOutputLineStartsWithAsync("Defined types = ", TimeSpan.FromSeconds(30)); return int.Parse(definedTypesMessage.Split('=').Last()); } } diff --git a/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs b/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs index 88c322b382..7725812bd6 100644 --- a/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs +++ b/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs @@ -7,7 +7,6 @@ using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.CommandLineUtils; using Xunit.Abstractions; @@ -41,16 +40,16 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public string SourceDirectory { get; } public Task HasRestarted() - => Process.GetOutputLineAsync(StartedMessage).TimeoutAfter(DefaultMessageTimeOut); + => Process.GetOutputLineAsync(StartedMessage, DefaultMessageTimeOut); public Task HasExited() - => Process.GetOutputLineAsync(ExitingMessage).TimeoutAfter(DefaultMessageTimeOut); + => Process.GetOutputLineAsync(ExitingMessage, DefaultMessageTimeOut); public bool UsePollingWatcher { get; set; } public async Task GetProcessId() { - var line = await Process.GetOutputLineAsync(l => l.StartsWith("PID =")).TimeoutAfter(DefaultMessageTimeOut); + var line = await Process.GetOutputLineStartsWithAsync("PID =", DefaultMessageTimeOut); var pid = line.Split('=').Last(); return int.Parse(pid); } @@ -106,7 +105,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // Make this timeout long because it depends much on the MSBuild compilation speed. // Slow machines may take a bit to compile and boot test apps - await Process.GetOutputLineAsync(StartedMessage).TimeoutAfter(TimeSpan.FromMinutes(2)); + await Process.GetOutputLineAsync(StartedMessage, TimeSpan.FromMinutes(2)); } public virtual void Dispose() From db8e0127c78cf0eda2b31bb4abb8504b3c124cfb Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Mon, 12 Feb 2018 16:25:21 -0800 Subject: [PATCH 0689/1029] Remove hyphen from the dev-certs tool name --- src/dotnet-dev-certs/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotnet-dev-certs/Program.cs b/src/dotnet-dev-certs/Program.cs index cda4f906c6..170e11b09d 100644 --- a/src/dotnet-dev-certs/Program.cs +++ b/src/dotnet-dev-certs/Program.cs @@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools { var app = new CommandLineApplication { - Name = "dotnet-dev-certs" + Name = "dotnet dev-certs" }; app.Command("https", c => From d9d4b8042eda0abed5acbdbfdefee7446d7ba3e8 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 18 Feb 2018 12:14:37 -0800 Subject: [PATCH 0690/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 555f37af6b..d17b7c5933 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15698 - 2.1.0-preview2-30077 - 2.1.0-preview2-30077 - 2.1.0-preview2-30077 - 2.1.0-preview2-30077 - 2.1.0-preview2-30077 + 2.1.0-preview2-15707 + 2.1.0-preview2-30131 + 2.1.0-preview2-30131 + 2.1.0-preview2-30131 + 2.1.0-preview2-30131 + 2.1.0-preview2-30131 2.0.0 2.1.0-preview2-26130-04 2.1.0-preview2-26130-01 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index c6125ba391..538f6228c3 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15698 -commithash:7216e5068cb1957e09d45fcbe58a744dd5c2de73 +version:2.1.0-preview2-15707 +commithash:e74e53f129ab34332947fea7ac7b7591b027cb22 From bee7ced54f90756c41362bbbb5a7cadac4b1ca3d Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 18 Feb 2018 12:17:51 -0800 Subject: [PATCH 0691/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index e01cfca7d0..9e7f39f805 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,11 +3,11 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15698 - 2.1.0-preview2-30077 - 2.1.0-preview2-30077 - 2.1.0-preview2-30077 - 2.1.0-preview2-30077 + 2.1.0-preview2-15707 + 2.1.0-preview2-30131 + 2.1.0-preview2-30131 + 2.1.0-preview2-30131 + 2.1.0-preview2-30131 2.0.0 2.1.0-preview2-26130-04 15.3.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 3e2b56b91b..89d0ad3d15 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15698 -commithash:7216e5068cb1957e09d45fcbe58a744dd5c2de73 +version:2.1.0-preview2-15707 +commithash:e74e53f129ab34332947fea7ac7b7591b027cb22 From 686b15825db4368e4738bfaa337d35ce2b138d6d Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 18 Feb 2018 12:22:41 -0800 Subject: [PATCH 0692/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 6 +++--- korebuild-lock.txt | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 31af71a3d5..ffa9c07cb7 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15698 - 2.1.0-preview2-30077 + 2.1.0-preview2-15707 + 2.1.0-preview2-30131 4.5.0-preview2-26130-01 - 2.1.0-preview2-30077 + 2.1.0-preview2-30131 2.0.0 2.1.0-preview2-26130-04 15.3.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 3e2b56b91b..89d0ad3d15 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15698 -commithash:7216e5068cb1957e09d45fcbe58a744dd5c2de73 +version:2.1.0-preview2-15707 +commithash:e74e53f129ab34332947fea7ac7b7591b027cb22 From f897a147181ab930e9ddf2d14468cc4bf21ab5ec Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 21 Feb 2018 18:26:53 -0800 Subject: [PATCH 0693/1029] Use FeatureBranchVersionSuffix when generating VersionSuffix --- version.props | 1 + 1 file changed, 1 insertion(+) diff --git a/version.props b/version.props index e271613fcc..fb30d256ce 100644 --- a/version.props +++ b/version.props @@ -8,6 +8,7 @@ $(VsixVersion).$(BuildNumber) $(VsixVersion).999999 t000 + $(VersionSuffix)-$([System.Text.RegularExpressions.Regex]::Replace('$(FeatureBranchVersionSuffix)', '[^\w-]', '-')) $(VersionSuffix)-$(BuildNumber) From b7873a42496513170360b374a1e5b9dd6203e7b6 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 21 Feb 2018 18:26:57 -0800 Subject: [PATCH 0694/1029] Use FeatureBranchVersionSuffix when generating VersionSuffix --- version.props | 1 + 1 file changed, 1 insertion(+) diff --git a/version.props b/version.props index 370d5ababd..65c8a07e37 100644 --- a/version.props +++ b/version.props @@ -5,6 +5,7 @@ $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 + $(VersionSuffix)-$([System.Text.RegularExpressions.Regex]::Replace('$(FeatureBranchVersionSuffix)', '[^\w-]', '-')) $(VersionSuffix)-$(BuildNumber) From d851546646260e5f7d94d655175d118fff7df368 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 21 Feb 2018 18:27:01 -0800 Subject: [PATCH 0695/1029] Use FeatureBranchVersionSuffix when generating VersionSuffix --- version.props | 1 + 1 file changed, 1 insertion(+) diff --git a/version.props b/version.props index 370d5ababd..65c8a07e37 100644 --- a/version.props +++ b/version.props @@ -5,6 +5,7 @@ $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 + $(VersionSuffix)-$([System.Text.RegularExpressions.Regex]::Replace('$(FeatureBranchVersionSuffix)', '[^\w-]', '-')) $(VersionSuffix)-$(BuildNumber) From 590c621c6f202758d0c4a151e73b1c422d5c8d2e Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 22 Feb 2018 12:01:50 -0800 Subject: [PATCH 0696/1029] Update README to reflect that dotnet-watch et. al. are bundled in the CLI --- README.md | 26 +++++++------------------- korebuild-lock.txt | 4 ++-- src/dotnet-dev-certs/README.md | 8 -------- src/dotnet-sql-cache/README.md | 8 -------- src/dotnet-user-secrets/README.md | 8 -------- src/dotnet-watch/README.md | 8 -------- 6 files changed, 9 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index 65998d0c54..471f8d3a5d 100644 --- a/README.md +++ b/README.md @@ -8,30 +8,18 @@ This project is part of ASP.NET Core. You can find samples, documentation and ge ## Projects -The repository contains command-line tools for the .NET Core CLI. Follow the links below for more details on each tool. +The repository contains command-line tools for ASP.NET Core that are bundled* in the .NET Core CLI. Follow the links below for more details on each tool. - - [dotnet-watch](src/dotnet-watch/) - - [dotnet-user-secrets](src/dotnet-user-secrets/) - - [dotnet-sql-cache](src/dotnet-sql-cache/) (dotnet-sql-cache) - - [dotnet-dev-certs](src/dotnet-dev-certs/) (dotnet-dev-certs) + - [dotnet-watch](src/dotnet-watch/README.md) + - [dotnet-user-secrets](src/dotnet-user-secrets/README.md) + - [dotnet-sql-cache](src/dotnet-sql-cache/README.md) + - [dotnet-dev-certs](src/dotnet-dev-certs/README.md) -## How to Install - -:warning: These instructions currently require a prerelease version of the [.NET Core SDK](https://github.com/dotnet/cli). -For stable, released versions of the tools, see [these instructions](https://github.com/aspnet/DotNetTools/tree/release/2.0#how-to-install). - -Install tools using the .NET Core command-line. - -``` -dotnet install tool --global dotnet-watch -dotnet install tool --global dotnet-user-secrets -dotnet install tool --global dotnet-dev-certs -dotnet install tool --global dotnet-sql-cache -``` +*\*This applies to .NET Core CLI 2.1.300 and up. For earlier versions of the CLI, these tools must be installed separately. See the [release/2.0](https://github.com/aspnet/DotNetTools/tree/release/2.0/README.md) branch for details.* ## Usage -The command line tools can be invoked as a new verb hanging off `dotnet`. +The command line tools can be invoked as a subcommand of `dotnet`. ```sh dotnet watch diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 538f6228c3..0bf8f620fb 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15707 -commithash:e74e53f129ab34332947fea7ac7b7591b027cb22 +version:2.1.0-preview2-15711 +commithash:da1ea560df398a50ef9a39a459c24dc36f9c87d9 diff --git a/src/dotnet-dev-certs/README.md b/src/dotnet-dev-certs/README.md index 4e8aaea714..e565dbc0e8 100644 --- a/src/dotnet-dev-certs/README.md +++ b/src/dotnet-dev-certs/README.md @@ -3,14 +3,6 @@ dotnet-dev-certs `dotnet-dev-certs` is a command line tool to generate certificates used in ASP.NET Core during development. -### How To Install - -From the command-line, execute: - -``` -dotnet install tool --global dotnet-dev-certs -``` - ### How To Use Run `dotnet dev-certs --help` for more information about usage. diff --git a/src/dotnet-sql-cache/README.md b/src/dotnet-sql-cache/README.md index 9c8ca25653..141c1cab65 100644 --- a/src/dotnet-sql-cache/README.md +++ b/src/dotnet-sql-cache/README.md @@ -3,14 +3,6 @@ dotnet-sql-cache `dotnet-sql-cache` is a command line tool that creates table and indexes in Microsoft SQL Server database to be used for distributed caching -### How To Install - -From the command-line, execute: - -``` -dotnet install tool --global dotnet-sql-cache -``` - ### How To Use Run `dotnet sql-cache --help` for more information about usage. diff --git a/src/dotnet-user-secrets/README.md b/src/dotnet-user-secrets/README.md index 50e4fbdb06..0d8666cdb6 100644 --- a/src/dotnet-user-secrets/README.md +++ b/src/dotnet-user-secrets/README.md @@ -3,14 +3,6 @@ dotnet-user-secrets `dotnet-user-secrets` is a command line tool for managing the secrets in a user secret store. -### How To Install - -From the command-line, execute: - -``` -dotnet install tool --global dotnet-user-secrets -``` - ### How To Use Run `dotnet user-secrets --help` for more information about usage. diff --git a/src/dotnet-watch/README.md b/src/dotnet-watch/README.md index 37725d97d4..ff7102a92e 100644 --- a/src/dotnet-watch/README.md +++ b/src/dotnet-watch/README.md @@ -2,14 +2,6 @@ dotnet-watch ============ `dotnet-watch` is a file watcher for `dotnet` that restarts the specified application when changes in the source code are detected. -### How To Install - -From the command-line, execute: - -``` -dotnet install tool --global dotnet-watch -``` - ### How To Use The command must be executed in the directory that contains the project to be watched. From 2b04f98591241e15eec4c2a4ec28ac7f746c04fe Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Mon, 26 Feb 2018 10:58:13 -0800 Subject: [PATCH 0697/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index d17b7c5933..7ced3d136f 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,16 +3,16 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15707 - 2.1.0-preview2-30131 - 2.1.0-preview2-30131 - 2.1.0-preview2-30131 - 2.1.0-preview2-30131 - 2.1.0-preview2-30131 + 2.1.0-preview2-15721 + 2.1.0-preview2-30187 + 2.1.0-preview2-30187 + 2.1.0-preview2-30187 + 2.1.0-preview2-30187 + 2.1.0-preview2-30187 2.0.0 2.1.0-preview2-26130-04 2.1.0-preview2-26130-01 - 15.3.0 + 15.6.0 4.5.0-preview2-26130-01 4.5.0-preview2-26130-01 9.0.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 0bf8f620fb..563446a93f 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15711 -commithash:da1ea560df398a50ef9a39a459c24dc36f9c87d9 +version:2.1.0-preview2-15721 +commithash:f9bb4be59e39938ec59a6975257e26099b0d03c1 From a992ce0d7b881dc6cf9fa579c22d5c7b4ecc8d83 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Mon, 26 Feb 2018 11:01:44 -0800 Subject: [PATCH 0698/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 9e7f39f805..a4ee848bcc 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,14 +3,14 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15707 - 2.1.0-preview2-30131 - 2.1.0-preview2-30131 - 2.1.0-preview2-30131 - 2.1.0-preview2-30131 + 2.1.0-preview2-15721 + 2.1.0-preview2-30187 + 2.1.0-preview2-30187 + 2.1.0-preview2-30187 + 2.1.0-preview2-30187 2.0.0 2.1.0-preview2-26130-04 - 15.3.0 + 15.6.0 4.5.0-preview2-26130-01 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 89d0ad3d15..e6c7fddffa 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15707 -commithash:e74e53f129ab34332947fea7ac7b7591b027cb22 +version:2.1.0-preview2-15721 +commithash:f9bb4be59e39938ec59a6975257e26099b0d03c1 From a1b6c4c7aad396bdd887448de21b41229a268c5f Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Mon, 26 Feb 2018 11:06:37 -0800 Subject: [PATCH 0699/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 8 ++++---- korebuild-lock.txt | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index ffa9c07cb7..4ada242a87 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,13 +3,13 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15707 - 2.1.0-preview2-30131 + 2.1.0-preview2-15721 + 2.1.0-preview2-30187 4.5.0-preview2-26130-01 - 2.1.0-preview2-30131 + 2.1.0-preview2-30187 2.0.0 2.1.0-preview2-26130-04 - 15.3.0 + 15.6.0 4.7.49 10.0.1 0.8.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 89d0ad3d15..e6c7fddffa 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15707 -commithash:e74e53f129ab34332947fea7ac7b7591b027cb22 +version:2.1.0-preview2-15721 +commithash:f9bb4be59e39938ec59a6975257e26099b0d03c1 From 0b579cda2f10e7079a73a6f683ef37e24c4909c7 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 27 Feb 2018 13:59:56 -0800 Subject: [PATCH 0700/1029] Update README.md with install instructions for dotnet-watch for preview1 and pre-preview1 [ci skip] --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 471f8d3a5d..0eb8eb3be8 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,11 @@ The repository contains command-line tools for ASP.NET Core that are bundled* in - [dotnet-sql-cache](src/dotnet-sql-cache/README.md) - [dotnet-dev-certs](src/dotnet-dev-certs/README.md) -*\*This applies to .NET Core CLI 2.1.300 and up. For earlier versions of the CLI, these tools must be installed separately. See the [release/2.0](https://github.com/aspnet/DotNetTools/tree/release/2.0/README.md) branch for details.* +*\*This applies to .NET Core CLI 2.1.300-preview2 and up. For earlier versions of the CLI, these tools must be installed separately.* + +*For 2.0 CLI and earlier, see for details.* + +*For 2.1.300-preview1 CLI, see for details.* ## Usage From 63f03228106c61b6af2965c874f09758f7a5439e Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Tue, 27 Feb 2018 12:41:38 -0800 Subject: [PATCH 0701/1029] Allow whitespace and backslash in path --- .../Internal/PathHelpers.cs | 7 ++--- .../JsonPatchDocument.cs | 12 ++++----- ...nPatchDocumentJsonPropertyAttributeTest.cs | 26 +++++++++++++++++++ 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/PathHelpers.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/PathHelpers.cs index d46314c148..f0afedb60e 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/PathHelpers.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/PathHelpers.cs @@ -2,23 +2,24 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.AspNetCore.JsonPatch.Exceptions; +using System; namespace Microsoft.AspNetCore.JsonPatch.Internal { internal static class PathHelpers { - internal static string NormalizePath(string path) + internal static string ValidateAndNormalizePath(string path) { // check for most common path errors on create. This is not // absolutely necessary, but it allows us to already catch mistakes // on creation of the patch document rather than on execute. - if (path.Contains("//") || path.Contains(" ") || path.Contains("\\")) + if (path.Contains("//")) { throw new JsonPatchException(Resources.FormatInvalidValueForPath(path), null); } - if (!(path.StartsWith("/"))) + if (!path.StartsWith("/", StringComparison.Ordinal)) { return "/" + path; } diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs index 4420e576bf..b6539caae8 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs @@ -60,7 +60,7 @@ namespace Microsoft.AspNetCore.JsonPatch throw new ArgumentNullException(nameof(path)); } - Operations.Add(new Operation("add", PathHelpers.NormalizePath(path), null, value)); + Operations.Add(new Operation("add", PathHelpers.ValidateAndNormalizePath(path), null, value)); return this; } @@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.JsonPatch throw new ArgumentNullException(nameof(path)); } - Operations.Add(new Operation("remove", PathHelpers.NormalizePath(path), null, null)); + Operations.Add(new Operation("remove", PathHelpers.ValidateAndNormalizePath(path), null, null)); return this; } @@ -95,7 +95,7 @@ namespace Microsoft.AspNetCore.JsonPatch throw new ArgumentNullException(nameof(path)); } - Operations.Add(new Operation("replace", PathHelpers.NormalizePath(path), null, value)); + Operations.Add(new Operation("replace", PathHelpers.ValidateAndNormalizePath(path), null, value)); return this; } @@ -113,7 +113,7 @@ namespace Microsoft.AspNetCore.JsonPatch throw new ArgumentNullException(nameof(path)); } - Operations.Add(new Operation("test", PathHelpers.NormalizePath(path), null, value)); + Operations.Add(new Operation("test", PathHelpers.ValidateAndNormalizePath(path), null, value)); return this; } @@ -136,7 +136,7 @@ namespace Microsoft.AspNetCore.JsonPatch throw new ArgumentNullException(nameof(path)); } - Operations.Add(new Operation("move", PathHelpers.NormalizePath(path), PathHelpers.NormalizePath(from))); + Operations.Add(new Operation("move", PathHelpers.ValidateAndNormalizePath(path), PathHelpers.ValidateAndNormalizePath(from))); return this; } @@ -159,7 +159,7 @@ namespace Microsoft.AspNetCore.JsonPatch throw new ArgumentNullException(nameof(path)); } - Operations.Add(new Operation("copy", PathHelpers.NormalizePath(path), PathHelpers.NormalizePath(from))); + Operations.Add(new Operation("copy", PathHelpers.ValidateAndNormalizePath(path), PathHelpers.ValidateAndNormalizePath(from))); return this; } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs index f5d6377989..a9c3d8500b 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs @@ -24,6 +24,23 @@ namespace Microsoft.AspNetCore.JsonPatch Assert.Equal("/AnotherName", pathToCheck); } + [Fact] + public void Add_RespectsJsonPropertyAttribute_WithDotWhitespaceAndBackslashInName() + { + // Arrange + var obj = new JsonPropertyObjectWithStrangeNames(); + var patchDocument = new JsonPatchDocument(); + + // Act + patchDocument.Add("/First Name.", "John"); + patchDocument.Add("Last\\Name", "Doe"); + patchDocument.ApplyTo(obj); + + // Assert + Assert.Equal("John", obj.FirstName); + Assert.Equal("Doe", obj.LastName); + } + [Fact] public void Move_FallsbackToPropertyName_WhenJsonPropertyAttributeName_IsEmpty() { @@ -46,6 +63,15 @@ namespace Microsoft.AspNetCore.JsonPatch public string Name { get; set; } } + private class JsonPropertyObjectWithStrangeNames + { + [JsonProperty("First Name.")] + public string FirstName { get; set; } + + [JsonProperty("Last\\Name")] + public string LastName { get; set; } + } + private class JsonPropertyWithNoPropertyName { [JsonProperty] From 9bd4a67f7dd422ed2eefdbddb88f07d2d640ddd9 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 28 Feb 2018 11:03:13 -0800 Subject: [PATCH 0702/1029] Remove Microsoft.NETCore.Platforms from tool package nuspec --- build/dependencies.props | 1 - src/PackGlobalTool.targets | 2 +- src/dotnet-dev-certs/dotnet-dev-certs.nuspec | 6 +----- src/dotnet-sql-cache/dotnet-sql-cache.nuspec | 6 +----- src/dotnet-user-secrets/dotnet-user-secrets.nuspec | 6 +----- src/dotnet-watch/dotnet-watch.nuspec | 6 +----- 6 files changed, 5 insertions(+), 22 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 7ced3d136f..128df649dd 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -11,7 +11,6 @@ 2.1.0-preview2-30187 2.0.0 2.1.0-preview2-26130-04 - 2.1.0-preview2-26130-01 15.6.0 4.5.0-preview2-26130-01 4.5.0-preview2-26130-01 diff --git a/src/PackGlobalTool.targets b/src/PackGlobalTool.targets index ed75c775b7..d97666110c 100644 --- a/src/PackGlobalTool.targets +++ b/src/PackGlobalTool.targets @@ -12,7 +12,7 @@ description=$(Description); repositoryUrl=$(RepositoryUrl); targetframework=$(TargetFramework); - MicrosoftNETCorePlatformsPackageVersion=$(MicrosoftNETCorePlatformsPackageVersion); + repositoryCommit=$(RepositoryCommit); diff --git a/src/dotnet-dev-certs/dotnet-dev-certs.nuspec b/src/dotnet-dev-certs/dotnet-dev-certs.nuspec index e8dce16395..878e0f4ab2 100644 --- a/src/dotnet-dev-certs/dotnet-dev-certs.nuspec +++ b/src/dotnet-dev-certs/dotnet-dev-certs.nuspec @@ -16,11 +16,7 @@ - - - - - + diff --git a/src/dotnet-sql-cache/dotnet-sql-cache.nuspec b/src/dotnet-sql-cache/dotnet-sql-cache.nuspec index a2498a00d2..0c6e9d05e2 100644 --- a/src/dotnet-sql-cache/dotnet-sql-cache.nuspec +++ b/src/dotnet-sql-cache/dotnet-sql-cache.nuspec @@ -16,11 +16,7 @@ - - - - - + diff --git a/src/dotnet-user-secrets/dotnet-user-secrets.nuspec b/src/dotnet-user-secrets/dotnet-user-secrets.nuspec index fdd3fb95d5..54caef9177 100644 --- a/src/dotnet-user-secrets/dotnet-user-secrets.nuspec +++ b/src/dotnet-user-secrets/dotnet-user-secrets.nuspec @@ -16,11 +16,7 @@ - - - - - + diff --git a/src/dotnet-watch/dotnet-watch.nuspec b/src/dotnet-watch/dotnet-watch.nuspec index 5a748260c1..5442df0874 100644 --- a/src/dotnet-watch/dotnet-watch.nuspec +++ b/src/dotnet-watch/dotnet-watch.nuspec @@ -16,11 +16,7 @@ - - - - - + From ba33becbe2caec59b1b6e03088949c7beb791aba Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 4 Mar 2018 12:12:52 -0800 Subject: [PATCH 0703/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 128df649dd..2053254c72 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15721 - 2.1.0-preview2-30187 - 2.1.0-preview2-30187 - 2.1.0-preview2-30187 - 2.1.0-preview2-30187 - 2.1.0-preview2-30187 + 2.1.0-preview2-15726 + 2.1.0-preview2-30230 + 2.1.0-preview2-30230 + 2.1.0-preview2-30230 + 2.1.0-preview2-30230 + 2.1.0-preview2-30230 2.0.0 - 2.1.0-preview2-26130-04 + 2.1.0-preview2-26225-03 15.6.0 - 4.5.0-preview2-26130-01 - 4.5.0-preview2-26130-01 + 4.5.0-preview2-26224-02 + 4.5.0-preview2-26224-02 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 563446a93f..ad1d7d3c02 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15721 -commithash:f9bb4be59e39938ec59a6975257e26099b0d03c1 +version:2.1.0-preview2-15726 +commithash:599e691c41f502ed9e062b1822ce13b673fc916e From e45a788f6553eb6736168ae0c1b1503b45d729cf Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 6 Mar 2018 10:03:21 -0800 Subject: [PATCH 0704/1029] Use dotnet-core feed in repos --- build/sources.props | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/sources.props b/build/sources.props index 903de4e87b..cada42ba91 100644 --- a/build/sources.props +++ b/build/sources.props @@ -1,10 +1,11 @@ - + $(DotNetRestoreSources) $(RestoreSources); + https://dotnet.myget.org/F/dotnet-core/api/v3/index.json; https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; https://vside.myget.org/F/vssdk/api/v3/index.json; From fe6515e4f11af7e0b86887d27da9f7ed65b9af8c Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 6 Mar 2018 10:03:21 -0800 Subject: [PATCH 0705/1029] Prepend FeatureBranchVersionPrefix if FeatureBranchVersionSuffix is specified --- version.props | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/version.props b/version.props index fb30d256ce..5f6ce7da95 100644 --- a/version.props +++ b/version.props @@ -8,7 +8,8 @@ $(VsixVersion).$(BuildNumber) $(VsixVersion).999999 t000 - $(VersionSuffix)-$([System.Text.RegularExpressions.Regex]::Replace('$(FeatureBranchVersionSuffix)', '[^\w-]', '-')) + a- + $(FeatureBranchVersionPrefix)$(VersionSuffix)-$([System.Text.RegularExpressions.Regex]::Replace('$(FeatureBranchVersionSuffix)', '[^\w-]', '-')) $(VersionSuffix)-$(BuildNumber) From a34a3e319ed1c07562a0dfcd6908485462242a1e Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 6 Mar 2018 10:03:51 -0800 Subject: [PATCH 0706/1029] Use dotnet-core feed in repos --- build/sources.props | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/sources.props b/build/sources.props index 9feff29d09..9215df9751 100644 --- a/build/sources.props +++ b/build/sources.props @@ -1,10 +1,11 @@ - + $(DotNetRestoreSources) $(RestoreSources); + https://dotnet.myget.org/F/dotnet-core/api/v3/index.json; https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; From 2e5964f709aedcff192587bd5ad636392b8c5797 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 6 Mar 2018 10:03:51 -0800 Subject: [PATCH 0707/1029] Prepend FeatureBranchVersionPrefix if FeatureBranchVersionSuffix is specified --- version.props | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/version.props b/version.props index 65c8a07e37..a11ea1ed52 100644 --- a/version.props +++ b/version.props @@ -5,7 +5,8 @@ $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 - $(VersionSuffix)-$([System.Text.RegularExpressions.Regex]::Replace('$(FeatureBranchVersionSuffix)', '[^\w-]', '-')) + a- + $(FeatureBranchVersionPrefix)$(VersionSuffix)-$([System.Text.RegularExpressions.Regex]::Replace('$(FeatureBranchVersionSuffix)', '[^\w-]', '-')) $(VersionSuffix)-$(BuildNumber) From a2c82ff883b77fca85d43b3ece416166339a2472 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 6 Mar 2018 10:04:32 -0800 Subject: [PATCH 0708/1029] Use dotnet-core feed in repos --- build/sources.props | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/sources.props b/build/sources.props index 9feff29d09..9215df9751 100644 --- a/build/sources.props +++ b/build/sources.props @@ -1,10 +1,11 @@ - + $(DotNetRestoreSources) $(RestoreSources); + https://dotnet.myget.org/F/dotnet-core/api/v3/index.json; https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; From 93817a51930e4734b6fa22025afbdc7df48abeae Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 6 Mar 2018 10:04:32 -0800 Subject: [PATCH 0709/1029] Prepend FeatureBranchVersionPrefix if FeatureBranchVersionSuffix is specified --- version.props | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/version.props b/version.props index 65c8a07e37..a11ea1ed52 100644 --- a/version.props +++ b/version.props @@ -5,7 +5,8 @@ $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 - $(VersionSuffix)-$([System.Text.RegularExpressions.Regex]::Replace('$(FeatureBranchVersionSuffix)', '[^\w-]', '-')) + a- + $(FeatureBranchVersionPrefix)$(VersionSuffix)-$([System.Text.RegularExpressions.Regex]::Replace('$(FeatureBranchVersionSuffix)', '[^\w-]', '-')) $(VersionSuffix)-$(BuildNumber) From abd4d62a80ba53cd94e11838756c63ac5547eb78 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 8 Mar 2018 12:56:55 -0800 Subject: [PATCH 0710/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 2053254c72..41da7d50f8 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15726 - 2.1.0-preview2-30230 - 2.1.0-preview2-30230 - 2.1.0-preview2-30230 - 2.1.0-preview2-30230 - 2.1.0-preview2-30230 + 2.1.0-preview2-15728 + 2.1.0-preview2-30272 + 2.1.0-preview2-30272 + 2.1.0-preview2-30272 + 2.1.0-preview2-30272 + 2.1.0-preview2-30272 2.0.0 2.1.0-preview2-26225-03 15.6.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index ad1d7d3c02..5ace9326ce 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15726 -commithash:599e691c41f502ed9e062b1822ce13b673fc916e +version:2.1.0-preview2-15728 +commithash:393377068ddcf51dfee0536536d455f57a828b06 From d5e6c6a81e857d798a4375e5524262037f49776e Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 8 Mar 2018 13:00:13 -0800 Subject: [PATCH 0711/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index a4ee848bcc..30d6e336de 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,15 +3,15 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15721 - 2.1.0-preview2-30187 - 2.1.0-preview2-30187 - 2.1.0-preview2-30187 - 2.1.0-preview2-30187 + 2.1.0-preview2-15728 + 2.1.0-preview2-30272 + 2.1.0-preview2-30272 + 2.1.0-preview2-30272 + 2.1.0-preview2-30272 2.0.0 - 2.1.0-preview2-26130-04 + 2.1.0-preview2-26225-03 15.6.0 - 4.5.0-preview2-26130-01 + 4.5.0-preview2-26224-02 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index e6c7fddffa..138d848db1 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15721 -commithash:f9bb4be59e39938ec59a6975257e26099b0d03c1 +version:2.1.0-preview2-15728 +commithash:393377068ddcf51dfee0536536d455f57a828b06 From 1f29add11975cb7858a6845fbf76b6f571099d64 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 8 Mar 2018 13:05:01 -0800 Subject: [PATCH 0712/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 4ada242a87..9335150db5 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15721 - 2.1.0-preview2-30187 - 4.5.0-preview2-26130-01 - 2.1.0-preview2-30187 + 2.1.0-preview2-15728 + 2.1.0-preview2-30272 + 4.5.0-preview2-26224-02 + 2.1.0-preview2-30272 2.0.0 - 2.1.0-preview2-26130-04 + 2.1.0-preview2-26225-03 15.6.0 4.7.49 10.0.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index e6c7fddffa..138d848db1 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15721 -commithash:f9bb4be59e39938ec59a6975257e26099b0d03c1 +version:2.1.0-preview2-15728 +commithash:393377068ddcf51dfee0536536d455f57a828b06 From b65bd7eb22510c3cc28f56968f8287d8e6bb8f71 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 16 Mar 2018 11:14:06 -0700 Subject: [PATCH 0713/1029] Branching for 2.1.0-preview2 --- build/dependencies.props | 18 +++++++++--------- build/repo.props | 4 ++-- build/sources.props | 2 +- korebuild-lock.txt | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 41da7d50f8..0a3ff46de7 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15728 - 2.1.0-preview2-30272 - 2.1.0-preview2-30272 - 2.1.0-preview2-30272 - 2.1.0-preview2-30272 - 2.1.0-preview2-30272 + 2.1.0-preview2-15742 + 2.1.0-preview2-30355 + 2.1.0-preview2-30355 + 2.1.0-preview2-30355 + 2.1.0-preview2-30355 + 2.1.0-preview2-30355 2.0.0 - 2.1.0-preview2-26225-03 + 2.1.0-preview2-26314-02 15.6.0 - 4.5.0-preview2-26224-02 - 4.5.0-preview2-26224-02 + 4.5.0-preview2-26313-01 + 4.5.0-preview2-26313-01 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/build/repo.props b/build/repo.props index 1be3632130..91a4b29fcf 100644 --- a/build/repo.props +++ b/build/repo.props @@ -1,4 +1,4 @@ - + @@ -10,7 +10,7 @@ Internal.AspNetCore.Universe.Lineup - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json + https://dotnet.myget.org/F/aspnetcore-release/api/v3/index.json diff --git a/build/sources.props b/build/sources.props index cada42ba91..6dfebee6d6 100644 --- a/build/sources.props +++ b/build/sources.props @@ -6,7 +6,7 @@ $(RestoreSources); https://dotnet.myget.org/F/dotnet-core/api/v3/index.json; - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; + https://dotnet.myget.org/F/aspnetcore-release/api/v3/index.json; https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; https://vside.myget.org/F/vssdk/api/v3/index.json; diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 5ace9326ce..e761020952 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15728 -commithash:393377068ddcf51dfee0536536d455f57a828b06 +version:2.1.0-preview2-15742 +commithash:21fbb0f2c3fe4a9216e2d59632b98cfd7d685962 From 7b13960c6d6bf71867a500eb8c1c1f7d89f6aa12 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 16 Mar 2018 11:14:38 -0700 Subject: [PATCH 0714/1029] Branching for 2.1.0-preview2 --- build/dependencies.props | 14 +++++++------- build/repo.props | 4 ++-- build/sources.props | 2 +- korebuild-lock.txt | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 30d6e336de..e2ad411a23 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,15 +3,15 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15728 - 2.1.0-preview2-30272 - 2.1.0-preview2-30272 - 2.1.0-preview2-30272 - 2.1.0-preview2-30272 + 2.1.0-preview2-15742 + 2.1.0-preview2-30355 + 2.1.0-preview2-30355 + 2.1.0-preview2-30355 + 2.1.0-preview2-30355 2.0.0 - 2.1.0-preview2-26225-03 + 2.1.0-preview2-26314-02 15.6.0 - 4.5.0-preview2-26224-02 + 4.5.0-preview2-26313-01 2.3.1 2.4.0-beta.1.build3945 diff --git a/build/repo.props b/build/repo.props index 78b0ce5879..d94ff7d00d 100644 --- a/build/repo.props +++ b/build/repo.props @@ -1,10 +1,10 @@ - + Internal.AspNetCore.Universe.Lineup - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json + https://dotnet.myget.org/F/aspnetcore-release/api/v3/index.json diff --git a/build/sources.props b/build/sources.props index 9215df9751..36045f12b5 100644 --- a/build/sources.props +++ b/build/sources.props @@ -6,7 +6,7 @@ $(RestoreSources); https://dotnet.myget.org/F/dotnet-core/api/v3/index.json; - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; + https://dotnet.myget.org/F/aspnetcore-release/api/v3/index.json; https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 138d848db1..e40ef6651b 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15728 -commithash:393377068ddcf51dfee0536536d455f57a828b06 +version:2.1.0-preview2-15742 +commithash:21fbb0f2c3fe4a9216e2d59632b98cfd7d685962 From 416dc545af13192f78e6ad286554b1c7923adfcc Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 16 Mar 2018 11:15:22 -0700 Subject: [PATCH 0715/1029] Branching for 2.1.0-preview2 --- build/dependencies.props | 10 +++++----- build/repo.props | 4 ++-- build/sources.props | 2 +- korebuild-lock.txt | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 9335150db5..e11bd088f7 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15728 - 2.1.0-preview2-30272 - 4.5.0-preview2-26224-02 - 2.1.0-preview2-30272 + 2.1.0-preview2-15742 + 2.1.0-preview2-30355 + 4.5.0-preview2-26313-01 + 2.1.0-preview2-30355 2.0.0 - 2.1.0-preview2-26225-03 + 2.1.0-preview2-26314-02 15.6.0 4.7.49 10.0.1 diff --git a/build/repo.props b/build/repo.props index 78b0ce5879..d94ff7d00d 100644 --- a/build/repo.props +++ b/build/repo.props @@ -1,10 +1,10 @@ - + Internal.AspNetCore.Universe.Lineup - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json + https://dotnet.myget.org/F/aspnetcore-release/api/v3/index.json diff --git a/build/sources.props b/build/sources.props index 9215df9751..36045f12b5 100644 --- a/build/sources.props +++ b/build/sources.props @@ -6,7 +6,7 @@ $(RestoreSources); https://dotnet.myget.org/F/dotnet-core/api/v3/index.json; - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; + https://dotnet.myget.org/F/aspnetcore-release/api/v3/index.json; https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 138d848db1..e40ef6651b 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15728 -commithash:393377068ddcf51dfee0536536d455f57a828b06 +version:2.1.0-preview2-15742 +commithash:21fbb0f2c3fe4a9216e2d59632b98cfd7d685962 From 1f84511e2337789aab161cf964bf334b18fb91b4 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 16 Mar 2018 11:25:55 -0700 Subject: [PATCH 0716/1029] Update version prefix to preview3 --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 5f6ce7da95..ce0b3d1a83 100644 --- a/version.props +++ b/version.props @@ -2,7 +2,7 @@ 2.1.0 15.6 - preview2 + preview3 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final $(VsixVersion).$(BuildNumber) From a12fa391fb7fab32b52abc4a9b002a427ba928a3 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 16 Mar 2018 11:26:21 -0700 Subject: [PATCH 0717/1029] Update version prefix to preview3 --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index a11ea1ed52..24f2b00a0a 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ 2.1.0 - preview2 + preview3 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From 39959a72ef8cc0a5cbbb7d078d6cabd592cd6a05 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 16 Mar 2018 11:26:57 -0700 Subject: [PATCH 0718/1029] Update version prefix to preview3 --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index a11ea1ed52..24f2b00a0a 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ 2.1.0 - preview2 + preview3 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From 86ceed533619b6ef7e042feebc30801fb22ece02 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 16 Mar 2018 12:28:58 -0700 Subject: [PATCH 0719/1029] Update KoreBuild channel --- korebuild.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/korebuild.json b/korebuild.json index 4d59ad132a..196a3ca537 100644 --- a/korebuild.json +++ b/korebuild.json @@ -1,6 +1,6 @@ { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev", + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.1/tools/korebuild.schema.json", + "channel": "release/2.1", "toolsets": { "visualstudio": { "required": [ From cb9a800b6b424edefe673e3988cd7a3f3759eb7b Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 16 Mar 2018 12:29:47 -0700 Subject: [PATCH 0720/1029] Update KoreBuild channel --- korebuild.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/korebuild.json b/korebuild.json index bd5d51a51b..678d8bb948 100644 --- a/korebuild.json +++ b/korebuild.json @@ -1,4 +1,4 @@ { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev" + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.1/tools/korebuild.schema.json", + "channel": "release/2.1" } From ed7c645939b3e9ca361b1af5a6c5bc0deeda22a1 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 16 Mar 2018 12:30:53 -0700 Subject: [PATCH 0721/1029] Update KoreBuild channel --- korebuild.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/korebuild.json b/korebuild.json index bd5d51a51b..678d8bb948 100644 --- a/korebuild.json +++ b/korebuild.json @@ -1,4 +1,4 @@ { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev" + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.1/tools/korebuild.schema.json", + "channel": "release/2.1" } From 39fc608adb59987e6a97f4d482a2544ebfda7924 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 21 Mar 2018 09:37:08 -0700 Subject: [PATCH 0722/1029] React to changes in NuGetPackageVerifier --- NuGetPackageVerifier.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index f0c02acf43..58eca3d2f2 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -27,6 +27,20 @@ "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + }, + "ASSEMBLY_FILE_VERSION_MISMATCH": { + "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + }, + "ASSEMBLY_VERSION_MISMATCH": { + "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." } } }, @@ -54,9 +68,11 @@ "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_FILE_VERSION_MISMATCH": { + "tools/any/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_VERSION_MISMATCH": { + "tools/any/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." } } From c8f5b2e3ae543c4ccb705b01a0702e4b89653860 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Wed, 14 Mar 2018 15:33:57 -0700 Subject: [PATCH 0723/1029] Set 2.0 baselines --- build/dependencies.props | 2 +- korebuild-lock.txt | 4 ++-- .../baseline.netcore.json | 10 +++++++++- .../baseline.netcore.json | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index e2ad411a23..dc9945767a 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,7 +3,7 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15742 + 2.1.0-preview2-15744 2.1.0-preview2-30355 2.1.0-preview2-30355 2.1.0-preview2-30355 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index e40ef6651b..f531e7b0f7 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15742 -commithash:21fbb0f2c3fe4a9216e2d59632b98cfd7d685962 +version:2.1.0-preview2-15744 +commithash:9e15cb6062ab5b9790d3fa699e018543a6950713 diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/baseline.netcore.json b/src/Microsoft.AspNetCore.Html.Abstractions/baseline.netcore.json index 7e3a4d0d00..b0b320e216 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/baseline.netcore.json +++ b/src/Microsoft.AspNetCore.Html.Abstractions/baseline.netcore.json @@ -1,5 +1,5 @@ { - "AssemblyIdentity": "Microsoft.AspNetCore.Html.Abstractions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "AssemblyIdentity": "Microsoft.AspNetCore.Html.Abstractions, Version=2.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "Types": [ { "Name": "Microsoft.AspNetCore.Html.HtmlContentBuilder", @@ -9,6 +9,14 @@ "Microsoft.AspNetCore.Html.IHtmlContentBuilder" ], "Members": [ + { + "Kind": "Method", + "Name": "get_Count", + "Parameters": [], + "ReturnType": "System.Int32", + "Visibility": "Public", + "GenericParameter": [] + }, { "Kind": "Method", "Name": "Append", diff --git a/src/Microsoft.Extensions.WebEncoders/baseline.netcore.json b/src/Microsoft.Extensions.WebEncoders/baseline.netcore.json index db16203ed1..cc93cc7458 100644 --- a/src/Microsoft.Extensions.WebEncoders/baseline.netcore.json +++ b/src/Microsoft.Extensions.WebEncoders/baseline.netcore.json @@ -1,5 +1,5 @@ { - "AssemblyIdentity": "Microsoft.Extensions.WebEncoders, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "AssemblyIdentity": "Microsoft.Extensions.WebEncoders, Version=2.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "Types": [ { "Name": "Microsoft.Extensions.WebEncoders.WebEncoderOptions", From 7e13e83348bea331ee8943c6649b27a681e872af Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 23 Mar 2018 16:34:43 -0700 Subject: [PATCH 0724/1029] Remove PackageArtifactCategory --- src/DotnetTool.props | 1 - .../Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj | 1 - 2 files changed, 2 deletions(-) diff --git a/src/DotnetTool.props b/src/DotnetTool.props index 75eca8d65f..5e34c077ce 100644 --- a/src/DotnetTool.props +++ b/src/DotnetTool.props @@ -4,7 +4,6 @@ true - ship Microsoft false false diff --git a/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj b/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj index a8e6fe928a..ae5cc3d68d 100644 --- a/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj +++ b/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj @@ -6,7 +6,6 @@ $(DefineConstants);XPLAT aspnet;cli - shipoob Microsoft From 12642be5f6712816bc91c3f7c0978a240e094d4f Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 25 Mar 2018 15:35:24 -0700 Subject: [PATCH 0725/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 20 ++++++++++---------- korebuild-lock.txt | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 41da7d50f8..c761969ee1 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15728 - 2.1.0-preview2-30272 - 2.1.0-preview2-30272 - 2.1.0-preview2-30272 - 2.1.0-preview2-30272 - 2.1.0-preview2-30272 + 2.1.0-preview3-17001 + 2.1.0-preview3-32037 + 2.1.0-preview3-32037 + 2.1.0-preview3-32037 + 2.1.0-preview3-32037 + 2.1.0-preview3-32037 2.0.0 - 2.1.0-preview2-26225-03 - 15.6.0 - 4.5.0-preview2-26224-02 - 4.5.0-preview2-26224-02 + 2.1.0-preview2-26314-02 + 15.6.1 + 4.5.0-preview2-26313-01 + 4.5.0-preview2-26313-01 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 5ace9326ce..50ba1b5737 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15728 -commithash:393377068ddcf51dfee0536536d455f57a828b06 +version:2.1.0-preview3-17001 +commithash:dda68c56abf0d3b911fe6a2315872c446b314585 From ede8417bb1a3da411cc1b2fb3cf77a2926dc59cc Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 25 Mar 2018 15:39:25 -0700 Subject: [PATCH 0726/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 16 ++++++++-------- korebuild-lock.txt | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 30d6e336de..7d0d2b0bf2 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,15 +3,15 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15728 - 2.1.0-preview2-30272 - 2.1.0-preview2-30272 - 2.1.0-preview2-30272 - 2.1.0-preview2-30272 + 2.1.0-preview3-17001 + 2.1.0-preview3-32037 + 2.1.0-preview3-32037 + 2.1.0-preview3-32037 + 2.1.0-preview3-32037 2.0.0 - 2.1.0-preview2-26225-03 - 15.6.0 - 4.5.0-preview2-26224-02 + 2.1.0-preview2-26314-02 + 15.6.1 + 4.5.0-preview2-26313-01 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 138d848db1..3a326c7d58 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15728 -commithash:393377068ddcf51dfee0536536d455f57a828b06 +version:2.1.0-preview3-17001 +commithash:dda68c56abf0d3b911fe6a2315872c446b314585 From 94374a2af5d4e28daf124502b1e630b041506f2d Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 25 Mar 2018 15:45:13 -0700 Subject: [PATCH 0727/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 9335150db5..6678906caa 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,15 +3,15 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15728 - 2.1.0-preview2-30272 - 4.5.0-preview2-26224-02 - 2.1.0-preview2-30272 + 2.1.0-preview3-17001 + 2.1.0-preview3-32037 + 4.5.0-preview2-26313-01 + 2.1.0-preview3-32037 2.0.0 - 2.1.0-preview2-26225-03 - 15.6.0 + 2.1.0-preview2-26314-02 + 15.6.1 4.7.49 - 10.0.1 + 11.0.1 0.8.0 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 138d848db1..3a326c7d58 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15728 -commithash:393377068ddcf51dfee0536536d455f57a828b06 +version:2.1.0-preview3-17001 +commithash:dda68c56abf0d3b911fe6a2315872c446b314585 From bcbc4f2a499749797fa94bfb038e7e6b1d889c74 Mon Sep 17 00:00:00 2001 From: "Nate McMaster (automated)" Date: Wed, 28 Mar 2018 10:41:01 -0700 Subject: [PATCH 0728/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 20 ++++++++++---------- korebuild-lock.txt | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 0a3ff46de7..7537f33f0a 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15742 - 2.1.0-preview2-30355 - 2.1.0-preview2-30355 - 2.1.0-preview2-30355 - 2.1.0-preview2-30355 - 2.1.0-preview2-30355 + 2.1.0-preview2-15749 + 2.1.0-preview2-30478 + 2.1.0-preview2-30478 + 2.1.0-preview2-30478 + 2.1.0-preview2-30478 + 2.1.0-preview2-30478 2.0.0 - 2.1.0-preview2-26314-02 - 15.6.0 - 4.5.0-preview2-26313-01 - 4.5.0-preview2-26313-01 + 2.1.0-preview2-26326-03 + 15.6.1 + 4.5.0-preview2-26326-04 + 4.5.0-preview2-26326-04 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index e761020952..76d2c851ca 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15742 -commithash:21fbb0f2c3fe4a9216e2d59632b98cfd7d685962 +version:2.1.0-preview2-15749 +commithash:5544c9ab20fa5e24b9e155d8958a3c3b6f5f9df9 From 00d595932354b96431e6684b49c3b436bae08e20 Mon Sep 17 00:00:00 2001 From: "Nate McMaster (automated)" Date: Wed, 28 Mar 2018 10:45:08 -0700 Subject: [PATCH 0729/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 16 ++++++++-------- korebuild-lock.txt | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index dc9945767a..8776af33dd 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,15 +3,15 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15744 - 2.1.0-preview2-30355 - 2.1.0-preview2-30355 - 2.1.0-preview2-30355 - 2.1.0-preview2-30355 + 2.1.0-preview2-15749 + 2.1.0-preview2-30478 + 2.1.0-preview2-30478 + 2.1.0-preview2-30478 + 2.1.0-preview2-30478 2.0.0 - 2.1.0-preview2-26314-02 - 15.6.0 - 4.5.0-preview2-26313-01 + 2.1.0-preview2-26326-03 + 15.6.1 + 4.5.0-preview2-26326-04 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index f531e7b0f7..b8e036fe2c 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15744 -commithash:9e15cb6062ab5b9790d3fa699e018543a6950713 +version:2.1.0-preview2-15749 +commithash:5544c9ab20fa5e24b9e155d8958a3c3b6f5f9df9 From fc1b2ab5489337be36e56b86b3ab7cf71f6596f2 Mon Sep 17 00:00:00 2001 From: "Nate McMaster (automated)" Date: Wed, 28 Mar 2018 10:52:05 -0700 Subject: [PATCH 0730/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index e11bd088f7..47dc1d300d 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,15 +3,15 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview2-15742 - 2.1.0-preview2-30355 - 4.5.0-preview2-26313-01 - 2.1.0-preview2-30355 + 2.1.0-preview2-15749 + 2.1.0-preview2-30478 + 4.5.0-preview2-26326-04 + 2.1.0-preview2-30478 2.0.0 - 2.1.0-preview2-26314-02 - 15.6.0 + 2.1.0-preview2-26326-03 + 15.6.1 4.7.49 - 10.0.1 + 11.0.2 0.8.0 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index e40ef6651b..b8e036fe2c 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview2-15742 -commithash:21fbb0f2c3fe4a9216e2d59632b98cfd7d685962 +version:2.1.0-preview2-15749 +commithash:5544c9ab20fa5e24b9e155d8958a3c3b6f5f9df9 From 1f41b26145b5f554c67fb0e3da9a0073c9948ca3 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Thu, 29 Mar 2018 11:13:36 -0700 Subject: [PATCH 0731/1029] Skip broken test --- test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs index ea9ffbec03..2cbf841ae0 100644 --- a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs +++ b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs @@ -41,7 +41,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests Assert.Throws(() => Process.GetProcessById(pid)); } - [Fact] + [Fact(Skip="https://github.com/aspnet/DotNetTools/issues/407")] public async Task RestartProcessThatTerminatesAfterFileChange() { await _app.StartWatcherAsync(); From 6d4a632b96bfe91a91304d58d8de095a544b6f12 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 30 Mar 2018 17:44:31 -0700 Subject: [PATCH 0732/1029] Fix race condition in test code waiting for dotnet-watch to restart --- src/dotnet-watch/Internal/ProcessRunner.cs | 16 +++++++++++++++- .../AwaitableProcess.cs | 2 ++ .../NoDepsAppTests.cs | 2 +- .../Scenario/WatchableApp.cs | 8 ++++++-- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/dotnet-watch/Internal/ProcessRunner.cs b/src/dotnet-watch/Internal/ProcessRunner.cs index c866b6db14..a5f7cac8ef 100644 --- a/src/dotnet-watch/Internal/ProcessRunner.cs +++ b/src/dotnet-watch/Internal/ProcessRunner.cs @@ -105,9 +105,23 @@ namespace Microsoft.DotNet.Watcher.Internal { _process = process; _process.Exited += OnExited; + Task = _tcs.Task.ContinueWith(_ => + { + // We need to use two WaitForExit calls to ensure that all of the output/events are processed. Previously + // this code used Process.Exited, which could result in us missing some output due to the ordering of + // events. + // + // See the remarks here: https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.waitforexit#System_Diagnostics_Process_WaitForExit_System_Int32_ + if (!process.WaitForExit(Int32.MaxValue)) + { + throw new TimeoutException(); + } + + process.WaitForExit(); + }); } - public Task Task => _tcs.Task; + public Task Task { get; } public void TryKill() { diff --git a/test/dotnet-watch.FunctionalTests/AwaitableProcess.cs b/test/dotnet-watch.FunctionalTests/AwaitableProcess.cs index 25a0189315..91b53133eb 100644 --- a/test/dotnet-watch.FunctionalTests/AwaitableProcess.cs +++ b/test/dotnet-watch.FunctionalTests/AwaitableProcess.cs @@ -116,6 +116,8 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests private void OnExit(object sender, EventArgs args) { + // Wait to ensure the process has exited and all output consumed + _process.WaitForExit(); _source.Complete(); } diff --git a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs index 2cbf841ae0..ea9ffbec03 100644 --- a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs +++ b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs @@ -41,7 +41,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests Assert.Throws(() => Process.GetProcessById(pid)); } - [Fact(Skip="https://github.com/aspnet/DotNetTools/issues/407")] + [Fact] public async Task RestartProcessThatTerminatesAfterFileChange() { await _app.StartWatcherAsync(); diff --git a/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs b/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs index 7725812bd6..16bfbacc8d 100644 --- a/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs +++ b/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs @@ -18,6 +18,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests private const string StartedMessage = "Started"; private const string ExitingMessage = "Exiting"; + private const string WatchExitedMessage = "watch : Exited"; private readonly ITestOutputHelper _logger; private string _appName; @@ -42,8 +43,11 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public Task HasRestarted() => Process.GetOutputLineAsync(StartedMessage, DefaultMessageTimeOut); - public Task HasExited() - => Process.GetOutputLineAsync(ExitingMessage, DefaultMessageTimeOut); + public async Task HasExited() + { + await Process.GetOutputLineAsync(ExitingMessage, DefaultMessageTimeOut); + await Process.GetOutputLineAsync(WatchExitedMessage, DefaultMessageTimeOut); + } public bool UsePollingWatcher { get; set; } From 26957e090deafb34d90cbd6842bfa5d867f3438b Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Mon, 2 Apr 2018 17:16:16 -0700 Subject: [PATCH 0733/1029] Reaction to *Memory changes (#420) --- NuGetPackageVerifier.json | 16 ++++++++++++---- build/dependencies.props | 6 +++--- src/dotnet-sql-cache/dotnet-sql-cache.csproj | 2 ++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index 58eca3d2f2..7c879c4a2e 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -19,28 +19,36 @@ "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_INFORMATIONAL_VERSION_MISMATCH": { "tools/any/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_FILE_VERSION_MISMATCH": { "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_VERSION_MISMATCH": { "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." } } }, diff --git a/build/dependencies.props b/build/dependencies.props index 7537f33f0a..2c58c4330c 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -10,10 +10,10 @@ 2.1.0-preview2-30478 2.1.0-preview2-30478 2.0.0 - 2.1.0-preview2-26326-03 + 2.1.0-preview3-26331-01 15.6.1 - 4.5.0-preview2-26326-04 - 4.5.0-preview2-26326-04 + 4.5.0-preview3-26331-02 + 4.5.0-preview3-26331-02 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/src/dotnet-sql-cache/dotnet-sql-cache.csproj b/src/dotnet-sql-cache/dotnet-sql-cache.csproj index 8b7a58f538..71b526b974 100644 --- a/src/dotnet-sql-cache/dotnet-sql-cache.csproj +++ b/src/dotnet-sql-cache/dotnet-sql-cache.csproj @@ -20,6 +20,8 @@ + + From 81bf9fb66b71032c3cd9b73c2e0e4b6364e49474 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Tue, 3 Apr 2018 10:45:34 -0700 Subject: [PATCH 0734/1029] Merge release/2.1 into dev (#421) --- NuGetPackageVerifier.json | 16 ++++++++++++---- build/dependencies.props | 6 +++--- src/dotnet-sql-cache/dotnet-sql-cache.csproj | 2 ++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index 58eca3d2f2..7c879c4a2e 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -19,28 +19,36 @@ "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_INFORMATIONAL_VERSION_MISMATCH": { "tools/any/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_FILE_VERSION_MISMATCH": { "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_VERSION_MISMATCH": { "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." } } }, diff --git a/build/dependencies.props b/build/dependencies.props index c761969ee1..08af041697 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -10,10 +10,10 @@ 2.1.0-preview3-32037 2.1.0-preview3-32037 2.0.0 - 2.1.0-preview2-26314-02 + 2.1.0-preview2-26326-03 15.6.1 - 4.5.0-preview2-26313-01 - 4.5.0-preview2-26313-01 + 4.5.0-preview2-26326-04 + 4.5.0-preview2-26326-04 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/src/dotnet-sql-cache/dotnet-sql-cache.csproj b/src/dotnet-sql-cache/dotnet-sql-cache.csproj index 8b7a58f538..71b526b974 100644 --- a/src/dotnet-sql-cache/dotnet-sql-cache.csproj +++ b/src/dotnet-sql-cache/dotnet-sql-cache.csproj @@ -20,6 +20,8 @@ + + From 0e02f8572426f576a58b010b6efb16be4c9bc3a7 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 3 Apr 2018 22:22:37 +0000 Subject: [PATCH 0735/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 08af041697..28af66d0ab 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview3-17001 - 2.1.0-preview3-32037 - 2.1.0-preview3-32037 - 2.1.0-preview3-32037 - 2.1.0-preview3-32037 - 2.1.0-preview3-32037 + 2.1.0-preview3-17002 + 2.1.0-preview3-32110 + 2.1.0-preview3-32110 + 2.1.0-preview3-32110 + 2.1.0-preview3-32110 + 2.1.0-preview3-32110 2.0.0 - 2.1.0-preview2-26326-03 + 2.1.0-preview3-26331-01 15.6.1 - 4.5.0-preview2-26326-04 - 4.5.0-preview2-26326-04 + 4.5.0-preview3-26331-02 + 4.5.0-preview3-26331-02 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 50ba1b5737..c879a84a90 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview3-17001 -commithash:dda68c56abf0d3b911fe6a2315872c446b314585 +version:2.1.0-preview3-17002 +commithash:b8e4e6ab104adc94c0719bb74229870e9b584a7f From ac3bce603baa478103f7c3c432ececa6a1744fd9 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 3 Apr 2018 22:26:47 +0000 Subject: [PATCH 0736/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 7d0d2b0bf2..ae5170fa13 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,15 +3,15 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview3-17001 - 2.1.0-preview3-32037 - 2.1.0-preview3-32037 - 2.1.0-preview3-32037 - 2.1.0-preview3-32037 + 2.1.0-preview3-17002 + 2.1.0-preview3-32110 + 2.1.0-preview3-32110 + 2.1.0-preview3-32110 + 2.1.0-preview3-32110 2.0.0 - 2.1.0-preview2-26314-02 + 2.1.0-preview3-26331-01 15.6.1 - 4.5.0-preview2-26313-01 + 4.5.0-preview3-26331-02 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 3a326c7d58..b3af0b8bce 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview3-17001 -commithash:dda68c56abf0d3b911fe6a2315872c446b314585 +version:2.1.0-preview3-17002 +commithash:b8e4e6ab104adc94c0719bb74229870e9b584a7f From 9969beccbcf471d8269f40a2196fe25e0f066716 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 3 Apr 2018 22:32:28 +0000 Subject: [PATCH 0737/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 6678906caa..dec32e9f37 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,15 +3,15 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview3-17001 - 2.1.0-preview3-32037 - 4.5.0-preview2-26313-01 - 2.1.0-preview3-32037 + 2.1.0-preview3-17002 + 2.1.0-preview3-32110 + 4.5.0-preview3-26331-02 + 2.1.0-preview3-32110 2.0.0 - 2.1.0-preview2-26314-02 + 2.1.0-preview3-26331-01 15.6.1 4.7.49 - 11.0.1 + 11.0.2 0.8.0 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 3a326c7d58..b3af0b8bce 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview3-17001 -commithash:dda68c56abf0d3b911fe6a2315872c446b314585 +version:2.1.0-preview3-17002 +commithash:b8e4e6ab104adc94c0719bb74229870e9b584a7f From 9b5015d6fee90cc77c9130d3faf7904bcdd36ed6 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 4 Apr 2018 22:22:07 -0700 Subject: [PATCH 0738/1029] Ensure restore settings and package versions flow into test projects during CI builds --- .gitignore | 2 - build/dependencies.props | 16 +++--- .../Scenario/ProjectToolScenario.cs | 57 +++++++++---------- .../AppWithDeps/AppWithDeps.csproj | 1 + .../TestProjects/Dependency/Dependency.csproj | 5 +- .../GlobbingApp/GlobbingApp.csproj | 1 + .../KitchenSink/KitchenSink.csproj | 1 + .../TestProjects/NoDepsApp/NoDepsApp.csproj | 1 + .../dotnet-watch.FunctionalTests.csproj | 35 ++++-------- testWorkDir/Directory.Build.props | 3 - testWorkDir/Directory.Build.targets | 3 - 11 files changed, 51 insertions(+), 74 deletions(-) delete mode 100644 testWorkDir/Directory.Build.props delete mode 100644 testWorkDir/Directory.Build.targets diff --git a/.gitignore b/.gitignore index 78ed833761..01ed76be4f 100644 --- a/.gitignore +++ b/.gitignore @@ -29,11 +29,9 @@ project.lock.json .build/ /.vs/ .vscode/ -testWorkDir/ *.nuget.props *.nuget.targets .idea/ .dotnet/ global.json *.binlog -test/dotnet-watch.FunctionalTests/TestProjects/NuGet.config \ No newline at end of file diff --git a/build/dependencies.props b/build/dependencies.props index 2c58c4330c..d79aa4648b 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,16 +4,16 @@ 2.1.0-preview2-15749 - 2.1.0-preview2-30478 - 2.1.0-preview2-30478 - 2.1.0-preview2-30478 - 2.1.0-preview2-30478 - 2.1.0-preview2-30478 + 2.1.0-preview2-30559 + 2.1.0-preview2-30559 + 2.1.0-preview2-30559 + 2.1.0-preview2-30559 + 2.1.0-preview2-30559 2.0.0 - 2.1.0-preview3-26331-01 + 2.1.0-preview2-26403-06 15.6.1 - 4.5.0-preview3-26331-02 - 4.5.0-preview3-26331-02 + 4.5.0-preview2-26403-05 + 4.5.0-preview2-26403-05 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs index a11310c6e9..a0a14093ec 100644 --- a/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -5,9 +5,11 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; +using System.Xml.Linq; using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Internal; using Microsoft.Extensions.Tools.Internal; @@ -17,7 +19,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { public class ProjectToolScenario : IDisposable { - private const string NugetConfigFileName = "NuGet.config"; private static readonly string TestProjectSourceRoot = Path.Combine(AppContext.BaseDirectory, "TestProjects"); private readonly ITestOutputHelper _logger; @@ -28,21 +29,18 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public ProjectToolScenario(ITestOutputHelper logger) { + WorkFolder = Path.Combine(AppContext.BaseDirectory, "tmp", Path.GetRandomFileName()); + DotNetWatchPath = Path.Combine(AppContext.BaseDirectory, "tool", "dotnet-watch.dll"); + _logger = logger; - _logger?.WriteLine($"The temporary test folder is {TempFolder}"); - WorkFolder = Path.Combine(TempFolder, "work"); + _logger?.WriteLine($"The temporary test folder is {WorkFolder}"); CreateTestDirectory(); } - - public static string TestWorkFolder { get; } = Path.Combine(AppContext.BaseDirectory, "testWorkDir"); - - public string TempFolder { get; } = Path.Combine(TestWorkFolder, Guid.NewGuid().ToString("N")); - public string WorkFolder { get; } - public string DotNetWatchPath { get; } = Path.Combine(AppContext.BaseDirectory, "tool", "dotnet-watch.dll"); + public string DotNetWatchPath { get; } public void AddTestProjectFolder(string projectName) { @@ -149,42 +147,39 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { Directory.CreateDirectory(WorkFolder); - var nugetConfigFilePath = FindNugetConfig(); + File.WriteAllText(Path.Combine(WorkFolder, "Directory.Build.props"), ""); - var tempNugetConfigFile = Path.Combine(WorkFolder, NugetConfigFileName); - File.Copy(nugetConfigFilePath, tempNugetConfigFile); + var restoreSources = GetMetadata("TestSettings:RestoreSources"); + var frameworkVersion = GetMetadata("TestSettings:RuntimeFrameworkVersion"); + + var dbTargets = new XDocument( + new XElement("Project", + new XElement("PropertyGroup", + new XElement("RuntimeFrameworkVersion", frameworkVersion), + new XElement("RestoreSources", restoreSources)))); + dbTargets.Save(Path.Combine(WorkFolder, "Directory.Build.targets")); } - private static string FindNugetConfig() + private string GetMetadata(string key) { - var currentDirPath = TestWorkFolder; - - string nugetConfigFile; - while (true) - { - nugetConfigFile = Path.Combine(currentDirPath, NugetConfigFileName); - if (File.Exists(nugetConfigFile)) - { - break; - } - - currentDirPath = Path.GetDirectoryName(currentDirPath); - } - - return nugetConfigFile; + return typeof(ProjectToolScenario) + .Assembly + .GetCustomAttributes() + .First(a => string.Equals(a.Key, key, StringComparison.Ordinal)) + .Value; } public void Dispose() { try { - Directory.Delete(TempFolder, recursive: true); + Directory.Delete(WorkFolder, recursive: true); } catch { - Console.WriteLine($"Failed to delete {TempFolder}. Retrying..."); + Console.WriteLine($"Failed to delete {WorkFolder}. Retrying..."); Thread.Sleep(TimeSpan.FromSeconds(5)); - Directory.Delete(TempFolder, recursive: true); + Directory.Delete(WorkFolder, recursive: true); } } } diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj b/test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj index 76d7446452..0dcb552112 100644 --- a/test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj +++ b/test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj @@ -3,6 +3,7 @@ netcoreapp2.1 exe + true diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/Dependency/Dependency.csproj b/test/dotnet-watch.FunctionalTests/TestProjects/Dependency/Dependency.csproj index 22361d48cb..0dbf97b944 100644 --- a/test/dotnet-watch.FunctionalTests/TestProjects/Dependency/Dependency.csproj +++ b/test/dotnet-watch.FunctionalTests/TestProjects/Dependency/Dependency.csproj @@ -1,7 +1,8 @@ - netstandard1.5 + netstandard2.0 + true - \ No newline at end of file + diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj b/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj index 60645a49da..a01efb4b2f 100644 --- a/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj +++ b/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj @@ -4,6 +4,7 @@ netcoreapp2.1 exe false + true diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj b/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj index 699071e138..72f7d5cae4 100644 --- a/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj +++ b/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj @@ -10,6 +10,7 @@ Exe netcoreapp2.1 + true diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj b/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj index 86e88b8b95..b242bd2546 100644 --- a/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj +++ b/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj @@ -3,6 +3,7 @@ netcoreapp2.1 exe + true diff --git a/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj b/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj index 5d97fcca6f..d7c0a3fdac 100644 --- a/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj +++ b/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj @@ -21,31 +21,16 @@ - - - $(MSBuildThisFileDirectory)/TestProjects/NuGet.config - - - - - - - - - - - - - - - - - - + + + <_Parameter1>TestSettings:RestoreSources + <_Parameter2>$(RestoreSources) + + + <_Parameter1>TestSettings:RuntimeFrameworkVersion + <_Parameter2>$(RuntimeFrameworkVersion) + + diff --git a/testWorkDir/Directory.Build.props b/testWorkDir/Directory.Build.props deleted file mode 100644 index b959507df8..0000000000 --- a/testWorkDir/Directory.Build.props +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/testWorkDir/Directory.Build.targets b/testWorkDir/Directory.Build.targets deleted file mode 100644 index b959507df8..0000000000 --- a/testWorkDir/Directory.Build.targets +++ /dev/null @@ -1,3 +0,0 @@ - - - From b7b6bd95337a8d7225db418125d8b5a6190a11ab Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 11 Apr 2018 09:59:22 -0700 Subject: [PATCH 0739/1029] React to updates in dependencies and removal of System.Runtime.CompilerServices.Unsafe from netcoreapp (#429) --- NuGetPackageVerifier.json | 23 ++++++++------------ build/dependencies.props | 8 +++---- korebuild-lock.txt | 4 ++-- src/dotnet-sql-cache/dotnet-sql-cache.csproj | 1 + 4 files changed, 16 insertions(+), 20 deletions(-) diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index 7c879c4a2e..ca0d81e371 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -14,39 +14,38 @@ "DotnetTool" ], "Exclusions": { + "NEUTRAL_RESOURCES_LANGUAGE": { + "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + }, "WRONG_PUBLICKEYTOKEN": { + "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_INFORMATIONAL_VERSION_MISMATCH": { + "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_FILE_VERSION_MISMATCH": { - "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_VERSION_MISMATCH": { - "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." } @@ -58,15 +57,11 @@ ], "Exclusions": { "NEUTRAL_RESOURCES_LANGUAGE": { - "tools/any/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." }, "SERVICING_ATTRIBUTE": { "tools/any/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg." }, - "VERSION_INFORMATIONALVERSION": { - "tools/any/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg." - }, "WRONG_PUBLICKEYTOKEN": { "tools/any/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." diff --git a/build/dependencies.props b/build/dependencies.props index 28af66d0ab..79fe354e08 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview3-17002 + 2.1.0-preview3-17005 2.1.0-preview3-32110 2.1.0-preview3-32110 2.1.0-preview3-32110 2.1.0-preview3-32110 2.1.0-preview3-32110 2.0.0 - 2.1.0-preview3-26331-01 + 2.1.0-preview3-26410-06 15.6.1 - 4.5.0-preview3-26331-02 - 4.5.0-preview3-26331-02 + 4.5.0-preview3-26409-05 + 4.5.0-preview3-26409-05 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index c879a84a90..c6329a2176 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview3-17002 -commithash:b8e4e6ab104adc94c0719bb74229870e9b584a7f +version:2.1.0-preview3-17005 +commithash:6e4c983b65fe55ba71bfb746df37e6bf2726ac1c diff --git a/src/dotnet-sql-cache/dotnet-sql-cache.csproj b/src/dotnet-sql-cache/dotnet-sql-cache.csproj index 71b526b974..64d2c8b51b 100644 --- a/src/dotnet-sql-cache/dotnet-sql-cache.csproj +++ b/src/dotnet-sql-cache/dotnet-sql-cache.csproj @@ -12,6 +12,7 @@ + From 5f9e70808902b074301166aacee7419804314002 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 15 Apr 2018 14:06:06 -0700 Subject: [PATCH 0740/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 79fe354e08..efa8ad53e7 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview3-17005 - 2.1.0-preview3-32110 - 2.1.0-preview3-32110 - 2.1.0-preview3-32110 - 2.1.0-preview3-32110 - 2.1.0-preview3-32110 + 2.1.0-preview3-17018 + 2.1.0-preview3-32233 + 2.1.0-preview3-32233 + 2.1.0-preview3-32233 + 2.1.0-preview3-32233 + 2.1.0-preview3-32233 2.0.0 - 2.1.0-preview3-26410-06 + 2.1.0-preview3-26413-05 15.6.1 - 4.5.0-preview3-26409-05 - 4.5.0-preview3-26409-05 + 4.5.0-preview3-26413-02 + 4.5.0-preview3-26413-02 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index c6329a2176..ce2f277c53 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview3-17005 -commithash:6e4c983b65fe55ba71bfb746df37e6bf2726ac1c +version:2.1.0-preview3-17018 +commithash:af264ca131f212b5ba8aafbc5110fc0fc510a2be From 411d583631e8ef191e8dbcc4eadfff0d99787d6b Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 15 Apr 2018 14:09:55 -0700 Subject: [PATCH 0741/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index ae5170fa13..d4c70b5608 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,15 +3,15 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview3-17002 - 2.1.0-preview3-32110 - 2.1.0-preview3-32110 - 2.1.0-preview3-32110 - 2.1.0-preview3-32110 + 2.1.0-preview3-17018 + 2.1.0-preview3-32233 + 2.1.0-preview3-32233 + 2.1.0-preview3-32233 + 2.1.0-preview3-32233 2.0.0 - 2.1.0-preview3-26331-01 + 2.1.0-preview3-26413-05 15.6.1 - 4.5.0-preview3-26331-02 + 4.5.0-preview3-26413-02 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index b3af0b8bce..b419d767b9 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview3-17002 -commithash:b8e4e6ab104adc94c0719bb74229870e9b584a7f +version:2.1.0-preview3-17018 +commithash:af264ca131f212b5ba8aafbc5110fc0fc510a2be From 4ca59af5469ddd6c38d80430944c19b13b8936f5 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 15 Apr 2018 14:16:23 -0700 Subject: [PATCH 0742/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index dec32e9f37..1fa3452a34 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview3-17002 - 2.1.0-preview3-32110 - 4.5.0-preview3-26331-02 - 2.1.0-preview3-32110 + 2.1.0-preview3-17018 + 2.1.0-preview3-32233 + 4.5.0-preview3-26413-02 + 2.1.0-preview3-32233 2.0.0 - 2.1.0-preview3-26331-01 + 2.1.0-preview3-26413-05 15.6.1 4.7.49 11.0.2 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index b3af0b8bce..b419d767b9 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview3-17002 -commithash:b8e4e6ab104adc94c0719bb74229870e9b584a7f +version:2.1.0-preview3-17018 +commithash:af264ca131f212b5ba8aafbc5110fc0fc510a2be From 3385cfea1b33f0d1f74b0d312b75b4aad969620c Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Mon, 16 Apr 2018 16:56:17 -0700 Subject: [PATCH 0743/1029] Branching for 2.1.0-rc1 --- build/repo.props | 3 ++- korebuild.json | 4 ++-- version.props | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/build/repo.props b/build/repo.props index 1be3632130..129e1465c8 100644 --- a/build/repo.props +++ b/build/repo.props @@ -1,4 +1,4 @@ - + @@ -10,6 +10,7 @@ Internal.AspNetCore.Universe.Lineup + 2.1.0-rc1-* https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json diff --git a/korebuild.json b/korebuild.json index 4d59ad132a..196a3ca537 100644 --- a/korebuild.json +++ b/korebuild.json @@ -1,6 +1,6 @@ { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev", + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.1/tools/korebuild.schema.json", + "channel": "release/2.1", "toolsets": { "visualstudio": { "required": [ diff --git a/version.props b/version.props index ce0b3d1a83..c64accb2d6 100644 --- a/version.props +++ b/version.props @@ -2,7 +2,7 @@ 2.1.0 15.6 - preview3 + rc1 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final $(VsixVersion).$(BuildNumber) From 08f7c2759ff1d43d9e9a9b855684bada7bbc94a4 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Mon, 16 Apr 2018 16:56:22 -0700 Subject: [PATCH 0744/1029] Update version number to 2.2.0 --- version.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.props b/version.props index ce0b3d1a83..4c749bb5d2 100644 --- a/version.props +++ b/version.props @@ -1,8 +1,8 @@ - 2.1.0 + 2.2.0 15.6 - preview3 + preview1 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final $(VsixVersion).$(BuildNumber) From 6c2432e5448fc71889e374fee3f6c7472c18628a Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Mon, 16 Apr 2018 16:57:26 -0700 Subject: [PATCH 0745/1029] Branching for 2.1.0-rc1 --- build/repo.props | 3 ++- korebuild.json | 4 ++-- version.props | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/build/repo.props b/build/repo.props index 78b0ce5879..dab1601c88 100644 --- a/build/repo.props +++ b/build/repo.props @@ -1,9 +1,10 @@ - + Internal.AspNetCore.Universe.Lineup + 2.1.0-rc1-* https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json diff --git a/korebuild.json b/korebuild.json index bd5d51a51b..678d8bb948 100644 --- a/korebuild.json +++ b/korebuild.json @@ -1,4 +1,4 @@ { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev" + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.1/tools/korebuild.schema.json", + "channel": "release/2.1" } diff --git a/version.props b/version.props index 24f2b00a0a..e27532787e 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ 2.1.0 - preview3 + rc1 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From 5fd1e648e2ec4eba89223efc1ab16b2f932bc196 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Mon, 16 Apr 2018 16:57:31 -0700 Subject: [PATCH 0746/1029] Update version number to 2.2.0 --- version.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.props b/version.props index 24f2b00a0a..44985cedb3 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ - 2.1.0 - preview3 + 2.2.0 + preview1 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From 40d5c7f839f86a927bd39777e8b4198aafc098ee Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Mon, 16 Apr 2018 16:58:44 -0700 Subject: [PATCH 0747/1029] Branching for 2.1.0-rc1 --- build/repo.props | 3 ++- korebuild.json | 4 ++-- version.props | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/build/repo.props b/build/repo.props index 78b0ce5879..dab1601c88 100644 --- a/build/repo.props +++ b/build/repo.props @@ -1,9 +1,10 @@ - + Internal.AspNetCore.Universe.Lineup + 2.1.0-rc1-* https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json diff --git a/korebuild.json b/korebuild.json index bd5d51a51b..678d8bb948 100644 --- a/korebuild.json +++ b/korebuild.json @@ -1,4 +1,4 @@ { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev" + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.1/tools/korebuild.schema.json", + "channel": "release/2.1" } diff --git a/version.props b/version.props index 24f2b00a0a..e27532787e 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ 2.1.0 - preview3 + rc1 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From 3aaf2726d9bf70cb3d922e3bcb43cf0f9516c67c Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Mon, 16 Apr 2018 16:58:49 -0700 Subject: [PATCH 0748/1029] Update version number to 2.2.0 --- version.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.props b/version.props index 24f2b00a0a..44985cedb3 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ - 2.1.0 - preview3 + 2.2.0 + preview1 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From a59aaa120332db52b95449ec8850a09e1a4ccb59 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 19 Apr 2018 16:32:37 -0700 Subject: [PATCH 0749/1029] Set NETStandardImplicitPackageVersion via dependencies.props --- Directory.Build.targets | 1 + build/dependencies.props | 1 + 2 files changed, 2 insertions(+) diff --git a/Directory.Build.targets b/Directory.Build.targets index c3d61be3b4..eb03b2565f 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,5 +1,6 @@  $(MicrosoftNETCoreApp21PackageVersion) + $(NETStandardLibrary20PackageVersion) diff --git a/build/dependencies.props b/build/dependencies.props index efa8ad53e7..9ace7fb631 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -12,6 +12,7 @@ 2.0.0 2.1.0-preview3-26413-05 15.6.1 + 2.0.1 4.5.0-preview3-26413-02 4.5.0-preview3-26413-02 9.0.1 From b392ef5ed7c1b509ceadfa9261c671bb78f6334e Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 19 Apr 2018 16:39:10 -0700 Subject: [PATCH 0750/1029] Set NETStandardImplicitPackageVersion via dependencies.props --- Directory.Build.targets | 1 + build/dependencies.props | 1 + 2 files changed, 2 insertions(+) diff --git a/Directory.Build.targets b/Directory.Build.targets index 894b1d0cf8..53b3f6e1da 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -2,5 +2,6 @@ $(MicrosoftNETCoreApp20PackageVersion) $(MicrosoftNETCoreApp21PackageVersion) + $(NETStandardLibrary20PackageVersion) diff --git a/build/dependencies.props b/build/dependencies.props index d4c70b5608..577926b344 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -11,6 +11,7 @@ 2.0.0 2.1.0-preview3-26413-05 15.6.1 + 2.0.1 4.5.0-preview3-26413-02 2.3.1 2.4.0-beta.1.build3945 From 6c6cd890865f4d6f61900c7274bd38bfca9d4f00 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 19 Apr 2018 16:40:16 -0700 Subject: [PATCH 0751/1029] Set NETStandardImplicitPackageVersion via dependencies.props --- Directory.Build.targets | 1 + build/dependencies.props | 1 + 2 files changed, 2 insertions(+) diff --git a/Directory.Build.targets b/Directory.Build.targets index 894b1d0cf8..53b3f6e1da 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -2,5 +2,6 @@ $(MicrosoftNETCoreApp20PackageVersion) $(MicrosoftNETCoreApp21PackageVersion) + $(NETStandardLibrary20PackageVersion) diff --git a/build/dependencies.props b/build/dependencies.props index 1fa3452a34..89f812caa6 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -11,6 +11,7 @@ 2.1.0-preview3-26413-05 15.6.1 4.7.49 + 2.0.1 11.0.2 0.8.0 2.3.1 From e2f4487d098bb118a0662c2ba6b31117e10fc64d Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 19 Apr 2018 22:18:35 -0700 Subject: [PATCH 0752/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 9ace7fb631..02852a5e72 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,18 +3,18 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview3-17018 - 2.1.0-preview3-32233 - 2.1.0-preview3-32233 - 2.1.0-preview3-32233 - 2.1.0-preview3-32233 - 2.1.0-preview3-32233 + 2.1.0-rc1-15774 + 2.1.0-rc1-30613 + 2.1.0-rc1-30613 + 2.1.0-rc1-30613 + 2.1.0-rc1-30613 + 2.1.0-rc1-30613 2.0.0 - 2.1.0-preview3-26413-05 + 2.1.0-rc1-26419-02 15.6.1 2.0.1 - 4.5.0-preview3-26413-02 - 4.5.0-preview3-26413-02 + 4.5.0-rc1-26419-03 + 4.5.0-rc1-26419-03 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index ce2f277c53..d35f5d62cf 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview3-17018 -commithash:af264ca131f212b5ba8aafbc5110fc0fc510a2be +version:2.1.0-rc1-15774 +commithash:ed5ca9de3c652347dbb0158a9a65eff3471d2114 From 065f9f9dbcba5cb8d1c37dc70f922a0b6609d934 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 19 Apr 2018 22:21:45 -0700 Subject: [PATCH 0753/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 577926b344..dc2db7956c 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,16 +3,16 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview3-17018 - 2.1.0-preview3-32233 - 2.1.0-preview3-32233 - 2.1.0-preview3-32233 - 2.1.0-preview3-32233 + 2.1.0-rc1-15774 + 2.1.0-rc1-30613 + 2.1.0-rc1-30613 + 2.1.0-rc1-30613 + 2.1.0-rc1-30613 2.0.0 - 2.1.0-preview3-26413-05 + 2.1.0-rc1-26419-02 15.6.1 2.0.1 - 4.5.0-preview3-26413-02 + 4.5.0-rc1-26419-03 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index b419d767b9..9d4ef8c888 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview3-17018 -commithash:af264ca131f212b5ba8aafbc5110fc0fc510a2be +version:2.1.0-rc1-15774 +commithash:ed5ca9de3c652347dbb0158a9a65eff3471d2114 From 09232faae42de90b96180645f83f82a4989e91b3 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 19 Apr 2018 22:27:34 -0700 Subject: [PATCH 0754/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 89f812caa6..649af28432 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-preview3-17018 - 2.1.0-preview3-32233 - 4.5.0-preview3-26413-02 - 2.1.0-preview3-32233 + 2.1.0-rc1-15774 + 2.1.0-rc1-30613 + 4.5.0-rc1-26419-03 + 2.1.0-rc1-30613 2.0.0 - 2.1.0-preview3-26413-05 + 2.1.0-rc1-26419-02 15.6.1 4.7.49 2.0.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index b419d767b9..9d4ef8c888 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview3-17018 -commithash:af264ca131f212b5ba8aafbc5110fc0fc510a2be +version:2.1.0-rc1-15774 +commithash:ed5ca9de3c652347dbb0158a9a65eff3471d2114 From aa181128ac60fb9164e7529c5bcc7e803615b7ad Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Thu, 19 Apr 2018 18:24:52 -0700 Subject: [PATCH 0755/1029] Generate symbol nupkgs for tools --- src/DotnetTool.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DotnetTool.props b/src/DotnetTool.props index 5e34c077ce..ec4a5965f3 100644 --- a/src/DotnetTool.props +++ b/src/DotnetTool.props @@ -5,7 +5,7 @@ true Microsoft - false + true false From 0c471a5b1329393a9478e000d581e4836eb12449 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Mon, 23 Apr 2018 12:05:18 -0700 Subject: [PATCH 0756/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 02852a5e72..fd54efdb1a 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,18 +3,18 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-rc1-15774 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 + 2.2.0-preview1-17037 + 2.2.0-preview1-34029 + 2.2.0-preview1-34029 + 2.2.0-preview1-34029 + 2.2.0-preview1-34029 + 2.2.0-preview1-34029 2.0.0 - 2.1.0-rc1-26419-02 + 2.1.0-preview3-26413-05 15.6.1 2.0.1 - 4.5.0-rc1-26419-03 - 4.5.0-rc1-26419-03 + 4.5.0-preview3-26413-02 + 4.5.0-preview3-26413-02 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index ce2f277c53..790ae84e6d 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview3-17018 -commithash:af264ca131f212b5ba8aafbc5110fc0fc510a2be +version:2.2.0-preview1-17037 +commithash:557055a86cbdc359c97d4fb1c2d23a3dc7ae731e From 39101569474435dd67f1d8ec7e872f675019eb92 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Mon, 23 Apr 2018 12:08:58 -0700 Subject: [PATCH 0757/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index dc2db7956c..360c641b28 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,16 +3,16 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-rc1-15774 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 + 2.2.0-preview1-17037 + 2.2.0-preview1-34029 + 2.2.0-preview1-34029 + 2.2.0-preview1-34029 + 2.2.0-preview1-34029 2.0.0 - 2.1.0-rc1-26419-02 + 2.1.0-preview3-26413-05 15.6.1 2.0.1 - 4.5.0-rc1-26419-03 + 4.5.0-preview3-26413-02 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index b419d767b9..f27a67b442 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview3-17018 -commithash:af264ca131f212b5ba8aafbc5110fc0fc510a2be +version:2.2.0-preview1-17037 +commithash:557055a86cbdc359c97d4fb1c2d23a3dc7ae731e From 39b31e022395c4750374140073c10970944d0c87 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Mon, 23 Apr 2018 12:15:24 -0700 Subject: [PATCH 0758/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 649af28432..1b21c323aa 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-rc1-15774 - 2.1.0-rc1-30613 - 4.5.0-rc1-26419-03 - 2.1.0-rc1-30613 + 2.2.0-preview1-17037 + 2.2.0-preview1-34029 + 4.5.0-preview3-26413-02 + 2.2.0-preview1-34029 2.0.0 - 2.1.0-rc1-26419-02 + 2.1.0-preview3-26413-05 15.6.1 4.7.49 2.0.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index b419d767b9..f27a67b442 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-preview3-17018 -commithash:af264ca131f212b5ba8aafbc5110fc0fc510a2be +version:2.2.0-preview1-17037 +commithash:557055a86cbdc359c97d4fb1c2d23a3dc7ae731e From 783090718f6aa89634facb9998c7fdaf1d2531a1 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 29 Apr 2018 12:12:59 -0700 Subject: [PATCH 0759/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 20 ++++++++++---------- korebuild-lock.txt | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index fd54efdb1a..ead6b8535d 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,18 +3,18 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17037 - 2.2.0-preview1-34029 - 2.2.0-preview1-34029 - 2.2.0-preview1-34029 - 2.2.0-preview1-34029 - 2.2.0-preview1-34029 + 2.2.0-preview1-17042 + 2.2.0-preview1-34066 + 2.2.0-preview1-34066 + 2.2.0-preview1-34066 + 2.2.0-preview1-34066 + 2.2.0-preview1-34066 2.0.0 - 2.1.0-preview3-26413-05 + 2.2.0-preview1-26424-04 15.6.1 - 2.0.1 - 4.5.0-preview3-26413-02 - 4.5.0-preview3-26413-02 + 2.0.3 + 4.5.0-preview3-26423-04 + 4.5.0-preview3-26423-04 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 790ae84e6d..5a9689541e 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17037 -commithash:557055a86cbdc359c97d4fb1c2d23a3dc7ae731e +version:2.2.0-preview1-17042 +commithash:edf0705d014293c260de763543784330514db9a3 From e9896d3be06f966612a469d304274bd81cb353f3 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 29 Apr 2018 12:16:29 -0700 Subject: [PATCH 0760/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 16 ++++++++-------- korebuild-lock.txt | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 360c641b28..509b7d5539 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,16 +3,16 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17037 - 2.2.0-preview1-34029 - 2.2.0-preview1-34029 - 2.2.0-preview1-34029 - 2.2.0-preview1-34029 + 2.2.0-preview1-17042 + 2.2.0-preview1-34066 + 2.2.0-preview1-34066 + 2.2.0-preview1-34066 + 2.2.0-preview1-34066 2.0.0 - 2.1.0-preview3-26413-05 + 2.2.0-preview1-26424-04 15.6.1 - 2.0.1 - 4.5.0-preview3-26413-02 + 2.0.3 + 4.5.0-preview3-26423-04 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index f27a67b442..335e579e06 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17037 -commithash:557055a86cbdc359c97d4fb1c2d23a3dc7ae731e +version:2.2.0-preview1-17042 +commithash:edf0705d014293c260de763543784330514db9a3 From d442f8c498b910f3fc12dcb6e2ab1cadafe608b9 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 29 Apr 2018 12:22:39 -0700 Subject: [PATCH 0761/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 1b21c323aa..03999cb59f 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,15 +3,15 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17037 - 2.2.0-preview1-34029 - 4.5.0-preview3-26413-02 - 2.2.0-preview1-34029 + 2.2.0-preview1-17042 + 2.2.0-preview1-34066 + 4.5.0-preview3-26423-04 + 2.2.0-preview1-34066 2.0.0 - 2.1.0-preview3-26413-05 + 2.2.0-preview1-26424-04 15.6.1 4.7.49 - 2.0.1 + 2.0.3 11.0.2 0.8.0 2.3.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index f27a67b442..335e579e06 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17037 -commithash:557055a86cbdc359c97d4fb1c2d23a3dc7ae731e +version:2.2.0-preview1-17042 +commithash:edf0705d014293c260de763543784330514db9a3 From 174ca79d25b1a6b4b4dd71b5f1914449b1250848 Mon Sep 17 00:00:00 2001 From: "Nate McMaster (automated)" Date: Mon, 30 Apr 2018 14:51:39 -0700 Subject: [PATCH 0762/1029] Bump version to 2.1.0-rtm --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index c64accb2d6..e19391f5bf 100644 --- a/version.props +++ b/version.props @@ -2,7 +2,7 @@ 2.1.0 15.6 - rc1 + rtm $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final $(VsixVersion).$(BuildNumber) From b8b90e1bed89ed2783b6d85d81828f7ef96d6d46 Mon Sep 17 00:00:00 2001 From: "Nate McMaster (automated)" Date: Mon, 30 Apr 2018 14:51:40 -0700 Subject: [PATCH 0763/1029] Bump version to 2.1.0-rtm --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index e27532787e..b9552451d8 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ 2.1.0 - rc1 + rtm $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From 4f3e31431a0c96d687b2ef41e436f878ae79db31 Mon Sep 17 00:00:00 2001 From: "Nate McMaster (automated)" Date: Mon, 30 Apr 2018 14:51:42 -0700 Subject: [PATCH 0764/1029] Bump version to 2.1.0-rtm --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index e27532787e..b9552451d8 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ 2.1.0 - rc1 + rtm $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From e0e9eb0b3609807912b1b885c67a5d0047800686 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 1 May 2018 16:57:36 -0700 Subject: [PATCH 0765/1029] Add pre-generated shims to dotnet tool packages --- NuGetPackageVerifier.json | 70 +++++++++---------- build/dependencies.props | 20 +++--- korebuild-lock.txt | 4 +- src/Directory.Build.props | 9 --- src/Directory.Build.targets | 3 - src/DotnetTool.props | 15 ---- ...NetCore.DeveloperCertificates.XPlat.csproj | 2 - src/PackGlobalTool.targets | 19 ----- src/dotnet-dev-certs/DotnetToolSettings.xml | 6 -- src/dotnet-dev-certs/dotnet-dev-certs.csproj | 10 ++- src/dotnet-dev-certs/dotnet-dev-certs.nuspec | 25 ------- src/dotnet-sql-cache/DotnetToolSettings.xml | 6 -- src/dotnet-sql-cache/dotnet-sql-cache.csproj | 24 +++---- src/dotnet-sql-cache/dotnet-sql-cache.nuspec | 25 ------- .../DotnetToolSettings.xml | 6 -- .../dotnet-user-secrets.csproj | 30 +++----- .../dotnet-user-secrets.nuspec | 25 ------- src/dotnet-watch/DotnetToolSettings.xml | 6 -- src/dotnet-watch/dotnet-watch.csproj | 12 +++- src/dotnet-watch/dotnet-watch.nuspec | 25 ------- .../dotnet-user-secrets.Tests.csproj | 4 ++ 21 files changed, 85 insertions(+), 261 deletions(-) delete mode 100644 src/DotnetTool.props delete mode 100644 src/PackGlobalTool.targets delete mode 100644 src/dotnet-dev-certs/DotnetToolSettings.xml delete mode 100644 src/dotnet-dev-certs/dotnet-dev-certs.nuspec delete mode 100644 src/dotnet-sql-cache/DotnetToolSettings.xml delete mode 100644 src/dotnet-sql-cache/dotnet-sql-cache.nuspec delete mode 100644 src/dotnet-user-secrets/DotnetToolSettings.xml delete mode 100644 src/dotnet-user-secrets/dotnet-user-secrets.nuspec delete mode 100644 src/dotnet-watch/DotnetToolSettings.xml delete mode 100644 src/dotnet-watch/dotnet-watch.nuspec diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index ca0d81e371..3e59aeb910 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -15,39 +15,39 @@ ], "Exclusions": { "NEUTRAL_RESOURCES_LANGUAGE": { - "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." }, "WRONG_PUBLICKEYTOKEN": { - "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_INFORMATIONAL_VERSION_MISMATCH": { - "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_FILE_VERSION_MISMATCH": { - "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_VERSION_MISMATCH": { - "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." } } }, @@ -57,26 +57,26 @@ ], "Exclusions": { "NEUTRAL_RESOURCES_LANGUAGE": { - "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." }, "SERVICING_ATTRIBUTE": { - "tools/any/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg." }, "WRONG_PUBLICKEYTOKEN": { - "tools/any/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_INFORMATIONAL_VERSION_MISMATCH": { - "tools/any/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_FILE_VERSION_MISMATCH": { - "tools/any/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_VERSION_MISMATCH": { - "tools/any/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/any/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." } } }, diff --git a/build/dependencies.props b/build/dependencies.props index 02852a5e72..73aaaa8abf 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,18 +3,18 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-rc1-15774 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 + 2.1.0-rtm-15776 + 2.1.0-rc1-30677 + 2.1.0-rc1-30677 + 2.1.0-rc1-30677 + 2.1.0-rc1-30677 + 2.1.0-rc1-30677 2.0.0 - 2.1.0-rc1-26419-02 + 2.1.0-rc1-26423-06 15.6.1 - 2.0.1 - 4.5.0-rc1-26419-03 - 4.5.0-rc1-26419-03 + 2.0.3 + 4.5.0-rc1-26423-06 + 4.5.0-rc1-26423-06 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index d35f5d62cf..d455c7a7a6 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-rc1-15774 -commithash:ed5ca9de3c652347dbb0158a9a65eff3471d2114 +version:2.1.0-rtm-15780 +commithash:4b54ae92ccebdf2a5aabca9748cc874eeafe5ac9 diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 7129734857..4b89a431e7 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,15 +1,6 @@ - - - false - - - false - - - diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index 9dd4a760bf..c7b5f24861 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -1,8 +1,5 @@ - - - diff --git a/src/DotnetTool.props b/src/DotnetTool.props deleted file mode 100644 index ec4a5965f3..0000000000 --- a/src/DotnetTool.props +++ /dev/null @@ -1,15 +0,0 @@ - - - $(MSBuildProjectDirectory)\$(MSBuildProjectName).nuspec - - true - - Microsoft - true - false - - - - - - diff --git a/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj b/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj index ae5cc3d68d..81c90a297c 100644 --- a/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj +++ b/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj @@ -5,8 +5,6 @@ Package for the CLI first run experience. $(DefineConstants);XPLAT aspnet;cli - - Microsoft diff --git a/src/PackGlobalTool.targets b/src/PackGlobalTool.targets deleted file mode 100644 index d97666110c..0000000000 --- a/src/PackGlobalTool.targets +++ /dev/null @@ -1,19 +0,0 @@ - - - - - publishDir=$(PublishDir); - version=$(PackageVersion); - licenseUrl=$(PackageLicenseUrl); - projectUrl=$(PackageProjectUrl); - iconUrl=$(PackageIconUrl); - serviceable=$(Serviceable); - copyright=$(Copyright); - description=$(Description); - repositoryUrl=$(RepositoryUrl); - targetframework=$(TargetFramework); - repositoryCommit=$(RepositoryCommit); - - - - diff --git a/src/dotnet-dev-certs/DotnetToolSettings.xml b/src/dotnet-dev-certs/DotnetToolSettings.xml deleted file mode 100644 index dbc7a5b6d9..0000000000 --- a/src/dotnet-dev-certs/DotnetToolSettings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/src/dotnet-dev-certs/dotnet-dev-certs.csproj b/src/dotnet-dev-certs/dotnet-dev-certs.csproj index 8c4d039c02..024cc705d2 100644 --- a/src/dotnet-dev-certs/dotnet-dev-certs.csproj +++ b/src/dotnet-dev-certs/dotnet-dev-certs.csproj @@ -1,11 +1,17 @@ - + + + netcoreapp2.1 exe Command line tool to generate certificates used in ASP.NET Core during development. - DotnetTool Microsoft.AspNetCore.DeveloperCertificates.Tools + dotnet;developercertificates + true + + + true diff --git a/src/dotnet-dev-certs/dotnet-dev-certs.nuspec b/src/dotnet-dev-certs/dotnet-dev-certs.nuspec deleted file mode 100644 index 878e0f4ab2..0000000000 --- a/src/dotnet-dev-certs/dotnet-dev-certs.nuspec +++ /dev/null @@ -1,25 +0,0 @@ - - - - dotnet-dev-certs - dotnet developercertificates - $version$ - Microsoft - Microsoft - $licenseUrl$ - $projectUrl$ - $iconUrl$ - $description$ - $copyright$ - true - $serviceable$ - - - - - - - - - - diff --git a/src/dotnet-sql-cache/DotnetToolSettings.xml b/src/dotnet-sql-cache/DotnetToolSettings.xml deleted file mode 100644 index 2619964f0e..0000000000 --- a/src/dotnet-sql-cache/DotnetToolSettings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/src/dotnet-sql-cache/dotnet-sql-cache.csproj b/src/dotnet-sql-cache/dotnet-sql-cache.csproj index 64d2c8b51b..ad1105f2b8 100644 --- a/src/dotnet-sql-cache/dotnet-sql-cache.csproj +++ b/src/dotnet-sql-cache/dotnet-sql-cache.csproj @@ -1,28 +1,20 @@ - + + + netcoreapp2.1 exe Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching. - DotnetTool - tools/any/any/ + cache;distributedcache;sqlserver + true + + + true - - - - - - - - - - - - - diff --git a/src/dotnet-sql-cache/dotnet-sql-cache.nuspec b/src/dotnet-sql-cache/dotnet-sql-cache.nuspec deleted file mode 100644 index 0c6e9d05e2..0000000000 --- a/src/dotnet-sql-cache/dotnet-sql-cache.nuspec +++ /dev/null @@ -1,25 +0,0 @@ - - - - dotnet-sql-cache - cache distributedcache sqlserver - $version$ - Microsoft - Microsoft - $licenseUrl$ - $projectUrl$ - $iconUrl$ - $description$ - $copyright$ - true - $serviceable$ - - - - - - - - - - diff --git a/src/dotnet-user-secrets/DotnetToolSettings.xml b/src/dotnet-user-secrets/DotnetToolSettings.xml deleted file mode 100644 index 0de9f13c31..0000000000 --- a/src/dotnet-user-secrets/DotnetToolSettings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/src/dotnet-user-secrets/dotnet-user-secrets.csproj b/src/dotnet-user-secrets/dotnet-user-secrets.csproj index 9f578a0c36..f431447a01 100644 --- a/src/dotnet-user-secrets/dotnet-user-secrets.csproj +++ b/src/dotnet-user-secrets/dotnet-user-secrets.csproj @@ -1,35 +1,23 @@ - + + + netcoreapp2.1 exe Command line tool to manage user secrets for Microsoft.Extensions.Configuration. - DotnetTool false Microsoft.Extensions.SecretManager.Tools - tools/any/any/ + configuration;secrets;usersecrets + true + + + true - - - - - - - - - - - - - - - - - - + diff --git a/src/dotnet-user-secrets/dotnet-user-secrets.nuspec b/src/dotnet-user-secrets/dotnet-user-secrets.nuspec deleted file mode 100644 index 54caef9177..0000000000 --- a/src/dotnet-user-secrets/dotnet-user-secrets.nuspec +++ /dev/null @@ -1,25 +0,0 @@ - - - - dotnet-user-secrets - configuration secrets usersecrets - $version$ - Microsoft - Microsoft - $licenseUrl$ - $projectUrl$ - $iconUrl$ - $description$ - $copyright$ - true - $serviceable$ - - - - - - - - - - diff --git a/src/dotnet-watch/DotnetToolSettings.xml b/src/dotnet-watch/DotnetToolSettings.xml deleted file mode 100644 index 7e9a7f40d4..0000000000 --- a/src/dotnet-watch/DotnetToolSettings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/src/dotnet-watch/dotnet-watch.csproj b/src/dotnet-watch/dotnet-watch.csproj index 19db471fe7..f20ea3ebc5 100644 --- a/src/dotnet-watch/dotnet-watch.csproj +++ b/src/dotnet-watch/dotnet-watch.csproj @@ -1,16 +1,22 @@ - + + + netcoreapp2.1 exe Command line tool to watch for source file changes during development and restart the dotnet command. - DotnetTool Microsoft.DotNet.Watcher.Tools + dotnet;watch + true + + + true - + diff --git a/src/dotnet-watch/dotnet-watch.nuspec b/src/dotnet-watch/dotnet-watch.nuspec deleted file mode 100644 index 5442df0874..0000000000 --- a/src/dotnet-watch/dotnet-watch.nuspec +++ /dev/null @@ -1,25 +0,0 @@ - - - - dotnet-watch - dotnet watch - $version$ - Microsoft - Microsoft - $licenseUrl$ - $projectUrl$ - $iconUrl$ - $description$ - $copyright$ - true - $serviceable$ - - - - - - - - - - diff --git a/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj b/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj index 360e9301cf..fd8be34db7 100644 --- a/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj +++ b/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj @@ -14,4 +14,8 @@ + + + + From 3193f45bae62c2dd2b0867e6efe26cce8f3738ce Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 3 May 2018 18:01:56 -0700 Subject: [PATCH 0766/1029] Attempt to address flaky dotnet-watch tests --- .../FileWatcherTests.cs | 26 +++++++++++++++---- .../NoDepsAppTests.cs | 4 +-- .../Scenario/WatchableApp.cs | 6 +++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs b/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs index 9f1cc132bc..60fd501ca8 100644 --- a/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs +++ b/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs @@ -8,12 +8,19 @@ using System.Linq; using System.Threading; using Microsoft.DotNet.Watcher.Internal; using Xunit; +using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { public class FileWatcherTests { + public FileWatcherTests(ITestOutputHelper output) + { + _output = output; + } + private const int DefaultTimeout = 10 * 1000; // 10 sec + private readonly ITestOutputHelper _output; [Theory] [InlineData(true)] @@ -277,16 +284,24 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [InlineData(false)] public void MultipleTriggers(bool usePolling) { + var filesChanged = new HashSet(); + + void Clear() + { + _output.WriteLine("Clear files changed list"); + filesChanged.Clear(); + } + UsingTempDirectory(dir => { using (var changedEv = new AutoResetEvent(false)) using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling)) { - var filesChanged = new HashSet(); EventHandler handler = null; handler = (_, f) => { + _output.WriteLine("File changed: " + f); filesChanged.Add(f); try { @@ -318,7 +333,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests Assert.True(changedEv.WaitOne(DefaultTimeout)); var fileChanged = Assert.Single(filesChanged); Assert.Equal(testFileFullPath, fileChanged); - filesChanged.Clear(); + Clear(); changedEv.Reset(); // On Unix the file write time is in 1s increments; @@ -331,7 +346,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests Assert.True(changedEv.WaitOne(DefaultTimeout)); fileChanged = Assert.Single(filesChanged); Assert.Equal(testFileFullPath, fileChanged); - filesChanged.Clear(); + Clear(); changedEv.Reset(); // On Unix the file write time is in 1s increments; @@ -342,8 +357,9 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests testFileFullPath = Path.Combine(dir, "foo3"); File.WriteAllText(testFileFullPath, string.Empty); Assert.True(changedEv.WaitOne(DefaultTimeout)); - Assert.Equal(testFileFullPath, filesChanged.Single()); - filesChanged.Clear(); + fileChanged = Assert.Single(filesChanged); + Assert.Equal(testFileFullPath, fileChanged); + Clear(); changedEv.Reset(); // On Unix the file write time is in 1s increments; diff --git a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs index ea9ffbec03..8ac2f694e7 100644 --- a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs +++ b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs @@ -1,11 +1,10 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Diagnostics; using System.IO; using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing; using Xunit; using Xunit.Abstractions; @@ -47,6 +46,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests await _app.StartWatcherAsync(); var pid = await _app.GetProcessId(); await _app.HasExited(); // process should exit after run + await _app.IsWaitingForFileChange(); var fileToChange = Path.Combine(_app.SourceDirectory, "Program.cs"); var programCs = File.ReadAllText(fileToChange); diff --git a/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs b/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs index 16bfbacc8d..56702afac2 100644 --- a/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs +++ b/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs @@ -19,6 +19,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests private const string StartedMessage = "Started"; private const string ExitingMessage = "Exiting"; private const string WatchExitedMessage = "watch : Exited"; + private const string WaitingForFileChangeMessage = "watch : Waiting for a file to change"; private readonly ITestOutputHelper _logger; private string _appName; @@ -49,6 +50,11 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests await Process.GetOutputLineAsync(WatchExitedMessage, DefaultMessageTimeOut); } + public async Task IsWaitingForFileChange() + { + await Process.GetOutputLineStartsWithAsync(WaitingForFileChangeMessage, DefaultMessageTimeOut); + } + public bool UsePollingWatcher { get; set; } public async Task GetProcessId() From e5da69070229a88393a1e63ce51754d983db81f0 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 3 May 2018 18:01:56 -0700 Subject: [PATCH 0767/1029] Attempt to address flaky dotnet-watch tests --- .../FileWatcherTests.cs | 26 +++++++++++++++---- .../NoDepsAppTests.cs | 4 +-- .../Scenario/WatchableApp.cs | 6 +++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs b/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs index 9f1cc132bc..60fd501ca8 100644 --- a/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs +++ b/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs @@ -8,12 +8,19 @@ using System.Linq; using System.Threading; using Microsoft.DotNet.Watcher.Internal; using Xunit; +using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { public class FileWatcherTests { + public FileWatcherTests(ITestOutputHelper output) + { + _output = output; + } + private const int DefaultTimeout = 10 * 1000; // 10 sec + private readonly ITestOutputHelper _output; [Theory] [InlineData(true)] @@ -277,16 +284,24 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [InlineData(false)] public void MultipleTriggers(bool usePolling) { + var filesChanged = new HashSet(); + + void Clear() + { + _output.WriteLine("Clear files changed list"); + filesChanged.Clear(); + } + UsingTempDirectory(dir => { using (var changedEv = new AutoResetEvent(false)) using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling)) { - var filesChanged = new HashSet(); EventHandler handler = null; handler = (_, f) => { + _output.WriteLine("File changed: " + f); filesChanged.Add(f); try { @@ -318,7 +333,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests Assert.True(changedEv.WaitOne(DefaultTimeout)); var fileChanged = Assert.Single(filesChanged); Assert.Equal(testFileFullPath, fileChanged); - filesChanged.Clear(); + Clear(); changedEv.Reset(); // On Unix the file write time is in 1s increments; @@ -331,7 +346,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests Assert.True(changedEv.WaitOne(DefaultTimeout)); fileChanged = Assert.Single(filesChanged); Assert.Equal(testFileFullPath, fileChanged); - filesChanged.Clear(); + Clear(); changedEv.Reset(); // On Unix the file write time is in 1s increments; @@ -342,8 +357,9 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests testFileFullPath = Path.Combine(dir, "foo3"); File.WriteAllText(testFileFullPath, string.Empty); Assert.True(changedEv.WaitOne(DefaultTimeout)); - Assert.Equal(testFileFullPath, filesChanged.Single()); - filesChanged.Clear(); + fileChanged = Assert.Single(filesChanged); + Assert.Equal(testFileFullPath, fileChanged); + Clear(); changedEv.Reset(); // On Unix the file write time is in 1s increments; diff --git a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs index ea9ffbec03..8ac2f694e7 100644 --- a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs +++ b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs @@ -1,11 +1,10 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Diagnostics; using System.IO; using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing; using Xunit; using Xunit.Abstractions; @@ -47,6 +46,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests await _app.StartWatcherAsync(); var pid = await _app.GetProcessId(); await _app.HasExited(); // process should exit after run + await _app.IsWaitingForFileChange(); var fileToChange = Path.Combine(_app.SourceDirectory, "Program.cs"); var programCs = File.ReadAllText(fileToChange); diff --git a/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs b/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs index 16bfbacc8d..56702afac2 100644 --- a/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs +++ b/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs @@ -19,6 +19,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests private const string StartedMessage = "Started"; private const string ExitingMessage = "Exiting"; private const string WatchExitedMessage = "watch : Exited"; + private const string WaitingForFileChangeMessage = "watch : Waiting for a file to change"; private readonly ITestOutputHelper _logger; private string _appName; @@ -49,6 +50,11 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests await Process.GetOutputLineAsync(WatchExitedMessage, DefaultMessageTimeOut); } + public async Task IsWaitingForFileChange() + { + await Process.GetOutputLineStartsWithAsync(WaitingForFileChangeMessage, DefaultMessageTimeOut); + } + public bool UsePollingWatcher { get; set; } public async Task GetProcessId() From e559cca71ef57d6583bd269201239109c3734c7f Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Fri, 4 May 2018 07:31:48 -0700 Subject: [PATCH 0768/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 73aaaa8abf..b34bf72810 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,18 +3,18 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-rtm-15776 - 2.1.0-rc1-30677 - 2.1.0-rc1-30677 - 2.1.0-rc1-30677 - 2.1.0-rc1-30677 - 2.1.0-rc1-30677 + 2.1.0-rtm-15783 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 2.0.0 - 2.1.0-rc1-26423-06 + 2.1.0-rtm-26502-02 15.6.1 2.0.3 - 4.5.0-rc1-26423-06 - 4.5.0-rc1-26423-06 + 4.5.0-rtm-26502-02 + 4.5.0-rtm-26502-02 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index d455c7a7a6..27e94579a9 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-rtm-15780 -commithash:4b54ae92ccebdf2a5aabca9748cc874eeafe5ac9 +version:2.1.0-rtm-15783 +commithash:5fc2b2f607f542a2ffde11c19825e786fc1a3774 From dd2eaa1ed3f9e7bebd3c7b001a2f7a95bf4b6c09 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Fri, 4 May 2018 07:35:13 -0700 Subject: [PATCH 0769/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 16 ++++++++-------- korebuild-lock.txt | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index dc2db7956c..007238eb66 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,16 +3,16 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-rc1-15774 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 - 2.1.0-rc1-30613 + 2.1.0-rtm-15783 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 + 2.1.0-rtm-30721 2.0.0 - 2.1.0-rc1-26419-02 + 2.1.0-rtm-26502-02 15.6.1 - 2.0.1 - 4.5.0-rc1-26419-03 + 2.0.3 + 4.5.0-rtm-26502-02 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 9d4ef8c888..3673744db9 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-rc1-15774 -commithash:ed5ca9de3c652347dbb0158a9a65eff3471d2114 +version:2.1.0-rtm-15783 +commithash:5fc2b2f607f542a2ffde11c19825e786fc1a3774 From 54e6ffce343b4b6113e824ccbb4006f786ad8e8c Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Fri, 4 May 2018 07:41:29 -0700 Subject: [PATCH 0770/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 649af28432..acedb0a6ca 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,15 +3,15 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-rc1-15774 - 2.1.0-rc1-30613 - 4.5.0-rc1-26419-03 - 2.1.0-rc1-30613 + 2.1.0-rtm-15783 + 2.1.0-rtm-30721 + 4.5.0-rtm-26502-02 + 2.1.0-rtm-30721 2.0.0 - 2.1.0-rc1-26419-02 + 2.1.0-rtm-26502-02 15.6.1 4.7.49 - 2.0.1 + 2.0.3 11.0.2 0.8.0 2.3.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 9d4ef8c888..3673744db9 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-rc1-15774 -commithash:ed5ca9de3c652347dbb0158a9a65eff3471d2114 +version:2.1.0-rtm-15783 +commithash:5fc2b2f607f542a2ffde11c19825e786fc1a3774 From 34c81aa794b165cd82ac91d6ed3b6f48acf81eb2 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 4 May 2018 11:27:22 -0700 Subject: [PATCH 0771/1029] Add link to dotnet-CLI in README [ci skip] --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0eb8eb3be8..438b665cd8 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,8 @@ This project is part of ASP.NET Core. You can find samples, documentation and ge ## Projects -The repository contains command-line tools for ASP.NET Core that are bundled* in the .NET Core CLI. Follow the links below for more details on each tool. +The repository contains command-line tools for ASP.NET Core that are bundled* in the [.NET Core CLI](https://github.com/dotnet/cli). +Follow the links below for more details on each tool. - [dotnet-watch](src/dotnet-watch/README.md) - [dotnet-user-secrets](src/dotnet-user-secrets/README.md) From 7cbb6220e44fb87e75e97ab65d602b35884b5ac2 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 6 May 2018 12:12:09 -0700 Subject: [PATCH 0772/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 40c71997ba..09717e8564 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17044 - 2.2.0-preview1-34089 - 2.2.0-preview1-34089 - 2.2.0-preview1-34089 - 2.2.0-preview1-34089 - 2.2.0-preview1-34089 + 2.2.0-preview1-17047 + 2.2.0-preview1-34135 + 2.2.0-preview1-34135 + 2.2.0-preview1-34135 + 2.2.0-preview1-34135 + 2.2.0-preview1-34135 2.0.0 2.2.0-preview1-26424-04 15.6.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 843f39817d..18df6940ae 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17044 -commithash:d9eb8a53eca84f61a7b0845c99fc43a3ec51e353 +version:2.2.0-preview1-17047 +commithash:e1957b52ddc8b62bd39c5c400322fccb5364624c From 7fe6dae3c5e4844bac3f0d36039c456e03a41e04 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 6 May 2018 12:15:43 -0700 Subject: [PATCH 0773/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 509b7d5539..de67da1c2a 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,11 +3,11 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17042 - 2.2.0-preview1-34066 - 2.2.0-preview1-34066 - 2.2.0-preview1-34066 - 2.2.0-preview1-34066 + 2.2.0-preview1-17047 + 2.2.0-preview1-34135 + 2.2.0-preview1-34135 + 2.2.0-preview1-34135 + 2.2.0-preview1-34135 2.0.0 2.2.0-preview1-26424-04 15.6.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 335e579e06..a16d4b9ee4 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17042 -commithash:edf0705d014293c260de763543784330514db9a3 +version:2.2.0-preview1-17047 +commithash:e1957b52ddc8b62bd39c5c400322fccb5364624c From 376a542a5dc6faff669423655a801667a3a1a029 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 6 May 2018 12:21:51 -0700 Subject: [PATCH 0774/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 6 +++--- korebuild-lock.txt | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 03999cb59f..3389a20912 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17042 - 2.2.0-preview1-34066 + 2.2.0-preview1-17047 + 2.2.0-preview1-34135 4.5.0-preview3-26423-04 - 2.2.0-preview1-34066 + 2.2.0-preview1-34135 2.0.0 2.2.0-preview1-26424-04 15.6.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 335e579e06..a16d4b9ee4 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17042 -commithash:edf0705d014293c260de763543784330514db9a3 +version:2.2.0-preview1-17047 +commithash:e1957b52ddc8b62bd39c5c400322fccb5364624c From 341ba98d27741e231f8850e3534ae93f7a8de1c0 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 7 May 2018 10:52:47 -0700 Subject: [PATCH 0775/1029] [dotnet-watch] Don't show false error messages (#434) --- src/dotnet-watch/DotNetWatcher.cs | 8 ++++---- .../dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/dotnet-watch/DotNetWatcher.cs b/src/dotnet-watch/DotNetWatcher.cs index 258ba0ab1e..f4b0423511 100644 --- a/src/dotnet-watch/DotNetWatcher.cs +++ b/src/dotnet-watch/DotNetWatcher.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -69,13 +69,13 @@ namespace Microsoft.DotNet.Watcher await Task.WhenAll(processTask, fileSetTask); - if (processTask.Result == 0) + if (processTask.Result != 0 && finishedTask == processTask) { - _reporter.Output("Exited"); + _reporter.Error($"Exited with error code {processTask.Result}"); } else { - _reporter.Error($"Exited with error code {processTask.Result}"); + _reporter.Output("Exited"); } if (finishedTask == cancelledTaskSource.Task || cancellationToken.IsCancellationRequested) diff --git a/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs b/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs index 56702afac2..4f2d575f01 100644 --- a/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs +++ b/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs @@ -47,7 +47,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public async Task HasExited() { await Process.GetOutputLineAsync(ExitingMessage, DefaultMessageTimeOut); - await Process.GetOutputLineAsync(WatchExitedMessage, DefaultMessageTimeOut); + await Process.GetOutputLineStartsWithAsync(WatchExitedMessage, DefaultMessageTimeOut); } public async Task IsWaitingForFileChange() From 73592b904b82d8f11d1d508dd54e5d08ebeeed1f Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Mon, 7 May 2018 15:11:20 -0700 Subject: [PATCH 0776/1029] Upgrade to netcoreapp22 --- Directory.Build.targets | 5 ++++- build/dependencies.props | 13 +++++++------ build/repo.props | 3 ++- korebuild-lock.txt | 4 ++-- test/Directory.Build.props | 4 ++-- 5 files changed, 17 insertions(+), 12 deletions(-) diff --git a/Directory.Build.targets b/Directory.Build.targets index 53b3f6e1da..78626b773e 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,7 +1,10 @@ - + $(MicrosoftNETCoreApp20PackageVersion) $(MicrosoftNETCoreApp21PackageVersion) + $(MicrosoftNETCoreApp22PackageVersion) $(NETStandardLibrary20PackageVersion) + + 99.9 diff --git a/build/dependencies.props b/build/dependencies.props index de67da1c2a..56bced18f5 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,15 +1,16 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17047 - 2.2.0-preview1-34135 - 2.2.0-preview1-34135 - 2.2.0-preview1-34135 - 2.2.0-preview1-34135 + 2.2.0-preview1-17048 + 2.2.0-preview1-34140 + 2.2.0-preview1-34140 + 2.2.0-preview1-34140 + 2.2.0-preview1-34140 2.0.0 2.2.0-preview1-26424-04 + 2.2.0-preview1-26502-01 15.6.1 2.0.3 4.5.0-preview3-26423-04 diff --git a/build/repo.props b/build/repo.props index 78b0ce5879..17a98ac7e7 100644 --- a/build/repo.props +++ b/build/repo.props @@ -1,4 +1,4 @@ - + @@ -10,5 +10,6 @@ + diff --git a/korebuild-lock.txt b/korebuild-lock.txt index a16d4b9ee4..2573a03995 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17047 -commithash:e1957b52ddc8b62bd39c5c400322fccb5364624c +version:2.2.0-preview1-17048 +commithash:de14a0ee5fb48508ee8a29c14280a2928f8dabf8 diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 0b706cbca5..d5d5869c56 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -2,9 +2,9 @@ - netcoreapp2.1 + netcoreapp2.2 $(DeveloperBuildTestTfms) - netcoreapp2.1;netcoreapp2.0 + $(StandardTestTfms);net461 From d7ac5c57efe1e7b3c8b1492107b5bf17744c83f7 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Mon, 7 May 2018 15:12:35 -0700 Subject: [PATCH 0777/1029] Upgrade to netcoreapp22 --- Directory.Build.targets | 5 ++++- build/dependencies.props | 9 +++++---- build/repo.props | 3 ++- korebuild-lock.txt | 4 ++-- test/Directory.Build.props | 4 ++-- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/Directory.Build.targets b/Directory.Build.targets index 53b3f6e1da..78626b773e 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,7 +1,10 @@ - + $(MicrosoftNETCoreApp20PackageVersion) $(MicrosoftNETCoreApp21PackageVersion) + $(MicrosoftNETCoreApp22PackageVersion) $(NETStandardLibrary20PackageVersion) + + 99.9 diff --git a/build/dependencies.props b/build/dependencies.props index 3389a20912..441743f2aa 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,14 +1,15 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17047 - 2.2.0-preview1-34135 + 2.2.0-preview1-17048 + 2.2.0-preview1-34140 4.5.0-preview3-26423-04 - 2.2.0-preview1-34135 + 2.2.0-preview1-34140 2.0.0 2.2.0-preview1-26424-04 + 2.2.0-preview1-26502-01 15.6.1 4.7.49 2.0.3 diff --git a/build/repo.props b/build/repo.props index 78b0ce5879..17a98ac7e7 100644 --- a/build/repo.props +++ b/build/repo.props @@ -1,4 +1,4 @@ - + @@ -10,5 +10,6 @@ + diff --git a/korebuild-lock.txt b/korebuild-lock.txt index a16d4b9ee4..2573a03995 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17047 -commithash:e1957b52ddc8b62bd39c5c400322fccb5364624c +version:2.2.0-preview1-17048 +commithash:de14a0ee5fb48508ee8a29c14280a2928f8dabf8 diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 98685a5e13..fc128b9108 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -2,9 +2,9 @@ - netcoreapp2.1 + netcoreapp2.2 $(DeveloperBuildTestTfms) - $(StandardTestTfms);netcoreapp2.0 + $(StandardTestTfms) $(StandardTestTfms);net461 From f71dad1055c2b2b9f661ec1552ac4afa4e1f2d89 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Mon, 7 May 2018 15:10:34 -0700 Subject: [PATCH 0778/1029] Upgrade to netcoreapp22 --- Directory.Build.targets | 5 ++++- build/dependencies.props | 15 ++++++++------- build/repo.props | 3 ++- korebuild-lock.txt | 4 ++-- .../LaunchAnyCommand/LaunchAnyCommand.csproj | 2 +- .../WatchJavascriptFiles.csproj | 2 +- .../WatchMultipleProjects/Test/Test.csproj | 2 +- .../WatchMultipleProjects/Web/Web.csproj | 2 +- .../WatchMultipleProjects/watch.csproj | 2 +- .../dotnet-user-secrets.Tests.csproj | 2 +- .../TestProjects/GlobbingApp/GlobbingApp.csproj | 2 +- .../TestProjects/NoDepsApp/NoDepsApp.csproj | 2 +- .../dotnet-watch.FunctionalTests.csproj | 2 +- test/dotnet-watch.Tests/dotnet-watch.Tests.csproj | 2 +- 14 files changed, 26 insertions(+), 21 deletions(-) diff --git a/Directory.Build.targets b/Directory.Build.targets index eb03b2565f..73b97f2807 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,6 +1,9 @@ - + $(MicrosoftNETCoreApp21PackageVersion) + $(MicrosoftNETCoreApp22PackageVersion) $(NETStandardLibrary20PackageVersion) + + 99.9 diff --git a/build/dependencies.props b/build/dependencies.props index 09717e8564..f0c4a4e0c4 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,16 +1,17 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17047 - 2.2.0-preview1-34135 - 2.2.0-preview1-34135 - 2.2.0-preview1-34135 - 2.2.0-preview1-34135 - 2.2.0-preview1-34135 + 2.2.0-preview1-17048 + 2.2.0-preview1-34140 + 2.2.0-preview1-34140 + 2.2.0-preview1-34140 + 2.2.0-preview1-34140 + 2.2.0-preview1-34140 2.0.0 2.2.0-preview1-26424-04 + 2.2.0-preview1-26502-01 15.6.1 2.0.3 4.5.0-preview3-26423-04 diff --git a/build/repo.props b/build/repo.props index 1be3632130..015f722dd9 100644 --- a/build/repo.props +++ b/build/repo.props @@ -1,10 +1,11 @@ - + + diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 18df6940ae..da5dcd1202 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17047 -commithash:e1957b52ddc8b62bd39c5c400322fccb5364624c +version:2.2.0-preview1-17048 +commithash:de14a0ee5fb48508ee8a29c14280a2928f8dabf8 diff --git a/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj b/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj index 1dc6efedd6..1609403042 100644 --- a/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj +++ b/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj @@ -1,6 +1,6 @@ - netcoreapp2.1 + netcoreapp2.2 diff --git a/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj b/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj index 008b0322e6..0c0cac78f3 100755 --- a/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj +++ b/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj @@ -1,7 +1,7 @@ - netcoreapp2.1 + netcoreapp2.2 diff --git a/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj b/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj index 0ffd10766a..0559578c32 100755 --- a/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj +++ b/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj @@ -1,7 +1,7 @@ - netcoreapp2.1 + netcoreapp2.2 diff --git a/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj b/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj index ec2a93ed3a..616246b199 100755 --- a/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj +++ b/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj @@ -1,7 +1,7 @@ - netcoreapp2.1 + netcoreapp2.2 diff --git a/samples/dotnet-watch/WatchMultipleProjects/watch.csproj b/samples/dotnet-watch/WatchMultipleProjects/watch.csproj index d890295d39..5ca4ee2379 100644 --- a/samples/dotnet-watch/WatchMultipleProjects/watch.csproj +++ b/samples/dotnet-watch/WatchMultipleProjects/watch.csproj @@ -1,6 +1,6 @@ - netcoreapp2.1 + netcoreapp2.2 false diff --git a/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj b/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj index fd8be34db7..834e7ede2b 100644 --- a/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj +++ b/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj @@ -1,4 +1,4 @@ - + netcoreapp2.1 diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj b/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj index a01efb4b2f..8d31551941 100644 --- a/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj +++ b/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj @@ -1,4 +1,4 @@ - + netcoreapp2.1 diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj b/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj index b242bd2546..d4ddbcd217 100644 --- a/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj +++ b/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj @@ -1,4 +1,4 @@ - + netcoreapp2.1 diff --git a/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj b/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj index d7c0a3fdac..768d08ce8c 100644 --- a/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj +++ b/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj @@ -1,4 +1,4 @@ - + netcoreapp2.1 diff --git a/test/dotnet-watch.Tests/dotnet-watch.Tests.csproj b/test/dotnet-watch.Tests/dotnet-watch.Tests.csproj index ce5349ad3e..c5578a357b 100644 --- a/test/dotnet-watch.Tests/dotnet-watch.Tests.csproj +++ b/test/dotnet-watch.Tests/dotnet-watch.Tests.csproj @@ -1,4 +1,4 @@ - + netcoreapp2.1 From e1e2970a41a4ab106774fbe87d075c284f6ac121 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 8 May 2018 15:40:53 -0700 Subject: [PATCH 0779/1029] Refactor MultipleTriggers test to better handle multiple events raised on the same file --- .../FileWatcherTests.cs | 125 +++++++----------- 1 file changed, 45 insertions(+), 80 deletions(-) diff --git a/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs b/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs index 60fd501ca8..7cd4bd15aa 100644 --- a/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs +++ b/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs @@ -286,98 +286,63 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { var filesChanged = new HashSet(); - void Clear() - { - _output.WriteLine("Clear files changed list"); - filesChanged.Clear(); - } - UsingTempDirectory(dir => { - using (var changedEv = new AutoResetEvent(false)) using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling)) { - - EventHandler handler = null; - handler = (_, f) => - { - _output.WriteLine("File changed: " + f); - filesChanged.Add(f); - try - { - changedEv.Set(); - } - catch (ObjectDisposedException) - { - // There's a known race condition here: - // even though we tell the watcher to stop raising events and we unsubscribe the handler - // there might be in-flight events that will still process. Since we dispose the reset - // event, this code will fail if the handler executes after Dispose happens. There's no - // better way to guard against it than catch because we cannot check if the object is - // disposed nor can we check if there are any in-flight events. - // This is actually a known issue in the corefx file watcher. It can trigger multiple - // times for the same item. - } - }; - - watcher.OnFileChange += handler; watcher.EnableRaisingEvents = true; - // On Unix the file write time is in 1s increments; - // if we don't wait, there's a chance that the polling - // watcher will not detect the change - Thread.Sleep(1000); - - var testFileFullPath = Path.Combine(dir, "foo1"); - File.WriteAllText(testFileFullPath, string.Empty); - Assert.True(changedEv.WaitOne(DefaultTimeout)); - var fileChanged = Assert.Single(filesChanged); - Assert.Equal(testFileFullPath, fileChanged); - Clear(); - changedEv.Reset(); - - // On Unix the file write time is in 1s increments; - // if we don't wait, there's a chance that the polling - // watcher will not detect the change - Thread.Sleep(1000); - - testFileFullPath = Path.Combine(dir, "foo2"); - File.WriteAllText(testFileFullPath, string.Empty); - Assert.True(changedEv.WaitOne(DefaultTimeout)); - fileChanged = Assert.Single(filesChanged); - Assert.Equal(testFileFullPath, fileChanged); - Clear(); - changedEv.Reset(); - - // On Unix the file write time is in 1s increments; - // if we don't wait, there's a chance that the polling - // watcher will not detect the change - Thread.Sleep(1000); - - testFileFullPath = Path.Combine(dir, "foo3"); - File.WriteAllText(testFileFullPath, string.Empty); - Assert.True(changedEv.WaitOne(DefaultTimeout)); - fileChanged = Assert.Single(filesChanged); - Assert.Equal(testFileFullPath, fileChanged); - Clear(); - changedEv.Reset(); - - // On Unix the file write time is in 1s increments; - // if we don't wait, there's a chance that the polling - // watcher will not detect the change - Thread.Sleep(1000); - - File.WriteAllText(testFileFullPath, string.Empty); - Assert.True(changedEv.WaitOne(DefaultTimeout)); - fileChanged = Assert.Single(filesChanged); - Assert.Equal(testFileFullPath, fileChanged); + for (var i = 0; i < 5; i++) + { + AssertFileChangeRaisesEvent(dir, watcher); + } watcher.EnableRaisingEvents = false; - watcher.OnFileChange -= handler; } }); } + private void AssertFileChangeRaisesEvent(string directory, IFileSystemWatcher watcher) + { + var semaphoreSlim = new SemaphoreSlim(0); + var expectedPath = Path.Combine(directory, Path.GetRandomFileName()); + EventHandler handler = (object _, string f) => + { + _output.WriteLine("File changed: " + f); + try + { + if (string.Equals(f, expectedPath, StringComparison.OrdinalIgnoreCase)) + { + semaphoreSlim.Release(); + } + } + catch (ObjectDisposedException) + { + // There's a known race condition here: + // even though we tell the watcher to stop raising events and we unsubscribe the handler + // there might be in-flight events that will still process. Since we dispose the reset + // event, this code will fail if the handler executes after Dispose happens. + } + }; + + File.AppendAllText(expectedPath, " "); + + watcher.OnFileChange += handler; + try + { + // On Unix the file write time is in 1s increments; + // if we don't wait, there's a chance that the polling + // watcher will not detect the change + Thread.Sleep(1000); + File.AppendAllText(expectedPath, " "); + Assert.True(semaphoreSlim.Wait(DefaultTimeout), "Expected a file change event for " + expectedPath); + } + finally + { + watcher.OnFileChange -= handler; + } + } + [Theory] [InlineData(true)] [InlineData(false)] From ddc478ab879b6dc17ea035f05410f1de945a167a Mon Sep 17 00:00:00 2001 From: Artak <34246760+mkArtakMSFT@users.noreply.github.com> Date: Wed, 9 May 2018 09:47:48 -0700 Subject: [PATCH 0780/1029] Added using block around a disposable type usage Noticed this when reviewed an already-merged PR --- .../FileWatcherTests.cs | 62 ++++++++++--------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs b/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs index 7cd4bd15aa..51c1895e05 100644 --- a/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs +++ b/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs @@ -304,42 +304,44 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests private void AssertFileChangeRaisesEvent(string directory, IFileSystemWatcher watcher) { - var semaphoreSlim = new SemaphoreSlim(0); - var expectedPath = Path.Combine(directory, Path.GetRandomFileName()); - EventHandler handler = (object _, string f) => + using (var semaphoreSlim = new SemaphoreSlim(0)) { - _output.WriteLine("File changed: " + f); + var expectedPath = Path.Combine(directory, Path.GetRandomFileName()); + EventHandler handler = (object _, string f) => + { + _output.WriteLine("File changed: " + f); + try + { + if (string.Equals(f, expectedPath, StringComparison.OrdinalIgnoreCase)) + { + semaphoreSlim.Release(); + } + } + catch (ObjectDisposedException) + { + // There's a known race condition here: + // even though we tell the watcher to stop raising events and we unsubscribe the handler + // there might be in-flight events that will still process. Since we dispose the reset + // event, this code will fail if the handler executes after Dispose happens. + } + }; + + File.AppendAllText(expectedPath, " "); + + watcher.OnFileChange += handler; try { - if (string.Equals(f, expectedPath, StringComparison.OrdinalIgnoreCase)) - { - semaphoreSlim.Release(); - } + // On Unix the file write time is in 1s increments; + // if we don't wait, there's a chance that the polling + // watcher will not detect the change + Thread.Sleep(1000); + File.AppendAllText(expectedPath, " "); + Assert.True(semaphoreSlim.Wait(DefaultTimeout), "Expected a file change event for " + expectedPath); } - catch (ObjectDisposedException) + finally { - // There's a known race condition here: - // even though we tell the watcher to stop raising events and we unsubscribe the handler - // there might be in-flight events that will still process. Since we dispose the reset - // event, this code will fail if the handler executes after Dispose happens. + watcher.OnFileChange -= handler; } - }; - - File.AppendAllText(expectedPath, " "); - - watcher.OnFileChange += handler; - try - { - // On Unix the file write time is in 1s increments; - // if we don't wait, there's a chance that the polling - // watcher will not detect the change - Thread.Sleep(1000); - File.AppendAllText(expectedPath, " "); - Assert.True(semaphoreSlim.Wait(DefaultTimeout), "Expected a file change event for " + expectedPath); - } - finally - { - watcher.OnFileChange -= handler; } } From 78236286b449f505a4073af0127dc62a0f77a5c2 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 9 May 2018 14:44:43 -0700 Subject: [PATCH 0781/1029] Upgrade tools to netcoreapp2.2 --- NuGetPackageVerifier.json | 72 +++++++++---------- build/dependencies.props | 18 ++--- korebuild-lock.txt | 4 +- ...NetCore.DeveloperCertificates.XPlat.csproj | 2 +- src/dotnet-dev-certs/dotnet-dev-certs.csproj | 2 +- src/dotnet-sql-cache/dotnet-sql-cache.csproj | 2 +- .../dotnet-user-secrets.csproj | 2 +- src/dotnet-watch/dotnet-watch.csproj | 2 +- .../UserSecretsTestFixture.cs | 2 +- .../dotnet-user-secrets.Tests.csproj | 2 +- .../AppWithDeps/AppWithDeps.csproj | 5 +- .../GlobbingApp/GlobbingApp.csproj | 5 +- .../KitchenSink/KitchenSink.csproj | 5 +- .../TestProjects/NoDepsApp/NoDepsApp.csproj | 5 +- .../dotnet-watch.FunctionalTests.csproj | 2 +- .../dotnet-watch.Tests.csproj | 2 +- 16 files changed, 72 insertions(+), 60 deletions(-) diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index 3e59aeb910..6503b35342 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -15,39 +15,39 @@ ], "Exclusions": { "NEUTRAL_RESOURCES_LANGUAGE": { - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.2/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." }, "WRONG_PUBLICKEYTOKEN": { - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.2/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_INFORMATIONAL_VERSION_MISMATCH": { - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.2/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_FILE_VERSION_MISMATCH": { - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.2/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_VERSION_MISMATCH": { - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.2/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg." } } }, @@ -57,26 +57,26 @@ ], "Exclusions": { "NEUTRAL_RESOURCES_LANGUAGE": { - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.2/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." }, "SERVICING_ATTRIBUTE": { - "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.2/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg." }, "WRONG_PUBLICKEYTOKEN": { - "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.2/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_INFORMATIONAL_VERSION_MISMATCH": { - "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.2/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_FILE_VERSION_MISMATCH": { - "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.2/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." }, "ASSEMBLY_VERSION_MISMATCH": { - "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + "tools/netcoreapp2.2/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.2/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." } } }, @@ -88,7 +88,7 @@ "Microsoft.AspNetCore.DeveloperCertificates.XPlat": { "Exclusions": { "DOC_MISSING": { - "lib/netcoreapp2.1/Microsoft.AspNetCore.DeveloperCertificates.XPlat.dll": "Docs not required to shipoob package" + "lib/netcoreapp2.2/Microsoft.AspNetCore.DeveloperCertificates.XPlat.dll": "Docs not required to shipoob package" } } } diff --git a/build/dependencies.props b/build/dependencies.props index f0c4a4e0c4..53d6c6353d 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,17 +1,17 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17048 - 2.2.0-preview1-34140 - 2.2.0-preview1-34140 - 2.2.0-preview1-34140 - 2.2.0-preview1-34140 - 2.2.0-preview1-34140 + 2.2.0-preview1-17050 + 2.2.0-preview1-34154 + 2.2.0-preview1-34154 + 2.2.0-preview1-34154 + 2.2.0-preview1-34154 + 2.2.0-preview1-34154 2.0.0 - 2.2.0-preview1-26424-04 - 2.2.0-preview1-26502-01 + 2.1.0-rc1 + 2.2.0-preview1-26424-04 15.6.1 2.0.3 4.5.0-preview3-26423-04 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index da5dcd1202..82ebcf2549 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17048 -commithash:de14a0ee5fb48508ee8a29c14280a2928f8dabf8 +version:2.2.0-preview1-17050 +commithash:24b548c969ffdf58730a7237a4c050b12c8711ed diff --git a/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj b/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj index 81c90a297c..19e0fc454b 100644 --- a/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj +++ b/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj @@ -1,7 +1,7 @@ - netcoreapp2.1 + netcoreapp2.2 Package for the CLI first run experience. $(DefineConstants);XPLAT aspnet;cli diff --git a/src/dotnet-dev-certs/dotnet-dev-certs.csproj b/src/dotnet-dev-certs/dotnet-dev-certs.csproj index 024cc705d2..b785b60c42 100644 --- a/src/dotnet-dev-certs/dotnet-dev-certs.csproj +++ b/src/dotnet-dev-certs/dotnet-dev-certs.csproj @@ -3,7 +3,7 @@ - netcoreapp2.1 + netcoreapp2.2 exe Command line tool to generate certificates used in ASP.NET Core during development. Microsoft.AspNetCore.DeveloperCertificates.Tools diff --git a/src/dotnet-sql-cache/dotnet-sql-cache.csproj b/src/dotnet-sql-cache/dotnet-sql-cache.csproj index ad1105f2b8..3949d90be0 100644 --- a/src/dotnet-sql-cache/dotnet-sql-cache.csproj +++ b/src/dotnet-sql-cache/dotnet-sql-cache.csproj @@ -3,7 +3,7 @@ - netcoreapp2.1 + netcoreapp2.2 exe Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching. cache;distributedcache;sqlserver diff --git a/src/dotnet-user-secrets/dotnet-user-secrets.csproj b/src/dotnet-user-secrets/dotnet-user-secrets.csproj index f431447a01..74bb54c602 100644 --- a/src/dotnet-user-secrets/dotnet-user-secrets.csproj +++ b/src/dotnet-user-secrets/dotnet-user-secrets.csproj @@ -3,7 +3,7 @@ - netcoreapp2.1 + netcoreapp2.2 exe Command line tool to manage user secrets for Microsoft.Extensions.Configuration. false diff --git a/src/dotnet-watch/dotnet-watch.csproj b/src/dotnet-watch/dotnet-watch.csproj index f20ea3ebc5..c5210a0cd2 100644 --- a/src/dotnet-watch/dotnet-watch.csproj +++ b/src/dotnet-watch/dotnet-watch.csproj @@ -3,7 +3,7 @@ - netcoreapp2.1 + netcoreapp2.2 exe Command line tool to watch for source file changes during development and restart the dotnet command. Microsoft.DotNet.Watcher.Tools diff --git a/test/dotnet-user-secrets.Tests/UserSecretsTestFixture.cs b/test/dotnet-user-secrets.Tests/UserSecretsTestFixture.cs index 14e62805bc..590787ec31 100644 --- a/test/dotnet-user-secrets.Tests/UserSecretsTestFixture.cs +++ b/test/dotnet-user-secrets.Tests/UserSecretsTestFixture.cs @@ -35,7 +35,7 @@ namespace Microsoft.Extensions.Configuration.UserSecrets.Tests private const string ProjectTemplate = @" Exe - netcoreapp2.1 + netcoreapp2.2 {0} false diff --git a/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj b/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj index 834e7ede2b..b52bd3eb92 100644 --- a/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj +++ b/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp2.1 + netcoreapp2.2 Microsoft.Extensions.SecretManager.Tools.Tests diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj b/test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj index 0dcb552112..7a55f33ef9 100644 --- a/test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj +++ b/test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj @@ -1,9 +1,12 @@ - netcoreapp2.1 + netcoreapp2.2 exe true + + + 99.9 diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj b/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj index 8d31551941..7c90a96aba 100644 --- a/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj +++ b/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj @@ -1,10 +1,13 @@ - netcoreapp2.1 + netcoreapp2.2 exe false true + + + 99.9 diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj b/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj index 72f7d5cae4..e2875bdba1 100644 --- a/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj +++ b/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj @@ -9,8 +9,11 @@ Exe - netcoreapp2.1 + netcoreapp2.2 true + + + 99.9 diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj b/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj index d4ddbcd217..47ca89d4f6 100644 --- a/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj +++ b/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj @@ -1,9 +1,12 @@ - netcoreapp2.1 + netcoreapp2.2 exe true + + + 99.9 diff --git a/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj b/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj index 768d08ce8c..7f92dede3c 100644 --- a/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj +++ b/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj @@ -1,7 +1,7 @@ - netcoreapp2.1 + netcoreapp2.2 $(DefaultItemExcludes);TestProjects\**\* Microsoft.DotNet.Watcher.Tools.FunctionalTests diff --git a/test/dotnet-watch.Tests/dotnet-watch.Tests.csproj b/test/dotnet-watch.Tests/dotnet-watch.Tests.csproj index c5578a357b..bc85a1119c 100644 --- a/test/dotnet-watch.Tests/dotnet-watch.Tests.csproj +++ b/test/dotnet-watch.Tests/dotnet-watch.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp2.1 + netcoreapp2.2 Microsoft.DotNet.Watcher.Tools.Tests From 4d92d76b64e3229ea61679945eb8a8bdf4537226 Mon Sep 17 00:00:00 2001 From: DHumphreys Date: Fri, 11 May 2018 15:08:09 -0400 Subject: [PATCH 0782/1029] Initial commit providing the AdapterFactory directly to the ObjectAdapter to all for customization of the Adapter selection and the ability to override the built in adapters to leverage their ability as much as possible. --- .../Adapters/AdapterFactory.cs | 39 ++++++++++ .../Adapters/IAdapterFactory.cs | 22 ++++++ .../Adapters/ObjectAdapter.cs | 36 +++++++-- .../Internal/DictionaryAdapterOfTU.cs | 16 ++-- .../Internal/DynamicObjectAdapter.cs | 18 ++--- .../Internal/ListAdapter.cs | 24 +++--- .../Internal/ObjectVisitor.cs | 39 +++++----- .../Internal/PocoAdapter.cs | 16 ++-- .../JsonPatchDocument.cs | 19 ++++- .../JsonPatchDocumentOfT.cs | 19 ++++- .../Adapters/AdapterFactoryTests.cs | 73 +++++++++++++++++++ .../Adapters/TestDynamicObject.cs | 10 +++ 12 files changed, 263 insertions(+), 68 deletions(-) create mode 100644 src/Microsoft.AspNetCore.JsonPatch/Adapters/AdapterFactory.cs create mode 100644 src/Microsoft.AspNetCore.JsonPatch/Adapters/IAdapterFactory.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/AdapterFactoryTests.cs create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/TestDynamicObject.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/AdapterFactory.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/AdapterFactory.cs new file mode 100644 index 0000000000..c963fcffdd --- /dev/null +++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/AdapterFactory.cs @@ -0,0 +1,39 @@ +using Microsoft.AspNetCore.JsonPatch.Internal; +using Newtonsoft.Json.Serialization; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.AspNetCore.JsonPatch.Adapters +{ + /// + /// The default AdapterFactory to be used for resolving . + /// + public class AdapterFactory : IAdapterFactory + { + /// + public virtual IAdapter Create(object target, IContractResolver contractResolver) + { + var jsonContract = contractResolver.ResolveContract(target.GetType()); + + if (target is IList) + { + return new ListAdapter(); + } + else if (jsonContract is JsonDictionaryContract jsonDictionaryContract) + { + var type = typeof(DictionaryAdapter<,>).MakeGenericType(jsonDictionaryContract.DictionaryKeyType, jsonDictionaryContract.DictionaryValueType); + return (IAdapter)Activator.CreateInstance(type); + } + else if (jsonContract is JsonDynamicContract) + { + return new DynamicObjectAdapter(); + } + else + { + return new PocoAdapter(); + } + } + } +} diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/IAdapterFactory.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/IAdapterFactory.cs new file mode 100644 index 0000000000..43ca1e65b6 --- /dev/null +++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/IAdapterFactory.cs @@ -0,0 +1,22 @@ +using Microsoft.AspNetCore.JsonPatch.Internal; +using Newtonsoft.Json.Serialization; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.AspNetCore.JsonPatch.Adapters +{ + /// + /// Defines the operations used for loading an based on the current object and ContractResolver. + /// + public interface IAdapterFactory + { + /// + /// Creates an for the current object + /// + /// The target object + /// The current contract resolver + /// The needed + IAdapter Create(object target, IContractResolver contractResolver); + } +} diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs index 73095b52c2..48d7e69b0f 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs @@ -18,17 +18,37 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters /// The for logging . public ObjectAdapter( IContractResolver contractResolver, - Action logErrorAction) + Action logErrorAction): + this(contractResolver, logErrorAction, new AdapterFactory()) { - ContractResolver = contractResolver ?? throw new ArgumentNullException(nameof(contractResolver)); - LogErrorAction = logErrorAction; } + /// + /// Initializes a new instance of . + /// + /// The . + /// The for logging . + /// The to use when creating adaptors. + public ObjectAdapter( + IContractResolver contractResolver, + Action logErrorAction, + IAdapterFactory adapterFactory) + { + ContractResolver = contractResolver ?? throw new ArgumentNullException(nameof(contractResolver)); + LogErrorAction = logErrorAction; + AdapterFactory = adapterFactory ?? throw new ArgumentNullException(nameof(adapterFactory)); + } + /// /// Gets or sets the . /// public IContractResolver ContractResolver { get; } + /// + /// Gets or sets the + /// + public IAdapterFactory AdapterFactory { get; set; } + /// /// Action for logging . /// @@ -75,7 +95,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters } var parsedPath = new ParsedPath(path); - var visitor = new ObjectVisitor(parsedPath, ContractResolver); + var visitor = new ObjectVisitor(parsedPath, ContractResolver, AdapterFactory); var target = objectToApplyTo; if (!visitor.TryVisit(ref target, out var adapter, out var errorMessage)) @@ -144,7 +164,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters private void Remove(string path, object objectToApplyTo, Operation operationToReport) { var parsedPath = new ParsedPath(path); - var visitor = new ObjectVisitor(parsedPath, ContractResolver); + var visitor = new ObjectVisitor(parsedPath, ContractResolver, AdapterFactory); var target = objectToApplyTo; if (!visitor.TryVisit(ref target, out var adapter, out var errorMessage)) @@ -175,7 +195,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters } var parsedPath = new ParsedPath(operation.path); - var visitor = new ObjectVisitor(parsedPath, ContractResolver); + var visitor = new ObjectVisitor(parsedPath, ContractResolver, AdapterFactory); var target = objectToApplyTo; if (!visitor.TryVisit(ref target, out var adapter, out var errorMessage)) @@ -239,7 +259,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters } var parsedPath = new ParsedPath(operation.path); - var visitor = new ObjectVisitor(parsedPath, ContractResolver); + var visitor = new ObjectVisitor(parsedPath, ContractResolver, AdapterFactory); var target = objectToApplyTo; if (!visitor.TryVisit(ref target, out var adapter, out var errorMessage)) @@ -281,7 +301,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters propertyValue = null; var parsedPath = new ParsedPath(fromLocation); - var visitor = new ObjectVisitor(parsedPath, ContractResolver); + var visitor = new ObjectVisitor(parsedPath, ContractResolver, AdapterFactory); var target = objectToGetValueFrom; if (!visitor.TryVisit(ref target, out var adapter, out var errorMessage)) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapterOfTU.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapterOfTU.cs index 8a344e24ee..be2bbffd86 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapterOfTU.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapterOfTU.cs @@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { public class DictionaryAdapter : IAdapter { - public bool TryAdd( + public virtual bool TryAdd( object target, string segment, IContractResolver contractResolver, @@ -37,7 +37,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryGet( + public virtual bool TryGet( object target, string segment, IContractResolver contractResolver, @@ -66,7 +66,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryRemove( + public virtual bool TryRemove( object target, string segment, IContractResolver contractResolver, @@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryReplace( + public virtual bool TryReplace( object target, string segment, IContractResolver contractResolver, @@ -128,7 +128,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryTest( + public virtual bool TryTest( object target, string segment, IContractResolver contractResolver, @@ -177,7 +177,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - public bool TryTraverse( + public virtual bool TryTraverse( object target, string segment, IContractResolver contractResolver, @@ -208,7 +208,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - private bool TryConvertKey(string key, out TKey convertedKey, out string errorMessage) + protected virtual bool TryConvertKey(string key, out TKey convertedKey, out string errorMessage) { var conversionResult = ConversionResultProvider.ConvertTo(key, typeof(TKey)); if (conversionResult.CanBeConverted) @@ -225,7 +225,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - private bool TryConvertValue(object value, out TValue convertedValue, out string errorMessage) + protected virtual bool TryConvertValue(object value, out TValue convertedValue, out string errorMessage) { var conversionResult = ConversionResultProvider.ConvertTo(value, typeof(TValue)); if (conversionResult.CanBeConverted) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs index fb4adeb1f2..dc3c48266f 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs @@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { public class DynamicObjectAdapter : IAdapter { - public bool TryAdd( + public virtual bool TryAdd( object target, string segment, IContractResolver contractResolver, @@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryGet( + public virtual bool TryGet( object target, string segment, IContractResolver contractResolver, @@ -48,7 +48,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryRemove( + public virtual bool TryRemove( object target, string segment, IContractResolver contractResolver, @@ -78,7 +78,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } - public bool TryReplace( + public virtual bool TryReplace( object target, string segment, IContractResolver contractResolver, @@ -105,7 +105,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryTest( + public virtual bool TryTest( object target, string segment, IContractResolver contractResolver, @@ -135,7 +135,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - public bool TryTraverse( + public virtual bool TryTraverse( object target, string segment, IContractResolver contractResolver, @@ -155,7 +155,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - private bool TryGetDynamicObjectProperty( + protected virtual bool TryGetDynamicObjectProperty( object target, IContractResolver contractResolver, string segment, @@ -191,7 +191,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - private bool TrySetDynamicObjectProperty( + protected virtual bool TrySetDynamicObjectProperty( object target, IContractResolver contractResolver, string segment, @@ -227,7 +227,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - private bool TryConvertValue(object value, Type propertyType, out object convertedValue) + protected virtual bool TryConvertValue(object value, Type propertyType, out object convertedValue) { var conversionResult = ConversionResultProvider.ConvertTo(value, propertyType); if (!conversionResult.CanBeConverted) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs index d1348fd5c6..597f7b9f5f 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { public class ListAdapter : IAdapter { - public bool TryAdd( + public virtual bool TryAdd( object target, string segment, IContractResolver contractResolver, @@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryGet( + public virtual bool TryGet( object target, string segment, IContractResolver contractResolver, @@ -84,7 +84,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryRemove( + public virtual bool TryRemove( object target, string segment, IContractResolver contractResolver, @@ -115,7 +115,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryReplace( + public virtual bool TryReplace( object target, string segment, IContractResolver contractResolver, @@ -152,7 +152,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryTest( + public virtual bool TryTest( object target, string segment, IContractResolver contractResolver, @@ -189,7 +189,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - public bool TryTraverse( + public virtual bool TryTraverse( object target, string segment, IContractResolver contractResolver, @@ -224,7 +224,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - private bool TryConvertValue( + protected virtual bool TryConvertValue( object originalValue, Type listTypeArgument, string segment, @@ -244,7 +244,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - private bool TryGetListTypeArgument(IList list, out Type listTypeArgument, out string errorMessage) + protected virtual bool TryGetListTypeArgument(IList list, out Type listTypeArgument, out string errorMessage) { // Arrays are not supported as they have fixed size and operations like Add, Insert do not make sense var listType = list.GetType(); @@ -272,7 +272,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - private bool TryGetPositionInfo( + protected virtual bool TryGetPositionInfo( IList list, string segment, OperationType operationType, @@ -318,7 +318,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } } - private struct PositionInfo + protected struct PositionInfo { public PositionInfo(PositionType type, int index) { @@ -330,7 +330,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal public int Index { get; } } - private enum PositionType + protected enum PositionType { Index, // valid index EndOfList, // '-' @@ -338,7 +338,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal OutOfBounds } - private enum OperationType + protected enum OperationType { Add, Remove, diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs index 8994f0aa52..a988afa300 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs @@ -3,19 +3,38 @@ using System; using System.Collections; +using Microsoft.AspNetCore.JsonPatch.Adapters; using Newtonsoft.Json.Serialization; namespace Microsoft.AspNetCore.JsonPatch.Internal { public class ObjectVisitor { + private readonly IAdapterFactory _adapterFactory; private readonly IContractResolver _contractResolver; private readonly ParsedPath _path; + /// + /// Initializes a new instance of . + /// + /// The path of the JsonPatch operation + /// The . public ObjectVisitor(ParsedPath path, IContractResolver contractResolver) + :this(path, contractResolver, new AdapterFactory()) { + } + + /// + /// Initializes a new instance of . + /// + /// The path of the JsonPatch operation + /// The . + /// The to use when creating adaptors. + public ObjectVisitor(ParsedPath path, IContractResolver contractResolver, IAdapterFactory adapterFactory) + { _path = path; _contractResolver = contractResolver ?? throw new ArgumentNullException(nameof(contractResolver)); + _adapterFactory = adapterFactory ?? throw new ArgumentNullException(nameof(adapterFactory)); } public bool TryVisit(ref object target, out IAdapter adapter, out string errorMessage) @@ -48,25 +67,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal private IAdapter SelectAdapter(object targetObject) { - var jsonContract = _contractResolver.ResolveContract(targetObject.GetType()); - - if (targetObject is IList) - { - return new ListAdapter(); - } - else if (jsonContract is JsonDictionaryContract jsonDictionaryContract) - { - var type = typeof(DictionaryAdapter<,>).MakeGenericType(jsonDictionaryContract.DictionaryKeyType, jsonDictionaryContract.DictionaryValueType); - return (IAdapter)Activator.CreateInstance(type); - } - else if (jsonContract is JsonDynamicContract) - { - return new DynamicObjectAdapter(); - } - else - { - return new PocoAdapter(); - } + return _adapterFactory.Create(targetObject, _contractResolver); } } } diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs index 0eee0fc889..5ba3e5587b 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs @@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal { public class PocoAdapter : IAdapter { - public bool TryAdd( + public virtual bool TryAdd( object target, string segment, IContractResolver contractResolver, @@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryGet( + public virtual bool TryGet( object target, string segment, IContractResolver contractResolver, @@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryRemove( + public virtual bool TryRemove( object target, string segment, IContractResolver contractResolver, @@ -102,7 +102,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryReplace( + public virtual bool TryReplace( object target, string segment, IContractResolver @@ -134,7 +134,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryTest( + public virtual bool TryTest( object target, string segment, IContractResolver @@ -171,7 +171,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return true; } - public bool TryTraverse( + public virtual bool TryTraverse( object target, string segment, IContractResolver contractResolver, @@ -197,7 +197,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return false; } - private bool TryGetJsonProperty( + protected virtual bool TryGetJsonProperty( object target, IContractResolver contractResolver, string segment, @@ -220,7 +220,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return false; } - private bool TryConvertValue(object value, Type propertyType, out object convertedValue) + protected virtual bool TryConvertValue(object value, Type propertyType, out object convertedValue) { var conversionResult = ConversionResultProvider.ConvertTo(value, propertyType); if (!conversionResult.CanBeConverted) diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs index b6539caae8..1888ea6b4b 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs @@ -174,7 +174,7 @@ namespace Microsoft.AspNetCore.JsonPatch throw new ArgumentNullException(nameof(objectToApplyTo)); } - ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction: null)); + ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, null, new AdapterFactory())); } /// @@ -183,13 +183,28 @@ namespace Microsoft.AspNetCore.JsonPatch /// Object to apply the JsonPatchDocument to /// Action to log errors public void ApplyTo(object objectToApplyTo, Action logErrorAction) + { + ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction, new AdapterFactory()), logErrorAction); + } + + /// + /// Apply this JsonPatchDocument + /// + /// Object to apply the JsonPatchDocument to + /// IObjectAdapter instance to use when applying + /// Action to log errors + public void ApplyTo(object objectToApplyTo, IObjectAdapter adapter, Action logErrorAction) { if (objectToApplyTo == null) { throw new ArgumentNullException(nameof(objectToApplyTo)); } - var adapter = new ObjectAdapter(ContractResolver, logErrorAction); + if (adapter == null) + { + throw new ArgumentNullException(nameof(adapter)); + } + foreach (var op in Operations) { try diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs index 8ae1430185..3db0aac458 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs @@ -697,7 +697,7 @@ namespace Microsoft.AspNetCore.JsonPatch throw new ArgumentNullException(nameof(objectToApplyTo)); } - ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction: null)); + ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, null, new AdapterFactory())); } /// @@ -706,13 +706,28 @@ namespace Microsoft.AspNetCore.JsonPatch /// Object to apply the JsonPatchDocument to /// Action to log errors public void ApplyTo(TModel objectToApplyTo, Action logErrorAction) + { + ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction, new AdapterFactory()), logErrorAction); + } + + /// + /// Apply this JsonPatchDocument + /// + /// Object to apply the JsonPatchDocument to + /// IObjectAdapter instance to use when applying + /// Action to log errors + public void ApplyTo(TModel objectToApplyTo, IObjectAdapter adapter, Action logErrorAction) { if (objectToApplyTo == null) { throw new ArgumentNullException(nameof(objectToApplyTo)); } - var adapter = new ObjectAdapter(ContractResolver, logErrorAction); + if (adapter == null) + { + throw new ArgumentNullException(nameof(adapter)); + } + foreach (var op in Operations) { try diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/AdapterFactoryTests.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/AdapterFactoryTests.cs new file mode 100644 index 0000000000..1e961c29e9 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/AdapterFactoryTests.cs @@ -0,0 +1,73 @@ +using Microsoft.AspNetCore.JsonPatch.Adapters; +using Microsoft.AspNetCore.JsonPatch.Internal; +using Moq; +using Newtonsoft.Json.Serialization; +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.Text; +using Xunit; + +namespace Microsoft.AspNetCore.JsonPatch.Test.Adapters +{ + public class AdapterFactoryTests + { + [Fact] + public void GetListAdapterForListTargets() + { + // Arrange + AdapterFactory factory = new AdapterFactory(); + + //Act: + IAdapter adapter = factory.Create(new List(), new DefaultContractResolver()); + + // Assert + Assert.Equal(typeof(ListAdapter), adapter.GetType()); + } + + [Fact] + public void GetDictionaryAdapterForDictionaryObjects() + { + // Arrange + AdapterFactory factory = new AdapterFactory(); + + //Act: + IAdapter adapter = factory.Create(new Dictionary(), new DefaultContractResolver()); + + // Assert + Assert.Equal(typeof(DictionaryAdapter), adapter.GetType()); + } + + private class PocoModel + {} + + + [Fact] + public void GetPocoAdapterForGenericObjects() + { + // Arrange + AdapterFactory factory = new AdapterFactory(); + + //Act: + IAdapter adapter = factory.Create(new PocoModel(), new DefaultContractResolver()); + + // Assert + Assert.Equal(typeof(PocoAdapter), adapter.GetType()); + } + + + + [Fact] + public void GetDynamicAdapterForGenericObjects() + { + // Arrange + AdapterFactory factory = new AdapterFactory(); + + //Act: + IAdapter adapter = factory.Create(new TestDynamicObject(), new DefaultContractResolver()); + + // Assert + Assert.Equal(typeof(DynamicObjectAdapter), adapter.GetType()); + } + } +} diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/TestDynamicObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/TestDynamicObject.cs new file mode 100644 index 0000000000..08371f25c6 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Adapters/TestDynamicObject.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.Text; + +namespace Microsoft.AspNetCore.JsonPatch.Test.Adapters +{ + public class TestDynamicObject : DynamicObject + { } +} From 146427fa5ade76db9c9a965a535a104a1de830d0 Mon Sep 17 00:00:00 2001 From: DHumphreys Date: Fri, 11 May 2018 16:33:59 -0400 Subject: [PATCH 0783/1029] Updates per PR feedback --- .../Adapters/AdapterFactory.cs | 10 ++++++++++ .../Adapters/ObjectAdapter.cs | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/AdapterFactory.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/AdapterFactory.cs index c963fcffdd..82aaa56a70 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Adapters/AdapterFactory.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/AdapterFactory.cs @@ -15,6 +15,16 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters /// public virtual IAdapter Create(object target, IContractResolver contractResolver) { + if (target == null) + { + throw new ArgumentNullException(nameof(target)); + } + + if (contractResolver == null) + { + throw new ArgumentNullException(nameof(contractResolver)); + } + var jsonContract = contractResolver.ResolveContract(target.GetType()); if (target is IList) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs index 48d7e69b0f..d625176376 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs @@ -47,7 +47,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters /// /// Gets or sets the /// - public IAdapterFactory AdapterFactory { get; set; } + public IAdapterFactory AdapterFactory { get; } /// /// Action for logging . From 31d7971d2e4529014ae4fbb8032934ce6b5173c1 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 13 May 2018 14:05:12 -0700 Subject: [PATCH 0784/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 53d6c6353d..64cad79092 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,19 +3,19 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17050 - 2.2.0-preview1-34154 - 2.2.0-preview1-34154 - 2.2.0-preview1-34154 - 2.2.0-preview1-34154 - 2.2.0-preview1-34154 + 2.2.0-preview1-17051 + 2.2.0-preview1-34184 + 2.2.0-preview1-34184 + 2.2.0-preview1-34184 + 2.2.0-preview1-34184 + 2.2.0-preview1-34184 2.0.0 2.1.0-rc1 - 2.2.0-preview1-26424-04 + 2.2.0-preview1-26509-06 15.6.1 2.0.3 - 4.5.0-preview3-26423-04 - 4.5.0-preview3-26423-04 + 4.6.0-preview1-26508-04 + 4.6.0-preview1-26508-04 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 82ebcf2549..56263a26fc 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17050 -commithash:24b548c969ffdf58730a7237a4c050b12c8711ed +version:2.2.0-preview1-17051 +commithash:253c3a480063bc3abaa5cde42f6e27b58457ef9b From d67c2cb2cc2bb582357bb54606f3e4d5d4ab6fb9 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 13 May 2018 14:08:54 -0700 Subject: [PATCH 0785/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 56bced18f5..0715a36542 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,19 +1,19 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17048 - 2.2.0-preview1-34140 - 2.2.0-preview1-34140 - 2.2.0-preview1-34140 - 2.2.0-preview1-34140 + 2.2.0-preview1-17051 + 2.2.0-preview1-34184 + 2.2.0-preview1-34184 + 2.2.0-preview1-34184 + 2.2.0-preview1-34184 2.0.0 - 2.2.0-preview1-26424-04 - 2.2.0-preview1-26502-01 + 2.1.0-rc1 + 2.2.0-preview1-26509-06 15.6.1 2.0.3 - 4.5.0-preview3-26423-04 + 4.6.0-preview1-26508-04 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 2573a03995..89629b454c 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17048 -commithash:de14a0ee5fb48508ee8a29c14280a2928f8dabf8 +version:2.2.0-preview1-17051 +commithash:253c3a480063bc3abaa5cde42f6e27b58457ef9b From 98d374d01c537044375203a54ec813f76ecd2d32 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 13 May 2018 14:14:38 -0700 Subject: [PATCH 0786/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 441743f2aa..81510fd56a 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,15 +1,15 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17048 - 2.2.0-preview1-34140 - 4.5.0-preview3-26423-04 - 2.2.0-preview1-34140 + 2.2.0-preview1-17051 + 2.2.0-preview1-34184 + 4.6.0-preview1-26508-04 + 2.2.0-preview1-34184 2.0.0 - 2.2.0-preview1-26424-04 - 2.2.0-preview1-26502-01 + 2.1.0-rc1 + 2.2.0-preview1-26509-06 15.6.1 4.7.49 2.0.3 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 2573a03995..89629b454c 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17048 -commithash:de14a0ee5fb48508ee8a29c14280a2928f8dabf8 +version:2.2.0-preview1-17051 +commithash:253c3a480063bc3abaa5cde42f6e27b58457ef9b From 6272b3625eb127d5d6ca248f34facba9bd7016a4 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 14 May 2018 14:17:27 -0700 Subject: [PATCH 0787/1029] Dispatch cancellation on CTRL+C to avoid deadlocks in killing the process tree --- shared/CliContext.cs | 9 ++-- src/dotnet-watch/DotNetWatcher.cs | 4 +- src/dotnet-watch/Internal/ProcessRunner.cs | 50 +++++++++++++------ src/dotnet-watch/Program.cs | 3 +- .../AwaitableProcess.cs | 25 ++++++++-- .../GlobbingAppTests.cs | 3 +- .../NoDepsAppTests.cs | 28 +++++++++++ .../Scenario/ProjectToolScenario.cs | 4 +- test/dotnet-watch.Tests/ProgramTests.cs | 22 ++++---- 9 files changed, 109 insertions(+), 39 deletions(-) diff --git a/shared/CliContext.cs b/shared/CliContext.cs index ad766a2e3b..854ea0fef6 100644 --- a/shared/CliContext.cs +++ b/shared/CliContext.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -8,14 +8,13 @@ namespace Microsoft.Extensions.Tools.Internal public static class CliContext { /// - /// dotnet --verbose subcommand + /// dotnet -d|--diagnostics subcommand /// /// public static bool IsGlobalVerbose() { - bool globalVerbose; - bool.TryParse(Environment.GetEnvironmentVariable("DOTNET_CLI_CONTEXT_VERBOSE"), out globalVerbose); + bool.TryParse(Environment.GetEnvironmentVariable("DOTNET_CLI_CONTEXT_VERBOSE"), out bool globalVerbose); return globalVerbose; } } -} \ No newline at end of file +} diff --git a/src/dotnet-watch/DotNetWatcher.cs b/src/dotnet-watch/DotNetWatcher.cs index f4b0423511..476acfcb43 100644 --- a/src/dotnet-watch/DotNetWatcher.cs +++ b/src/dotnet-watch/DotNetWatcher.cs @@ -69,8 +69,10 @@ namespace Microsoft.DotNet.Watcher await Task.WhenAll(processTask, fileSetTask); - if (processTask.Result != 0 && finishedTask == processTask) + if (processTask.Result != 0 && finishedTask == processTask && !cancellationToken.IsCancellationRequested) { + // Only show this error message if the process exited non-zero due to a normal process exit. + // Don't show this if dotnet-watch killed the inner process due to file change or CTRL+C by the user _reporter.Error($"Exited with error code {processTask.Result}"); } else diff --git a/src/dotnet-watch/Internal/ProcessRunner.cs b/src/dotnet-watch/Internal/ProcessRunner.cs index a5f7cac8ef..bbded25611 100644 --- a/src/dotnet-watch/Internal/ProcessRunner.cs +++ b/src/dotnet-watch/Internal/ProcessRunner.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -33,7 +33,7 @@ namespace Microsoft.DotNet.Watcher.Internal var stopwatch = new Stopwatch(); using (var process = CreateProcess(processSpec)) - using (var processState = new ProcessState(process)) + using (var processState = new ProcessState(process, _reporter)) { cancellationToken.Register(() => processState.TryKill()); @@ -97,27 +97,36 @@ namespace Microsoft.DotNet.Watcher.Internal private class ProcessState : IDisposable { + private readonly IReporter _reporter; private readonly Process _process; private readonly TaskCompletionSource _tcs = new TaskCompletionSource(); private volatile bool _disposed; - public ProcessState(Process process) + public ProcessState(Process process, IReporter reporter) { + _reporter = reporter; _process = process; _process.Exited += OnExited; Task = _tcs.Task.ContinueWith(_ => { - // We need to use two WaitForExit calls to ensure that all of the output/events are processed. Previously - // this code used Process.Exited, which could result in us missing some output due to the ordering of - // events. - // - // See the remarks here: https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.waitforexit#System_Diagnostics_Process_WaitForExit_System_Int32_ - if (!process.WaitForExit(Int32.MaxValue)) + try { - throw new TimeoutException(); - } + // We need to use two WaitForExit calls to ensure that all of the output/events are processed. Previously + // this code used Process.Exited, which could result in us missing some output due to the ordering of + // events. + // + // See the remarks here: https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.waitforexit#System_Diagnostics_Process_WaitForExit_System_Int32_ + if (!_process.WaitForExit(Int32.MaxValue)) + { + throw new TimeoutException(); + } - process.WaitForExit(); + _process.WaitForExit(); + } + catch (InvalidOperationException) + { + // suppress if this throws if no process is associated with this object anymore. + } }); } @@ -125,15 +134,26 @@ namespace Microsoft.DotNet.Watcher.Internal public void TryKill() { + if (_disposed) + { + return; + } + try { if (!_process.HasExited) { + _reporter.Verbose($"Killing process {_process.Id}"); _process.KillTree(); } } - catch - { } + catch (Exception ex) + { + _reporter.Verbose($"Error while killing process '{_process.StartInfo.FileName} {_process.StartInfo.Arguments}': {ex.Message}"); +#if DEBUG + _reporter.Verbose(ex.ToString()); +#endif + } } private void OnExited(object sender, EventArgs args) @@ -143,8 +163,8 @@ namespace Microsoft.DotNet.Watcher.Internal { if (!_disposed) { - _disposed = true; TryKill(); + _disposed = true; _process.Exited -= OnExited; _process.Dispose(); } diff --git a/src/dotnet-watch/Program.cs b/src/dotnet-watch/Program.cs index 7e8200b102..3ef376d048 100644 --- a/src/dotnet-watch/Program.cs +++ b/src/dotnet-watch/Program.cs @@ -121,7 +121,8 @@ namespace Microsoft.DotNet.Watcher _reporter.Output("Shutdown requested. Press Ctrl+C again to force exit."); } - _cts.Cancel(); + // Invoke the cancellation on the default thread pool to workaround https://github.com/dotnet/corefx/issues/29699 + ThreadPool.QueueUserWorkItem(_ => _cts.Cancel()); } private async Task MainInternalAsync( diff --git a/test/dotnet-watch.FunctionalTests/AwaitableProcess.cs b/test/dotnet-watch.FunctionalTests/AwaitableProcess.cs index 91b53133eb..86e2f90f79 100644 --- a/test/dotnet-watch.FunctionalTests/AwaitableProcess.cs +++ b/test/dotnet-watch.FunctionalTests/AwaitableProcess.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -17,16 +17,26 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { private Process _process; private readonly ProcessSpec _spec; + private readonly List _lines; private BufferBlock _source; private ITestOutputHelper _logger; + private TaskCompletionSource _exited; public AwaitableProcess(ProcessSpec spec, ITestOutputHelper logger) { _spec = spec; _logger = logger; _source = new BufferBlock(); + _lines = new List(); + _exited = new TaskCompletionSource(); } + public IEnumerable Output => _lines; + + public Task Exited => _exited.Task; + + public int Id => _process.Id; + public void Start() { if (_process != null) @@ -52,6 +62,11 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } }; + foreach (var env in _spec.EnvironmentVariables) + { + _process.StartInfo.EnvironmentVariables[env.Key] = env.Value; + } + _process.OutputDataReceived += OnData; _process.ErrorDataReceived += OnData; _process.Exited += OnExit; @@ -65,13 +80,13 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public async Task GetOutputLineAsync(string message, TimeSpan timeout) { _logger.WriteLine($"Waiting for output line [msg == '{message}']. Will wait for {timeout.TotalSeconds} sec."); - return await GetOutputLineAsync(m => message == m).TimeoutAfter(timeout); + return await GetOutputLineAsync(m => string.Equals(m, message, StringComparison.Ordinal)).TimeoutAfter(timeout); } public async Task GetOutputLineStartsWithAsync(string message, TimeSpan timeout) { _logger.WriteLine($"Waiting for output line [msg.StartsWith('{message}')]. Will wait for {timeout.TotalSeconds} sec."); - return await GetOutputLineAsync(m => m.StartsWith(message)).TimeoutAfter(timeout); + return await GetOutputLineAsync(m => m != null && m.StartsWith(message, StringComparison.Ordinal)).TimeoutAfter(timeout); } private async Task GetOutputLineAsync(Predicate predicate) @@ -81,6 +96,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests while (await _source.OutputAvailableAsync()) { var next = await _source.ReceiveAsync(); + _lines.Add(next); _logger.WriteLine($"{DateTime.Now}: recv: '{next}'"); if (predicate(next)) { @@ -119,6 +135,8 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests // Wait to ensure the process has exited and all output consumed _process.WaitForExit(); _source.Complete(); + _exited.TrySetResult(_process.ExitCode); + _logger.WriteLine($"Process {_process.Id} has exited"); } public void Dispose() @@ -135,6 +153,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests _process.ErrorDataReceived -= OnData; _process.OutputDataReceived -= OnData; _process.Exited -= OnExit; + _process.Dispose(); } } } diff --git a/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs b/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs index 71b5d068bf..a01a28e7d8 100644 --- a/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs +++ b/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs @@ -102,6 +102,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests await _app.PrepareAsync(); _app.Start(new [] { "--list" }); var lines = await _app.Process.GetAllOutputLines(); + var files = lines.Where(l => !l.StartsWith("watch :")); AssertEx.EqualFileList( _app.Scenario.WorkFolder, @@ -111,7 +112,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests "GlobbingApp/include/Foo.cs", "GlobbingApp/GlobbingApp.csproj", }, - lines); + files); } public void Dispose() diff --git a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs index 8ac2f694e7..df2521b5d3 100644 --- a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs +++ b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs @@ -5,6 +5,8 @@ using System; using System.Diagnostics; using System.IO; using System.Threading.Tasks; +using Microsoft.AspNetCore.Testing; +using Microsoft.AspNetCore.Testing.xunit; using Xunit; using Xunit.Abstractions; @@ -15,10 +17,34 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(30); private readonly WatchableApp _app; + private readonly ITestOutputHelper _output; public NoDepsAppTests(ITestOutputHelper logger) { _app = new WatchableApp("NoDepsApp", logger); + _output = logger; + } + + [ConditionalFact] + [OSSkipCondition(OperatingSystems.Windows, SkipReason = "Testing SIGINT is specific to macOS/Linux")] + public async Task KillsProcessOnSigInt() + { + void SendSigInt(int pid) + { + _output.WriteLine($"kill -SIGINT {pid}"); + Process.Start("kill", $"-SIGINT {pid}"); + } + + await _app.StartWatcherAsync(new[] { "--no-exit" }); + + var childPid = await _app.GetProcessId(); + + SendSigInt(_app.Process.Id); + SendSigInt(childPid); + + await _app.Process.Exited.TimeoutAfter(TimeSpan.FromSeconds(30)); + + Assert.DoesNotContain(_app.Process.Output, l => l.StartsWith("Exited with error code")); } [Fact] @@ -33,6 +59,8 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests File.WriteAllText(fileToChange, programCs); await _app.HasRestarted(); + Assert.DoesNotContain(_app.Process.Output, l => l.StartsWith("Exited with error code")); + var pid2 = await _app.GetProcessId(); Assert.NotEqual(pid, pid2); diff --git a/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs index a0a14093ec..b5c064563b 100644 --- a/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -1,8 +1,7 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; @@ -12,7 +11,6 @@ using System.Threading.Tasks; using System.Xml.Linq; using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Internal; -using Microsoft.Extensions.Tools.Internal; using Xunit.Abstractions; namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests diff --git a/test/dotnet-watch.Tests/ProgramTests.cs b/test/dotnet-watch.Tests/ProgramTests.cs index 8c116b5595..a5998b25c8 100644 --- a/test/dotnet-watch.Tests/ProgramTests.cs +++ b/test/dotnet-watch.Tests/ProgramTests.cs @@ -28,23 +28,25 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests { _tempDir .WithCSharpProject("testproj") - .WithTargetFrameworks("netcoreapp1.0") + .WithTargetFrameworks("netcoreapp2.2") .Dir() .WithFile("Program.cs") .Create(); - var stdout = new StringBuilder(); - _console.Out = new StringWriter(stdout); - var program = new Program(_console, _tempDir.Root) - .RunAsync(new[] { "run" }); + var output = new StringBuilder(); + _console.Error = _console.Out = new StringWriter(output); + using (var app = new Program(_console, _tempDir.Root)) + { + var run = app.RunAsync(new[] { "run" }); - await _console.CancelKeyPressSubscribed.TimeoutAfter(TimeSpan.FromSeconds(30)); - _console.ConsoleCancelKey(); + await _console.CancelKeyPressSubscribed.TimeoutAfter(TimeSpan.FromSeconds(30)); + _console.ConsoleCancelKey(); - var exitCode = await program.TimeoutAfter(TimeSpan.FromSeconds(30)); + var exitCode = await run.TimeoutAfter(TimeSpan.FromSeconds(30)); - Assert.Contains("Shutdown requested. Press Ctrl+C again to force exit.", stdout.ToString()); - Assert.Equal(0, exitCode); + Assert.Contains("Shutdown requested. Press Ctrl+C again to force exit.", output.ToString()); + Assert.Equal(0, exitCode); + } } public void Dispose() From 5dac1be2d75a3acdf20531d07044bca6d79f9196 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 16 May 2018 16:47:34 -0700 Subject: [PATCH 0788/1029] Mark UserSecrets extension as a system component (#439) --- .../source.extension.vsixmanifest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest b/tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest index 37bb50c5da..68b5347ce6 100644 --- a/tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest +++ b/tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest @@ -6,7 +6,7 @@ Microsoft.VisualStudio.SecretManager Enables IVsProjectSecrets for ASP.NET Core projects that use Microsoft.Extensions.Configuration.UserSecrets. - + From 2d70bb90214e1e16ac7e3b2f0cae670567f3651b Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 20 May 2018 19:28:26 +0000 Subject: [PATCH 0789/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 64cad79092..e4d7319982 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17051 - 2.2.0-preview1-34184 - 2.2.0-preview1-34184 - 2.2.0-preview1-34184 - 2.2.0-preview1-34184 - 2.2.0-preview1-34184 + 2.2.0-preview1-17060 + 2.2.0-preview1-34255 + 2.2.0-preview1-34255 + 2.2.0-preview1-34255 + 2.2.0-preview1-34255 + 2.2.0-preview1-34255 2.0.0 2.1.0-rc1 2.2.0-preview1-26509-06 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 56263a26fc..06fc8a13e4 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17051 -commithash:253c3a480063bc3abaa5cde42f6e27b58457ef9b +version:2.2.0-preview1-17060 +commithash:25b4b134d6f8f7b461928f0d495cfc695ccabb5b From b4be87d7a369065177ce505b778969423bb2adbf Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 20 May 2018 19:32:03 +0000 Subject: [PATCH 0790/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 0715a36542..c873c30462 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,11 +3,11 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17051 - 2.2.0-preview1-34184 - 2.2.0-preview1-34184 - 2.2.0-preview1-34184 - 2.2.0-preview1-34184 + 2.2.0-preview1-17060 + 2.2.0-preview1-34255 + 2.2.0-preview1-34255 + 2.2.0-preview1-34255 + 2.2.0-preview1-34255 2.0.0 2.1.0-rc1 2.2.0-preview1-26509-06 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 89629b454c..cf2fff7def 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17051 -commithash:253c3a480063bc3abaa5cde42f6e27b58457ef9b +version:2.2.0-preview1-17060 +commithash:25b4b134d6f8f7b461928f0d495cfc695ccabb5b From 38c530f265b8953c190af0fd79edabbeaba1e47d Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 20 May 2018 19:37:47 +0000 Subject: [PATCH 0791/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 6 +++--- korebuild-lock.txt | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 81510fd56a..99209a80a1 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17051 - 2.2.0-preview1-34184 + 2.2.0-preview1-17060 + 2.2.0-preview1-34255 4.6.0-preview1-26508-04 - 2.2.0-preview1-34184 + 2.2.0-preview1-34255 2.0.0 2.1.0-rc1 2.2.0-preview1-26509-06 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 89629b454c..cf2fff7def 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17051 -commithash:253c3a480063bc3abaa5cde42f6e27b58457ef9b +version:2.2.0-preview1-17060 +commithash:25b4b134d6f8f7b461928f0d495cfc695ccabb5b From 4fb42482d9a65bbd1a792d2cd22280dfa4faca47 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 23 May 2018 10:51:58 -0700 Subject: [PATCH 0792/1029] Add myget.org aspnetcore-tools to Nuget.config --- NuGet.config | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/NuGet.config b/NuGet.config index e32bddfd51..8c30f1c84e 100644 --- a/NuGet.config +++ b/NuGet.config @@ -2,6 +2,10 @@ - + + From 83134227ab4ea17238b84c12d55a8dae6d530208 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 24 May 2018 08:24:56 -0700 Subject: [PATCH 0793/1029] Add support for DOTNET_WATCH_ITERATION (#443) This environment variable can be used to determine how many types the inner command has been re-launched Resolves #387 --- build/repo.props | 3 --- src/dotnet-watch/CommandLineOptions.cs | 4 ++++ src/dotnet-watch/DotNetWatcher.cs | 6 ++++++ .../DotNetWatcherTests.cs | 19 +++++++++++++++++++ .../TestProjects/KitchenSink/Program.cs | 1 + 5 files changed, 30 insertions(+), 3 deletions(-) diff --git a/build/repo.props b/build/repo.props index 015f722dd9..9569f0ba08 100644 --- a/build/repo.props +++ b/build/repo.props @@ -2,9 +2,6 @@ - - - diff --git a/src/dotnet-watch/CommandLineOptions.cs b/src/dotnet-watch/CommandLineOptions.cs index e6e23890d5..5cbaab33e9 100644 --- a/src/dotnet-watch/CommandLineOptions.cs +++ b/src/dotnet-watch/CommandLineOptions.cs @@ -53,6 +53,10 @@ Environment variables: DOTNET_WATCH dotnet-watch sets this variable to '1' on all child processes launched. + DOTNET_WATCH_ITERATION + dotnet-watch sets this variable to '1' and increments by one each time + a file is changed and the command is restarted. + Remarks: The special option '--' is used to delimit the end of the options and the beginning of arguments that will be passed to the child dotnet process. diff --git a/src/dotnet-watch/DotNetWatcher.cs b/src/dotnet-watch/DotNetWatcher.cs index 476acfcb43..8431615c1e 100644 --- a/src/dotnet-watch/DotNetWatcher.cs +++ b/src/dotnet-watch/DotNetWatcher.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Threading; using System.Threading.Tasks; using Microsoft.DotNet.Watcher.Internal; @@ -32,8 +33,13 @@ namespace Microsoft.DotNet.Watcher cancellationToken.Register(state => ((TaskCompletionSource) state).TrySetResult(null), cancelledTaskSource); + var iteration = 1; + while (true) { + processSpec.EnvironmentVariables["DOTNET_WATCH_ITERATION"] = iteration.ToString(CultureInfo.InvariantCulture); + iteration++; + var fileSet = await fileSetFactory.CreateAsync(cancellationToken); if (fileSet == null) diff --git a/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs b/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs index d0dc735247..d1dd022a15 100644 --- a/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs +++ b/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs @@ -3,6 +3,8 @@ using System; using System.Collections.Generic; +using System.IO; +using System.Globalization; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; @@ -30,6 +32,23 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests Assert.Equal("1", envValue); } + [Fact] + public async Task RunsWithIterationEnvVariable() + { + await _app.StartWatcherAsync(); + var source = Path.Combine(_app.SourceDirectory, "Program.cs"); + const string messagePrefix = "DOTNET_WATCH_ITERATION = "; + for (var i = 1; i <= 4; i++) + { + var message = await _app.Process.GetOutputLineStartsWithAsync(messagePrefix, TimeSpan.FromMinutes(2)); + var count = int.Parse(message.Substring(messagePrefix.Length), CultureInfo.InvariantCulture); + Assert.Equal(i, count); + + File.SetLastWriteTime(source, DateTime.Now); + await _app.HasRestarted(); + } + } + public void Dispose() { _app.Dispose(); diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/Program.cs b/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/Program.cs index 5251cdc1e0..f38dc8231b 100644 --- a/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/Program.cs +++ b/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/Program.cs @@ -13,6 +13,7 @@ namespace KitchenSink Console.WriteLine("Started"); Console.WriteLine("PID = " + Process.GetCurrentProcess().Id); Console.WriteLine("DOTNET_WATCH = " + Environment.GetEnvironmentVariable("DOTNET_WATCH")); + Console.WriteLine("DOTNET_WATCH_ITERATION = " + Environment.GetEnvironmentVariable("DOTNET_WATCH_ITERATION")); } } } From e7e9cdc5eeb1c893b6d1aa2a08b8acbe93ef0354 Mon Sep 17 00:00:00 2001 From: "Nate McMaster (automated)" Date: Fri, 25 May 2018 16:13:50 -0700 Subject: [PATCH 0794/1029] Update bootstrapper scripts (automated commit) [ci skip] --- run.ps1 | 25 +++++++++++++++++++------ run.sh | 33 +++++++++++++++++++++++++++++---- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/run.ps1 b/run.ps1 index 27dcf848f8..3b27382468 100644 --- a/run.ps1 +++ b/run.ps1 @@ -26,12 +26,18 @@ The base url where build tools can be downloaded. Overrides the value from the c .PARAMETER Update Updates KoreBuild to the latest version even if a lock file is present. +.PARAMETER Reinstall +Re-installs KoreBuild + .PARAMETER ConfigFile The path to the configuration file that stores values. Defaults to korebuild.json. .PARAMETER ToolsSourceSuffix The Suffix to append to the end of the ToolsSource. Useful for query strings in blob stores. +.PARAMETER CI +Sets up CI specific settings and variables. + .PARAMETER Arguments Arguments to be passed to the command @@ -65,8 +71,10 @@ param( [string]$ToolsSource, [Alias('u')] [switch]$Update, - [string]$ConfigFile, + [switch]$Reinstall, [string]$ToolsSourceSuffix, + [string]$ConfigFile = $null, + [switch]$CI, [Parameter(ValueFromRemainingArguments = $true)] [string[]]$Arguments ) @@ -93,6 +101,10 @@ function Get-KoreBuild { $version = $version.TrimStart('version:').Trim() $korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version) + if ($Reinstall -and (Test-Path $korebuildPath)) { + Remove-Item -Force -Recurse $korebuildPath + } + if (!(Test-Path $korebuildPath)) { Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version" New-Item -ItemType Directory -Path $korebuildPath | Out-Null @@ -101,9 +113,9 @@ function Get-KoreBuild { try { $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip" Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix - if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) { + if (Get-Command -Name 'Microsoft.PowerShell.Archive\Expand-Archive' -ErrorAction Ignore) { # Use built-in commands where possible as they are cross-plat compatible - Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath + Microsoft.PowerShell.Archive\Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath } else { # Fallback to old approach for old installations of PowerShell @@ -167,8 +179,9 @@ if (Test-Path $ConfigFile) { } } catch { - Write-Warning "$ConfigFile could not be read. Its settings will be ignored." - Write-Warning $Error[0] + Write-Host -ForegroundColor Red $Error[0] + Write-Error "$ConfigFile contains invalid JSON." + exit 1 } } @@ -188,7 +201,7 @@ $korebuildPath = Get-KoreBuild Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1') try { - Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile + Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile -CI:$CI Invoke-KoreBuildCommand $Command @Arguments } finally { diff --git a/run.sh b/run.sh index 834961fc3a..02aac15874 100755 --- a/run.sh +++ b/run.sh @@ -14,10 +14,12 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" [ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" verbose=false update=false +reinstall=false repo_path="$DIR" channel='' tools_source='' tools_source_suffix='' +ci=false # # Functions @@ -38,6 +40,8 @@ __usage() { echo " -s|--tools-source|-ToolsSource The base url where build tools can be downloaded. Overrides the value from the config file." echo " --tools-source-suffix|-ToolsSourceSuffix The suffix to append to tools-source. Useful for query strings." echo " -u|--update Update to the latest KoreBuild even if the lock file is present." + echo " --reinstall Reinstall KoreBuild." + echo " --ci Apply CI specific settings and environment variables." echo "" echo "Description:" echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." @@ -62,6 +66,10 @@ get_korebuild() { version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" + if [ "$reinstall" = true ] && [ -d "$korebuild_path" ]; then + rm -rf "$korebuild_path" + fi + { if [ ! -d "$korebuild_path" ]; then mkdir -p "$korebuild_path" @@ -175,6 +183,12 @@ while [[ $# -gt 0 ]]; do -u|--update|-Update) update=true ;; + --reinstall|-[Rr]einstall) + reinstall=true + ;; + --ci|-[Cc][Ii]) + ci=true + ;; --verbose|-Verbose) verbose=true ;; @@ -206,17 +220,28 @@ if [ -f "$config_file" ]; then config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")" else - __warn "$config_file is invalid JSON. Its settings will be ignored." + _error "$config_file contains invalid JSON." + exit 1 fi elif __machine_has python ; then if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" else - __warn "$config_file is invalid JSON. Its settings will be ignored." + _error "$config_file contains invalid JSON." + exit 1 + fi + elif __machine_has python3 ; then + if python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then + config_channel="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" + config_tools_source="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" + else + _error "$config_file contains invalid JSON." + exit 1 fi else - __warn 'Missing required command: jq or pyton. Could not parse the JSON file. Its settings will be ignored.' + _error 'Missing required command: jq or python. Could not parse the JSON file.' + exit 1 fi [ ! -z "${config_channel:-}" ] && channel="$config_channel" @@ -227,5 +252,5 @@ fi [ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' get_korebuild -set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file" +set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file" "$ci" invoke_korebuild_command "$command" "$@" From 79a90e5ed85f7aaa05dadc584173480fe99a89b6 Mon Sep 17 00:00:00 2001 From: "Nate McMaster (automated)" Date: Fri, 25 May 2018 16:14:17 -0700 Subject: [PATCH 0795/1029] Update bootstrapper scripts (automated commit) [ci skip] --- run.ps1 | 25 +++++++++++++++++++------ run.sh | 33 +++++++++++++++++++++++++++++---- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/run.ps1 b/run.ps1 index 27dcf848f8..3b27382468 100644 --- a/run.ps1 +++ b/run.ps1 @@ -26,12 +26,18 @@ The base url where build tools can be downloaded. Overrides the value from the c .PARAMETER Update Updates KoreBuild to the latest version even if a lock file is present. +.PARAMETER Reinstall +Re-installs KoreBuild + .PARAMETER ConfigFile The path to the configuration file that stores values. Defaults to korebuild.json. .PARAMETER ToolsSourceSuffix The Suffix to append to the end of the ToolsSource. Useful for query strings in blob stores. +.PARAMETER CI +Sets up CI specific settings and variables. + .PARAMETER Arguments Arguments to be passed to the command @@ -65,8 +71,10 @@ param( [string]$ToolsSource, [Alias('u')] [switch]$Update, - [string]$ConfigFile, + [switch]$Reinstall, [string]$ToolsSourceSuffix, + [string]$ConfigFile = $null, + [switch]$CI, [Parameter(ValueFromRemainingArguments = $true)] [string[]]$Arguments ) @@ -93,6 +101,10 @@ function Get-KoreBuild { $version = $version.TrimStart('version:').Trim() $korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version) + if ($Reinstall -and (Test-Path $korebuildPath)) { + Remove-Item -Force -Recurse $korebuildPath + } + if (!(Test-Path $korebuildPath)) { Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version" New-Item -ItemType Directory -Path $korebuildPath | Out-Null @@ -101,9 +113,9 @@ function Get-KoreBuild { try { $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip" Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix - if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) { + if (Get-Command -Name 'Microsoft.PowerShell.Archive\Expand-Archive' -ErrorAction Ignore) { # Use built-in commands where possible as they are cross-plat compatible - Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath + Microsoft.PowerShell.Archive\Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath } else { # Fallback to old approach for old installations of PowerShell @@ -167,8 +179,9 @@ if (Test-Path $ConfigFile) { } } catch { - Write-Warning "$ConfigFile could not be read. Its settings will be ignored." - Write-Warning $Error[0] + Write-Host -ForegroundColor Red $Error[0] + Write-Error "$ConfigFile contains invalid JSON." + exit 1 } } @@ -188,7 +201,7 @@ $korebuildPath = Get-KoreBuild Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1') try { - Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile + Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile -CI:$CI Invoke-KoreBuildCommand $Command @Arguments } finally { diff --git a/run.sh b/run.sh index 834961fc3a..02aac15874 100755 --- a/run.sh +++ b/run.sh @@ -14,10 +14,12 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" [ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" verbose=false update=false +reinstall=false repo_path="$DIR" channel='' tools_source='' tools_source_suffix='' +ci=false # # Functions @@ -38,6 +40,8 @@ __usage() { echo " -s|--tools-source|-ToolsSource The base url where build tools can be downloaded. Overrides the value from the config file." echo " --tools-source-suffix|-ToolsSourceSuffix The suffix to append to tools-source. Useful for query strings." echo " -u|--update Update to the latest KoreBuild even if the lock file is present." + echo " --reinstall Reinstall KoreBuild." + echo " --ci Apply CI specific settings and environment variables." echo "" echo "Description:" echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." @@ -62,6 +66,10 @@ get_korebuild() { version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" + if [ "$reinstall" = true ] && [ -d "$korebuild_path" ]; then + rm -rf "$korebuild_path" + fi + { if [ ! -d "$korebuild_path" ]; then mkdir -p "$korebuild_path" @@ -175,6 +183,12 @@ while [[ $# -gt 0 ]]; do -u|--update|-Update) update=true ;; + --reinstall|-[Rr]einstall) + reinstall=true + ;; + --ci|-[Cc][Ii]) + ci=true + ;; --verbose|-Verbose) verbose=true ;; @@ -206,17 +220,28 @@ if [ -f "$config_file" ]; then config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")" else - __warn "$config_file is invalid JSON. Its settings will be ignored." + _error "$config_file contains invalid JSON." + exit 1 fi elif __machine_has python ; then if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" else - __warn "$config_file is invalid JSON. Its settings will be ignored." + _error "$config_file contains invalid JSON." + exit 1 + fi + elif __machine_has python3 ; then + if python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then + config_channel="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" + config_tools_source="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" + else + _error "$config_file contains invalid JSON." + exit 1 fi else - __warn 'Missing required command: jq or pyton. Could not parse the JSON file. Its settings will be ignored.' + _error 'Missing required command: jq or python. Could not parse the JSON file.' + exit 1 fi [ ! -z "${config_channel:-}" ] && channel="$config_channel" @@ -227,5 +252,5 @@ fi [ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' get_korebuild -set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file" +set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file" "$ci" invoke_korebuild_command "$command" "$@" From b731294dc17e3a6062ddacba9348ab8c95011bf3 Mon Sep 17 00:00:00 2001 From: "Nate McMaster (automated)" Date: Fri, 25 May 2018 16:15:53 -0700 Subject: [PATCH 0796/1029] Update bootstrapper scripts (automated commit) [ci skip] --- run.ps1 | 25 +++++++++++++++++++------ run.sh | 33 +++++++++++++++++++++++++++++---- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/run.ps1 b/run.ps1 index 27dcf848f8..3b27382468 100644 --- a/run.ps1 +++ b/run.ps1 @@ -26,12 +26,18 @@ The base url where build tools can be downloaded. Overrides the value from the c .PARAMETER Update Updates KoreBuild to the latest version even if a lock file is present. +.PARAMETER Reinstall +Re-installs KoreBuild + .PARAMETER ConfigFile The path to the configuration file that stores values. Defaults to korebuild.json. .PARAMETER ToolsSourceSuffix The Suffix to append to the end of the ToolsSource. Useful for query strings in blob stores. +.PARAMETER CI +Sets up CI specific settings and variables. + .PARAMETER Arguments Arguments to be passed to the command @@ -65,8 +71,10 @@ param( [string]$ToolsSource, [Alias('u')] [switch]$Update, - [string]$ConfigFile, + [switch]$Reinstall, [string]$ToolsSourceSuffix, + [string]$ConfigFile = $null, + [switch]$CI, [Parameter(ValueFromRemainingArguments = $true)] [string[]]$Arguments ) @@ -93,6 +101,10 @@ function Get-KoreBuild { $version = $version.TrimStart('version:').Trim() $korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version) + if ($Reinstall -and (Test-Path $korebuildPath)) { + Remove-Item -Force -Recurse $korebuildPath + } + if (!(Test-Path $korebuildPath)) { Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version" New-Item -ItemType Directory -Path $korebuildPath | Out-Null @@ -101,9 +113,9 @@ function Get-KoreBuild { try { $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip" Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix - if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) { + if (Get-Command -Name 'Microsoft.PowerShell.Archive\Expand-Archive' -ErrorAction Ignore) { # Use built-in commands where possible as they are cross-plat compatible - Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath + Microsoft.PowerShell.Archive\Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath } else { # Fallback to old approach for old installations of PowerShell @@ -167,8 +179,9 @@ if (Test-Path $ConfigFile) { } } catch { - Write-Warning "$ConfigFile could not be read. Its settings will be ignored." - Write-Warning $Error[0] + Write-Host -ForegroundColor Red $Error[0] + Write-Error "$ConfigFile contains invalid JSON." + exit 1 } } @@ -188,7 +201,7 @@ $korebuildPath = Get-KoreBuild Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1') try { - Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile + Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile -CI:$CI Invoke-KoreBuildCommand $Command @Arguments } finally { diff --git a/run.sh b/run.sh index 834961fc3a..02aac15874 100755 --- a/run.sh +++ b/run.sh @@ -14,10 +14,12 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" [ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" verbose=false update=false +reinstall=false repo_path="$DIR" channel='' tools_source='' tools_source_suffix='' +ci=false # # Functions @@ -38,6 +40,8 @@ __usage() { echo " -s|--tools-source|-ToolsSource The base url where build tools can be downloaded. Overrides the value from the config file." echo " --tools-source-suffix|-ToolsSourceSuffix The suffix to append to tools-source. Useful for query strings." echo " -u|--update Update to the latest KoreBuild even if the lock file is present." + echo " --reinstall Reinstall KoreBuild." + echo " --ci Apply CI specific settings and environment variables." echo "" echo "Description:" echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." @@ -62,6 +66,10 @@ get_korebuild() { version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" + if [ "$reinstall" = true ] && [ -d "$korebuild_path" ]; then + rm -rf "$korebuild_path" + fi + { if [ ! -d "$korebuild_path" ]; then mkdir -p "$korebuild_path" @@ -175,6 +183,12 @@ while [[ $# -gt 0 ]]; do -u|--update|-Update) update=true ;; + --reinstall|-[Rr]einstall) + reinstall=true + ;; + --ci|-[Cc][Ii]) + ci=true + ;; --verbose|-Verbose) verbose=true ;; @@ -206,17 +220,28 @@ if [ -f "$config_file" ]; then config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")" else - __warn "$config_file is invalid JSON. Its settings will be ignored." + _error "$config_file contains invalid JSON." + exit 1 fi elif __machine_has python ; then if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" else - __warn "$config_file is invalid JSON. Its settings will be ignored." + _error "$config_file contains invalid JSON." + exit 1 + fi + elif __machine_has python3 ; then + if python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then + config_channel="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" + config_tools_source="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" + else + _error "$config_file contains invalid JSON." + exit 1 fi else - __warn 'Missing required command: jq or pyton. Could not parse the JSON file. Its settings will be ignored.' + _error 'Missing required command: jq or python. Could not parse the JSON file.' + exit 1 fi [ ! -z "${config_channel:-}" ] && channel="$config_channel" @@ -227,5 +252,5 @@ fi [ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' get_korebuild -set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file" +set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file" "$ci" invoke_korebuild_command "$command" "$@" From f573ab6c8216cdac599bad06695dbe6cfa1c1259 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 27 May 2018 19:11:20 +0000 Subject: [PATCH 0797/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index e4d7319982..d2adad6991 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,19 +3,19 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17060 - 2.2.0-preview1-34255 - 2.2.0-preview1-34255 - 2.2.0-preview1-34255 - 2.2.0-preview1-34255 - 2.2.0-preview1-34255 + 2.2.0-preview1-17064 + 2.2.0-preview1-34326 + 2.2.0-preview1-34326 + 2.2.0-preview1-34326 + 2.2.0-preview1-34326 + 2.2.0-preview1-34326 2.0.0 2.1.0-rc1 - 2.2.0-preview1-26509-06 + 2.2.0-preview1-26526-03 15.6.1 2.0.3 - 4.6.0-preview1-26508-04 - 4.6.0-preview1-26508-04 + 4.6.0-preview1-26525-01 + 4.6.0-preview1-26525-01 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 06fc8a13e4..de5df64434 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17060 -commithash:25b4b134d6f8f7b461928f0d495cfc695ccabb5b +version:2.2.0-preview1-17064 +commithash:5380a2461b135b261646f31d1c919ab0a7b577a8 From f2eb510b83b368089eddba695421594be6d51d18 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 27 May 2018 19:14:45 +0000 Subject: [PATCH 0798/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index c873c30462..0c63257c38 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17060 - 2.2.0-preview1-34255 - 2.2.0-preview1-34255 - 2.2.0-preview1-34255 - 2.2.0-preview1-34255 + 2.2.0-preview1-17064 + 2.2.0-preview1-34326 + 2.2.0-preview1-34326 + 2.2.0-preview1-34326 + 2.2.0-preview1-34326 2.0.0 2.1.0-rc1 - 2.2.0-preview1-26509-06 + 2.2.0-preview1-26526-03 15.6.1 2.0.3 - 4.6.0-preview1-26508-04 + 4.6.0-preview1-26525-01 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index cf2fff7def..3028b66761 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17060 -commithash:25b4b134d6f8f7b461928f0d495cfc695ccabb5b +version:2.2.0-preview1-17064 +commithash:5380a2461b135b261646f31d1c919ab0a7b577a8 From fdafad711b11ff22563df005741f6ec8bf86432b Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 27 May 2018 19:20:26 +0000 Subject: [PATCH 0799/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 99209a80a1..9163891c8c 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,13 +3,13 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17060 - 2.2.0-preview1-34255 - 4.6.0-preview1-26508-04 - 2.2.0-preview1-34255 + 2.2.0-preview1-17064 + 2.2.0-preview1-34326 + 4.6.0-preview1-26525-01 + 2.2.0-preview1-34326 2.0.0 2.1.0-rc1 - 2.2.0-preview1-26509-06 + 2.2.0-preview1-26526-03 15.6.1 4.7.49 2.0.3 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index cf2fff7def..3028b66761 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17060 -commithash:25b4b134d6f8f7b461928f0d495cfc695ccabb5b +version:2.2.0-preview1-17064 +commithash:5380a2461b135b261646f31d1c919ab0a7b577a8 From 8d1011fe29d8acf4c30f8c9844660b7f16553004 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 29 May 2018 09:34:54 -0700 Subject: [PATCH 0800/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index b34bf72810..7e572a8f72 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,18 +3,18 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-rtm-15783 - 2.1.0-rtm-30721 - 2.1.0-rtm-30721 - 2.1.0-rtm-30721 - 2.1.0-rtm-30721 - 2.1.0-rtm-30721 + 2.1.1-rtm-15790 + 2.1.0 + 2.1.0 + 2.1.0 + 2.1.0 + 2.1.0 2.0.0 - 2.1.0-rtm-26502-02 + 2.1.0 15.6.1 2.0.3 - 4.5.0-rtm-26502-02 - 4.5.0-rtm-26502-02 + 4.5.0 + 4.5.0 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 27e94579a9..de0eb84cf3 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-rtm-15783 -commithash:5fc2b2f607f542a2ffde11c19825e786fc1a3774 +version:2.1.1-rtm-15790 +commithash:274c65868e735f29f4078c1884c61c4371ee1fc0 From f4b98641d2ae8f95682bed02802dea5beffc9b46 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 29 May 2018 09:38:05 -0700 Subject: [PATCH 0801/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 007238eb66..a1e264ee96 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,16 +3,16 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-rtm-15783 - 2.1.0-rtm-30721 - 2.1.0-rtm-30721 - 2.1.0-rtm-30721 - 2.1.0-rtm-30721 + 2.1.1-rtm-15790 + 2.1.0 + 2.1.0 + 2.1.0 + 2.1.0 2.0.0 - 2.1.0-rtm-26502-02 + 2.1.0 15.6.1 2.0.3 - 4.5.0-rtm-26502-02 + 4.5.0 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 3673744db9..cd5b409a1e 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-rtm-15783 -commithash:5fc2b2f607f542a2ffde11c19825e786fc1a3774 +version:2.1.1-rtm-15790 +commithash:274c65868e735f29f4078c1884c61c4371ee1fc0 From e3a21b2a92ddc8d971f4f21c617bb69ca0ae3761 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 29 May 2018 09:44:06 -0700 Subject: [PATCH 0802/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index acedb0a6ca..5b7c18bdae 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.0-rtm-15783 - 2.1.0-rtm-30721 - 4.5.0-rtm-26502-02 - 2.1.0-rtm-30721 + 2.1.1-rtm-15790 + 2.1.0 + 4.5.0 + 2.1.0 2.0.0 - 2.1.0-rtm-26502-02 + 2.1.0 15.6.1 4.7.49 2.0.3 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 3673744db9..cd5b409a1e 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.0-rtm-15783 -commithash:5fc2b2f607f542a2ffde11c19825e786fc1a3774 +version:2.1.1-rtm-15790 +commithash:274c65868e735f29f4078c1884c61c4371ee1fc0 From 9b7f097870af894b6ceb375ae9ba3825100a354c Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 29 May 2018 10:03:19 -0700 Subject: [PATCH 0803/1029] Add aspnet tools myget feed --- NuGet.config | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/NuGet.config b/NuGet.config index e32bddfd51..8c30f1c84e 100644 --- a/NuGet.config +++ b/NuGet.config @@ -2,6 +2,10 @@ - + + From e74907d6bf0d426678c36040f21c63bfc1913472 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 31 May 2018 20:16:06 -0700 Subject: [PATCH 0804/1029] Resolves #444 - remove workaround for CTRL+C deadlocks --- src/dotnet-watch/Program.cs | 5 ++-- .../DotNetWatcherTests.cs | 4 +++- .../NoDepsAppTests.cs | 24 ------------------- 3 files changed, 5 insertions(+), 28 deletions(-) diff --git a/src/dotnet-watch/Program.cs b/src/dotnet-watch/Program.cs index 3ef376d048..25317fb6b2 100644 --- a/src/dotnet-watch/Program.cs +++ b/src/dotnet-watch/Program.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -121,8 +121,7 @@ namespace Microsoft.DotNet.Watcher _reporter.Output("Shutdown requested. Press Ctrl+C again to force exit."); } - // Invoke the cancellation on the default thread pool to workaround https://github.com/dotnet/corefx/issues/29699 - ThreadPool.QueueUserWorkItem(_ => _cts.Cancel()); + _cts.Cancel(); } private async Task MainInternalAsync( diff --git a/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs b/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs index d1dd022a15..cc0a1c3fc0 100644 --- a/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs +++ b/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs @@ -37,6 +37,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { await _app.StartWatcherAsync(); var source = Path.Combine(_app.SourceDirectory, "Program.cs"); + var contents = File.ReadAllText(source); const string messagePrefix = "DOTNET_WATCH_ITERATION = "; for (var i = 1; i <= 4; i++) { @@ -44,7 +45,8 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests var count = int.Parse(message.Substring(messagePrefix.Length), CultureInfo.InvariantCulture); Assert.Equal(i, count); - File.SetLastWriteTime(source, DateTime.Now); + File.Delete(source); + File.WriteAllText(source, contents); await _app.HasRestarted(); } } diff --git a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs index df2521b5d3..22f46cbbe0 100644 --- a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs +++ b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs @@ -5,8 +5,6 @@ using System; using System.Diagnostics; using System.IO; using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing; -using Microsoft.AspNetCore.Testing.xunit; using Xunit; using Xunit.Abstractions; @@ -25,28 +23,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests _output = logger; } - [ConditionalFact] - [OSSkipCondition(OperatingSystems.Windows, SkipReason = "Testing SIGINT is specific to macOS/Linux")] - public async Task KillsProcessOnSigInt() - { - void SendSigInt(int pid) - { - _output.WriteLine($"kill -SIGINT {pid}"); - Process.Start("kill", $"-SIGINT {pid}"); - } - - await _app.StartWatcherAsync(new[] { "--no-exit" }); - - var childPid = await _app.GetProcessId(); - - SendSigInt(_app.Process.Id); - SendSigInt(childPid); - - await _app.Process.Exited.TimeoutAfter(TimeSpan.FromSeconds(30)); - - Assert.DoesNotContain(_app.Process.Output, l => l.StartsWith("Exited with error code")); - } - [Fact] public async Task RestartProcessOnFileChange() { From fed623db5c2c10008e8aaae739606eaa914d3a89 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 3 Jun 2018 19:11:05 +0000 Subject: [PATCH 0805/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 20 ++++++++++---------- korebuild-lock.txt | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index d2adad6991..ce7db6101f 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,19 +3,19 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17064 - 2.2.0-preview1-34326 - 2.2.0-preview1-34326 - 2.2.0-preview1-34326 - 2.2.0-preview1-34326 - 2.2.0-preview1-34326 + 2.2.0-preview1-17067 + 2.2.0-preview1-34373 + 2.2.0-preview1-34373 + 2.2.0-preview1-34373 + 2.2.0-preview1-34373 + 2.2.0-preview1-34373 2.0.0 - 2.1.0-rc1 - 2.2.0-preview1-26526-03 + 2.1.0 + 2.2.0-preview1-26531-03 15.6.1 2.0.3 - 4.6.0-preview1-26525-01 - 4.6.0-preview1-26525-01 + 4.6.0-preview1-26531-03 + 4.6.0-preview1-26531-03 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index de5df64434..34bf7eb808 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17064 -commithash:5380a2461b135b261646f31d1c919ab0a7b577a8 +version:2.2.0-preview1-17067 +commithash:2af0e2e3d02329b4f0290061ab9bd8c7ca1aa26f From fe4ff1a2c437d08a67282fdb4fdab9f0800842c9 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 3 Jun 2018 19:14:37 +0000 Subject: [PATCH 0806/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 16 ++++++++-------- korebuild-lock.txt | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 0c63257c38..8331dd7d03 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17064 - 2.2.0-preview1-34326 - 2.2.0-preview1-34326 - 2.2.0-preview1-34326 - 2.2.0-preview1-34326 + 2.2.0-preview1-17067 + 2.2.0-preview1-34373 + 2.2.0-preview1-34373 + 2.2.0-preview1-34373 + 2.2.0-preview1-34373 2.0.0 - 2.1.0-rc1 - 2.2.0-preview1-26526-03 + 2.1.0 + 2.2.0-preview1-26531-03 15.6.1 2.0.3 - 4.6.0-preview1-26525-01 + 4.6.0-preview1-26531-03 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 3028b66761..06ba6285b7 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17064 -commithash:5380a2461b135b261646f31d1c919ab0a7b577a8 +version:2.2.0-preview1-17067 +commithash:2af0e2e3d02329b4f0290061ab9bd8c7ca1aa26f From 75126c0726bb3f19cfe7b17b2a01faf749872789 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 3 Jun 2018 19:19:39 +0000 Subject: [PATCH 0807/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 9163891c8c..2cfb5c02e8 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,13 +3,13 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17064 - 2.2.0-preview1-34326 - 4.6.0-preview1-26525-01 - 2.2.0-preview1-34326 + 2.2.0-preview1-17067 + 2.2.0-preview1-34373 + 4.6.0-preview1-26531-03 + 2.2.0-preview1-34373 2.0.0 - 2.1.0-rc1 - 2.2.0-preview1-26526-03 + 2.1.0 + 2.2.0-preview1-26531-03 15.6.1 4.7.49 2.0.3 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 3028b66761..06ba6285b7 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17064 -commithash:5380a2461b135b261646f31d1c919ab0a7b577a8 +version:2.2.0-preview1-17067 +commithash:2af0e2e3d02329b4f0290061ab9bd8c7ca1aa26f From 0ce4004cde8798b377608f14bc54bafcb0dc52af Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 5 Jun 2018 09:11:31 -0700 Subject: [PATCH 0808/1029] Bumping version from 2.1.0 to 2.1.1 --- version.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.props b/version.props index e19391f5bf..4078cfc422 100644 --- a/version.props +++ b/version.props @@ -1,6 +1,6 @@ - + - 2.1.0 + 2.1.1 15.6 rtm $(VersionPrefix) From 4764c44e93d0bb772def90285d16572bc2bc376c Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 5 Jun 2018 09:11:34 -0700 Subject: [PATCH 0809/1029] Bumping version from 2.1.0 to 2.1.1 --- version.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.props b/version.props index b9552451d8..669c874829 100644 --- a/version.props +++ b/version.props @@ -1,6 +1,6 @@ - + - 2.1.0 + 2.1.1 rtm $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final From d89db5fcd7302d08a94a995f280fb30f715b0b16 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 5 Jun 2018 09:11:39 -0700 Subject: [PATCH 0810/1029] Bumping version from 2.1.0 to 2.1.1 --- version.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.props b/version.props index b9552451d8..669c874829 100644 --- a/version.props +++ b/version.props @@ -1,6 +1,6 @@ - + - 2.1.0 + 2.1.1 rtm $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final From 124b6ba9a193ce9753b06e0bae4725a6bd3d8342 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 5 Jun 2018 22:31:24 -0700 Subject: [PATCH 0811/1029] Add certificate names for code signing --- Directory.Build.props | 3 +- NuGetPackageVerifier.json | 65 +------------------ korebuild-lock.txt | 4 +- src/dotnet-sql-cache/dotnet-sql-cache.csproj | 13 ++++ .../dotnet-user-secrets.csproj | 19 ++++++ 5 files changed, 38 insertions(+), 66 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 29d623306f..8ca8a8757b 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -14,8 +14,9 @@ $(MSBuildThisFileDirectory) $(MSBuildThisFileDirectory)build\Key.snk true - true + MicrosoftNuGet Microsoft + true true diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index 6503b35342..fb43448889 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -12,73 +12,12 @@ "dotnet-sql-cache": { "packageTypes": [ "DotnetTool" - ], - "Exclusions": { - "NEUTRAL_RESOURCES_LANGUAGE": { - "tools/netcoreapp2.2/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." - }, - "WRONG_PUBLICKEYTOKEN": { - "tools/netcoreapp2.2/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg." - }, - "ASSEMBLY_INFORMATIONAL_VERSION_MISMATCH": { - "tools/netcoreapp2.2/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg." - }, - "ASSEMBLY_FILE_VERSION_MISMATCH": { - "tools/netcoreapp2.2/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg." - }, - "ASSEMBLY_VERSION_MISMATCH": { - "tools/netcoreapp2.2/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg." - } - } + ] }, "dotnet-user-secrets": { "packageTypes": [ "DotnetTool" - ], - "Exclusions": { - "NEUTRAL_RESOURCES_LANGUAGE": { - "tools/netcoreapp2.2/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." - }, - "SERVICING_ATTRIBUTE": { - "tools/netcoreapp2.2/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg." - }, - "WRONG_PUBLICKEYTOKEN": { - "tools/netcoreapp2.2/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." - }, - "ASSEMBLY_INFORMATIONAL_VERSION_MISMATCH": { - "tools/netcoreapp2.2/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." - }, - "ASSEMBLY_FILE_VERSION_MISMATCH": { - "tools/netcoreapp2.2/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." - }, - "ASSEMBLY_VERSION_MISMATCH": { - "tools/netcoreapp2.2/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.2/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." - } - } + ] }, "dotnet-dev-certs": { "packageTypes": [ diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 34bf7eb808..2dedb9dd4c 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17067 -commithash:2af0e2e3d02329b4f0290061ab9bd8c7ca1aa26f +version:2.2.0-preview1-17075 +commithash:d9f07c7f313a0af1d49f003f5424b4dbbdd3e09f diff --git a/src/dotnet-sql-cache/dotnet-sql-cache.csproj b/src/dotnet-sql-cache/dotnet-sql-cache.csproj index 3949d90be0..4ab0f3425c 100644 --- a/src/dotnet-sql-cache/dotnet-sql-cache.csproj +++ b/src/dotnet-sql-cache/dotnet-sql-cache.csproj @@ -22,4 +22,17 @@ + + + + + + + + + + + + + diff --git a/src/dotnet-user-secrets/dotnet-user-secrets.csproj b/src/dotnet-user-secrets/dotnet-user-secrets.csproj index 74bb54c602..bcb37e37b2 100644 --- a/src/dotnet-user-secrets/dotnet-user-secrets.csproj +++ b/src/dotnet-user-secrets/dotnet-user-secrets.csproj @@ -25,4 +25,23 @@ + + + + + + + + + + + + + + + + + + + From 2b9d2c1c97aad072ddae2af30f66427cae5df6e8 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 5 Jun 2018 22:32:10 -0700 Subject: [PATCH 0812/1029] Add certificate names for code signing --- Directory.Build.props | 2 ++ korebuild-lock.txt | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index b7176c688d..d5b8bf3650 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,6 +13,8 @@ $(MSBuildThisFileDirectory) $(MSBuildThisFileDirectory)build\Key.snk true + Microsoft + MicrosoftNuGet true true diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 06ba6285b7..b679b80427 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17067 -commithash:2af0e2e3d02329b4f0290061ab9bd8c7ca1aa26f +version:2.2.0-preview1-17075 +commithash:d9f07c7f313a0af1d49f003f5424b4dbbdd3e09f From 5613206ffe01846738551f59c7f01e4136744a7a Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 5 Jun 2018 22:33:05 -0700 Subject: [PATCH 0813/1029] Add certificate names for code signing --- Directory.Build.props | 2 ++ korebuild-lock.txt | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 88b93729bb..0c6cb2e37f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -14,6 +14,8 @@ $(MSBuildThisFileDirectory) $(MSBuildThisFileDirectory)build\Key.snk true + Microsoft + MicrosoftNuGet true true diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 06ba6285b7..b679b80427 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17067 -commithash:2af0e2e3d02329b4f0290061ab9bd8c7ca1aa26f +version:2.2.0-preview1-17075 +commithash:d9f07c7f313a0af1d49f003f5424b4dbbdd3e09f From 736a09e889f30e28249a6bfeacd5ec8caef9879e Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 7 Jun 2018 19:31:53 +0000 Subject: [PATCH 0814/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index ce7db6101f..0b26eb5044 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,19 +3,19 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17067 - 2.2.0-preview1-34373 - 2.2.0-preview1-34373 - 2.2.0-preview1-34373 - 2.2.0-preview1-34373 - 2.2.0-preview1-34373 + 2.2.0-preview1-17081 + 2.2.0-preview1-34411 + 2.2.0-preview1-34411 + 2.2.0-preview1-34411 + 2.2.0-preview1-34411 + 2.2.0-preview1-34411 2.0.0 2.1.0 - 2.2.0-preview1-26531-03 + 2.2.0-preview1-26606-01 15.6.1 2.0.3 - 4.6.0-preview1-26531-03 - 4.6.0-preview1-26531-03 + 4.6.0-preview1-26605-01 + 4.6.0-preview1-26605-01 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 2dedb9dd4c..9592880b2a 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17075 -commithash:d9f07c7f313a0af1d49f003f5424b4dbbdd3e09f +version:2.2.0-preview1-17081 +commithash:73f09c256e2a54270951562ecc0ef4a953926c36 From c4ce63be536d0b28e50713d0b11281633cf32729 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 7 Jun 2018 19:35:24 +0000 Subject: [PATCH 0815/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 8331dd7d03..b793716276 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17067 - 2.2.0-preview1-34373 - 2.2.0-preview1-34373 - 2.2.0-preview1-34373 - 2.2.0-preview1-34373 + 2.2.0-preview1-17081 + 2.2.0-preview1-34411 + 2.2.0-preview1-34411 + 2.2.0-preview1-34411 + 2.2.0-preview1-34411 2.0.0 2.1.0 - 2.2.0-preview1-26531-03 + 2.2.0-preview1-26606-01 15.6.1 2.0.3 - 4.6.0-preview1-26531-03 + 4.6.0-preview1-26605-01 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index b679b80427..deb7e546f0 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17075 -commithash:d9f07c7f313a0af1d49f003f5424b4dbbdd3e09f +version:2.2.0-preview1-17081 +commithash:73f09c256e2a54270951562ecc0ef4a953926c36 From d45ef9d007278b8898303574bad5393398c0a867 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 7 Jun 2018 19:40:35 +0000 Subject: [PATCH 0816/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 2cfb5c02e8..15ef04fe4b 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,13 +3,13 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17067 - 2.2.0-preview1-34373 - 4.6.0-preview1-26531-03 - 2.2.0-preview1-34373 + 2.2.0-preview1-17081 + 2.2.0-preview1-34411 + 4.6.0-preview1-26605-01 + 2.2.0-preview1-34411 2.0.0 2.1.0 - 2.2.0-preview1-26531-03 + 2.2.0-preview1-26606-01 15.6.1 4.7.49 2.0.3 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index b679b80427..deb7e546f0 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17075 -commithash:d9f07c7f313a0af1d49f003f5424b4dbbdd3e09f +version:2.2.0-preview1-17081 +commithash:73f09c256e2a54270951562ecc0ef4a953926c36 From 556c2de4829f976d8b6d6ecb6105a50934c91616 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Thu, 7 Jun 2018 15:45:02 -0700 Subject: [PATCH 0817/1029] Adding VSTS file --- .vsts-pipelines/builds/ci-internal.yml | 13 +++++++++++++ .vsts-pipelines/builds/ci-public.yml | 15 +++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 .vsts-pipelines/builds/ci-internal.yml create mode 100644 .vsts-pipelines/builds/ci-public.yml diff --git a/.vsts-pipelines/builds/ci-internal.yml b/.vsts-pipelines/builds/ci-internal.yml new file mode 100644 index 0000000000..d7ceb76378 --- /dev/null +++ b/.vsts-pipelines/builds/ci-internal.yml @@ -0,0 +1,13 @@ +trigger: +- dev +- release/* + +resources: + repositories: + - repository: buildtools + type: git + name: aspnet-BuildTools + ref: refs/heads/dev + +phases: +- template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/.vsts-pipelines/builds/ci-public.yml b/.vsts-pipelines/builds/ci-public.yml new file mode 100644 index 0000000000..b7f25723f8 --- /dev/null +++ b/.vsts-pipelines/builds/ci-public.yml @@ -0,0 +1,15 @@ +trigger: +- dev +- release/* + +# See https://github.com/aspnet/BuildTools +resources: + repositories: + - repository: buildtools + type: github + endpoint: DotNet-Bot GitHub Connection + name: aspnet/BuildTools + ref: refs/heads/dev + +phases: +- template: .vsts-pipelines/templates/project-ci.yml@buildtools From 3033dd6b19357d50417d7e79bea4d7f1585607bd Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Thu, 7 Jun 2018 15:44:17 -0700 Subject: [PATCH 0818/1029] Adding VSTS file --- .vsts-pipelines/builds/ci-internal.yml | 13 +++++++++++++ .vsts-pipelines/builds/ci-public.yml | 15 +++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 .vsts-pipelines/builds/ci-internal.yml create mode 100644 .vsts-pipelines/builds/ci-public.yml diff --git a/.vsts-pipelines/builds/ci-internal.yml b/.vsts-pipelines/builds/ci-internal.yml new file mode 100644 index 0000000000..d7ceb76378 --- /dev/null +++ b/.vsts-pipelines/builds/ci-internal.yml @@ -0,0 +1,13 @@ +trigger: +- dev +- release/* + +resources: + repositories: + - repository: buildtools + type: git + name: aspnet-BuildTools + ref: refs/heads/dev + +phases: +- template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/.vsts-pipelines/builds/ci-public.yml b/.vsts-pipelines/builds/ci-public.yml new file mode 100644 index 0000000000..b7f25723f8 --- /dev/null +++ b/.vsts-pipelines/builds/ci-public.yml @@ -0,0 +1,15 @@ +trigger: +- dev +- release/* + +# See https://github.com/aspnet/BuildTools +resources: + repositories: + - repository: buildtools + type: github + endpoint: DotNet-Bot GitHub Connection + name: aspnet/BuildTools + ref: refs/heads/dev + +phases: +- template: .vsts-pipelines/templates/project-ci.yml@buildtools From 9657ed60e83d82ae0b9d25d704b74064f262aba3 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Thu, 7 Jun 2018 15:45:57 -0700 Subject: [PATCH 0819/1029] Adding VSTS file --- .vsts-pipelines/builds/ci-internal.yml | 13 +++++++++++++ .vsts-pipelines/builds/ci-public.yml | 15 +++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 .vsts-pipelines/builds/ci-internal.yml create mode 100644 .vsts-pipelines/builds/ci-public.yml diff --git a/.vsts-pipelines/builds/ci-internal.yml b/.vsts-pipelines/builds/ci-internal.yml new file mode 100644 index 0000000000..d7ceb76378 --- /dev/null +++ b/.vsts-pipelines/builds/ci-internal.yml @@ -0,0 +1,13 @@ +trigger: +- dev +- release/* + +resources: + repositories: + - repository: buildtools + type: git + name: aspnet-BuildTools + ref: refs/heads/dev + +phases: +- template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/.vsts-pipelines/builds/ci-public.yml b/.vsts-pipelines/builds/ci-public.yml new file mode 100644 index 0000000000..b7f25723f8 --- /dev/null +++ b/.vsts-pipelines/builds/ci-public.yml @@ -0,0 +1,15 @@ +trigger: +- dev +- release/* + +# See https://github.com/aspnet/BuildTools +resources: + repositories: + - repository: buildtools + type: github + endpoint: DotNet-Bot GitHub Connection + name: aspnet/BuildTools + ref: refs/heads/dev + +phases: +- template: .vsts-pipelines/templates/project-ci.yml@buildtools From ee20ecf20e4ac1f2aaffac591580d2fdc6d6f6de Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 12 Jun 2018 19:16:34 +0000 Subject: [PATCH 0820/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 7e572a8f72..4453d8db2a 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.1-rtm-15790 - 2.1.0 + 2.1.1-rtm-15793 + 2.1.1 2.1.0 - 2.1.0 - 2.1.0 - 2.1.0 + 2.1.1 + 2.1.1 + 2.1.1 2.0.0 - 2.1.0 + 2.1.1 15.6.1 2.0.3 - 4.5.0 + 4.5.1 4.5.0 9.0.1 2.3.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index de0eb84cf3..d2f4947bc8 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.1-rtm-15790 -commithash:274c65868e735f29f4078c1884c61c4371ee1fc0 +version:2.1.1-rtm-15793 +commithash:988313f4b064d6c69fc6f7b845b6384a6af3447a From 256f7755bae10204ba6c3b669d2289b7de33308a Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 12 Jun 2018 19:19:58 +0000 Subject: [PATCH 0821/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index a1e264ee96..dc47d2ca18 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,13 +3,13 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.1-rtm-15790 + 2.1.1-rtm-15793 2.1.0 - 2.1.0 - 2.1.0 - 2.1.0 + 2.1.1 + 2.1.1 + 2.1.1 2.0.0 - 2.1.0 + 2.1.1 15.6.1 2.0.3 4.5.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index cd5b409a1e..bc84e0cd53 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.1-rtm-15790 -commithash:274c65868e735f29f4078c1884c61c4371ee1fc0 +version:2.1.1-rtm-15793 +commithash:988313f4b064d6c69fc6f7b845b6384a6af3447a From 1780662ac507c9b21bf7054bc1f68ccd07ed93ff Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 12 Jun 2018 19:25:45 +0000 Subject: [PATCH 0822/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 6 +++--- korebuild-lock.txt | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 5b7c18bdae..c7a3e03395 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.1.1-rtm-15790 + 2.1.1-rtm-15793 2.1.0 4.5.0 - 2.1.0 + 2.1.1 2.0.0 - 2.1.0 + 2.1.1 15.6.1 4.7.49 2.0.3 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index cd5b409a1e..bc84e0cd53 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.1-rtm-15790 -commithash:274c65868e735f29f4078c1884c61c4371ee1fc0 +version:2.1.1-rtm-15793 +commithash:988313f4b064d6c69fc6f7b845b6384a6af3447a From d396d85defb44dbb8032f65f295586016d16e8a2 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Wed, 13 Jun 2018 10:55:16 -0700 Subject: [PATCH 0823/1029] Set 2.1 baselines --- .../baseline.netcore.json | 106 +++++++++--------- .../baseline.netcore.json | 2 +- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/baseline.netcore.json b/src/Microsoft.AspNetCore.Html.Abstractions/baseline.netcore.json index b0b320e216..29f855f97b 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/baseline.netcore.json +++ b/src/Microsoft.AspNetCore.Html.Abstractions/baseline.netcore.json @@ -1,5 +1,5 @@ { - "AssemblyIdentity": "Microsoft.AspNetCore.Html.Abstractions, Version=2.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "AssemblyIdentity": "Microsoft.AspNetCore.Html.Abstractions, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "Types": [ { "Name": "Microsoft.AspNetCore.Html.HtmlContentBuilder", @@ -9,6 +9,58 @@ "Microsoft.AspNetCore.Html.IHtmlContentBuilder" ], "Members": [ + { + "Kind": "Method", + "Name": "CopyTo", + "Parameters": [ + { + "Name": "destination", + "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContentContainer", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "MoveTo", + "Parameters": [ + { + "Name": "destination", + "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContentContainer", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "WriteTo", + "Parameters": [ + { + "Name": "writer", + "Type": "System.IO.TextWriter" + }, + { + "Name": "encoder", + "Type": "System.Text.Encodings.Web.HtmlEncoder" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContent", + "Visibility": "Public", + "GenericParameter": [] + }, { "Kind": "Method", "Name": "get_Count", @@ -76,58 +128,6 @@ "Visibility": "Public", "GenericParameter": [] }, - { - "Kind": "Method", - "Name": "CopyTo", - "Parameters": [ - { - "Name": "destination", - "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" - } - ], - "ReturnType": "System.Void", - "Sealed": true, - "Virtual": true, - "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContentContainer", - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "MoveTo", - "Parameters": [ - { - "Name": "destination", - "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" - } - ], - "ReturnType": "System.Void", - "Sealed": true, - "Virtual": true, - "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContentContainer", - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "WriteTo", - "Parameters": [ - { - "Name": "writer", - "Type": "System.IO.TextWriter" - }, - { - "Name": "encoder", - "Type": "System.Text.Encodings.Web.HtmlEncoder" - } - ], - "ReturnType": "System.Void", - "Sealed": true, - "Virtual": true, - "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContent", - "Visibility": "Public", - "GenericParameter": [] - }, { "Kind": "Constructor", "Name": ".ctor", diff --git a/src/Microsoft.Extensions.WebEncoders/baseline.netcore.json b/src/Microsoft.Extensions.WebEncoders/baseline.netcore.json index cc93cc7458..6da0ae0754 100644 --- a/src/Microsoft.Extensions.WebEncoders/baseline.netcore.json +++ b/src/Microsoft.Extensions.WebEncoders/baseline.netcore.json @@ -1,5 +1,5 @@ { - "AssemblyIdentity": "Microsoft.Extensions.WebEncoders, Version=2.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "AssemblyIdentity": "Microsoft.Extensions.WebEncoders, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "Types": [ { "Name": "Microsoft.Extensions.WebEncoders.WebEncoderOptions", From b7c722bb68233b28475748c3c6fdabb63b854205 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Wed, 13 Jun 2018 10:55:16 -0700 Subject: [PATCH 0824/1029] Set 2.1 baselines --- .../baseline.netcore.json | 106 +++++++++--------- .../baseline.netcore.json | 2 +- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/baseline.netcore.json b/src/Microsoft.AspNetCore.Html.Abstractions/baseline.netcore.json index b0b320e216..29f855f97b 100644 --- a/src/Microsoft.AspNetCore.Html.Abstractions/baseline.netcore.json +++ b/src/Microsoft.AspNetCore.Html.Abstractions/baseline.netcore.json @@ -1,5 +1,5 @@ { - "AssemblyIdentity": "Microsoft.AspNetCore.Html.Abstractions, Version=2.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "AssemblyIdentity": "Microsoft.AspNetCore.Html.Abstractions, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "Types": [ { "Name": "Microsoft.AspNetCore.Html.HtmlContentBuilder", @@ -9,6 +9,58 @@ "Microsoft.AspNetCore.Html.IHtmlContentBuilder" ], "Members": [ + { + "Kind": "Method", + "Name": "CopyTo", + "Parameters": [ + { + "Name": "destination", + "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContentContainer", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "MoveTo", + "Parameters": [ + { + "Name": "destination", + "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContentContainer", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "WriteTo", + "Parameters": [ + { + "Name": "writer", + "Type": "System.IO.TextWriter" + }, + { + "Name": "encoder", + "Type": "System.Text.Encodings.Web.HtmlEncoder" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContent", + "Visibility": "Public", + "GenericParameter": [] + }, { "Kind": "Method", "Name": "get_Count", @@ -76,58 +128,6 @@ "Visibility": "Public", "GenericParameter": [] }, - { - "Kind": "Method", - "Name": "CopyTo", - "Parameters": [ - { - "Name": "destination", - "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" - } - ], - "ReturnType": "System.Void", - "Sealed": true, - "Virtual": true, - "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContentContainer", - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "MoveTo", - "Parameters": [ - { - "Name": "destination", - "Type": "Microsoft.AspNetCore.Html.IHtmlContentBuilder" - } - ], - "ReturnType": "System.Void", - "Sealed": true, - "Virtual": true, - "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContentContainer", - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "WriteTo", - "Parameters": [ - { - "Name": "writer", - "Type": "System.IO.TextWriter" - }, - { - "Name": "encoder", - "Type": "System.Text.Encodings.Web.HtmlEncoder" - } - ], - "ReturnType": "System.Void", - "Sealed": true, - "Virtual": true, - "ImplementedInterface": "Microsoft.AspNetCore.Html.IHtmlContent", - "Visibility": "Public", - "GenericParameter": [] - }, { "Kind": "Constructor", "Name": ".ctor", diff --git a/src/Microsoft.Extensions.WebEncoders/baseline.netcore.json b/src/Microsoft.Extensions.WebEncoders/baseline.netcore.json index cc93cc7458..6da0ae0754 100644 --- a/src/Microsoft.Extensions.WebEncoders/baseline.netcore.json +++ b/src/Microsoft.Extensions.WebEncoders/baseline.netcore.json @@ -1,5 +1,5 @@ { - "AssemblyIdentity": "Microsoft.Extensions.WebEncoders, Version=2.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "AssemblyIdentity": "Microsoft.Extensions.WebEncoders, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "Types": [ { "Name": "Microsoft.Extensions.WebEncoders.WebEncoderOptions", From 78fc55675861ee33f102bd601ac951eff9bdbad3 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Thu, 14 Jun 2018 10:28:12 -0700 Subject: [PATCH 0825/1029] Set 2.1 baselines --- .../baseline.netcore.json | 315 +++++++++++++----- 1 file changed, 230 insertions(+), 85 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/baseline.netcore.json b/src/Microsoft.AspNetCore.JsonPatch/baseline.netcore.json index c84771a03c..3d90a8f017 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/baseline.netcore.json +++ b/src/Microsoft.AspNetCore.JsonPatch/baseline.netcore.json @@ -1,6 +1,73 @@ { - "AssemblyIdentity": "Microsoft.AspNetCore.JsonPatch, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "AssemblyIdentity": "Microsoft.AspNetCore.JsonPatch, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "Types": [ + { + "Name": "Microsoft.AspNetCore.JsonPatch.JsonPatchProperty", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_Property", + "Parameters": [], + "ReturnType": "Newtonsoft.Json.Serialization.JsonProperty", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Property", + "Parameters": [ + { + "Name": "value", + "Type": "Newtonsoft.Json.Serialization.JsonProperty" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Parent", + "Parameters": [], + "ReturnType": "System.Object", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Parent", + "Parameters": [ + { + "Name": "value", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "property", + "Type": "Newtonsoft.Json.Serialization.JsonProperty" + }, + { + "Name": "parent", + "Type": "System.Object" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, { "Name": "Microsoft.AspNetCore.JsonPatch.IJsonPatchDocument", "Visibility": "Public", @@ -127,6 +194,23 @@ "Visibility": "Public", "GenericParameter": [] }, + { + "Kind": "Method", + "Name": "Test", + "Parameters": [ + { + "Name": "path", + "Type": "System.String" + }, + { + "Name": "value", + "Type": "System.Object" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [] + }, { "Kind": "Method", "Name": "Move", @@ -484,6 +568,79 @@ } ] }, + { + "Kind": "Method", + "Name": "Test", + "Parameters": [ + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>" + }, + { + "Name": "value", + "Type": "T0" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Test", + "Parameters": [ + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>>" + }, + { + "Name": "value", + "Type": "T0" + }, + { + "Name": "position", + "Type": "System.Int32" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Test", + "Parameters": [ + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>>" + }, + { + "Name": "value", + "Type": "T0" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, { "Kind": "Method", "Name": "Move", @@ -933,73 +1090,6 @@ ], "GenericParameters": [] }, - { - "Name": "Microsoft.AspNetCore.JsonPatch.JsonPatchProperty", - "Visibility": "Public", - "Kind": "Class", - "ImplementedInterfaces": [], - "Members": [ - { - "Kind": "Method", - "Name": "get_Property", - "Parameters": [], - "ReturnType": "Newtonsoft.Json.Serialization.JsonProperty", - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "set_Property", - "Parameters": [ - { - "Name": "value", - "Type": "Newtonsoft.Json.Serialization.JsonProperty" - } - ], - "ReturnType": "System.Void", - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "get_Parent", - "Parameters": [], - "ReturnType": "System.Object", - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "set_Parent", - "Parameters": [ - { - "Name": "value", - "Type": "System.Object" - } - ], - "ReturnType": "System.Void", - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Constructor", - "Name": ".ctor", - "Parameters": [ - { - "Name": "property", - "Type": "Newtonsoft.Json.Serialization.JsonProperty" - }, - { - "Name": "parent", - "Type": "System.Object" - } - ], - "Visibility": "Public", - "GenericParameter": [] - } - ], - "GenericParameters": [] - }, { "Name": "Microsoft.AspNetCore.JsonPatch.Operations.Operation", "Visibility": "Public", @@ -1355,6 +1445,13 @@ "Parameters": [], "GenericParameter": [], "Literal": "5" + }, + { + "Kind": "Field", + "Name": "Invalid", + "Parameters": [], + "GenericParameter": [], + "Literal": "6" } ], "GenericParameters": [] @@ -1694,29 +1791,41 @@ "GenericParameters": [] }, { - "Name": "Microsoft.AspNetCore.JsonPatch.Adapters.ObjectAdapter", + "Name": "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapterWithTest", "Visibility": "Public", - "Kind": "Class", + "Kind": "Interface", + "Abstract": true, "ImplementedInterfaces": [ "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapter" ], "Members": [ { "Kind": "Method", - "Name": "get_ContractResolver", - "Parameters": [], - "ReturnType": "Newtonsoft.Json.Serialization.IContractResolver", - "Visibility": "Public", + "Name": "Test", + "Parameters": [ + { + "Name": "operation", + "Type": "Microsoft.AspNetCore.JsonPatch.Operations.Operation" + }, + { + "Name": "objectToApplyTo", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "get_LogErrorAction", - "Parameters": [], - "ReturnType": "System.Action", - "Visibility": "Public", - "GenericParameter": [] - }, + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.JsonPatch.Adapters.ObjectAdapter", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapterWithTest" + ], + "Members": [ { "Kind": "Method", "Name": "Add", @@ -1737,6 +1846,26 @@ "Visibility": "Public", "GenericParameter": [] }, + { + "Kind": "Method", + "Name": "Copy", + "Parameters": [ + { + "Name": "operation", + "Type": "Microsoft.AspNetCore.JsonPatch.Operations.Operation" + }, + { + "Name": "objectToApplyTo", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapter", + "Visibility": "Public", + "GenericParameter": [] + }, { "Kind": "Method", "Name": "Move", @@ -1799,7 +1928,23 @@ }, { "Kind": "Method", - "Name": "Copy", + "Name": "get_ContractResolver", + "Parameters": [], + "ReturnType": "Newtonsoft.Json.Serialization.IContractResolver", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_LogErrorAction", + "Parameters": [], + "ReturnType": "System.Action", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Test", "Parameters": [ { "Name": "operation", @@ -1813,7 +1958,7 @@ "ReturnType": "System.Void", "Sealed": true, "Virtual": true, - "ImplementedInterface": "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapter", + "ImplementedInterface": "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapterWithTest", "Visibility": "Public", "GenericParameter": [] }, From b59f5dd8d4a90cc3de50b5abb8342442212cd2d3 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Thu, 14 Jun 2018 10:28:12 -0700 Subject: [PATCH 0826/1029] Set 2.1 baselines --- .../baseline.netcore.json | 315 +++++++++++++----- 1 file changed, 230 insertions(+), 85 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/baseline.netcore.json b/src/Microsoft.AspNetCore.JsonPatch/baseline.netcore.json index c84771a03c..3d90a8f017 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/baseline.netcore.json +++ b/src/Microsoft.AspNetCore.JsonPatch/baseline.netcore.json @@ -1,6 +1,73 @@ { - "AssemblyIdentity": "Microsoft.AspNetCore.JsonPatch, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "AssemblyIdentity": "Microsoft.AspNetCore.JsonPatch, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "Types": [ + { + "Name": "Microsoft.AspNetCore.JsonPatch.JsonPatchProperty", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_Property", + "Parameters": [], + "ReturnType": "Newtonsoft.Json.Serialization.JsonProperty", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Property", + "Parameters": [ + { + "Name": "value", + "Type": "Newtonsoft.Json.Serialization.JsonProperty" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Parent", + "Parameters": [], + "ReturnType": "System.Object", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Parent", + "Parameters": [ + { + "Name": "value", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "property", + "Type": "Newtonsoft.Json.Serialization.JsonProperty" + }, + { + "Name": "parent", + "Type": "System.Object" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, { "Name": "Microsoft.AspNetCore.JsonPatch.IJsonPatchDocument", "Visibility": "Public", @@ -127,6 +194,23 @@ "Visibility": "Public", "GenericParameter": [] }, + { + "Kind": "Method", + "Name": "Test", + "Parameters": [ + { + "Name": "path", + "Type": "System.String" + }, + { + "Name": "value", + "Type": "System.Object" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [] + }, { "Kind": "Method", "Name": "Move", @@ -484,6 +568,79 @@ } ] }, + { + "Kind": "Method", + "Name": "Test", + "Parameters": [ + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>" + }, + { + "Name": "value", + "Type": "T0" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Test", + "Parameters": [ + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>>" + }, + { + "Name": "value", + "Type": "T0" + }, + { + "Name": "position", + "Type": "System.Int32" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, + { + "Kind": "Method", + "Name": "Test", + "Parameters": [ + { + "Name": "path", + "Type": "System.Linq.Expressions.Expression>>" + }, + { + "Name": "value", + "Type": "T0" + } + ], + "ReturnType": "Microsoft.AspNetCore.JsonPatch.JsonPatchDocument", + "Visibility": "Public", + "GenericParameter": [ + { + "ParameterName": "TProp", + "ParameterPosition": 0, + "BaseTypeOrInterfaces": [] + } + ] + }, { "Kind": "Method", "Name": "Move", @@ -933,73 +1090,6 @@ ], "GenericParameters": [] }, - { - "Name": "Microsoft.AspNetCore.JsonPatch.JsonPatchProperty", - "Visibility": "Public", - "Kind": "Class", - "ImplementedInterfaces": [], - "Members": [ - { - "Kind": "Method", - "Name": "get_Property", - "Parameters": [], - "ReturnType": "Newtonsoft.Json.Serialization.JsonProperty", - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "set_Property", - "Parameters": [ - { - "Name": "value", - "Type": "Newtonsoft.Json.Serialization.JsonProperty" - } - ], - "ReturnType": "System.Void", - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "get_Parent", - "Parameters": [], - "ReturnType": "System.Object", - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "set_Parent", - "Parameters": [ - { - "Name": "value", - "Type": "System.Object" - } - ], - "ReturnType": "System.Void", - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Constructor", - "Name": ".ctor", - "Parameters": [ - { - "Name": "property", - "Type": "Newtonsoft.Json.Serialization.JsonProperty" - }, - { - "Name": "parent", - "Type": "System.Object" - } - ], - "Visibility": "Public", - "GenericParameter": [] - } - ], - "GenericParameters": [] - }, { "Name": "Microsoft.AspNetCore.JsonPatch.Operations.Operation", "Visibility": "Public", @@ -1355,6 +1445,13 @@ "Parameters": [], "GenericParameter": [], "Literal": "5" + }, + { + "Kind": "Field", + "Name": "Invalid", + "Parameters": [], + "GenericParameter": [], + "Literal": "6" } ], "GenericParameters": [] @@ -1694,29 +1791,41 @@ "GenericParameters": [] }, { - "Name": "Microsoft.AspNetCore.JsonPatch.Adapters.ObjectAdapter", + "Name": "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapterWithTest", "Visibility": "Public", - "Kind": "Class", + "Kind": "Interface", + "Abstract": true, "ImplementedInterfaces": [ "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapter" ], "Members": [ { "Kind": "Method", - "Name": "get_ContractResolver", - "Parameters": [], - "ReturnType": "Newtonsoft.Json.Serialization.IContractResolver", - "Visibility": "Public", + "Name": "Test", + "Parameters": [ + { + "Name": "operation", + "Type": "Microsoft.AspNetCore.JsonPatch.Operations.Operation" + }, + { + "Name": "objectToApplyTo", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "get_LogErrorAction", - "Parameters": [], - "ReturnType": "System.Action", - "Visibility": "Public", - "GenericParameter": [] - }, + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.JsonPatch.Adapters.ObjectAdapter", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapterWithTest" + ], + "Members": [ { "Kind": "Method", "Name": "Add", @@ -1737,6 +1846,26 @@ "Visibility": "Public", "GenericParameter": [] }, + { + "Kind": "Method", + "Name": "Copy", + "Parameters": [ + { + "Name": "operation", + "Type": "Microsoft.AspNetCore.JsonPatch.Operations.Operation" + }, + { + "Name": "objectToApplyTo", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapter", + "Visibility": "Public", + "GenericParameter": [] + }, { "Kind": "Method", "Name": "Move", @@ -1799,7 +1928,23 @@ }, { "Kind": "Method", - "Name": "Copy", + "Name": "get_ContractResolver", + "Parameters": [], + "ReturnType": "Newtonsoft.Json.Serialization.IContractResolver", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_LogErrorAction", + "Parameters": [], + "ReturnType": "System.Action", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Test", "Parameters": [ { "Name": "operation", @@ -1813,7 +1958,7 @@ "ReturnType": "System.Void", "Sealed": true, "Virtual": true, - "ImplementedInterface": "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapter", + "ImplementedInterface": "Microsoft.AspNetCore.JsonPatch.Adapters.IObjectAdapterWithTest", "Visibility": "Public", "GenericParameter": [] }, From b882d9727751f58435368444270495838f236060 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Mon, 25 Jun 2018 11:11:57 -0700 Subject: [PATCH 0827/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 0b26eb5044..cc06d1b63b 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,19 +3,19 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17081 - 2.2.0-preview1-34411 - 2.2.0-preview1-34411 - 2.2.0-preview1-34411 - 2.2.0-preview1-34411 - 2.2.0-preview1-34411 + 2.2.0-preview1-17090 + 2.2.0-preview1-34530 + 2.2.0-preview1-34530 + 2.2.0-preview1-34530 + 2.2.0-preview1-34530 + 2.2.0-preview1-34530 2.0.0 2.1.0 - 2.2.0-preview1-26606-01 + 2.2.0-preview1-26618-02 15.6.1 2.0.3 - 4.6.0-preview1-26605-01 - 4.6.0-preview1-26605-01 + 4.6.0-preview1-26617-01 + 4.6.0-preview1-26617-01 9.0.1 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 9592880b2a..3e694b2ed8 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17081 -commithash:73f09c256e2a54270951562ecc0ef4a953926c36 +version:2.2.0-preview1-17090 +commithash:b19e903e946579cd9482089bce7d917e8bacd765 From fdf97c547ed8a38118fd5866ebd42b4aff609579 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Mon, 25 Jun 2018 11:15:22 -0700 Subject: [PATCH 0828/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index b793716276..e3fbf6767d 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17081 - 2.2.0-preview1-34411 - 2.2.0-preview1-34411 - 2.2.0-preview1-34411 - 2.2.0-preview1-34411 + 2.2.0-preview1-17090 + 2.2.0-preview1-34530 + 2.2.0-preview1-34530 + 2.2.0-preview1-34530 + 2.2.0-preview1-34530 2.0.0 2.1.0 - 2.2.0-preview1-26606-01 + 2.2.0-preview1-26618-02 15.6.1 2.0.3 - 4.6.0-preview1-26605-01 + 4.6.0-preview1-26617-01 2.3.1 2.4.0-beta.1.build3945 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index deb7e546f0..a8109db529 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17081 -commithash:73f09c256e2a54270951562ecc0ef4a953926c36 +version:2.2.0-preview1-17090 +commithash:b19e903e946579cd9482089bce7d917e8bacd765 From a3ff5cfef7e02edf8b7ab05b437dfa4918669b3d Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Mon, 25 Jun 2018 11:20:42 -0700 Subject: [PATCH 0829/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 15ef04fe4b..3474d55494 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,13 +3,13 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17081 - 2.2.0-preview1-34411 - 4.6.0-preview1-26605-01 - 2.2.0-preview1-34411 + 2.2.0-preview1-17090 + 2.2.0-preview1-34530 + 4.6.0-preview1-26617-01 + 2.2.0-preview1-34530 2.0.0 2.1.0 - 2.2.0-preview1-26606-01 + 2.2.0-preview1-26618-02 15.6.1 4.7.49 2.0.3 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index deb7e546f0..a8109db529 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17081 -commithash:73f09c256e2a54270951562ecc0ef4a953926c36 +version:2.2.0-preview1-17090 +commithash:b19e903e946579cd9482089bce7d917e8bacd765 From 4d3886fa378e61ccc21e8b8adb5e1666de0ecb40 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 27 Jun 2018 13:39:45 -0700 Subject: [PATCH 0830/1029] Bumping version from 2.1.1 to 2.1.2 --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 4078cfc422..71841a8512 100644 --- a/version.props +++ b/version.props @@ -1,6 +1,6 @@  - 2.1.1 + 2.1.2 15.6 rtm $(VersionPrefix) From 47c5edd37aad2a12d14c9dea8cfb22ef48ddb005 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 27 Jun 2018 13:39:46 -0700 Subject: [PATCH 0831/1029] Bumping version from 2.1.1 to 2.1.2 --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 669c874829..478dfd16ed 100644 --- a/version.props +++ b/version.props @@ -1,6 +1,6 @@  - 2.1.1 + 2.1.2 rtm $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final From 5d39e86f1985d99d0c530e312d5b478ddc8682a4 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 27 Jun 2018 13:39:48 -0700 Subject: [PATCH 0832/1029] Bumping version from 2.1.1 to 2.1.2 --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 669c874829..478dfd16ed 100644 --- a/version.props +++ b/version.props @@ -1,6 +1,6 @@  - 2.1.1 + 2.1.2 rtm $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final From 3177be42f50495aa2295ddbe28a4b52163c8bc01 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 28 Jun 2018 16:19:32 -0700 Subject: [PATCH 0833/1029] Update infrastructure for the 2.2 release --- .vsts-pipelines/builds/ci-internal.yml | 4 ++-- .vsts-pipelines/builds/ci-public.yml | 6 +++--- build/repo.props | 1 + korebuild.json | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.vsts-pipelines/builds/ci-internal.yml b/.vsts-pipelines/builds/ci-internal.yml index d7ceb76378..dc7b8a3cb9 100644 --- a/.vsts-pipelines/builds/ci-internal.yml +++ b/.vsts-pipelines/builds/ci-internal.yml @@ -1,5 +1,5 @@ trigger: -- dev +- master - release/* resources: @@ -7,7 +7,7 @@ resources: - repository: buildtools type: git name: aspnet-BuildTools - ref: refs/heads/dev + ref: refs/heads/release/2.2 phases: - template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/.vsts-pipelines/builds/ci-public.yml b/.vsts-pipelines/builds/ci-public.yml index b7f25723f8..f5087d9c30 100644 --- a/.vsts-pipelines/builds/ci-public.yml +++ b/.vsts-pipelines/builds/ci-public.yml @@ -1,5 +1,5 @@ trigger: -- dev +- master - release/* # See https://github.com/aspnet/BuildTools @@ -9,7 +9,7 @@ resources: type: github endpoint: DotNet-Bot GitHub Connection name: aspnet/BuildTools - ref: refs/heads/dev - + ref: refs/heads/release/2.2 + phases: - template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/build/repo.props b/build/repo.props index 9569f0ba08..2108954d7e 100644 --- a/build/repo.props +++ b/build/repo.props @@ -8,6 +8,7 @@ Internal.AspNetCore.Universe.Lineup + 2.2.0-* https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json diff --git a/korebuild.json b/korebuild.json index 4d59ad132a..7002d25ca1 100644 --- a/korebuild.json +++ b/korebuild.json @@ -1,6 +1,6 @@ { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev", + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.2/tools/korebuild.schema.json", + "channel": "release/2.2", "toolsets": { "visualstudio": { "required": [ From 2d659e53829c4fab0a03fed934b5fedc2ce39c79 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 28 Jun 2018 16:19:54 -0700 Subject: [PATCH 0834/1029] Update infrastructure for the 2.2 release --- .vsts-pipelines/builds/ci-internal.yml | 4 ++-- .vsts-pipelines/builds/ci-public.yml | 6 +++--- build/repo.props | 1 + korebuild.json | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.vsts-pipelines/builds/ci-internal.yml b/.vsts-pipelines/builds/ci-internal.yml index d7ceb76378..dc7b8a3cb9 100644 --- a/.vsts-pipelines/builds/ci-internal.yml +++ b/.vsts-pipelines/builds/ci-internal.yml @@ -1,5 +1,5 @@ trigger: -- dev +- master - release/* resources: @@ -7,7 +7,7 @@ resources: - repository: buildtools type: git name: aspnet-BuildTools - ref: refs/heads/dev + ref: refs/heads/release/2.2 phases: - template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/.vsts-pipelines/builds/ci-public.yml b/.vsts-pipelines/builds/ci-public.yml index b7f25723f8..f5087d9c30 100644 --- a/.vsts-pipelines/builds/ci-public.yml +++ b/.vsts-pipelines/builds/ci-public.yml @@ -1,5 +1,5 @@ trigger: -- dev +- master - release/* # See https://github.com/aspnet/BuildTools @@ -9,7 +9,7 @@ resources: type: github endpoint: DotNet-Bot GitHub Connection name: aspnet/BuildTools - ref: refs/heads/dev - + ref: refs/heads/release/2.2 + phases: - template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/build/repo.props b/build/repo.props index 17a98ac7e7..f1fe24dd27 100644 --- a/build/repo.props +++ b/build/repo.props @@ -4,6 +4,7 @@ Internal.AspNetCore.Universe.Lineup + 2.2.0-* https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json diff --git a/korebuild.json b/korebuild.json index bd5d51a51b..d217d06e3e 100644 --- a/korebuild.json +++ b/korebuild.json @@ -1,4 +1,4 @@ { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev" + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.2/tools/korebuild.schema.json", + "channel": "release/2.2" } From 2c1b6f9e8dec7f071a9d61f490d4edd639746688 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 28 Jun 2018 16:20:31 -0700 Subject: [PATCH 0835/1029] Update infrastructure for the 2.2 release --- .vsts-pipelines/builds/ci-internal.yml | 4 ++-- .vsts-pipelines/builds/ci-public.yml | 6 +++--- build/repo.props | 1 + korebuild.json | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.vsts-pipelines/builds/ci-internal.yml b/.vsts-pipelines/builds/ci-internal.yml index d7ceb76378..dc7b8a3cb9 100644 --- a/.vsts-pipelines/builds/ci-internal.yml +++ b/.vsts-pipelines/builds/ci-internal.yml @@ -1,5 +1,5 @@ trigger: -- dev +- master - release/* resources: @@ -7,7 +7,7 @@ resources: - repository: buildtools type: git name: aspnet-BuildTools - ref: refs/heads/dev + ref: refs/heads/release/2.2 phases: - template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/.vsts-pipelines/builds/ci-public.yml b/.vsts-pipelines/builds/ci-public.yml index b7f25723f8..f5087d9c30 100644 --- a/.vsts-pipelines/builds/ci-public.yml +++ b/.vsts-pipelines/builds/ci-public.yml @@ -1,5 +1,5 @@ trigger: -- dev +- master - release/* # See https://github.com/aspnet/BuildTools @@ -9,7 +9,7 @@ resources: type: github endpoint: DotNet-Bot GitHub Connection name: aspnet/BuildTools - ref: refs/heads/dev - + ref: refs/heads/release/2.2 + phases: - template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/build/repo.props b/build/repo.props index 17a98ac7e7..f1fe24dd27 100644 --- a/build/repo.props +++ b/build/repo.props @@ -4,6 +4,7 @@ Internal.AspNetCore.Universe.Lineup + 2.2.0-* https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json diff --git a/korebuild.json b/korebuild.json index bd5d51a51b..d217d06e3e 100644 --- a/korebuild.json +++ b/korebuild.json @@ -1,4 +1,4 @@ { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev" + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.2/tools/korebuild.schema.json", + "channel": "release/2.2" } From 6a2f83f2830a91520db647623ca8859bc7ce10e7 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 28 Jun 2018 16:48:47 -0700 Subject: [PATCH 0836/1029] Bumping version from 2.2.0 to 3.0.0 --- version.props | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/version.props b/version.props index 4c749bb5d2..0b4b9416cf 100644 --- a/version.props +++ b/version.props @@ -1,8 +1,8 @@ - + - 2.2.0 + 3.0.0 15.6 - preview1 + alpha1 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final $(VsixVersion).$(BuildNumber) From 94cbc0cccba5b880caa80b3d9adf6c10edbf7f83 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 28 Jun 2018 16:48:50 -0700 Subject: [PATCH 0837/1029] Bumping version from 2.2.0 to 3.0.0 --- version.props | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/version.props b/version.props index 44985cedb3..71a78cddd8 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ - + - 2.2.0 - preview1 + 3.0.0 + alpha1 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From ec8a21cc560fe6458efaf1edbfd259d3d4c58a3b Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 28 Jun 2018 16:48:53 -0700 Subject: [PATCH 0838/1029] Bumping version from 2.2.0 to 3.0.0 --- version.props | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/version.props b/version.props index 44985cedb3..71a78cddd8 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ - + - 2.2.0 - preview1 + 3.0.0 + alpha1 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From 90c00988bfd586acef4c9309609d046b3f897871 Mon Sep 17 00:00:00 2001 From: "Nate McMaster (automated)" Date: Mon, 2 Jul 2018 12:40:18 -0700 Subject: [PATCH 0839/1029] [automated] Change default branch to master --- .appveyor.yml | 2 +- .travis.yml | 2 +- .vsts-pipelines/builds/ci-internal.yml | 4 ++-- .vsts-pipelines/builds/ci-public.yml | 6 +++--- korebuild.json | 4 ++-- run.ps1 | 6 +++--- run.sh | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 4eea96ab69..d45bd5a1f8 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -2,7 +2,7 @@ init: - git config --global core.autocrlf true branches: only: - - dev + - master - /^release\/.*$/ - /^(.*\/)?ci-.*$/ build_script: diff --git a/.travis.yml b/.travis.yml index 64bdbb4441..ab3980055c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ addons: - libunwind8 branches: only: - - dev + - master - /^release\/.*$/ - /^(.*\/)?ci-.*$/ before_install: diff --git a/.vsts-pipelines/builds/ci-internal.yml b/.vsts-pipelines/builds/ci-internal.yml index d7ceb76378..c2c5336fd0 100644 --- a/.vsts-pipelines/builds/ci-internal.yml +++ b/.vsts-pipelines/builds/ci-internal.yml @@ -1,5 +1,5 @@ trigger: -- dev +- master - release/* resources: @@ -7,7 +7,7 @@ resources: - repository: buildtools type: git name: aspnet-BuildTools - ref: refs/heads/dev + ref: refs/heads/master phases: - template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/.vsts-pipelines/builds/ci-public.yml b/.vsts-pipelines/builds/ci-public.yml index b7f25723f8..507c89b025 100644 --- a/.vsts-pipelines/builds/ci-public.yml +++ b/.vsts-pipelines/builds/ci-public.yml @@ -1,5 +1,5 @@ trigger: -- dev +- master - release/* # See https://github.com/aspnet/BuildTools @@ -9,7 +9,7 @@ resources: type: github endpoint: DotNet-Bot GitHub Connection name: aspnet/BuildTools - ref: refs/heads/dev - + ref: refs/heads/master + phases: - template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/korebuild.json b/korebuild.json index 4d59ad132a..1d75d9ef89 100644 --- a/korebuild.json +++ b/korebuild.json @@ -1,6 +1,6 @@ { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev", + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", + "channel": "master", "toolsets": { "visualstudio": { "required": [ diff --git a/run.ps1 b/run.ps1 index 3b27382468..34604c7175 100644 --- a/run.ps1 +++ b/run.ps1 @@ -52,8 +52,8 @@ in the file are overridden by command line parameters. Example config file: ```json { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev", + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", + "channel": "master", "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" } ``` @@ -192,7 +192,7 @@ if (!$DotNetHome) { else { Join-Path $PSScriptRoot '.dotnet'} } -if (!$Channel) { $Channel = 'dev' } +if (!$Channel) { $Channel = 'master' } if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } # Execute diff --git a/run.sh b/run.sh index 02aac15874..61f7a53385 100755 --- a/run.sh +++ b/run.sh @@ -248,7 +248,7 @@ if [ -f "$config_file" ]; then [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" fi -[ -z "$channel" ] && channel='dev' +[ -z "$channel" ] && channel='master' [ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' get_korebuild From 163441fd8de1e7a5662ad1ad6c853521b354f158 Mon Sep 17 00:00:00 2001 From: "Nate McMaster (automated)" Date: Mon, 2 Jul 2018 12:40:21 -0700 Subject: [PATCH 0840/1029] [automated] Change default branch to master --- .appveyor.yml | 2 +- .travis.yml | 2 +- .vsts-pipelines/builds/ci-internal.yml | 4 ++-- .vsts-pipelines/builds/ci-public.yml | 6 +++--- korebuild.json | 4 ++-- run.ps1 | 6 +++--- run.sh | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 4eea96ab69..d45bd5a1f8 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -2,7 +2,7 @@ init: - git config --global core.autocrlf true branches: only: - - dev + - master - /^release\/.*$/ - /^(.*\/)?ci-.*$/ build_script: diff --git a/.travis.yml b/.travis.yml index 64bdbb4441..ab3980055c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ addons: - libunwind8 branches: only: - - dev + - master - /^release\/.*$/ - /^(.*\/)?ci-.*$/ before_install: diff --git a/.vsts-pipelines/builds/ci-internal.yml b/.vsts-pipelines/builds/ci-internal.yml index d7ceb76378..c2c5336fd0 100644 --- a/.vsts-pipelines/builds/ci-internal.yml +++ b/.vsts-pipelines/builds/ci-internal.yml @@ -1,5 +1,5 @@ trigger: -- dev +- master - release/* resources: @@ -7,7 +7,7 @@ resources: - repository: buildtools type: git name: aspnet-BuildTools - ref: refs/heads/dev + ref: refs/heads/master phases: - template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/.vsts-pipelines/builds/ci-public.yml b/.vsts-pipelines/builds/ci-public.yml index b7f25723f8..507c89b025 100644 --- a/.vsts-pipelines/builds/ci-public.yml +++ b/.vsts-pipelines/builds/ci-public.yml @@ -1,5 +1,5 @@ trigger: -- dev +- master - release/* # See https://github.com/aspnet/BuildTools @@ -9,7 +9,7 @@ resources: type: github endpoint: DotNet-Bot GitHub Connection name: aspnet/BuildTools - ref: refs/heads/dev - + ref: refs/heads/master + phases: - template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/korebuild.json b/korebuild.json index bd5d51a51b..8a276a7f35 100644 --- a/korebuild.json +++ b/korebuild.json @@ -1,4 +1,4 @@ { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev" + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", + "channel": "master" } diff --git a/run.ps1 b/run.ps1 index 3b27382468..34604c7175 100644 --- a/run.ps1 +++ b/run.ps1 @@ -52,8 +52,8 @@ in the file are overridden by command line parameters. Example config file: ```json { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev", + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", + "channel": "master", "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" } ``` @@ -192,7 +192,7 @@ if (!$DotNetHome) { else { Join-Path $PSScriptRoot '.dotnet'} } -if (!$Channel) { $Channel = 'dev' } +if (!$Channel) { $Channel = 'master' } if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } # Execute diff --git a/run.sh b/run.sh index 02aac15874..61f7a53385 100755 --- a/run.sh +++ b/run.sh @@ -248,7 +248,7 @@ if [ -f "$config_file" ]; then [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" fi -[ -z "$channel" ] && channel='dev' +[ -z "$channel" ] && channel='master' [ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' get_korebuild From a487da3863c6561afd3bc5cc5c21f67bfbb5a58c Mon Sep 17 00:00:00 2001 From: "Nate McMaster (automated)" Date: Mon, 2 Jul 2018 12:40:25 -0700 Subject: [PATCH 0841/1029] [automated] Change default branch to master --- .appveyor.yml | 2 +- .travis.yml | 2 +- .vsts-pipelines/builds/ci-internal.yml | 4 ++-- .vsts-pipelines/builds/ci-public.yml | 6 +++--- korebuild.json | 4 ++-- run.ps1 | 6 +++--- run.sh | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 4eea96ab69..d45bd5a1f8 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -2,7 +2,7 @@ init: - git config --global core.autocrlf true branches: only: - - dev + - master - /^release\/.*$/ - /^(.*\/)?ci-.*$/ build_script: diff --git a/.travis.yml b/.travis.yml index 64bdbb4441..ab3980055c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ addons: - libunwind8 branches: only: - - dev + - master - /^release\/.*$/ - /^(.*\/)?ci-.*$/ before_install: diff --git a/.vsts-pipelines/builds/ci-internal.yml b/.vsts-pipelines/builds/ci-internal.yml index d7ceb76378..c2c5336fd0 100644 --- a/.vsts-pipelines/builds/ci-internal.yml +++ b/.vsts-pipelines/builds/ci-internal.yml @@ -1,5 +1,5 @@ trigger: -- dev +- master - release/* resources: @@ -7,7 +7,7 @@ resources: - repository: buildtools type: git name: aspnet-BuildTools - ref: refs/heads/dev + ref: refs/heads/master phases: - template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/.vsts-pipelines/builds/ci-public.yml b/.vsts-pipelines/builds/ci-public.yml index b7f25723f8..507c89b025 100644 --- a/.vsts-pipelines/builds/ci-public.yml +++ b/.vsts-pipelines/builds/ci-public.yml @@ -1,5 +1,5 @@ trigger: -- dev +- master - release/* # See https://github.com/aspnet/BuildTools @@ -9,7 +9,7 @@ resources: type: github endpoint: DotNet-Bot GitHub Connection name: aspnet/BuildTools - ref: refs/heads/dev - + ref: refs/heads/master + phases: - template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/korebuild.json b/korebuild.json index bd5d51a51b..8a276a7f35 100644 --- a/korebuild.json +++ b/korebuild.json @@ -1,4 +1,4 @@ { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev" + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", + "channel": "master" } diff --git a/run.ps1 b/run.ps1 index 3b27382468..34604c7175 100644 --- a/run.ps1 +++ b/run.ps1 @@ -52,8 +52,8 @@ in the file are overridden by command line parameters. Example config file: ```json { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev", + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", + "channel": "master", "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" } ``` @@ -192,7 +192,7 @@ if (!$DotNetHome) { else { Join-Path $PSScriptRoot '.dotnet'} } -if (!$Channel) { $Channel = 'dev' } +if (!$Channel) { $Channel = 'master' } if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } # Execute diff --git a/run.sh b/run.sh index 02aac15874..61f7a53385 100755 --- a/run.sh +++ b/run.sh @@ -248,7 +248,7 @@ if [ -f "$config_file" ]; then [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" fi -[ -z "$channel" ] && channel='dev' +[ -z "$channel" ] && channel='master' [ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' get_korebuild From 5b5c587943ae33d3658826ca9b62dd05ea675790 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 3 Jul 2018 16:09:25 +0000 Subject: [PATCH 0842/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index cc06d1b63b..90bd265250 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17090 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 + 3.0.0-alpha1-10000 + 3.0.0-alpha1-10016 + 3.0.0-alpha1-10016 + 3.0.0-alpha1-10016 + 3.0.0-alpha1-10016 + 3.0.0-alpha1-10016 2.0.0 2.1.0 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 3e694b2ed8..3f870e51fe 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17090 -commithash:b19e903e946579cd9482089bce7d917e8bacd765 +version:3.0.0-alpha1-10000 +commithash:b7b88d08d55abc8b71de9abf16e26fc713e332cd From e60d98aa7658c5d9c91324e58a5bb600a4a9db23 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 3 Jul 2018 16:12:53 +0000 Subject: [PATCH 0843/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index e3fbf6767d..0a193a7135 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,11 +3,11 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17090 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 + 3.0.0-alpha1-10000 + 3.0.0-alpha1-10016 + 3.0.0-alpha1-10016 + 3.0.0-alpha1-10016 + 3.0.0-alpha1-10016 2.0.0 2.1.0 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index a8109db529..f0b76184fd 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17090 -commithash:b19e903e946579cd9482089bce7d917e8bacd765 +version:3.0.0-alpha1-10000 +commithash:b7b88d08d55abc8b71de9abf16e26fc713e332cd From 37d83280198fd7b99ebd149fa23868128d10744b Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 3 Jul 2018 16:18:33 +0000 Subject: [PATCH 0844/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 6 +++--- korebuild-lock.txt | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 3474d55494..7deed8c494 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17090 - 2.2.0-preview1-34530 + 3.0.0-alpha1-10000 + 3.0.0-alpha1-10016 4.6.0-preview1-26617-01 - 2.2.0-preview1-34530 + 3.0.0-alpha1-10016 2.0.0 2.1.0 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index a8109db529..f0b76184fd 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17090 -commithash:b19e903e946579cd9482089bce7d917e8bacd765 +version:3.0.0-alpha1-10000 +commithash:b7b88d08d55abc8b71de9abf16e26fc713e332cd From 26d9ef2ad7cebeeb8fe8e5bcf62420e9c3fd4038 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 2 Jul 2018 13:32:00 -0700 Subject: [PATCH 0845/1029] Upgrade to netcoreapp3.0 --- Directory.Build.targets | 3 +-- NuGetPackageVerifier.json | 2 +- build/dependencies.props | 14 ++++++-------- build/repo.props | 2 +- .../LaunchAnyCommand/LaunchAnyCommand.csproj | 2 +- .../WatchJavascriptFiles.csproj | 2 +- .../WatchMultipleProjects/Test/Test.csproj | 2 +- .../WatchMultipleProjects/Web/Web.csproj | 2 +- .../WatchMultipleProjects/watch.csproj | 2 +- ...t.AspNetCore.DeveloperCertificates.XPlat.csproj | 2 +- src/dotnet-dev-certs/dotnet-dev-certs.csproj | 2 +- src/dotnet-sql-cache/dotnet-sql-cache.csproj | 2 +- src/dotnet-user-secrets/dotnet-user-secrets.csproj | 2 +- src/dotnet-watch/dotnet-watch.csproj | 2 +- .../UserSecretsTestFixture.cs | 2 +- .../dotnet-user-secrets.Tests.csproj | 2 +- .../TestProjects/AppWithDeps/AppWithDeps.csproj | 2 +- .../TestProjects/GlobbingApp/GlobbingApp.csproj | 2 +- .../TestProjects/KitchenSink/KitchenSink.csproj | 2 +- .../TestProjects/NoDepsApp/NoDepsApp.csproj | 2 +- .../dotnet-watch.FunctionalTests.csproj | 2 +- test/dotnet-watch.Tests/ProgramTests.cs | 2 +- test/dotnet-watch.Tests/dotnet-watch.Tests.csproj | 2 +- 23 files changed, 28 insertions(+), 31 deletions(-) diff --git a/Directory.Build.targets b/Directory.Build.targets index 73b97f2807..4bcc9df925 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,7 +1,6 @@ - $(MicrosoftNETCoreApp21PackageVersion) - $(MicrosoftNETCoreApp22PackageVersion) + $(MicrosoftNETCoreApp30PackageVersion) $(NETStandardLibrary20PackageVersion) 99.9 diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index fb43448889..f5555f4929 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -27,7 +27,7 @@ "Microsoft.AspNetCore.DeveloperCertificates.XPlat": { "Exclusions": { "DOC_MISSING": { - "lib/netcoreapp2.2/Microsoft.AspNetCore.DeveloperCertificates.XPlat.dll": "Docs not required to shipoob package" + "lib/netcoreapp3.0/Microsoft.AspNetCore.DeveloperCertificates.XPlat.dll": "Docs not required to shipoob package" } } } diff --git a/build/dependencies.props b/build/dependencies.props index 90bd265250..e477bd4b50 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,14 +4,12 @@ 3.0.0-alpha1-10000 - 3.0.0-alpha1-10016 - 3.0.0-alpha1-10016 - 3.0.0-alpha1-10016 - 3.0.0-alpha1-10016 - 3.0.0-alpha1-10016 - 2.0.0 - 2.1.0 - 2.2.0-preview1-26618-02 + 3.0.0-alpha1-10018 + 3.0.0-alpha1-10018 + 3.0.0-alpha1-10018 + 3.0.0-alpha1-10018 + 3.0.0-alpha1-10018 + 3.0.0-preview1-26629-04 15.6.1 2.0.3 4.6.0-preview1-26617-01 diff --git a/build/repo.props b/build/repo.props index 9569f0ba08..a1d0408af2 100644 --- a/build/repo.props +++ b/build/repo.props @@ -2,7 +2,7 @@ - + diff --git a/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj b/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj index 1609403042..c1914554b4 100644 --- a/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj +++ b/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj @@ -1,6 +1,6 @@ - netcoreapp2.2 + netcoreapp3.0 diff --git a/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj b/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj index 0c0cac78f3..25158a8566 100755 --- a/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj +++ b/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp3.0 diff --git a/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj b/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj index 0559578c32..a88898d3ce 100755 --- a/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj +++ b/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp3.0 diff --git a/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj b/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj index 616246b199..8f0133c1ef 100755 --- a/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj +++ b/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp3.0 diff --git a/samples/dotnet-watch/WatchMultipleProjects/watch.csproj b/samples/dotnet-watch/WatchMultipleProjects/watch.csproj index 5ca4ee2379..0989ee016e 100644 --- a/samples/dotnet-watch/WatchMultipleProjects/watch.csproj +++ b/samples/dotnet-watch/WatchMultipleProjects/watch.csproj @@ -1,6 +1,6 @@ - netcoreapp2.2 + netcoreapp3.0 false diff --git a/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj b/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj index 19e0fc454b..5a20f14ca8 100644 --- a/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj +++ b/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp3.0 Package for the CLI first run experience. $(DefineConstants);XPLAT aspnet;cli diff --git a/src/dotnet-dev-certs/dotnet-dev-certs.csproj b/src/dotnet-dev-certs/dotnet-dev-certs.csproj index b785b60c42..d5c4bb29f4 100644 --- a/src/dotnet-dev-certs/dotnet-dev-certs.csproj +++ b/src/dotnet-dev-certs/dotnet-dev-certs.csproj @@ -3,7 +3,7 @@ - netcoreapp2.2 + netcoreapp3.0 exe Command line tool to generate certificates used in ASP.NET Core during development. Microsoft.AspNetCore.DeveloperCertificates.Tools diff --git a/src/dotnet-sql-cache/dotnet-sql-cache.csproj b/src/dotnet-sql-cache/dotnet-sql-cache.csproj index 4ab0f3425c..0385351e84 100644 --- a/src/dotnet-sql-cache/dotnet-sql-cache.csproj +++ b/src/dotnet-sql-cache/dotnet-sql-cache.csproj @@ -3,7 +3,7 @@ - netcoreapp2.2 + netcoreapp3.0 exe Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching. cache;distributedcache;sqlserver diff --git a/src/dotnet-user-secrets/dotnet-user-secrets.csproj b/src/dotnet-user-secrets/dotnet-user-secrets.csproj index bcb37e37b2..0210d49bca 100644 --- a/src/dotnet-user-secrets/dotnet-user-secrets.csproj +++ b/src/dotnet-user-secrets/dotnet-user-secrets.csproj @@ -3,7 +3,7 @@ - netcoreapp2.2 + netcoreapp3.0 exe Command line tool to manage user secrets for Microsoft.Extensions.Configuration. false diff --git a/src/dotnet-watch/dotnet-watch.csproj b/src/dotnet-watch/dotnet-watch.csproj index c5210a0cd2..cea982794f 100644 --- a/src/dotnet-watch/dotnet-watch.csproj +++ b/src/dotnet-watch/dotnet-watch.csproj @@ -3,7 +3,7 @@ - netcoreapp2.2 + netcoreapp3.0 exe Command line tool to watch for source file changes during development and restart the dotnet command. Microsoft.DotNet.Watcher.Tools diff --git a/test/dotnet-user-secrets.Tests/UserSecretsTestFixture.cs b/test/dotnet-user-secrets.Tests/UserSecretsTestFixture.cs index 590787ec31..4c76950548 100644 --- a/test/dotnet-user-secrets.Tests/UserSecretsTestFixture.cs +++ b/test/dotnet-user-secrets.Tests/UserSecretsTestFixture.cs @@ -35,7 +35,7 @@ namespace Microsoft.Extensions.Configuration.UserSecrets.Tests private const string ProjectTemplate = @" Exe - netcoreapp2.2 + netcoreapp3.0 {0} false diff --git a/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj b/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj index b52bd3eb92..d535a46d76 100644 --- a/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj +++ b/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp3.0 Microsoft.Extensions.SecretManager.Tools.Tests diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj b/test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj index 7a55f33ef9..b50fcbd34f 100644 --- a/test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj +++ b/test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp3.0 exe true diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj b/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj index 7c90a96aba..9f581dea57 100644 --- a/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj +++ b/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp3.0 exe false true diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj b/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj index e2875bdba1..76292e00b3 100644 --- a/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj +++ b/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj @@ -9,7 +9,7 @@ Exe - netcoreapp2.2 + netcoreapp3.0 true diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj b/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj index 47ca89d4f6..3c9f4ede9d 100644 --- a/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj +++ b/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp3.0 exe true diff --git a/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj b/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj index 7f92dede3c..72b98d8868 100644 --- a/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj +++ b/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp3.0 $(DefaultItemExcludes);TestProjects\**\* Microsoft.DotNet.Watcher.Tools.FunctionalTests diff --git a/test/dotnet-watch.Tests/ProgramTests.cs b/test/dotnet-watch.Tests/ProgramTests.cs index a5998b25c8..922139a73f 100644 --- a/test/dotnet-watch.Tests/ProgramTests.cs +++ b/test/dotnet-watch.Tests/ProgramTests.cs @@ -28,7 +28,7 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests { _tempDir .WithCSharpProject("testproj") - .WithTargetFrameworks("netcoreapp2.2") + .WithTargetFrameworks("netcoreapp3.0") .Dir() .WithFile("Program.cs") .Create(); diff --git a/test/dotnet-watch.Tests/dotnet-watch.Tests.csproj b/test/dotnet-watch.Tests/dotnet-watch.Tests.csproj index bc85a1119c..086e0d2078 100644 --- a/test/dotnet-watch.Tests/dotnet-watch.Tests.csproj +++ b/test/dotnet-watch.Tests/dotnet-watch.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp3.0 Microsoft.DotNet.Watcher.Tools.Tests From cb954e15f88ffb164d2f23704bfb2a56ff7cf344 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 8 Jul 2018 12:10:46 -0700 Subject: [PATCH 0846/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index cc06d1b63b..3c51bc3d39 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,14 +3,14 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17090 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.0.0 - 2.1.0 + 2.2.0-preview1-17099 + 2.2.0-preview1-34640 + 2.2.0-preview1-34640 + 2.2.0-preview1-34640 + 2.2.0-preview1-34640 + 2.2.0-preview1-34640 + 2.0.7 + 2.1.1 2.2.0-preview1-26618-02 15.6.1 2.0.3 @@ -18,7 +18,7 @@ 4.6.0-preview1-26617-01 9.0.1 2.3.1 - 2.4.0-beta.1.build3945 + 2.4.0-rc.1.build4038 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 3e694b2ed8..8b9d17825f 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17090 -commithash:b19e903e946579cd9482089bce7d917e8bacd765 +version:2.2.0-preview1-17099 +commithash:263ed1db9866b6b419b1f5d5189a712aa218acb3 From 8bb788ef9eef5ae4a6b48c04b3903f7c8319bbe9 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 8 Jul 2018 12:14:12 -0700 Subject: [PATCH 0847/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 16 ++++++++-------- korebuild-lock.txt | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index e3fbf6767d..be2fe575b9 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,19 +3,19 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17090 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.2.0-preview1-34530 - 2.0.0 - 2.1.0 + 2.2.0-preview1-17099 + 2.2.0-preview1-34640 + 2.2.0-preview1-34640 + 2.2.0-preview1-34640 + 2.2.0-preview1-34640 + 2.0.7 + 2.1.1 2.2.0-preview1-26618-02 15.6.1 2.0.3 4.6.0-preview1-26617-01 2.3.1 - 2.4.0-beta.1.build3945 + 2.4.0-rc.1.build4038 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index a8109db529..27e2e80f9a 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17090 -commithash:b19e903e946579cd9482089bce7d917e8bacd765 +version:2.2.0-preview1-17099 +commithash:263ed1db9866b6b419b1f5d5189a712aa218acb3 From b34f6284126e38e8b510b58e735a3d5587a8989c Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 8 Jul 2018 12:19:37 -0700 Subject: [PATCH 0848/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 3474d55494..df86701c7b 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17090 - 2.2.0-preview1-34530 + 2.2.0-preview1-17099 + 2.2.0-preview1-34640 4.6.0-preview1-26617-01 - 2.2.0-preview1-34530 - 2.0.0 - 2.1.0 + 2.2.0-preview1-34640 + 2.0.7 + 2.1.1 2.2.0-preview1-26618-02 15.6.1 4.7.49 @@ -16,7 +16,7 @@ 11.0.2 0.8.0 2.3.1 - 2.4.0-beta.1.build3945 + 2.4.0-rc.1.build4038 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index a8109db529..27e2e80f9a 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17090 -commithash:b19e903e946579cd9482089bce7d917e8bacd765 +version:2.2.0-preview1-17099 +commithash:263ed1db9866b6b419b1f5d5189a712aa218acb3 From 7f627772a2171e9447c4e5cd5114b0e37933045b Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 8 Jul 2018 19:50:54 +0000 Subject: [PATCH 0849/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index e477bd4b50..cbef771775 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-10000 - 3.0.0-alpha1-10018 - 3.0.0-alpha1-10018 - 3.0.0-alpha1-10018 - 3.0.0-alpha1-10018 - 3.0.0-alpha1-10018 + 3.0.0-alpha1-10005 + 3.0.0-alpha1-10044 + 3.0.0-alpha1-10044 + 3.0.0-alpha1-10044 + 3.0.0-alpha1-10044 + 3.0.0-alpha1-10044 3.0.0-preview1-26629-04 15.6.1 2.0.3 @@ -16,7 +16,7 @@ 4.6.0-preview1-26617-01 9.0.1 2.3.1 - 2.4.0-beta.1.build3945 + 2.4.0-rc.1.build4038 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 3f870e51fe..2395ab5956 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-10000 -commithash:b7b88d08d55abc8b71de9abf16e26fc713e332cd +version:3.0.0-alpha1-10005 +commithash:05570853de976a526462ca140a55b1ac59d9a351 From 1fe94914452c0af5998f25f8e0053628f79ddf71 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 8 Jul 2018 19:54:25 +0000 Subject: [PATCH 0850/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 0a193a7135..8c1380e0fe 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,11 +3,11 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-10000 - 3.0.0-alpha1-10016 - 3.0.0-alpha1-10016 - 3.0.0-alpha1-10016 - 3.0.0-alpha1-10016 + 3.0.0-alpha1-10005 + 3.0.0-alpha1-10044 + 3.0.0-alpha1-10044 + 3.0.0-alpha1-10044 + 3.0.0-alpha1-10044 2.0.0 2.1.0 2.2.0-preview1-26618-02 @@ -15,7 +15,7 @@ 2.0.3 4.6.0-preview1-26617-01 2.3.1 - 2.4.0-beta.1.build3945 + 2.4.0-rc.1.build4038 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index f0b76184fd..f357ac9f7d 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-10000 -commithash:b7b88d08d55abc8b71de9abf16e26fc713e332cd +version:3.0.0-alpha1-10005 +commithash:05570853de976a526462ca140a55b1ac59d9a351 From 40dfd77fd025d74cfe831bd79f261f548a61a2bb Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 8 Jul 2018 20:00:07 +0000 Subject: [PATCH 0851/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 8 ++++---- korebuild-lock.txt | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 7deed8c494..2fbed485be 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-10000 - 3.0.0-alpha1-10016 + 3.0.0-alpha1-10005 + 3.0.0-alpha1-10044 4.6.0-preview1-26617-01 - 3.0.0-alpha1-10016 + 3.0.0-alpha1-10044 2.0.0 2.1.0 2.2.0-preview1-26618-02 @@ -16,7 +16,7 @@ 11.0.2 0.8.0 2.3.1 - 2.4.0-beta.1.build3945 + 2.4.0-rc.1.build4038 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index f0b76184fd..f357ac9f7d 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-10000 -commithash:b7b88d08d55abc8b71de9abf16e26fc713e332cd +version:3.0.0-alpha1-10005 +commithash:05570853de976a526462ca140a55b1ac59d9a351 From c80c5f4a01fa2d76e82f4d97a658b3919c6fc6e4 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 10 Jul 2018 16:27:28 -0700 Subject: [PATCH 0852/1029] Update dotnet-sql-cache.csproj --- src/dotnet-sql-cache/dotnet-sql-cache.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dotnet-sql-cache/dotnet-sql-cache.csproj b/src/dotnet-sql-cache/dotnet-sql-cache.csproj index 0385351e84..5596b79543 100644 --- a/src/dotnet-sql-cache/dotnet-sql-cache.csproj +++ b/src/dotnet-sql-cache/dotnet-sql-cache.csproj @@ -28,6 +28,7 @@ + From 498c77ed2986383c6d0d2043c64e15e347af1f92 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 11 Jul 2018 15:06:29 -0700 Subject: [PATCH 0853/1029] Reverting version from 2.1.2 back to 2.1.1 As a result of changing the way we apply servicing updates to aspnet core, this repo did not need the version bump because there are no planned product changes in this repo. --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 71841a8512..4078cfc422 100644 --- a/version.props +++ b/version.props @@ -1,6 +1,6 @@  - 2.1.2 + 2.1.1 15.6 rtm $(VersionPrefix) From b24ae3eef557b13215950e9642b2a1d0da0ae895 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 11 Jul 2018 15:06:31 -0700 Subject: [PATCH 0854/1029] Reverting version from 2.1.2 back to 2.1.1 As a result of changing the way we apply servicing updates to aspnet core, this repo did not need the version bump because there are no planned product changes in this repo. --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 478dfd16ed..669c874829 100644 --- a/version.props +++ b/version.props @@ -1,6 +1,6 @@  - 2.1.2 + 2.1.1 rtm $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final From 3a16fe8d53d8fd8cf876854268071eba863f4f8d Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 11 Jul 2018 15:06:35 -0700 Subject: [PATCH 0855/1029] Reverting version from 2.1.2 back to 2.1.1 As a result of changing the way we apply servicing updates to aspnet core, this repo did not need the version bump because there are no planned product changes in this repo. --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 478dfd16ed..669c874829 100644 --- a/version.props +++ b/version.props @@ -1,6 +1,6 @@  - 2.1.2 + 2.1.1 rtm $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final From 349ccf680bc4491cf3c3e97aca36a6893ccc14e8 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 11 Jul 2018 18:48:17 -0700 Subject: [PATCH 0856/1029] Updating dependencies to 2.1.2 and adding a section for pinned variable versions --- build/dependencies.props | 13 ++++++++++--- korebuild-lock.txt | 4 ++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 4453d8db2a..8043e0803d 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -2,15 +2,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - 2.1.1-rtm-15793 + + + + 2.1.3-rtm-15802 2.1.1 2.1.0 2.1.1 2.1.1 2.1.1 2.0.0 - 2.1.1 + 2.1.2 15.6.1 2.0.3 4.5.1 @@ -19,5 +21,10 @@ 2.3.1 2.4.0-beta.1.build3945 + + + + + diff --git a/korebuild-lock.txt b/korebuild-lock.txt index d2f4947bc8..1dfc352a0a 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.1-rtm-15793 -commithash:988313f4b064d6c69fc6f7b845b6384a6af3447a +version:2.1.3-rtm-15802 +commithash:a7c08b45b440a7d2058a0aa1eaa3eb6ba811976a From fd2613f1b2ba062a10015add7db585ca15293632 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 11 Jul 2018 18:48:36 -0700 Subject: [PATCH 0857/1029] Updating dependencies to 2.1.2 and adding a section for pinned variable versions --- build/dependencies.props | 13 ++++++++++--- korebuild-lock.txt | 4 ++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index dc47d2ca18..c5bba50310 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -2,19 +2,26 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - 2.1.1-rtm-15793 + + + + 2.1.3-rtm-15802 2.1.0 2.1.1 2.1.1 2.1.1 2.0.0 - 2.1.1 + 2.1.2 15.6.1 2.0.3 4.5.0 2.3.1 2.4.0-beta.1.build3945 + + + + + diff --git a/korebuild-lock.txt b/korebuild-lock.txt index bc84e0cd53..251c227c83 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.1-rtm-15793 -commithash:988313f4b064d6c69fc6f7b845b6384a6af3447a +version:2.1.3-rtm-15802 +commithash:a7c08b45b440a7d2058a0aa1eaa3eb6ba811976a From 8177229ac88fd6f864a8819ac7e81b4cfc1c4df3 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 11 Jul 2018 18:49:06 -0700 Subject: [PATCH 0858/1029] Updating dependencies to 2.1.2 and adding a section for pinned variable versions --- build/dependencies.props | 13 ++++++++++--- korebuild-lock.txt | 4 ++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index c7a3e03395..d52f8aee1c 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -2,13 +2,15 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - 2.1.1-rtm-15793 + + + + 2.1.3-rtm-15802 2.1.0 4.5.0 2.1.1 2.0.0 - 2.1.1 + 2.1.2 15.6.1 4.7.49 2.0.3 @@ -17,5 +19,10 @@ 2.3.1 2.4.0-beta.1.build3945 + + + + + diff --git a/korebuild-lock.txt b/korebuild-lock.txt index bc84e0cd53..251c227c83 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.1-rtm-15793 -commithash:988313f4b064d6c69fc6f7b845b6384a6af3447a +version:2.1.3-rtm-15802 +commithash:a7c08b45b440a7d2058a0aa1eaa3eb6ba811976a From 252ae0c434d93f5bfaf949c35edb9ef59730d0a3 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 12 Jul 2018 11:53:20 -0700 Subject: [PATCH 0859/1029] Pin version variables to the ASP.NET Core 2.1.2 baseline This reverts our previous policy of cascading versions on all servicing updates. This moves variables into the 'pinned' section, and points them to the latest stable release (versions that were used at the time of the 2.1.2 release). --- build/dependencies.props | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index c5bba50310..3c314a3476 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,12 +4,8 @@ - + 2.1.3-rtm-15802 - 2.1.0 - 2.1.1 - 2.1.1 - 2.1.1 2.0.0 2.1.2 15.6.1 @@ -23,5 +19,10 @@ - - + + 2.1.0 + 2.1.1 + 2.1.1 + 2.1.1 + + \ No newline at end of file From 218064c300a7cf5a76669e133340a98a0c5517a5 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 12 Jul 2018 11:54:35 -0700 Subject: [PATCH 0860/1029] Pin version variables to the ASP.NET Core 2.1.2 baseline This reverts our previous policy of cascading versions on all servicing updates. This moves variables into the 'pinned' section, and points them to the latest stable release (versions that were used at the time of the 2.1.2 release). --- build/dependencies.props | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index d52f8aee1c..55c598b536 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,11 +4,9 @@ - + 2.1.3-rtm-15802 - 2.1.0 4.5.0 - 2.1.1 2.0.0 2.1.2 15.6.1 @@ -24,5 +22,8 @@ - - + + 2.1.0 + 2.1.1 + + \ No newline at end of file From 084406441e607886565bca38b9a756442bc7469e Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 12 Jul 2018 11:52:23 -0700 Subject: [PATCH 0861/1029] Pin version variables to the ASP.NET Core 2.1.2 baseline This reverts our previous policy of cascading versions on all servicing updates. This moves variables into the 'pinned' section, and points them to the latest stable release (versions that were used at the time of the 2.1.2 release). --- build/dependencies.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/dependencies.props b/build/dependencies.props index 8043e0803d..cf3681c3c2 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,7 +4,7 @@ - + 2.1.3-rtm-15802 2.1.1 2.1.0 From 93c12758277030e7c368f780d03f91b2ad10c504 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 15 Jul 2018 12:10:39 -0700 Subject: [PATCH 0862/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 3c51bc3d39..a9483aa4d5 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,18 +4,18 @@ 2.2.0-preview1-17099 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.0.7 - 2.1.1 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.0.9 + 2.1.2 2.2.0-preview1-26618-02 15.6.1 2.0.3 - 4.6.0-preview1-26617-01 - 4.6.0-preview1-26617-01 + 4.5.1 + 4.5.0 9.0.1 2.3.1 2.4.0-rc.1.build4038 From 2d44d6396e774122fb2be04d7317dbf011ba7213 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 15 Jul 2018 12:13:58 -0700 Subject: [PATCH 0863/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index be2fe575b9..c5526396b7 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,16 +4,16 @@ 2.2.0-preview1-17099 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.0.7 - 2.1.1 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.0.9 + 2.1.2 2.2.0-preview1-26618-02 15.6.1 2.0.3 - 4.6.0-preview1-26617-01 + 4.5.0 2.3.1 2.4.0-rc.1.build4038 From bf2acb9c96787977ae26c34a050635e845066639 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 15 Jul 2018 12:19:00 -0700 Subject: [PATCH 0864/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index df86701c7b..16fb368215 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,17 +4,17 @@ 2.2.0-preview1-17099 - 2.2.0-preview1-34640 - 4.6.0-preview1-26617-01 - 2.2.0-preview1-34640 - 2.0.7 - 2.1.1 + 2.2.0-preview1-34694 + 4.5.0 + 2.2.0-preview1-34694 + 2.0.9 + 2.1.2 2.2.0-preview1-26618-02 15.6.1 4.7.49 2.0.3 11.0.2 - 0.8.0 + 0.9.0 2.3.1 2.4.0-rc.1.build4038 From 52b6c34ed40177c8b6c48853710abad1e65a1808 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 15 Jul 2018 19:54:16 +0000 Subject: [PATCH 0865/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index cbef771775..e074884d52 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-10005 - 3.0.0-alpha1-10044 - 3.0.0-alpha1-10044 - 3.0.0-alpha1-10044 - 3.0.0-alpha1-10044 - 3.0.0-alpha1-10044 - 3.0.0-preview1-26629-04 + 3.0.0-alpha1-10009 + 3.0.0-alpha1-10081 + 3.0.0-alpha1-10081 + 3.0.0-alpha1-10081 + 3.0.0-alpha1-10081 + 3.0.0-alpha1-10081 + 3.0.0-preview1-26710-03 15.6.1 2.0.3 - 4.6.0-preview1-26617-01 - 4.6.0-preview1-26617-01 + 4.6.0-preview1-26708-04 + 4.6.0-preview1-26708-04 9.0.1 2.3.1 2.4.0-rc.1.build4038 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 2395ab5956..c6adb40215 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-10005 -commithash:05570853de976a526462ca140a55b1ac59d9a351 +version:3.0.0-alpha1-10009 +commithash:86be4707e47d2f1930a982f2b59eacfc4196da33 From 43df97739e41fb9271b0058a51e9f4d8d01e5e36 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 15 Jul 2018 19:57:46 +0000 Subject: [PATCH 0866/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 16 ++++++++-------- korebuild-lock.txt | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 8c1380e0fe..cb3e212ef1 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-10005 - 3.0.0-alpha1-10044 - 3.0.0-alpha1-10044 - 3.0.0-alpha1-10044 - 3.0.0-alpha1-10044 - 2.0.0 - 2.1.0 + 3.0.0-alpha1-10009 + 3.0.0-alpha1-10081 + 3.0.0-alpha1-10081 + 3.0.0-alpha1-10081 + 3.0.0-alpha1-10081 + 2.0.9 + 2.1.2 2.2.0-preview1-26618-02 15.6.1 2.0.3 - 4.6.0-preview1-26617-01 + 4.6.0-preview1-26708-04 2.3.1 2.4.0-rc.1.build4038 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index f357ac9f7d..4db537685b 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-10005 -commithash:05570853de976a526462ca140a55b1ac59d9a351 +version:3.0.0-alpha1-10009 +commithash:86be4707e47d2f1930a982f2b59eacfc4196da33 From deb4605df3d011cb0f37e080d8f35cf90108e49a Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 15 Jul 2018 20:03:05 +0000 Subject: [PATCH 0867/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 2fbed485be..1709cb6135 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,18 +3,18 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-10005 - 3.0.0-alpha1-10044 - 4.6.0-preview1-26617-01 - 3.0.0-alpha1-10044 - 2.0.0 - 2.1.0 + 3.0.0-alpha1-10009 + 3.0.0-alpha1-10081 + 4.6.0-preview1-26708-04 + 3.0.0-alpha1-10081 + 2.0.9 + 2.1.2 2.2.0-preview1-26618-02 15.6.1 4.7.49 2.0.3 11.0.2 - 0.8.0 + 0.9.0 2.3.1 2.4.0-rc.1.build4038 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index f357ac9f7d..4db537685b 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-10005 -commithash:05570853de976a526462ca140a55b1ac59d9a351 +version:3.0.0-alpha1-10009 +commithash:86be4707e47d2f1930a982f2b59eacfc4196da33 From dcde9afc4888af1b8b1e71e50f1183c240155a47 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 22 Jul 2018 12:10:11 -0700 Subject: [PATCH 0868/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index a9483aa4d5..607267c52c 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,11 +4,11 @@ 2.2.0-preview1-17099 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 + 2.2.0-preview1-34755 + 2.2.0-preview1-34755 + 2.2.0-preview1-34755 + 2.2.0-preview1-34755 + 2.2.0-preview1-34755 2.0.9 2.1.2 2.2.0-preview1-26618-02 From d503b0803436caa0637fc47e99342b3d57990738 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 22 Jul 2018 12:13:31 -0700 Subject: [PATCH 0869/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index c5526396b7..ee95b37bfd 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,10 +4,10 @@ 2.2.0-preview1-17099 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 + 2.2.0-preview1-34755 + 2.2.0-preview1-34755 + 2.2.0-preview1-34755 + 2.2.0-preview1-34755 2.0.9 2.1.2 2.2.0-preview1-26618-02 From f47e0f61431fe7079e8f9fac79a63035b2f35bf1 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 22 Jul 2018 12:18:27 -0700 Subject: [PATCH 0870/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 16fb368215..fe09987679 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,9 +4,9 @@ 2.2.0-preview1-17099 - 2.2.0-preview1-34694 + 2.2.0-preview1-34755 4.5.0 - 2.2.0-preview1-34694 + 2.2.0-preview1-34755 2.0.9 2.1.2 2.2.0-preview1-26618-02 From c3768ec342c8c7b0b1ff713111f371afd2314635 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 22 Jul 2018 12:55:04 -0700 Subject: [PATCH 0871/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index e074884d52..774a546054 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-10009 - 3.0.0-alpha1-10081 - 3.0.0-alpha1-10081 - 3.0.0-alpha1-10081 - 3.0.0-alpha1-10081 - 3.0.0-alpha1-10081 + 3.0.0-alpha1-10011 + 3.0.0-alpha1-10123 + 3.0.0-alpha1-10123 + 3.0.0-alpha1-10123 + 3.0.0-alpha1-10123 + 3.0.0-alpha1-10123 3.0.0-preview1-26710-03 15.6.1 2.0.3 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index c6adb40215..4cfdfb010e 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-10009 -commithash:86be4707e47d2f1930a982f2b59eacfc4196da33 +version:3.0.0-alpha1-10011 +commithash:717c2eb1f91dafd2580c1a9b8e5064d12dd8c054 From dd4d3156b50e2d4f7e817dee3de376e0dea1c59e Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 22 Jul 2018 12:58:48 -0700 Subject: [PATCH 0872/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index cb3e212ef1..b538e7466b 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,11 +3,11 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-10009 - 3.0.0-alpha1-10081 - 3.0.0-alpha1-10081 - 3.0.0-alpha1-10081 - 3.0.0-alpha1-10081 + 3.0.0-alpha1-10011 + 3.0.0-alpha1-10123 + 3.0.0-alpha1-10123 + 3.0.0-alpha1-10123 + 3.0.0-alpha1-10123 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 4db537685b..9a67ee9c28 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-10009 -commithash:86be4707e47d2f1930a982f2b59eacfc4196da33 +version:3.0.0-alpha1-10011 +commithash:717c2eb1f91dafd2580c1a9b8e5064d12dd8c054 From afe088a8e827bdeb821610cbb7e2b447cf30e012 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 22 Jul 2018 13:04:41 -0700 Subject: [PATCH 0873/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 6 +++--- korebuild-lock.txt | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 1709cb6135..a08a37bca3 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-10009 - 3.0.0-alpha1-10081 + 3.0.0-alpha1-10011 + 3.0.0-alpha1-10123 4.6.0-preview1-26708-04 - 3.0.0-alpha1-10081 + 3.0.0-alpha1-10123 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 4db537685b..9a67ee9c28 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-10009 -commithash:86be4707e47d2f1930a982f2b59eacfc4196da33 +version:3.0.0-alpha1-10011 +commithash:717c2eb1f91dafd2580c1a9b8e5064d12dd8c054 From cd4e197b647cb5e1ea7c9cb9f49654c760cc425e Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Tue, 24 Jul 2018 10:50:20 -0700 Subject: [PATCH 0874/1029] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 64ff041d5c..eac4268e4c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ Contributing ====== -Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/dev/CONTRIBUTING.md) in the Home repo. +Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/master/CONTRIBUTING.md) in the Home repo. From a5a9e63ff2fcddae277db4280890d11adc43bb4e Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Tue, 24 Jul 2018 10:50:56 -0700 Subject: [PATCH 0875/1029] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 64ff041d5c..eac4268e4c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ Contributing ====== -Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/dev/CONTRIBUTING.md) in the Home repo. +Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/master/CONTRIBUTING.md) in the Home repo. From 629d985a0cce11ee552b70805d617ccdfdeb24e3 Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Tue, 24 Jul 2018 10:51:33 -0700 Subject: [PATCH 0876/1029] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 64ff041d5c..eac4268e4c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ Contributing ====== -Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/dev/CONTRIBUTING.md) in the Home repo. +Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/master/CONTRIBUTING.md) in the Home repo. From 05b3040f85b78361b63c05ad48bb105b4f3049da Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 29 Jul 2018 12:09:56 -0700 Subject: [PATCH 0877/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 15 ++++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 607267c52c..0f57ae33b0 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17099 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 + 2.2.0-preview1-17102 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 2.0.9 2.1.2 2.2.0-preview1-26618-02 @@ -18,7 +18,8 @@ 4.5.0 9.0.1 2.3.1 - 2.4.0-rc.1.build4038 + 2.4.0 + diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 8b9d17825f..28cd6a5b03 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17099 -commithash:263ed1db9866b6b419b1f5d5189a712aa218acb3 +version:2.2.0-preview1-17102 +commithash:e7e2b5a97ca92cfc6acc4def534cb0901a6d1eb9 From 884b1eb7adacb4680667cc045843dac3a12b3df9 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 29 Jul 2018 12:13:05 -0700 Subject: [PATCH 0878/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 13 +++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index ee95b37bfd..09d37136bd 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,11 +3,11 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17099 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 - 2.2.0-preview1-34755 + 2.2.0-preview1-17102 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 + 2.2.0-preview1-34823 2.0.9 2.1.2 2.2.0-preview1-26618-02 @@ -15,7 +15,8 @@ 2.0.3 4.5.0 2.3.1 - 2.4.0-rc.1.build4038 + 2.4.0 + diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 27e2e80f9a..6b8da29e6b 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17099 -commithash:263ed1db9866b6b419b1f5d5189a712aa218acb3 +version:2.2.0-preview1-17102 +commithash:e7e2b5a97ca92cfc6acc4def534cb0901a6d1eb9 From 31249603df7d0bedfb993e330484085a2dcfa317 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 29 Jul 2018 12:18:03 -0700 Subject: [PATCH 0879/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 11 ++++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index fe09987679..5b45506395 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17099 - 2.2.0-preview1-34755 + 2.2.0-preview1-17102 + 2.2.0-preview1-34823 4.5.0 - 2.2.0-preview1-34755 + 2.2.0-preview1-34823 2.0.9 2.1.2 2.2.0-preview1-26618-02 @@ -14,9 +14,10 @@ 4.7.49 2.0.3 11.0.2 - 0.9.0 + 0.10.0 2.3.1 - 2.4.0-rc.1.build4038 + 2.4.0 + diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 27e2e80f9a..6b8da29e6b 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17099 -commithash:263ed1db9866b6b419b1f5d5189a712aa218acb3 +version:2.2.0-preview1-17102 +commithash:e7e2b5a97ca92cfc6acc4def534cb0901a6d1eb9 From d9fd86b754080c2db32e58dda58744e356882c22 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 29 Jul 2018 19:53:06 +0000 Subject: [PATCH 0880/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 21 +++++++++++---------- korebuild-lock.txt | 4 ++-- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 774a546054..8da79df136 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,20 +3,21 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-10011 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-preview1-26710-03 + 3.0.0-alpha1-10015 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-preview1-26727-03 15.6.1 2.0.3 - 4.6.0-preview1-26708-04 - 4.6.0-preview1-26708-04 + 4.6.0-preview1-26727-04 + 4.6.0-preview1-26727-04 9.0.1 2.3.1 - 2.4.0-rc.1.build4038 + 2.4.0 + diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 4cfdfb010e..8c70cbad9f 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-10011 -commithash:717c2eb1f91dafd2580c1a9b8e5064d12dd8c054 +version:3.0.0-alpha1-10015 +commithash:3f36e5c2f061712f76f2766c435d2555681d5c55 From cba488f7a3715fd8ebf743a722866dd2f98b42f3 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 29 Jul 2018 19:56:30 +0000 Subject: [PATCH 0881/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 15 ++++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index b538e7466b..7c3160369c 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,19 +3,20 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-10011 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 - 3.0.0-alpha1-10123 + 3.0.0-alpha1-10015 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 + 3.0.0-alpha1-10173 2.0.9 2.1.2 2.2.0-preview1-26618-02 15.6.1 2.0.3 - 4.6.0-preview1-26708-04 + 4.6.0-preview1-26727-04 2.3.1 - 2.4.0-rc.1.build4038 + 2.4.0 + diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 9a67ee9c28..1e75dc3a23 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-10011 -commithash:717c2eb1f91dafd2580c1a9b8e5064d12dd8c054 +version:3.0.0-alpha1-10015 +commithash:3f36e5c2f061712f76f2766c435d2555681d5c55 From 18661ed6f4f3f5b83d7295cffdf08a15e29fd1ba Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 29 Jul 2018 20:01:37 +0000 Subject: [PATCH 0882/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 13 +++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index a08a37bca3..1fec5379c4 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-10011 - 3.0.0-alpha1-10123 - 4.6.0-preview1-26708-04 - 3.0.0-alpha1-10123 + 3.0.0-alpha1-10015 + 3.0.0-alpha1-10173 + 4.6.0-preview1-26727-04 + 3.0.0-alpha1-10173 2.0.9 2.1.2 2.2.0-preview1-26618-02 @@ -14,9 +14,10 @@ 4.7.49 2.0.3 11.0.2 - 0.9.0 + 0.10.0 2.3.1 - 2.4.0-rc.1.build4038 + 2.4.0 + diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 9a67ee9c28..1e75dc3a23 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-10011 -commithash:717c2eb1f91dafd2580c1a9b8e5064d12dd8c054 +version:3.0.0-alpha1-10015 +commithash:3f36e5c2f061712f76f2766c435d2555681d5c55 From 4baed363e5c96c3774627cc6eb01740c289eeff1 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 30 Jul 2018 15:54:16 -0700 Subject: [PATCH 0883/1029] Close #467 - fix race conditions in tests that restart a watchable app * Ensure the test app is actually watching for file changes before attempting to trigger a restart. * Add retry if the first attempt times out --- .../DotNetWatcherTests.cs | 18 ++++++++++++++---- .../NoDepsAppTests.cs | 15 ++++++++++++--- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs b/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs index cc0a1c3fc0..65ff6416e2 100644 --- a/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs +++ b/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs @@ -39,15 +39,25 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests var source = Path.Combine(_app.SourceDirectory, "Program.cs"); var contents = File.ReadAllText(source); const string messagePrefix = "DOTNET_WATCH_ITERATION = "; - for (var i = 1; i <= 4; i++) + for (var i = 1; i <= 3; i++) { var message = await _app.Process.GetOutputLineStartsWithAsync(messagePrefix, TimeSpan.FromMinutes(2)); var count = int.Parse(message.Substring(messagePrefix.Length), CultureInfo.InvariantCulture); Assert.Equal(i, count); - File.Delete(source); - File.WriteAllText(source, contents); - await _app.HasRestarted(); + await _app.IsWaitingForFileChange(); + + try + { + File.SetLastWriteTime(source, DateTime.Now); + await _app.HasRestarted(); + } + catch + { + // retry + File.SetLastWriteTime(source, DateTime.Now); + await _app.HasRestarted(); + } } } diff --git a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs index 22f46cbbe0..55d0441552 100644 --- a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs +++ b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs @@ -53,10 +53,19 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests await _app.IsWaitingForFileChange(); var fileToChange = Path.Combine(_app.SourceDirectory, "Program.cs"); - var programCs = File.ReadAllText(fileToChange); - File.WriteAllText(fileToChange, programCs); - await _app.HasRestarted(); + try + { + File.SetLastWriteTime(fileToChange, DateTime.Now); + await _app.HasRestarted(); + } + catch + { + // retry + File.SetLastWriteTime(fileToChange, DateTime.Now); + await _app.HasRestarted(); + } + var pid2 = await _app.GetProcessId(); Assert.NotEqual(pid, pid2); await _app.HasExited(); // process should exit after run From 89ab0cfde80b1da1e87f563220fcb9bed232d2f3 Mon Sep 17 00:00:00 2001 From: Mike Lorbetske Date: Sun, 29 Jul 2018 12:38:02 -0700 Subject: [PATCH 0884/1029] Initial commit of the HTTP REPL --- DotNetTools.sln | 44 ++ NuGetPackageVerifier.json | 21 + build/dependencies.props | 2 + .../AggregateDirectoryStructure.cs | 38 ++ .../Commands/BaseHttpCommand.cs | 574 ++++++++++++++++++ .../Commands/ChangeDirectoryCommand.cs | 78 +++ .../Commands/ClearCommand.cs | 62 ++ .../Commands/ConfigCommand.cs | 67 ++ .../Commands/DeleteCommand.cs | 9 + .../Commands/EchoCommand.cs | 55 ++ .../Commands/ExitCommand.cs | 29 + src/Microsoft.HttpRepl/Commands/Formatter.cs | 33 + src/Microsoft.HttpRepl/Commands/GetCommand.cs | 9 + .../Commands/HeadCommand.cs | 9 + .../Commands/HelpCommand.cs | 172 ++++++ .../Commands/ListCommand.cs | 160 +++++ .../Commands/OptionsCommand.cs | 9 + .../Commands/PatchCommand.cs | 9 + .../Commands/PostCommand.cs | 9 + .../Commands/PrefCommand.cs | 172 ++++++ src/Microsoft.HttpRepl/Commands/PutCommand.cs | 9 + src/Microsoft.HttpRepl/Commands/RunCommand.cs | 80 +++ .../Commands/SetBaseCommand.cs | 100 +++ .../Commands/SetDiagCommand.cs | 138 +++++ .../Commands/SetHeaderCommand.cs | 92 +++ .../Commands/SetSwaggerCommand.cs | 272 +++++++++ src/Microsoft.HttpRepl/Commands/TreeNode.cs | 47 ++ src/Microsoft.HttpRepl/Commands/UICommand.cs | 78 +++ .../Diagnostics/ConfigItem.cs | 9 + .../Diagnostics/DiagEndpoint.cs | 9 + .../Diagnostics/DiagEndpointMetadata.cs | 9 + .../Diagnostics/DiagItem.cs | 11 + .../Diagnostics/DiagnosticsState.cs | 13 + src/Microsoft.HttpRepl/DirectoryStructure.cs | 105 ++++ .../DirectoryStructureExtensions.cs | 57 ++ .../Formatting/JsonVisitor.cs | 111 ++++ src/Microsoft.HttpRepl/HttpState.cs | 370 +++++++++++ src/Microsoft.HttpRepl/IDirectoryStructure.cs | 24 + .../Microsoft.HttpRepl.csproj | 31 + src/Microsoft.HttpRepl/OpenApi/Either.cs | 33 + .../OpenApi/EitherConverter.cs | 32 + .../OpenApi/EndpointMetadata.cs | 17 + .../OpenApi/EndpointMetadataReader.cs | 38 ++ .../OpenApi/IEndpointMetadataReader.cs | 12 + .../OpenApiV3EndpointMetadataReader.cs | 98 +++ src/Microsoft.HttpRepl/OpenApi/Parameter.cs | 13 + src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs | 218 +++++++ src/Microsoft.HttpRepl/OpenApi/Schema.cs | 125 ++++ .../SwaggerV1EndpointMetadataReader.cs | 106 ++++ .../SwaggerV2EndpointMetadataReader.cs | 87 +++ .../Preferences/IJsonConfig.cs | 29 + .../Preferences/JsonConfig.cs | 42 ++ .../Preferences/RequestConfig.cs | 46 ++ .../Preferences/RequestOrResponseConfig.cs | 44 ++ .../Preferences/ResponseConfig.cs | 42 ++ .../Preferences/WellKnownPreference.cs | 200 ++++++ src/Microsoft.HttpRepl/Program.cs | 52 ++ .../Properties/launchSettings.json | 8 + .../Suggestions/HeaderCompletion.cs | 97 +++ .../Suggestions/ServerPathCompletion.cs | 54 ++ .../Commanding/CommandHistory.cs | 75 +++ .../Commanding/CommandInputLocation.cs | 10 + .../Commanding/CommandInputProcessingIssue.cs | 15 + .../CommandInputProcessingIssueKind.cs | 11 + .../Commanding/CommandInputSpecification.cs | 44 ++ .../CommandInputSpecificationBuilder.cs | 66 ++ .../Commanding/CommandOptionSpecification.cs | 29 + .../CommandWithStructuredInputBase.cs | 193 ++++++ .../Commanding/DefaultCommandDispatcher.cs | 169 ++++++ .../Commanding/DefaultCommandInput.cs | 193 ++++++ src/Microsoft.Repl/Commanding/ICommand.cs | 21 + .../Commanding/ICommandDispatcher.cs | 24 + .../Commanding/ICommandHistory.cs | 15 + src/Microsoft.Repl/Commanding/InputElement.cs | 29 + .../ConsoleHandling/AllowedColors.cs | 27 + .../ConsoleHandling/AnsiColorExtensions.cs | 80 +++ .../ConsoleHandling/AnsiConsole.cs | 151 +++++ .../ConsoleHandling/ConsoleManager.cs | 204 +++++++ .../ConsoleHandling/IConsoleManager.cs | 28 + .../ConsoleHandling/IWritable.cs | 15 + src/Microsoft.Repl/ConsoleHandling/Point.cs | 50 ++ .../ConsoleHandling/Reporter.cs | 115 ++++ .../ConsoleHandling/Writable.cs | 54 ++ src/Microsoft.Repl/Disposable.cs | 42 ++ src/Microsoft.Repl/IShellState.cs | 22 + .../Input/AsyncKeyPressHandler.cs | 8 + src/Microsoft.Repl/Input/IInputManager.cs | 27 + src/Microsoft.Repl/Input/InputManager.cs | 344 +++++++++++ src/Microsoft.Repl/Input/KeyHandlers.cs | 239 ++++++++ src/Microsoft.Repl/Microsoft.Repl.csproj | 9 + src/Microsoft.Repl/Parsing/CoreParseResult.cs | 78 +++ src/Microsoft.Repl/Parsing/CoreParser.cs | 129 ++++ .../Parsing/ICoreParseResult.cs | 23 + src/Microsoft.Repl/Parsing/IParser.cs | 12 + .../Scripting/IScriptExecutor.cs | 11 + .../Scripting/ScriptExecutor.cs | 49 ++ src/Microsoft.Repl/Shell.cs | 30 + src/Microsoft.Repl/ShellState.cs | 31 + .../Suggestions/FileSystemCompletion.cs | 52 ++ .../Suggestions/ISuggestionManager.cs | 9 + .../Suggestions/SuggestionManager.cs | 95 +++ src/Microsoft.Repl/Utils.cs | 12 + .../JsonVisitorTests.cs | 60 ++ .../Microsoft.HttpRepl.Tests.csproj | 21 + .../Microsoft.Repl.Tests.csproj | 19 + test/Microsoft.Repl.Tests/ParserTests.cs | 26 + 106 files changed, 7485 insertions(+) create mode 100644 src/Microsoft.HttpRepl/AggregateDirectoryStructure.cs create mode 100644 src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/ChangeDirectoryCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/ClearCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/ConfigCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/DeleteCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/EchoCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/ExitCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/Formatter.cs create mode 100644 src/Microsoft.HttpRepl/Commands/GetCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/HeadCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/HelpCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/ListCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/OptionsCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/PatchCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/PostCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/PrefCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/PutCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/RunCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/SetDiagCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/SetHeaderCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/SetSwaggerCommand.cs create mode 100644 src/Microsoft.HttpRepl/Commands/TreeNode.cs create mode 100644 src/Microsoft.HttpRepl/Commands/UICommand.cs create mode 100644 src/Microsoft.HttpRepl/Diagnostics/ConfigItem.cs create mode 100644 src/Microsoft.HttpRepl/Diagnostics/DiagEndpoint.cs create mode 100644 src/Microsoft.HttpRepl/Diagnostics/DiagEndpointMetadata.cs create mode 100644 src/Microsoft.HttpRepl/Diagnostics/DiagItem.cs create mode 100644 src/Microsoft.HttpRepl/Diagnostics/DiagnosticsState.cs create mode 100644 src/Microsoft.HttpRepl/DirectoryStructure.cs create mode 100644 src/Microsoft.HttpRepl/DirectoryStructureExtensions.cs create mode 100644 src/Microsoft.HttpRepl/Formatting/JsonVisitor.cs create mode 100644 src/Microsoft.HttpRepl/HttpState.cs create mode 100644 src/Microsoft.HttpRepl/IDirectoryStructure.cs create mode 100644 src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj create mode 100644 src/Microsoft.HttpRepl/OpenApi/Either.cs create mode 100644 src/Microsoft.HttpRepl/OpenApi/EitherConverter.cs create mode 100644 src/Microsoft.HttpRepl/OpenApi/EndpointMetadata.cs create mode 100644 src/Microsoft.HttpRepl/OpenApi/EndpointMetadataReader.cs create mode 100644 src/Microsoft.HttpRepl/OpenApi/IEndpointMetadataReader.cs create mode 100644 src/Microsoft.HttpRepl/OpenApi/OpenApiV3EndpointMetadataReader.cs create mode 100644 src/Microsoft.HttpRepl/OpenApi/Parameter.cs create mode 100644 src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs create mode 100644 src/Microsoft.HttpRepl/OpenApi/Schema.cs create mode 100644 src/Microsoft.HttpRepl/OpenApi/SwaggerV1EndpointMetadataReader.cs create mode 100644 src/Microsoft.HttpRepl/OpenApi/SwaggerV2EndpointMetadataReader.cs create mode 100644 src/Microsoft.HttpRepl/Preferences/IJsonConfig.cs create mode 100644 src/Microsoft.HttpRepl/Preferences/JsonConfig.cs create mode 100644 src/Microsoft.HttpRepl/Preferences/RequestConfig.cs create mode 100644 src/Microsoft.HttpRepl/Preferences/RequestOrResponseConfig.cs create mode 100644 src/Microsoft.HttpRepl/Preferences/ResponseConfig.cs create mode 100644 src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs create mode 100644 src/Microsoft.HttpRepl/Program.cs create mode 100644 src/Microsoft.HttpRepl/Properties/launchSettings.json create mode 100644 src/Microsoft.HttpRepl/Suggestions/HeaderCompletion.cs create mode 100644 src/Microsoft.HttpRepl/Suggestions/ServerPathCompletion.cs create mode 100644 src/Microsoft.Repl/Commanding/CommandHistory.cs create mode 100644 src/Microsoft.Repl/Commanding/CommandInputLocation.cs create mode 100644 src/Microsoft.Repl/Commanding/CommandInputProcessingIssue.cs create mode 100644 src/Microsoft.Repl/Commanding/CommandInputProcessingIssueKind.cs create mode 100644 src/Microsoft.Repl/Commanding/CommandInputSpecification.cs create mode 100644 src/Microsoft.Repl/Commanding/CommandInputSpecificationBuilder.cs create mode 100644 src/Microsoft.Repl/Commanding/CommandOptionSpecification.cs create mode 100644 src/Microsoft.Repl/Commanding/CommandWithStructuredInputBase.cs create mode 100644 src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs create mode 100644 src/Microsoft.Repl/Commanding/DefaultCommandInput.cs create mode 100644 src/Microsoft.Repl/Commanding/ICommand.cs create mode 100644 src/Microsoft.Repl/Commanding/ICommandDispatcher.cs create mode 100644 src/Microsoft.Repl/Commanding/ICommandHistory.cs create mode 100644 src/Microsoft.Repl/Commanding/InputElement.cs create mode 100644 src/Microsoft.Repl/ConsoleHandling/AllowedColors.cs create mode 100644 src/Microsoft.Repl/ConsoleHandling/AnsiColorExtensions.cs create mode 100644 src/Microsoft.Repl/ConsoleHandling/AnsiConsole.cs create mode 100644 src/Microsoft.Repl/ConsoleHandling/ConsoleManager.cs create mode 100644 src/Microsoft.Repl/ConsoleHandling/IConsoleManager.cs create mode 100644 src/Microsoft.Repl/ConsoleHandling/IWritable.cs create mode 100644 src/Microsoft.Repl/ConsoleHandling/Point.cs create mode 100644 src/Microsoft.Repl/ConsoleHandling/Reporter.cs create mode 100644 src/Microsoft.Repl/ConsoleHandling/Writable.cs create mode 100644 src/Microsoft.Repl/Disposable.cs create mode 100644 src/Microsoft.Repl/IShellState.cs create mode 100644 src/Microsoft.Repl/Input/AsyncKeyPressHandler.cs create mode 100644 src/Microsoft.Repl/Input/IInputManager.cs create mode 100644 src/Microsoft.Repl/Input/InputManager.cs create mode 100644 src/Microsoft.Repl/Input/KeyHandlers.cs create mode 100644 src/Microsoft.Repl/Microsoft.Repl.csproj create mode 100644 src/Microsoft.Repl/Parsing/CoreParseResult.cs create mode 100644 src/Microsoft.Repl/Parsing/CoreParser.cs create mode 100644 src/Microsoft.Repl/Parsing/ICoreParseResult.cs create mode 100644 src/Microsoft.Repl/Parsing/IParser.cs create mode 100644 src/Microsoft.Repl/Scripting/IScriptExecutor.cs create mode 100644 src/Microsoft.Repl/Scripting/ScriptExecutor.cs create mode 100644 src/Microsoft.Repl/Shell.cs create mode 100644 src/Microsoft.Repl/ShellState.cs create mode 100644 src/Microsoft.Repl/Suggestions/FileSystemCompletion.cs create mode 100644 src/Microsoft.Repl/Suggestions/ISuggestionManager.cs create mode 100644 src/Microsoft.Repl/Suggestions/SuggestionManager.cs create mode 100644 src/Microsoft.Repl/Utils.cs create mode 100644 test/Microsoft.HttpRepl.Tests/JsonVisitorTests.cs create mode 100644 test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj create mode 100644 test/Microsoft.Repl.Tests/Microsoft.Repl.Tests.csproj create mode 100644 test/Microsoft.Repl.Tests/ParserTests.cs diff --git a/DotNetTools.sln b/DotNetTools.sln index 82fefe40d0..d996c043b6 100644 --- a/DotNetTools.sln +++ b/DotNetTools.sln @@ -56,6 +56,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.VisualStudio.Secr EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DeveloperCertificates.XPlat", "src\Microsoft.AspNetCore.DeveloperCertificates.XPlat\Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj", "{96E71881-1465-44F5-B4B7-DF9B370FFD02}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.HttpRepl", "src\Microsoft.HttpRepl\Microsoft.HttpRepl.csproj", "{4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Repl", "src\Microsoft.Repl\Microsoft.Repl.csproj", "{EE9A6128-3DE2-4206-A5A4-3ED935084590}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Repl.Tests", "test\Microsoft.Repl.Tests\Microsoft.Repl.Tests.csproj", "{59C2B354-3B5E-40EB-A7BC-74583A5707CA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.HttpRepl.Tests", "test\Microsoft.HttpRepl.Tests\Microsoft.HttpRepl.Tests.csproj", "{BE7CC4CD-CD76-4211-B593-CAC84407162A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -140,6 +148,38 @@ Global {96E71881-1465-44F5-B4B7-DF9B370FFD02}.Release|Any CPU.Build.0 = Release|Any CPU {96E71881-1465-44F5-B4B7-DF9B370FFD02}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU {96E71881-1465-44F5-B4B7-DF9B370FFD02}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU + {4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU + {4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU + {4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.Release|Any CPU.Build.0 = Release|Any CPU + {4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU + {4725BEAD-34F0-43C1-BF46-7AB16B4DE81D}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU + {EE9A6128-3DE2-4206-A5A4-3ED935084590}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EE9A6128-3DE2-4206-A5A4-3ED935084590}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EE9A6128-3DE2-4206-A5A4-3ED935084590}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU + {EE9A6128-3DE2-4206-A5A4-3ED935084590}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU + {EE9A6128-3DE2-4206-A5A4-3ED935084590}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EE9A6128-3DE2-4206-A5A4-3ED935084590}.Release|Any CPU.Build.0 = Release|Any CPU + {EE9A6128-3DE2-4206-A5A4-3ED935084590}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU + {EE9A6128-3DE2-4206-A5A4-3ED935084590}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU + {59C2B354-3B5E-40EB-A7BC-74583A5707CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {59C2B354-3B5E-40EB-A7BC-74583A5707CA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {59C2B354-3B5E-40EB-A7BC-74583A5707CA}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU + {59C2B354-3B5E-40EB-A7BC-74583A5707CA}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU + {59C2B354-3B5E-40EB-A7BC-74583A5707CA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {59C2B354-3B5E-40EB-A7BC-74583A5707CA}.Release|Any CPU.Build.0 = Release|Any CPU + {59C2B354-3B5E-40EB-A7BC-74583A5707CA}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU + {59C2B354-3B5E-40EB-A7BC-74583A5707CA}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU + {BE7CC4CD-CD76-4211-B593-CAC84407162A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE7CC4CD-CD76-4211-B593-CAC84407162A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE7CC4CD-CD76-4211-B593-CAC84407162A}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU + {BE7CC4CD-CD76-4211-B593-CAC84407162A}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU + {BE7CC4CD-CD76-4211-B593-CAC84407162A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE7CC4CD-CD76-4211-B593-CAC84407162A}.Release|Any CPU.Build.0 = Release|Any CPU + {BE7CC4CD-CD76-4211-B593-CAC84407162A}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU + {BE7CC4CD-CD76-4211-B593-CAC84407162A}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -155,6 +195,10 @@ Global {5E117F2E-7152-447F-BF47-59F759EEF3A7} = {62826851-7D74-4F1E-B7D1-12553B789CD8} {965F8820-F809-4081-9090-1AEC903F291B} = {62826851-7D74-4F1E-B7D1-12553B789CD8} {96E71881-1465-44F5-B4B7-DF9B370FFD02} = {66517987-2A5A-4330-B130-207039378FD4} + {4725BEAD-34F0-43C1-BF46-7AB16B4DE81D} = {66517987-2A5A-4330-B130-207039378FD4} + {EE9A6128-3DE2-4206-A5A4-3ED935084590} = {66517987-2A5A-4330-B130-207039378FD4} + {59C2B354-3B5E-40EB-A7BC-74583A5707CA} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} + {BE7CC4CD-CD76-4211-B593-CAC84407162A} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {57C07F14-2EAC-44FF-A277-B9221B4B2BF7} diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index fb43448889..4167e36811 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -24,12 +24,33 @@ "DotnetTool" ] }, + "dotnet-httprepl": { + "packageTypes": [ + "DotnetTool" + ], + "Exclusions": { + "ASSEMBLY_DESCRIPTION": { + "tools/netcoreapp2.2/any/System.Net.Http.Formatting.dll": "Referenced assembly, not built as part of this process" + }, + "VERSION_INFORMATIONALVERSION": { + "tools/netcoreapp2.2/any/Newtonsoft.Json.dll": "Referenced assembly, not built as part of this process", + "tools/netcoreapp2.2/any/Newtonsoft.Json.Bson.dll": "Referenced assembly, not built as part of this process" + } + } + }, "Microsoft.AspNetCore.DeveloperCertificates.XPlat": { "Exclusions": { "DOC_MISSING": { "lib/netcoreapp2.2/Microsoft.AspNetCore.DeveloperCertificates.XPlat.dll": "Docs not required to shipoob package" } } + }, + "Microsoft.Repl": { + "Exclusions": { + "DOC_MISSING": { + "lib/netcoreapp2.2/Microsoft.Repl.dll": "Docs not required to shipoob package" + } + } } } }, diff --git a/build/dependencies.props b/build/dependencies.props index 0f57ae33b0..0c7d2bca9d 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -13,9 +13,11 @@ 2.1.2 2.2.0-preview1-26618-02 15.6.1 + 5.2.6 2.0.3 4.5.1 4.5.0 + 10.0.1 9.0.1 2.3.1 2.4.0 diff --git a/src/Microsoft.HttpRepl/AggregateDirectoryStructure.cs b/src/Microsoft.HttpRepl/AggregateDirectoryStructure.cs new file mode 100644 index 0000000000..ed763a3e8f --- /dev/null +++ b/src/Microsoft.HttpRepl/AggregateDirectoryStructure.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.HttpRepl +{ + public class AggregateDirectoryStructure : IDirectoryStructure + { + private readonly IDirectoryStructure _first; + private readonly IDirectoryStructure _second; + + public AggregateDirectoryStructure(IDirectoryStructure first, IDirectoryStructure second) + { + _first = first; + _second = second; + } + + public IEnumerable DirectoryNames + { + get + { + HashSet values = new HashSet(StringComparer.OrdinalIgnoreCase); + values.UnionWith(_first.DirectoryNames); + values.UnionWith(_second.DirectoryNames); + return values.OrderBy(x => x, StringComparer.OrdinalIgnoreCase); + } + } + + public IDirectoryStructure Parent => _first.Parent ?? _second.Parent; + + public IDirectoryStructure GetChildDirectory(string name) + { + return new AggregateDirectoryStructure(_first.GetChildDirectory(name), _second.GetChildDirectory(name)); + } + + public IRequestInfo RequestInfo => _first.RequestInfo ?? _second.RequestInfo; + } +} diff --git a/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs b/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs new file mode 100644 index 0000000000..3db2f39b7b --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs @@ -0,0 +1,574 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Xml.Linq; +using Microsoft.HttpRepl.Formatting; +using Microsoft.HttpRepl.Preferences; +using Microsoft.HttpRepl.Suggestions; +using Microsoft.Repl; +using Microsoft.Repl.Commanding; +using Microsoft.Repl.ConsoleHandling; +using Microsoft.Repl.Parsing; +using Microsoft.Repl.Suggestions; +using Newtonsoft.Json.Linq; + +namespace Microsoft.HttpRepl.Commands +{ + public abstract class BaseHttpCommand : CommandWithStructuredInputBase + { + private const string HeaderOption = nameof(HeaderOption); + private const string ResponseHeadersFileOption = nameof(ResponseHeadersFileOption); + private const string ResponseBodyFileOption = nameof(ResponseBodyFileOption); + private const string ResponseFileOption = nameof(ResponseFileOption); + private const string BodyFileOption = nameof(BodyFileOption); + private const string NoBodyOption = nameof(NoBodyOption); + private const string BodyContentOption = nameof(BodyContentOption); + private static readonly char[] HeaderSeparatorChars = new[] { '=', ':' }; + + private CommandInputSpecification _inputSpec; + + protected abstract string Verb { get; } + + protected abstract bool RequiresBody { get; } + + protected override CommandInputSpecification InputSpec + { + get + { + if (_inputSpec != null) + { + return _inputSpec; + } + + CommandInputSpecificationBuilder builder = CommandInputSpecification.Create(Verb) + .MaximumArgCount(1) + .WithOption(new CommandOptionSpecification(HeaderOption, requiresValue: true, forms: new[] {"--header", "-h"})) + .WithOption(new CommandOptionSpecification(ResponseFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] { "--response", })) + .WithOption(new CommandOptionSpecification(ResponseHeadersFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] { "--response:headers", })) + .WithOption(new CommandOptionSpecification(ResponseBodyFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] { "--response:body", })); + + if (RequiresBody) + { + builder = builder.WithOption(new CommandOptionSpecification(NoBodyOption, maximumOccurrences: 1, forms: "--no-body")) + .WithOption(new CommandOptionSpecification(BodyFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] {"--file", "-f"})) + .WithOption(new CommandOptionSpecification(BodyContentOption, requiresValue: true, maximumOccurrences: 1, forms: new[] {"--content", "-c"})); + } + + _inputSpec = builder.Finish(); + return _inputSpec; + } + } + + protected override async Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) + { + if (programState.BaseAddress == null) + { + shellState.ConsoleManager.Error.WriteLine("'set base {url}' must be called before issuing requests".Bold().Red()); + return; + } + + Dictionary thisRequestHeaders = new Dictionary(); + + foreach (InputElement header in commandInput.Options[HeaderOption]) + { + int equalsIndex = header.Text.IndexOfAny(HeaderSeparatorChars); + + if (equalsIndex < 0) + { + shellState.ConsoleManager.Error.WriteLine("Headers must be formatted as {header}={value} or {header}:{value}".Bold().Red()); + return; + } + + thisRequestHeaders[header.Text.Substring(0, equalsIndex)] = header.Text.Substring(equalsIndex + 1); + } + + Uri effectivePath = programState.GetEffectivePath(commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty); + HttpRequestMessage request = new HttpRequestMessage(new HttpMethod(Verb.ToUpperInvariant()), effectivePath); + bool noBody = false; + + if (RequiresBody) + { + string filePath = null; + string bodyContent = null; + bool deleteFile = false; + noBody = commandInput.Options[NoBodyOption].Count > 0; + + if (!noBody) + { + if (commandInput.Options[BodyFileOption].Count > 0) + { + filePath = commandInput.Options[BodyFileOption][0].Text; + + if (!File.Exists(filePath)) + { + shellState.ConsoleManager.Error.WriteLine($"Content file {filePath} does not exist".Bold().Red()); + return; + } + } + else if (commandInput.Options[BodyContentOption].Count > 0) + { + bodyContent = commandInput.Options[BodyContentOption][0].Text; + } + else + { + string defaultEditorCommand = programState.GetStringPreference(WellKnownPreference.DefaultEditorCommand); + if (defaultEditorCommand == null) + { + shellState.ConsoleManager.Error.WriteLine($"The default editor must be configured using the command `pref set {WellKnownPreference.DefaultEditorCommand} \"{{commandline}}\"`".Bold().Red()); + return; + } + + deleteFile = true; + filePath = Path.GetTempFileName(); + + if (!thisRequestHeaders.TryGetValue("content-type", out string contentType) && programState.Headers.TryGetValue("content-type", out IEnumerable contentTypes)) + { + contentType = contentTypes.FirstOrDefault(); + } + + if (contentType == null) + { + contentType = "application/json"; + } + + string exampleBody = programState.GetExampleBody(commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty, contentType, Verb); + + if (!string.IsNullOrEmpty(exampleBody)) + { + File.WriteAllText(filePath, exampleBody); + } + + string defaultEditorArguments = programState.GetStringPreference(WellKnownPreference.DefaultEditorArguments) ?? ""; + string original = defaultEditorArguments; + string pathString = $"\"{filePath}\""; + + defaultEditorArguments = defaultEditorArguments.Replace("{filename}", pathString); + + if (string.Equals(defaultEditorArguments, original, StringComparison.Ordinal)) + { + defaultEditorArguments = (defaultEditorArguments + " " + pathString).Trim(); + } + + ProcessStartInfo info = new ProcessStartInfo(defaultEditorCommand, defaultEditorArguments); + + Process.Start(info)?.WaitForExit(); + } + } + + byte[] data = noBody + ? new byte[0] + : string.IsNullOrEmpty(bodyContent) + ? File.ReadAllBytes(filePath) + : Encoding.UTF8.GetBytes(bodyContent); + + HttpContent content = new ByteArrayContent(data); + request.Content = content; + + if (deleteFile) + { + File.Delete(filePath); + } + + foreach (KeyValuePair> header in programState.Headers) + { + content.Headers.TryAddWithoutValidation(header.Key, header.Value); + } + + foreach (KeyValuePair header in thisRequestHeaders) + { + content.Headers.TryAddWithoutValidation(header.Key, header.Value); + } + } + + foreach (KeyValuePair> header in programState.Headers) + { + request.Headers.TryAddWithoutValidation(header.Key, header.Value); + } + + foreach (KeyValuePair header in thisRequestHeaders) + { + request.Headers.TryAddWithoutValidation(header.Key, header.Value); + } + + string headersTarget = commandInput.Options[ResponseHeadersFileOption].FirstOrDefault()?.Text ?? commandInput.Options[ResponseFileOption].FirstOrDefault()?.Text; + string bodyTarget = commandInput.Options[ResponseBodyFileOption].FirstOrDefault()?.Text ?? commandInput.Options[ResponseFileOption].FirstOrDefault()?.Text; + + HttpResponseMessage response = await programState.Client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + await HandleResponseAsync(programState, shellState.ConsoleManager, response, programState.EchoRequest, headersTarget, bodyTarget, cancellationToken).ConfigureAwait(false); + } + + private static async Task HandleResponseAsync(HttpState programState, IConsoleManager consoleManager, HttpResponseMessage response, bool echoRequest, string headersTargetFile, string bodyTargetFile, CancellationToken cancellationToken) + { + RequestConfig requestConfig = new RequestConfig(programState); + ResponseConfig responseConfig = new ResponseConfig(programState); + string protocolInfo; + + if (echoRequest) + { + string hostString = response.RequestMessage.RequestUri.Scheme + "://" + response.RequestMessage.RequestUri.Host + (!response.RequestMessage.RequestUri.IsDefaultPort ? ":" + response.RequestMessage.RequestUri.Port : ""); + consoleManager.WriteLine($"Request to {hostString}...".SetColor(requestConfig.AddressColor)); + consoleManager.WriteLine(); + + string method = response.RequestMessage.Method.ToString().ToUpperInvariant().SetColor(requestConfig.MethodColor); + string pathAndQuery = response.RequestMessage.RequestUri.PathAndQuery.SetColor(requestConfig.AddressColor); + protocolInfo = $"{"HTTP".SetColor(requestConfig.ProtocolNameColor)}{"/".SetColor(requestConfig.ProtocolSeparatorColor)}{response.RequestMessage.Version.ToString().SetColor(requestConfig.ProtocolVersionColor)}"; + + consoleManager.WriteLine($"{method} {pathAndQuery} {protocolInfo}"); + IEnumerable>> requestHeaders = response.RequestMessage.Headers; + + if (response.RequestMessage.Content != null) + { + requestHeaders = requestHeaders.Union(response.RequestMessage.Content.Headers); + } + + foreach (KeyValuePair> header in requestHeaders.OrderBy(x => x.Key)) + { + string headerKey = header.Key.SetColor(requestConfig.HeaderKeyColor); + string headerSep = ":".SetColor(requestConfig.HeaderSeparatorColor); + string headerValue = string.Join(";".SetColor(requestConfig.HeaderValueSeparatorColor), header.Value.Select(x => x.Trim().SetColor(requestConfig.HeaderValueColor))); + consoleManager.WriteLine($"{headerKey}{headerSep} {headerValue}"); + } + + consoleManager.WriteLine(); + + if (response.RequestMessage.Content != null) + { + using (StreamWriter writer = new StreamWriter(new MemoryStream())) + { + await FormatBodyAsync(programState, consoleManager, response.RequestMessage.Content, writer, cancellationToken).ConfigureAwait(false); + } + } + + consoleManager.WriteLine(); + consoleManager.WriteLine($"Response from {hostString}...".SetColor(requestConfig.AddressColor)); + consoleManager.WriteLine(); + } + + protocolInfo = $"{"HTTP".SetColor(responseConfig.ProtocolNameColor)}{"/".SetColor(responseConfig.ProtocolSeparatorColor)}{response.Version.ToString().SetColor(responseConfig.ProtocolVersionColor)}"; + string status = ((int)response.StatusCode).ToString().SetColor(responseConfig.StatusCodeColor) + " " + response.ReasonPhrase.SetColor(responseConfig.StatusReasonPhraseColor); + + consoleManager.WriteLine($"{protocolInfo} {status}"); + + IEnumerable>> responseHeaders = response.Headers; + + if (response.Content != null) + { + responseHeaders = responseHeaders.Union(response.Content.Headers); + } + + StreamWriter headerFileWriter; + + if (headersTargetFile != null) + { + headerFileWriter = new StreamWriter(File.Create(headersTargetFile)); + } + else + { + headerFileWriter = new StreamWriter(new MemoryStream()); + } + + foreach (KeyValuePair> header in responseHeaders.OrderBy(x => x.Key)) + { + string headerKey = header.Key.SetColor(responseConfig.HeaderKeyColor); + string headerSep = ":".SetColor(responseConfig.HeaderSeparatorColor); + string headerValue = string.Join(";".SetColor(responseConfig.HeaderValueSeparatorColor), header.Value.Select(x => x.Trim().SetColor(responseConfig.HeaderValueColor))); + consoleManager.WriteLine($"{headerKey}{headerSep} {headerValue}"); + headerFileWriter.WriteLine($"{header.Key}: {string.Join(";", header.Value.Select(x => x.Trim()))}"); + } + + StreamWriter bodyFileWriter; + if (!string.Equals(headersTargetFile, bodyTargetFile, StringComparison.Ordinal)) + { + headerFileWriter.Flush(); + headerFileWriter.Close(); + headerFileWriter.Dispose(); + + if (bodyTargetFile != null) + { + bodyFileWriter = new StreamWriter(File.Create(bodyTargetFile)); + } + else + { + bodyFileWriter = new StreamWriter(new MemoryStream()); + } + } + else + { + headerFileWriter.WriteLine(); + bodyFileWriter = headerFileWriter; + } + + consoleManager.WriteLine(); + + if (response.Content != null) + { + await FormatBodyAsync(programState, consoleManager, response.Content, bodyFileWriter, cancellationToken).ConfigureAwait(false); + } + + bodyFileWriter.Flush(); + bodyFileWriter.Close(); + bodyFileWriter.Dispose(); + + consoleManager.WriteLine(); + } + + private static async Task FormatBodyAsync(HttpState programState, IConsoleManager consoleManager, HttpContent content, StreamWriter bodyFileWriter, CancellationToken cancellationToken) + { + string contentType = null; + if (content.Headers.TryGetValues("Content-Type", out IEnumerable contentTypeValues)) + { + contentType = contentTypeValues.FirstOrDefault()?.Split(';').FirstOrDefault(); + } + + contentType = contentType?.ToUpperInvariant() ?? "text/plain"; + + if (contentType.EndsWith("/JSON", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("-JSON", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("+JSON", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("/JAVASCRIPT", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("-JAVASCRIPT", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("+JAVASCRIPT", StringComparison.OrdinalIgnoreCase)) + { + if (await FormatJsonAsync(programState, consoleManager, content, bodyFileWriter)) + { + return; + } + } + else if (contentType.EndsWith("/HTML", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("-HTML", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("+HTML", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("/XML", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("-XML", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("+XML", StringComparison.OrdinalIgnoreCase)) + { + if (await FormatXmlAsync(consoleManager, content, bodyFileWriter)) + { + return; + } + } + + //If we don't have content length, assume streaming + if (!content.Headers.TryGetValues("Content-Length", out IEnumerable _)) + { + Memory buffer = new Memory(new char[2048]); + Stream s = await content.ReadAsStreamAsync().ConfigureAwait(false); + StreamReader reader = new StreamReader(s); + consoleManager.WriteLine("Streaming the response, press any key to stop...".Bold().Yellow()); + + while (!cancellationToken.IsCancellationRequested) + { + try + { + ValueTask readTask = reader.ReadAsync(buffer, cancellationToken); + if (await WaitForCompletionAsync(readTask, cancellationToken).ConfigureAwait(false)) + { + if (readTask.Result == 0) + { + break; + } + + string str = new string(buffer.Span.Slice(0, readTask.Result)); + consoleManager.Write(str); + bodyFileWriter.Write(str); + } + else + { + break; + } + } + catch (OperationCanceledException) + { + } + } + + return; + } + + string responseContent = await content.ReadAsStringAsync().ConfigureAwait(false); + bodyFileWriter.WriteLine(responseContent); + consoleManager.WriteLine(responseContent); + } + + private static async Task WaitForCompletionAsync(ValueTask readTask, CancellationToken cancellationToken) + { + while (!readTask.IsCompleted && !cancellationToken.IsCancellationRequested && !Console.KeyAvailable) + { + await Task.Delay(1, cancellationToken).ConfigureAwait(false); + } + + if (Console.KeyAvailable) + { + Console.ReadKey(false); + return false; + } + + return readTask.IsCompleted; + } + + private static async Task FormatXmlAsync(IWritable consoleManager, HttpContent content, StreamWriter bodyFileWriter) + { + string responseContent = await content.ReadAsStringAsync().ConfigureAwait(false); + try + { + XDocument body = XDocument.Parse(responseContent); + consoleManager.WriteLine(body.ToString()); + bodyFileWriter.WriteLine(body.ToString()); + return true; + } + catch + { + } + + return false; + } + + private static async Task FormatJsonAsync(HttpState programState, IWritable outputSink, HttpContent content, StreamWriter bodyFileWriter) + { + string responseContent = await content.ReadAsStringAsync().ConfigureAwait(false); + + try + { + JsonConfig config = new JsonConfig(programState); + string formatted = JsonVisitor.FormatAndColorize(config, responseContent); + outputSink.WriteLine(formatted); + bodyFileWriter.WriteLine(JToken.Parse(responseContent).ToString()); + return true; + } + catch + { + } + + return false; + } + + protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult) + { + return $"Issues a {Verb.ToUpperInvariant()} request"; + } + + public override string GetHelpSummary(IShellState shellState, HttpState programState) + { + return $"{Verb.ToLowerInvariant()} - Issues a {Verb.ToUpperInvariant()} request"; + } + + protected override IEnumerable GetArgumentSuggestionsForText(IShellState shellState, HttpState programState, ICoreParseResult parseResult, DefaultCommandInput commandInput, string normalCompletionString) + { + List results = new List(); + + if (programState.Structure != null && programState.BaseAddress != null) + { + //If it's an absolute URI, nothing to suggest + if (Uri.TryCreate(parseResult.Sections[1], UriKind.Absolute, out Uri _)) + { + return null; + } + + string path = normalCompletionString.Replace('\\', '/'); + int searchFrom = normalCompletionString.Length - 1; + int lastSlash = path.LastIndexOf('/', searchFrom); + string prefix; + + if (lastSlash < 0) + { + path = string.Empty; + prefix = normalCompletionString; + } + else + { + path = path.Substring(0, lastSlash + 1); + prefix = normalCompletionString.Substring(lastSlash + 1); + } + + IDirectoryStructure s = programState.Structure.TraverseTo(programState.PathSections.Reverse()).TraverseTo(path); + + foreach (string child in s.DirectoryNames) + { + if (child.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) + { + results.Add(path + child); + } + } + } + + return results; + } + + protected override IEnumerable GetOptionValueCompletions(IShellState shellState, HttpState programState, string optionId, DefaultCommandInput commandInput, ICoreParseResult parseResult, string normalizedCompletionText) + { + if (string.Equals(optionId, BodyFileOption, StringComparison.Ordinal) || string.Equals(optionId, ResponseFileOption, StringComparison.OrdinalIgnoreCase) || string.Equals(optionId, ResponseBodyFileOption, StringComparison.OrdinalIgnoreCase) || string.Equals(optionId, ResponseHeadersFileOption, StringComparison.OrdinalIgnoreCase)) + { + return FileSystemCompletion.GetCompletions(normalizedCompletionText); + } + + if (string.Equals(optionId, HeaderOption, StringComparison.Ordinal)) + { + HashSet alreadySpecifiedHeaders = new HashSet(StringComparer.Ordinal); + IReadOnlyList options = commandInput.Options[HeaderOption]; + for (int i = 0; i < options.Count; ++i) + { + if (options[i] == commandInput.SelectedElement) + { + continue; + } + + string elementText = options[i].Text; + string existingHeaderName = elementText.Split(HeaderSeparatorChars)[0]; + alreadySpecifiedHeaders.Add(existingHeaderName); + } + + //Check to see if the selected element is in a header name or value + int equalsIndex = normalizedCompletionText.IndexOfAny(HeaderSeparatorChars); + string path = commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty; + + if (equalsIndex < 0) + { + IEnumerable headerNameOptions = HeaderCompletion.GetCompletions(alreadySpecifiedHeaders, normalizedCompletionText); + + if (headerNameOptions == null) + { + return null; + } + + List allSuggestions = new List(); + foreach (string suggestion in headerNameOptions.Select(x => x)) + { + allSuggestions.Add(suggestion + ":"); + + IEnumerable suggestions = HeaderCompletion.GetValueCompletions(Verb, path, suggestion, string.Empty, programState); + + if (suggestions != null) + { + foreach (string valueSuggestion in suggestions) + { + allSuggestions.Add(suggestion + ":" + valueSuggestion); + } + } + } + + return allSuggestions; + } + else + { + //Didn't exit from the header name check, so must be a value + string headerName = normalizedCompletionText.Substring(0, equalsIndex); + IEnumerable suggestions = HeaderCompletion.GetValueCompletions(Verb, path, headerName, normalizedCompletionText.Substring(equalsIndex + 1), programState); + + if (suggestions == null) + { + return null; + } + + return suggestions.Select(x => normalizedCompletionText.Substring(0, equalsIndex + 1) + x); + } + } + + return null; + } + } +} diff --git a/src/Microsoft.HttpRepl/Commands/ChangeDirectoryCommand.cs b/src/Microsoft.HttpRepl/Commands/ChangeDirectoryCommand.cs new file mode 100644 index 0000000000..3a983698cf --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/ChangeDirectoryCommand.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.HttpRepl.Suggestions; +using Microsoft.Repl; +using Microsoft.Repl.Commanding; +using Microsoft.Repl.Parsing; + +namespace Microsoft.HttpRepl.Commands +{ + public class ChangeDirectoryCommand : CommandWithStructuredInputBase + { + protected override Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) + { + if (commandInput.Arguments.Count == 0 || string.IsNullOrEmpty(commandInput.Arguments[0]?.Text)) + { + shellState.ConsoleManager.WriteLine($"/{string.Join("/", programState.PathSections.Reverse())}"); + } + else + { + string[] parts = commandInput.Arguments[0].Text.Replace('\\', '/').Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + + if (commandInput.Arguments[0].Text.StartsWith("/", StringComparison.Ordinal)) + { + programState.PathSections.Clear(); + } + + foreach (string part in parts) + { + switch (part) + { + case ".": + break; + case "..": + if (programState.PathSections.Count > 0) + { + programState.PathSections.Pop(); + } + break; + default: + programState.PathSections.Push(part); + break; + } + } + + shellState.ConsoleManager.WriteLine($"/{string.Join("/", programState.PathSections.Reverse())}"); + } + + return Task.CompletedTask; + } + + protected override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("cd") + .MaximumArgCount(1) + .Finish(); + + protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult) + { + if (commandInput.Arguments.Count == 1 && !string.IsNullOrEmpty(commandInput.Arguments[0]?.Text)) + { + return "Prints the current directory if no argument is specified, otherwise changes to the specified directory"; + } + + return "Changes to the directory " + commandInput.Arguments[0].Text; + } + + public override string GetHelpSummary(IShellState shellState, HttpState programState) + { + return "cd [directory name] - Prints the current directory if no argument is specified, otherwise changes to the specified directory"; + } + + protected override IEnumerable GetArgumentSuggestionsForText(IShellState shellState, HttpState programState, ICoreParseResult parseResult, DefaultCommandInput commandInput, string normalCompletionString) + { + return ServerPathCompletion.GetCompletions(programState, normalCompletionString); + } + } +} diff --git a/src/Microsoft.HttpRepl/Commands/ClearCommand.cs b/src/Microsoft.HttpRepl/Commands/ClearCommand.cs new file mode 100644 index 0000000000..a695dfc544 --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/ClearCommand.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Repl; +using Microsoft.Repl.Commanding; +using Microsoft.Repl.Parsing; + +namespace Microsoft.HttpRepl.Commands +{ + public class ClearCommand : ICommand + { + private static readonly string Name = "clear"; + private static readonly string AlternateName = "cls"; + + public bool? CanHandle(IShellState shellState, object programState, ICoreParseResult parseResult) + { + return parseResult.Sections.Count == 1 && (string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) || string.Equals(parseResult.Sections[0], AlternateName, StringComparison.OrdinalIgnoreCase)) + ? (bool?) true + : null; + } + + public Task ExecuteAsync(IShellState shellState, object programState, ICoreParseResult parseResult, CancellationToken cancellationToken) + { + shellState.ConsoleManager.Clear(); + shellState.CommandDispatcher.OnReady(shellState); + return Task.CompletedTask; + } + + public string GetHelpDetails(IShellState shellState, object programState, ICoreParseResult parseResult) + { + if (parseResult.Sections.Count == 1 && (string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) || string.Equals(parseResult.Sections[0], AlternateName, StringComparison.OrdinalIgnoreCase))) + { + return "Clears the shell"; + } + + return null; + } + + public string GetHelpSummary(IShellState shellState, object programState) + { + return "clear - Clears the shell"; + } + + public IEnumerable Suggest(IShellState shellState, object programState, ICoreParseResult parseResult) + { + if (parseResult.SelectedSection == 0 && + (string.IsNullOrEmpty(parseResult.Sections[parseResult.SelectedSection]) || Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase))) + { + return new[] { Name }; + } + + if (parseResult.SelectedSection == 0 && + (string.IsNullOrEmpty(parseResult.Sections[parseResult.SelectedSection]) || AlternateName.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase))) + { + return new[] { Name }; + } + + return null; + } + } +} diff --git a/src/Microsoft.HttpRepl/Commands/ConfigCommand.cs b/src/Microsoft.HttpRepl/Commands/ConfigCommand.cs new file mode 100644 index 0000000000..56003280ab --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/ConfigCommand.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.HttpRepl.Diagnostics; +using Microsoft.Repl; +using Microsoft.Repl.Commanding; +using Microsoft.Repl.ConsoleHandling; +using Microsoft.Repl.Parsing; + +namespace Microsoft.HttpRepl.Commands +{ + public class ConfigCommand : CommandWithStructuredInputBase + { + protected override async Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) + { + if (programState.BaseAddress == null) + { + shellState.ConsoleManager.Error.WriteLine("Must be connected to a server to query configuration".Bold().Red()); + return; + } + + if (string.IsNullOrEmpty(programState.DiagnosticsState.DiagnosticsEndpoint)) + { + shellState.ConsoleManager.Error.WriteLine("Diagnostics endpoint must be set to query configuration (see set diag)".Bold().Red()); + return; + } + + string configUrl = programState.DiagnosticsState.DiagnosticItems.FirstOrDefault(x => x.DisplayName == "Configuration")?.Url; + + if (configUrl == null) + { + shellState.ConsoleManager.Error.WriteLine("Diagnostics endpoint does not expose configuration information".Bold().Red()); + return; + } + + HttpResponseMessage response = await programState.Client.GetAsync(new Uri(programState.BaseAddress, configUrl), cancellationToken).ConfigureAwait(false); + + if (!response.IsSuccessStatusCode) + { + shellState.ConsoleManager.Error.WriteLine("Unable to get configuration information from diagnostics endpoint".Bold().Red()); + return; + } + + List configItems = await response.Content.ReadAsAsync>(cancellationToken).ConfigureAwait(false); + + foreach (ConfigItem item in configItems) + { + shellState.ConsoleManager.WriteLine($"{item.Key.Cyan()}: {item.Value}"); + } + } + + protected override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("config").Finish(); + + protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult) + { + return "config - Gets configuration information for the site if connected to a diagnostics endpoint"; + } + + public override string GetHelpSummary(IShellState shellState, HttpState programState) + { + return "config - Gets configuration information for the site if connected to a diagnostics endpoint"; + } + } +} diff --git a/src/Microsoft.HttpRepl/Commands/DeleteCommand.cs b/src/Microsoft.HttpRepl/Commands/DeleteCommand.cs new file mode 100644 index 0000000000..a861b35142 --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/DeleteCommand.cs @@ -0,0 +1,9 @@ +namespace Microsoft.HttpRepl.Commands +{ + public class DeleteCommand : BaseHttpCommand + { + protected override string Verb => "delete"; + + protected override bool RequiresBody => true; + } +} diff --git a/src/Microsoft.HttpRepl/Commands/EchoCommand.cs b/src/Microsoft.HttpRepl/Commands/EchoCommand.cs new file mode 100644 index 0000000000..19eb33788b --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/EchoCommand.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Repl; +using Microsoft.Repl.Commanding; +using Microsoft.Repl.ConsoleHandling; +using Microsoft.Repl.Parsing; + +namespace Microsoft.HttpRepl.Commands +{ + public class EchoCommand : CommandWithStructuredInputBase + { + private readonly HashSet _allowedModes = new HashSet(StringComparer.OrdinalIgnoreCase) {"on", "off"}; + + protected override bool CanHandle(IShellState shellState, HttpState programState, DefaultCommandInput commandInput) + { + if (commandInput.Arguments.Count == 0 || !_allowedModes.Contains(commandInput.Arguments[0]?.Text)) + { + shellState.ConsoleManager.Error.WriteLine("Allowed echo modes are 'on' and 'off'".Bold().Red()); + return false; + } + + return true; + } + + protected override Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) + { + bool turnOn = string.Equals(commandInput.Arguments[0].Text, "on", StringComparison.OrdinalIgnoreCase); + programState.EchoRequest = turnOn; + + shellState.ConsoleManager.WriteLine("Request echoing is " + (turnOn ? "on" : "off")); + return Task.CompletedTask; + } + + protected override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("echo").ExactArgCount(1).Finish(); + + protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult) + { + return "Turns request echoing on or off"; + } + + public override string GetHelpSummary(IShellState shellState, HttpState programState) + { + return "echo [on/off] - Turns request echoing on or off"; + } + + protected override IEnumerable GetArgumentSuggestionsForText(IShellState shellState, HttpState programState, ICoreParseResult parseResult, DefaultCommandInput commandInput, string normalCompletionString) + { + List result = _allowedModes.Where(x => x.StartsWith(normalCompletionString, StringComparison.OrdinalIgnoreCase)).ToList(); + return result.Count > 0 ? result : null; + } + } +} diff --git a/src/Microsoft.HttpRepl/Commands/ExitCommand.cs b/src/Microsoft.HttpRepl/Commands/ExitCommand.cs new file mode 100644 index 0000000000..ebc0635876 --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/ExitCommand.cs @@ -0,0 +1,29 @@ +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Repl; +using Microsoft.Repl.Commanding; +using Microsoft.Repl.Parsing; + +namespace Microsoft.HttpRepl.Commands +{ + public class ExitCommand : CommandWithStructuredInputBase + { + protected override Task ExecuteAsync(IShellState shellState, object programState, DefaultCommandInput commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) + { + shellState.IsExiting = true; + return Task.CompletedTask; + } + + protected override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("exit").ExactArgCount(0).Finish(); + + protected override string GetHelpDetails(IShellState shellState, object programState, DefaultCommandInput commandInput, ICoreParseResult parseResult) + { + return "Exits the shell"; + } + + public override string GetHelpSummary(IShellState shellState, object programState) + { + return "exit - Exits the shell"; + } + } +} diff --git a/src/Microsoft.HttpRepl/Commands/Formatter.cs b/src/Microsoft.HttpRepl/Commands/Formatter.cs new file mode 100644 index 0000000000..5a450e3406 --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/Formatter.cs @@ -0,0 +1,33 @@ +namespace Microsoft.HttpRepl.Commands +{ + public class Formatter + { + //private readonly List _prefix = new List(); + private int _prefix; + private int _maxDepth; + + public void RegisterEntry(int prefixLength, int depth) + { + //while (_prefix.Count < depth + 1) + //{ + // _prefix.Add(0); + //} + + if (depth > _maxDepth) + { + _maxDepth = depth; + } + + if (prefixLength > _prefix) + { + _prefix = prefixLength; + } + } + + public string Format(string prefix, string entry, int level) + { + string indent = "".PadRight(level * 4); + return (indent + prefix).PadRight(_prefix + 3 + _maxDepth * 4) + entry; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.HttpRepl/Commands/GetCommand.cs b/src/Microsoft.HttpRepl/Commands/GetCommand.cs new file mode 100644 index 0000000000..76765ce374 --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/GetCommand.cs @@ -0,0 +1,9 @@ +namespace Microsoft.HttpRepl.Commands +{ + public class GetCommand : BaseHttpCommand + { + protected override string Verb => "get"; + + protected override bool RequiresBody => false; + } +} diff --git a/src/Microsoft.HttpRepl/Commands/HeadCommand.cs b/src/Microsoft.HttpRepl/Commands/HeadCommand.cs new file mode 100644 index 0000000000..97023f5860 --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/HeadCommand.cs @@ -0,0 +1,9 @@ +namespace Microsoft.HttpRepl.Commands +{ + public class HeadCommand : BaseHttpCommand + { + protected override string Verb => "head"; + + protected override bool RequiresBody => false; + } +} diff --git a/src/Microsoft.HttpRepl/Commands/HelpCommand.cs b/src/Microsoft.HttpRepl/Commands/HelpCommand.cs new file mode 100644 index 0000000000..de909a4906 --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/HelpCommand.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.HttpRepl.Suggestions; +using Microsoft.Repl; +using Microsoft.Repl.Commanding; +using Microsoft.Repl.Parsing; + +namespace Microsoft.HttpRepl.Commands +{ + public class HelpCommand : ICommand + { + private static readonly string Name = "help"; + + public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + return parseResult.Sections.Count > 0 && string.Equals(parseResult.Sections[0], Name) + ? (bool?)true + : null; + } + + public Task ExecuteAsync(IShellState shellState, HttpState programState, ICoreParseResult parseResult, CancellationToken cancellationToken) + { + if (shellState.CommandDispatcher is ICommandDispatcher dispatcher) + { + if (parseResult.Sections.Count == 1) + { + foreach (ICommand command in dispatcher.Commands) + { + string help = command.GetHelpSummary(shellState, programState); + + if (!string.IsNullOrEmpty(help)) + { + shellState.ConsoleManager.WriteLine(help); + } + } + } + else + { + bool anyHelp = false; + + if (parseResult.Slice(1) is ICoreParseResult continuationParseResult) + { + foreach (ICommand command in dispatcher.Commands) + { + string help = command.GetHelpDetails(shellState, programState, continuationParseResult); + + if (!string.IsNullOrEmpty(help)) + { + anyHelp = true; + shellState.ConsoleManager.WriteLine(help); + } + } + } + + if (!anyHelp) + { + //Maybe the input is an URL + if (parseResult.Sections.Count == 2) + { + IDirectoryStructure structure = programState.Structure.TraverseTo(parseResult.Sections[1]); + if (structure.DirectoryNames.Any()) + { + shellState.ConsoleManager.WriteLine("Child directories:"); + + foreach (string name in structure.DirectoryNames) + { + shellState.ConsoleManager.WriteLine(" " + name + "/"); + } + + anyHelp = true; + } + + if (structure.RequestInfo != null) + { + if (structure.RequestInfo.Methods.Count > 0) + { + if (anyHelp) + { + shellState.ConsoleManager.WriteLine(); + } + + anyHelp = true; + shellState.ConsoleManager.WriteLine("Available methods:"); + + foreach (string method in structure.RequestInfo.Methods) + { + shellState.ConsoleManager.WriteLine(" " + method.ToUpperInvariant()); + IReadOnlyList accepts = structure.RequestInfo.ContentTypesByMethod[method]; + string acceptsString = string.Join(", ", accepts.Where(x => !string.IsNullOrEmpty(x))); + if (!string.IsNullOrEmpty(acceptsString)) + { + shellState.ConsoleManager.WriteLine(" Accepts: " + acceptsString); + } + } + } + } + } + + if (!anyHelp) + { + shellState.ConsoleManager.WriteLine("Unable to locate any help information for the specified command"); + } + } + } + } + + return Task.CompletedTask; + } + + public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + if (parseResult.Sections.Count > 0 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase)) + { + if (parseResult.Sections.Count > 1) + { + return "Gets help about " + parseResult.Slice(1).CommandText; + } + else + { + return "Gets help"; + } + } + + return null; + } + + public string GetHelpSummary(IShellState shellState, HttpState programState) + { + return "help - Gets help"; + } + + public IEnumerable Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + if (parseResult.SelectedSection == 0 && + (string.IsNullOrEmpty(parseResult.Sections[parseResult.SelectedSection]) || Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase))) + { + return new[] { Name }; + } + else if (parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase)) + { + if (shellState.CommandDispatcher is ICommandDispatcher dispatcher + && parseResult.Slice(1) is ICoreParseResult continuationParseResult) + { + HashSet suggestions = new HashSet(StringComparer.OrdinalIgnoreCase); + + foreach (ICommand command in dispatcher.Commands) + { + IEnumerable commandSuggestions = command.Suggest(shellState, programState, continuationParseResult); + + if (commandSuggestions != null) + { + suggestions.UnionWith(commandSuggestions); + } + } + + if (continuationParseResult.SelectedSection == 0) + { + string normalizedCompletionText = continuationParseResult.Sections[0].Substring(0, continuationParseResult.CaretPositionWithinSelectedSection); + suggestions.UnionWith(ServerPathCompletion.GetCompletions(programState, normalizedCompletionText)); + } + + return suggestions.OrderBy(x => x, StringComparer.OrdinalIgnoreCase).ToList(); + } + } + + return null; + } + } +} diff --git a/src/Microsoft.HttpRepl/Commands/ListCommand.cs b/src/Microsoft.HttpRepl/Commands/ListCommand.cs new file mode 100644 index 0000000000..078a20d398 --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/ListCommand.cs @@ -0,0 +1,160 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Repl; +using Microsoft.Repl.Commanding; +using Microsoft.Repl.Parsing; + +namespace Microsoft.HttpRepl.Commands +{ + public class ListCommand : CommandWithStructuredInputBase + { + private const string RecursiveOption = nameof(RecursiveOption); + + protected override Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) + { + if (programState.Structure == null || programState.BaseAddress == null) + { + return Task.CompletedTask; + } + + string path = commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty; + + //If it's an absolute URI, nothing to suggest + if (Uri.TryCreate(path, UriKind.Absolute, out Uri _)) + { + return Task.CompletedTask; + } + + IDirectoryStructure s = programState.Structure.TraverseTo(programState.PathSections.Reverse()).TraverseTo(path); + + List roots = new List(); + Formatter formatter = new Formatter(); + + roots.Add(new TreeNode(formatter, ".", string.Empty)); + + if (s.Parent != null) + { + roots.Add(new TreeNode(formatter, "..", string.Empty)); + } + + int recursionDepth = 1; + + if (commandInput.Options[RecursiveOption].Count > 0) + { + if (string.IsNullOrEmpty(commandInput.Options[RecursiveOption][0]?.Text)) + { + recursionDepth = int.MaxValue; + } + else if (int.TryParse(commandInput.Options[RecursiveOption][0].Text, NumberStyles.Integer, CultureInfo.InvariantCulture, out int rd) && rd > 1) + { + recursionDepth = rd; + } + } + + foreach (string child in s.DirectoryNames) + { + IDirectoryStructure dir = s.GetChildDirectory(child); + + string methods = dir.RequestInfo != null && dir.RequestInfo.Methods.Count > 0 + ? "[" + string.Join("|", dir.RequestInfo.Methods) + "]" + : "[]"; + + TreeNode dirNode = new TreeNode(formatter, child, methods); + roots.Add(dirNode); + Recurse(dirNode, dir, recursionDepth - 1); + } + + foreach (TreeNode node in roots) + { + shellState.ConsoleManager.WriteLine(node.ToString()); + } + + return Task.CompletedTask; + } + + private static void Recurse(TreeNode parentNode, IDirectoryStructure parent, int remainingDepth) + { + if (remainingDepth <= 0) + { + return; + } + + foreach (string child in parent.DirectoryNames) + { + IDirectoryStructure dir = parent.GetChildDirectory(child); + + string methods = dir.RequestInfo != null && dir.RequestInfo.Methods.Count > 0 + ? "[" + string.Join("|", dir.RequestInfo.Methods) + "]" + : "[]"; + + TreeNode node = parentNode.AddChild(child, methods); + Recurse(node, dir, remainingDepth - 1); + } + } + + + + protected override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("ls") + .MaximumArgCount(1) + .WithOption(new CommandOptionSpecification(RecursiveOption, maximumOccurrences: 1, acceptsValue: true, forms: new[] {"-r", "--recursive"})) + .Finish(); + + protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult) + { + return "Lists the contents of a directory"; + } + + public override string GetHelpSummary(IShellState shellState, HttpState programState) + { + return "ls - Performs a directory listing"; + } + + protected override IEnumerable GetArgumentSuggestionsForText(IShellState shellState, HttpState programState, ICoreParseResult parseResult, DefaultCommandInput commandInput, string normalCompletionString) + { + if (programState.Structure == null || programState.BaseAddress == null) + { + return null; + } + + //If it's an absolute URI, nothing to suggest + if (Uri.TryCreate(normalCompletionString, UriKind.Absolute, out Uri _)) + { + return null; + } + + string path = normalCompletionString.Replace('\\', '/'); + int searchFrom = normalCompletionString.Length - 1; + int lastSlash = path.LastIndexOf('/', searchFrom); + string prefix; + + if (lastSlash < 0) + { + path = string.Empty; + prefix = normalCompletionString; + } + else + { + path = path.Substring(0, lastSlash + 1); + prefix = normalCompletionString.Substring(lastSlash + 1); + } + + IDirectoryStructure s = programState.Structure.TraverseTo(programState.PathSections.Reverse()).TraverseTo(path); + + List results = new List(); + + foreach (string child in s.DirectoryNames) + { + if (child.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) + { + results.Add(path + child); + } + } + + return results; + } + } +} diff --git a/src/Microsoft.HttpRepl/Commands/OptionsCommand.cs b/src/Microsoft.HttpRepl/Commands/OptionsCommand.cs new file mode 100644 index 0000000000..f6a3c8903c --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/OptionsCommand.cs @@ -0,0 +1,9 @@ +namespace Microsoft.HttpRepl.Commands +{ + public class OptionsCommand : BaseHttpCommand + { + protected override string Verb => "options"; + + protected override bool RequiresBody => false; + } +} diff --git a/src/Microsoft.HttpRepl/Commands/PatchCommand.cs b/src/Microsoft.HttpRepl/Commands/PatchCommand.cs new file mode 100644 index 0000000000..c5d9c875be --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/PatchCommand.cs @@ -0,0 +1,9 @@ +namespace Microsoft.HttpRepl.Commands +{ + public class PatchCommand : BaseHttpCommand + { + protected override string Verb => "patch"; + + protected override bool RequiresBody => true; + } +} diff --git a/src/Microsoft.HttpRepl/Commands/PostCommand.cs b/src/Microsoft.HttpRepl/Commands/PostCommand.cs new file mode 100644 index 0000000000..216fe8ef1d --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/PostCommand.cs @@ -0,0 +1,9 @@ +namespace Microsoft.HttpRepl.Commands +{ + public class PostCommand : BaseHttpCommand + { + protected override string Verb => "post"; + + protected override bool RequiresBody => true; + } +} diff --git a/src/Microsoft.HttpRepl/Commands/PrefCommand.cs b/src/Microsoft.HttpRepl/Commands/PrefCommand.cs new file mode 100644 index 0000000000..7f16af09b3 --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/PrefCommand.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.HttpRepl.Preferences; +using Microsoft.Repl; +using Microsoft.Repl.Commanding; +using Microsoft.Repl.ConsoleHandling; +using Microsoft.Repl.Parsing; + +namespace Microsoft.HttpRepl.Commands +{ + public class PrefCommand : CommandWithStructuredInputBase + { + private readonly HashSet _allowedSubcommands = new HashSet(StringComparer.OrdinalIgnoreCase) {"get", "set"}; + + public override string GetHelpSummary(IShellState shellState, HttpState programState) + { + return "pref [get/set] {setting} [{value}] - Allows viewing or changing preferences"; + } + + protected override bool CanHandle(IShellState shellState, HttpState programState, DefaultCommandInput commandInput) + { + if (commandInput.Arguments.Count == 0 || !_allowedSubcommands.Contains(commandInput.Arguments[0]?.Text)) + { + shellState.ConsoleManager.Error.WriteLine("Whether get or set settings must be specified"); + return false; + } + + if (!string.Equals("get", commandInput.Arguments[0].Text) && (commandInput.Arguments.Count < 2 || string.IsNullOrEmpty(commandInput.Arguments[1]?.Text))) + { + shellState.ConsoleManager.Error.WriteLine("The preference to set must be specified"); + return false; + } + + return true; + } + + protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult) + { + if (commandInput.Arguments.Count == 0 || !_allowedSubcommands.Contains(commandInput.Arguments[0]?.Text)) + { + return "pref [get/set] {setting} [{value}] - Get or sets a preference to a particular value"; + } + + if (string.Equals(commandInput.Arguments[0].Text, "get", StringComparison.OrdinalIgnoreCase)) + { + return "pref get [{setting}] - Gets the value of the specified preference or lists all preferences if no preference is specified"; + } + else + { + return "pref set {setting} [{value}] - Sets (or clears if value is not specified) the value of the specified preference"; + } + } + + protected override Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) + { + if (string.Equals(commandInput.Arguments[0].Text, "get", StringComparison.OrdinalIgnoreCase)) + { + return GetSetting(shellState, programState, commandInput); + } + + return SetSetting(shellState, programState, commandInput); + } + + private static Task SetSetting(IShellState shellState, HttpState programState, DefaultCommandInput commandInput) + { + string prefName = commandInput.Arguments[1].Text; + string prefValue = commandInput.Arguments.Count > 2 ? commandInput.Arguments[2]?.Text : null; + + if (string.IsNullOrEmpty(prefValue)) + { + if (!programState.DefaultPreferences.TryGetValue(prefName, out string defaultValue)) + { + programState.Preferences.Remove(prefName); + } + else + { + programState.Preferences[prefName] = defaultValue; + } + } + else + { + programState.Preferences[prefName] = prefValue; + } + + if (!programState.SavePreferences()) + { + shellState.ConsoleManager.Error.WriteLine("Error saving preferences".Bold().Red()); + } + + return Task.CompletedTask; + } + + private static Task GetSetting(IShellState shellState, HttpState programState, DefaultCommandInput commandInput) + { + string preferenceName = commandInput.Arguments.Count > 1 ? commandInput.Arguments[1]?.Text : null; + + //If there's a particular setting to get the value of + if (!string.IsNullOrEmpty(preferenceName)) + { + if (programState.Preferences.TryGetValue(preferenceName, out string value)) + { + shellState.ConsoleManager.WriteLine("Configured value: " + value); + } + else + { + shellState.ConsoleManager.Error.WriteLine((commandInput.Arguments[1].Text + " does not have a configured value").Bold().Red()); + } + } + else + { + foreach (KeyValuePair entry in programState.Preferences.OrderBy(x => x.Key)) + { + shellState.ConsoleManager.WriteLine($"{entry.Key}={entry.Value}"); + } + } + + return Task.CompletedTask; + } + + protected override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("pref") + .MinimumArgCount(1) + .MaximumArgCount(3) + .Finish(); + + + protected override IEnumerable GetArgumentSuggestionsForText(IShellState shellState, HttpState programState, ICoreParseResult parseResult, DefaultCommandInput commandInput, string normalCompletionString) + { + if (parseResult.SelectedSection == 1) + { + return _allowedSubcommands.Where(x => x.StartsWith(normalCompletionString, StringComparison.OrdinalIgnoreCase)); + } + + if (parseResult.SelectedSection == 2) + { + string prefix = parseResult.Sections.Count > 2 ? normalCompletionString : string.Empty; + List matchingProperties = new List(); + + foreach (string val in WellKnownPreference.Catalog.Names) + { + if (val.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) + { + matchingProperties.Add(val); + } + } + + return matchingProperties; + } + + if (parseResult.SelectedSection == 3 + && parseResult.Sections[2].StartsWith("colors.", StringComparison.OrdinalIgnoreCase)) + { + string prefix = parseResult.Sections.Count > 3 ? normalCompletionString : string.Empty; + List matchingProperties = new List(); + + foreach (string val in Enum.GetNames(typeof(AllowedColors))) + { + if (val.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) + { + matchingProperties.Add(val); + } + } + + return matchingProperties; + } + + return null; + } + } +} diff --git a/src/Microsoft.HttpRepl/Commands/PutCommand.cs b/src/Microsoft.HttpRepl/Commands/PutCommand.cs new file mode 100644 index 0000000000..a65439dfb7 --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/PutCommand.cs @@ -0,0 +1,9 @@ +namespace Microsoft.HttpRepl.Commands +{ + public class PutCommand : BaseHttpCommand + { + protected override string Verb => "put"; + + protected override bool RequiresBody => true; + } +} diff --git a/src/Microsoft.HttpRepl/Commands/RunCommand.cs b/src/Microsoft.HttpRepl/Commands/RunCommand.cs new file mode 100644 index 0000000000..6dd2f4a378 --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/RunCommand.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Repl; +using Microsoft.Repl.Commanding; +using Microsoft.Repl.Parsing; +using Microsoft.Repl.Scripting; +using Microsoft.Repl.Suggestions; + +namespace Microsoft.HttpRepl.Commands +{ + public class RunCommand : ICommand + { + private static readonly string Name = "run"; + + public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + return parseResult.Sections.Count > 1 && parseResult.Sections.Count < 4 && string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase) + ? (bool?)true + : null; + } + + public async Task ExecuteAsync(IShellState shellState, HttpState programState, ICoreParseResult parseResult, CancellationToken cancellationToken) + { + if (!File.Exists(parseResult.Sections[1])) + { + shellState.ConsoleManager.Error.WriteLine($"Could not file script file {parseResult.Sections[1]}"); + return; + } + + bool suppressScriptLinesInHistory = true; + if (parseResult.Sections.Count == 3) + { + suppressScriptLinesInHistory = !string.Equals(parseResult.Sections[2], "+history"); + } + + string[] lines = File.ReadAllLines(parseResult.Sections[1]); + IScriptExecutor scriptExecutor = new ScriptExecutor(suppressScriptLinesInHistory); + await scriptExecutor.ExecuteScriptAsync(shellState, lines, cancellationToken).ConfigureAwait(false); + } + + public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + if (parseResult.Sections.Count > 0 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase)) + { + if (parseResult.Sections.Count == 1) + { + return "Runs the specified script"; + } + + return "Runs the script " + parseResult.Sections[1]; + } + + return null; + } + + public string GetHelpSummary(IShellState shellState, HttpState programState) + { + return "run {path to script} - Runs a script"; + } + + public IEnumerable Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + if (parseResult.SelectedSection == 0 && + (string.IsNullOrEmpty(parseResult.Sections[parseResult.SelectedSection]) || Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase))) + { + return new[] { Name }; + } + + if (parseResult.SelectedSection == 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase)) + { + return FileSystemCompletion.GetCompletions(parseResult.Sections[1].Substring(0, parseResult.CaretPositionWithinSelectedSection)); + } + + return null; + } + } +} diff --git a/src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs b/src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs new file mode 100644 index 0000000000..c346f541d4 --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Repl; +using Microsoft.Repl.Commanding; +using Microsoft.Repl.ConsoleHandling; +using Microsoft.Repl.Parsing; + +namespace Microsoft.HttpRepl.Commands +{ + public class SetBaseCommand : ICommand + { + private const string Name = "set"; + private const string SubCommand = "base"; + + public string Description => "Sets the base address to direct requests to."; + + public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + return parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase) + ? (bool?)true + : null; + } + + public async Task ExecuteAsync(IShellState shellState, HttpState state, ICoreParseResult parseResult, CancellationToken cancellationToken) + { + if (parseResult.Sections.Count == 2) + { + state.BaseAddress = null; + } + else if (parseResult.Sections.Count != 3 || string.IsNullOrEmpty(parseResult.Sections[2]) || !Uri.TryCreate(EnsureTrailingSlash(parseResult.Sections[2]), UriKind.Absolute, out Uri serverUri)) + { + shellState.ConsoleManager.Error.WriteLine("Must specify a server".Bold().Red()); + } + else + { + state.BaseAddress = serverUri; + } + + if (state.BaseAddress == null || !Uri.TryCreate(state.BaseAddress, "/swagger/v1/swagger.json", out Uri result)) + { + state.SwaggerStructure = null; + } + else + { + await SetSwaggerCommand.CreateDirectoryStructureForSwaggerEndpointAsync(shellState, state, result, cancellationToken).ConfigureAwait(false); + if (state.SwaggerStructure != null) + { + shellState.ConsoleManager.WriteLine("Using swagger metadata from " + result); + } + } + } + + private string EnsureTrailingSlash(string v) + { + if (!v.EndsWith("/", StringComparison.Ordinal)) + { + v += "/"; + } + + return v; + } + + public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + if (parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase)) + { + return Description; + } + + return null; + } + + public string GetHelpSummary(IShellState shellState, HttpState programState) + { + return Description; + } + + public IEnumerable Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + if (parseResult.Sections.Count == 0) + { + return new[] { Name }; + } + + if (parseResult.Sections.Count > 0 && parseResult.SelectedSection == 0 && Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)) + { + return new[] { Name }; + } + + if (string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase) && parseResult.SelectedSection == 1 && (parseResult.Sections.Count < 2 || SubCommand.StartsWith(parseResult.Sections[1].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase))) + { + return new[] { SubCommand }; + } + + return null; + } + } +} diff --git a/src/Microsoft.HttpRepl/Commands/SetDiagCommand.cs b/src/Microsoft.HttpRepl/Commands/SetDiagCommand.cs new file mode 100644 index 0000000000..4e86452b7c --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/SetDiagCommand.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.HttpRepl.Diagnostics; +using Microsoft.Repl; +using Microsoft.Repl.Commanding; +using Microsoft.Repl.ConsoleHandling; +using Microsoft.Repl.Parsing; + +namespace Microsoft.HttpRepl.Commands +{ + public class SetDiagCommand : ICommand + { + private static readonly string Name = "set"; + private static readonly string SubCommand = "diag"; + + public string Description => "Sets the diagnostics path to direct requests to."; + + public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + return parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase) + ? (bool?)true + : null; + } + + public async Task ExecuteAsync(IShellState shellState, HttpState programState, ICoreParseResult parseResult, CancellationToken cancellationToken) + { + if (parseResult.Sections.Count == 2) + { + programState.DiagnosticsState.DiagnosticsEndpoint = null; + programState.DiagnosticsState.DiagnosticItems = null; + programState.DiagnosticsState.DiagEndpointsStructure = null; + return; + } + + if (parseResult.Sections.Count != 3 || string.IsNullOrEmpty(parseResult.Sections[2]) || !Uri.TryCreate(parseResult.Sections[2], UriKind.Relative, out Uri _)) + { + shellState.ConsoleManager.Error.WriteLine("Must specify a relative path".Bold().Red()); + } + else + { + programState.DiagnosticsState.DiagnosticsEndpoint = parseResult.Sections[2]; + HttpResponseMessage response = await programState.Client.GetAsync(new Uri(programState.BaseAddress, programState.DiagnosticsState.DiagnosticsEndpoint), cancellationToken).ConfigureAwait(false); + + if (!response.IsSuccessStatusCode) + { + shellState.ConsoleManager.Error.WriteLine("Unable to access diagnostics endpoint".Bold().Red()); + programState.DiagnosticsState.DiagnosticsEndpoint = null; + programState.DiagnosticsState.DiagnosticItems = null; + } + else + { + programState.DiagnosticsState.DiagnosticItems = (await response.Content.ReadAsAsync>(cancellationToken).ConfigureAwait(false))?.Select(x => x.Value).ToList(); + + DiagItem endpointsItem = programState.DiagnosticsState.DiagnosticItems?.FirstOrDefault(x => string.Equals(x.DisplayName, "Endpoints", StringComparison.OrdinalIgnoreCase)); + + if (endpointsItem != null) + { + HttpResponseMessage endpointsResponse = await programState.Client.GetAsync(new Uri(programState.BaseAddress, endpointsItem.Url), cancellationToken).ConfigureAwait(false); + + if (!endpointsResponse.IsSuccessStatusCode) + { + shellState.ConsoleManager.Error.WriteLine("Unable to get endpoints information from diagnostics endpoint".Bold().Red()); + return; + } + + List endpoints = await endpointsResponse.Content.ReadAsAsync>(cancellationToken).ConfigureAwait(false); + DirectoryStructure structure = new DirectoryStructure(null); + + foreach (DiagEndpoint endpoint in endpoints) + { + if (endpoint.Url.StartsWith(endpointsItem.Url, StringComparison.OrdinalIgnoreCase) + || endpoint.Url.StartsWith("/graphql", StringComparison.OrdinalIgnoreCase)) + { + continue; + } + + FillDirectoryInfo(structure, endpoint.Url); + } + + programState.DiagnosticsState.DiagEndpointsStructure = structure; + } + } + } + } + + private static void FillDirectoryInfo(DirectoryStructure parent, string endpoint) + { + string[] parts = endpoint.Split('/'); + + foreach (string part in parts) + { + if (!string.IsNullOrEmpty(part)) + { + parent = parent.DeclareDirectory(part); + } + } + } + + public string GetHelpSummary(IShellState shellState, HttpState programState) + { + return Description; + } + + public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + if (parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase)) + { + return Description; + } + + return null; + } + + public IEnumerable Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + if (parseResult.Sections.Count == 0) + { + return new[] { Name }; + } + + if (parseResult.Sections.Count > 0 && parseResult.SelectedSection == 0 && Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)) + { + return new[] { Name }; + } + + if (string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase) && parseResult.SelectedSection == 1 && (parseResult.Sections.Count < 2 || SubCommand.StartsWith(parseResult.Sections[1].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase))) + { + return new[] { SubCommand }; + } + + return null; + } + } +} diff --git a/src/Microsoft.HttpRepl/Commands/SetHeaderCommand.cs b/src/Microsoft.HttpRepl/Commands/SetHeaderCommand.cs new file mode 100644 index 0000000000..c95d22a6be --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/SetHeaderCommand.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.HttpRepl.Suggestions; +using Microsoft.Repl; +using Microsoft.Repl.Commanding; +using Microsoft.Repl.Parsing; + +namespace Microsoft.HttpRepl.Commands +{ + public class SetHeaderCommand : ICommand + { + private static readonly string Name = "set"; + private static readonly string SubCommand = "header"; + + public string Description => "set header {name} [{{value}}] - Sets or clears a header"; + + public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + return parseResult.Sections.Count > 2 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase) + ? (bool?)true + : null; + } + + public Task ExecuteAsync(IShellState shellState, HttpState programState, ICoreParseResult parseResult, CancellationToken cancellationToken) + { + if (parseResult.Sections.Count == 3) + { + programState.Headers.Remove(parseResult.Sections[2]); + } + else + { + programState.Headers[parseResult.Sections[2]] = parseResult.Sections.Skip(3).ToList(); + } + + return Task.CompletedTask; + } + + public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + if (parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase)) + { + return Description; + } + + return null; + } + + public string GetHelpSummary(IShellState shellState, HttpState programState) + { + return Description; + } + + public IEnumerable Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + if (parseResult.Sections.Count == 0) + { + return new[] { Name }; + } + + if (parseResult.Sections.Count > 0 && parseResult.SelectedSection == 0 && Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)) + { + return new[] { Name }; + } + + if (string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase) && parseResult.SelectedSection == 1 && (parseResult.Sections.Count < 2 || SubCommand.StartsWith(parseResult.Sections[1].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase))) + { + return new[] { SubCommand }; + } + + if (parseResult.Sections.Count > 2 + && string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase) + && string.Equals(SubCommand, parseResult.Sections[1], StringComparison.OrdinalIgnoreCase) && parseResult.SelectedSection == 2) + { + string prefix = parseResult.Sections[2].Substring(0, parseResult.CaretPositionWithinSelectedSection); + return HeaderCompletion.GetCompletions(null, prefix); + } + + if (parseResult.Sections.Count > 3 + && string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase) + && string.Equals(SubCommand, parseResult.Sections[1], StringComparison.OrdinalIgnoreCase) && parseResult.SelectedSection == 3) + { + string prefix = parseResult.Sections[3].Substring(0, parseResult.CaretPositionWithinSelectedSection); + return HeaderCompletion.GetValueCompletions(null, string.Empty, parseResult.Sections[2], prefix, programState); + } + + return null; + } + } +} diff --git a/src/Microsoft.HttpRepl/Commands/SetSwaggerCommand.cs b/src/Microsoft.HttpRepl/Commands/SetSwaggerCommand.cs new file mode 100644 index 0000000000..9c9a1f36cc --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/SetSwaggerCommand.cs @@ -0,0 +1,272 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.HttpRepl.OpenApi; +using Microsoft.Repl; +using Microsoft.Repl.Commanding; +using Microsoft.Repl.ConsoleHandling; +using Microsoft.Repl.Parsing; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Microsoft.HttpRepl.Commands +{ + public class SetSwaggerCommand : ICommand + { + private static readonly string Name = "set"; + private static readonly string SubCommand = "swagger"; + + public string Description => "Sets the swagger document to use for information about the current server"; + + private static void FillDirectoryInfo(DirectoryStructure parent, EndpointMetadata entry) + { + string[] parts = entry.Path.Split('/'); + + foreach (string part in parts) + { + if (!string.IsNullOrEmpty(part)) + { + parent = parent.DeclareDirectory(part); + } + } + + RequestInfo dirRequestInfo = new RequestInfo(); + + foreach (KeyValuePair>> requestInfo in entry.AvailableRequests) + { + string method = requestInfo.Key; + + foreach (KeyValuePair> parameterSetsByContentType in requestInfo.Value) + { + if (string.IsNullOrEmpty(parameterSetsByContentType.Key)) + { + dirRequestInfo.SetFallbackRequestBody(method, GetBodyString(null, parameterSetsByContentType.Value)); + } + + dirRequestInfo.SetRequestBody(method, parameterSetsByContentType.Key, GetBodyString(parameterSetsByContentType.Key, parameterSetsByContentType.Value)); + } + + dirRequestInfo.AddMethod(method); + } + + if (dirRequestInfo.Methods.Count > 0) + { + parent.RequestInfo = dirRequestInfo; + } + } + + private static string GetBodyString(string contentType, IEnumerable operation) + { + Parameter body = operation.FirstOrDefault(x => string.Equals(x.Location, "body", StringComparison.OrdinalIgnoreCase)); + + if (body != null) + { + JToken result = GenerateData(body.Schema); + return result?.ToString() ?? "{\n}"; + } + + return null; + } + + private static JToken GenerateData(Schema schema) + { + if (schema == null) + { + return null; + } + + if (schema.Example != null) + { + return JToken.FromObject(schema.Example); + } + + if (schema.Default != null) + { + return JToken.FromObject(schema.Default); + } + + if (schema.Type is null) + { + if (schema.Properties != null || schema.AdditionalProperties != null || schema.MinProperties.HasValue || schema.MaxProperties.HasValue) + { + schema.Type = "OBJECT"; + } + else if (schema.Items != null || schema.MinItems.HasValue || schema.MaxItems.HasValue) + { + schema.Type = "ARRAY"; + } + else if (schema.Minimum.HasValue || schema.Maximum.HasValue || schema.MultipleOf.HasValue) + { + schema.Type = "INTEGER"; + } + } + + switch (schema.Type?.ToUpperInvariant()) + { + case null: + case "STRING": + return ""; + case "NUMBER": + if (schema.Minimum.HasValue) + { + if (schema.Maximum.HasValue) + { + return (schema.Maximum.Value + schema.Minimum.Value) / 2; + } + + if (schema.ExclusiveMinimum) + { + return schema.Minimum.Value + 1; + } + + return schema.Minimum.Value; + } + return 1.1; + case "INTEGER": + if (schema.Minimum.HasValue) + { + if (schema.Maximum.HasValue) + { + return (int)((schema.Maximum.Value + schema.Minimum.Value) / 2); + } + + if (schema.ExclusiveMinimum) + { + return schema.Minimum.Value + 1; + } + + return schema.Minimum.Value; + } + return 0; + case "BOOLEAN": + return true; + case "ARRAY": + JArray container = new JArray(); + JToken item = GenerateData(schema.Items) ?? ""; + + int count = schema.MinItems.GetValueOrDefault(); + count = Math.Max(1, count); + + for (int i = 0; i < count; ++i) + { + container.Add(item.DeepClone()); + } + + return container; + case "OBJECT": + JObject obj = new JObject(); + foreach (KeyValuePair property in schema.Properties) + { + JToken data = GenerateData(property.Value) ?? ""; + obj[property.Key] = data; + } + return obj; + } + + return null; + } + + private static async Task> GetSwaggerDocAsync(HttpClient client, Uri uri) + { + var resp = await client.GetAsync(uri).ConfigureAwait(false); + resp.EnsureSuccessStatusCode(); + string responseString = await resp.Content.ReadAsStringAsync().ConfigureAwait(false); + JsonSerializer serializer = new JsonSerializer{ PreserveReferencesHandling = PreserveReferencesHandling.All }; + JObject responseObject = (JObject)serializer.Deserialize(new StringReader(responseString), typeof(JObject)); + EndpointMetadataReader reader = new EndpointMetadataReader(); + responseObject = await PointerUtil.ResolvePointersAsync(uri, responseObject, client).ConfigureAwait(false) as JObject; + + if (responseObject is null) + { + return new EndpointMetadata[0]; + } + + return reader.Read(responseObject); + } + + public string GetHelpSummary(IShellState shellState, HttpState programState) + { + return Description; + } + + public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + if (parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase)) + { + return Description; + } + + return null; + } + + public IEnumerable Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + if (parseResult.Sections.Count == 0) + { + return new[] { Name }; + } + + if (parseResult.Sections.Count > 0 && parseResult.SelectedSection == 0 && Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase)) + { + return new[] { Name }; + } + + if (string.Equals(Name, parseResult.Sections[0], StringComparison.OrdinalIgnoreCase) && parseResult.SelectedSection == 1 && (parseResult.Sections.Count < 2 || SubCommand.StartsWith(parseResult.Sections[1].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase))) + { + return new[] { SubCommand }; + } + + return null; + } + + public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + return parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase) + ? (bool?)true + : null; + } + + public async Task ExecuteAsync(IShellState shellState, HttpState programState, ICoreParseResult parseResult, CancellationToken cancellationToken) + { + if (parseResult.Sections.Count == 2) + { + programState.SwaggerStructure = null; + return; + } + + if (parseResult.Sections.Count != 3 || string.IsNullOrEmpty(parseResult.Sections[2]) || !Uri.TryCreate(parseResult.Sections[2], UriKind.Absolute, out Uri serverUri)) + { + shellState.ConsoleManager.Error.WriteLine("Must specify a swagger document".Bold().Red()); + } + else + { + await CreateDirectoryStructureForSwaggerEndpointAsync(shellState, programState, serverUri, cancellationToken).ConfigureAwait(false); + } + } + + internal static async Task CreateDirectoryStructureForSwaggerEndpointAsync(IShellState shellState, HttpState programState, Uri serverUri, CancellationToken cancellationToken) + { + try + { + IEnumerable doc = await GetSwaggerDocAsync(programState.Client, serverUri).ConfigureAwait(false); + + DirectoryStructure d = new DirectoryStructure(null); + + foreach (EndpointMetadata entry in doc) + { + FillDirectoryInfo(d, entry); + } + + programState.SwaggerStructure = !cancellationToken.IsCancellationRequested ? d : null; + } + catch + { + programState.SwaggerStructure = null; + } + } + } +} diff --git a/src/Microsoft.HttpRepl/Commands/TreeNode.cs b/src/Microsoft.HttpRepl/Commands/TreeNode.cs new file mode 100644 index 0000000000..256d5d9dae --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/TreeNode.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; + +namespace Microsoft.HttpRepl.Commands +{ + public class TreeNode + { + private readonly int _depth; + private readonly Formatter _formatter; + private readonly string _prefix; + private readonly string _entry; + private readonly List _children = new List(); + + public TreeNode(Formatter formatter, string prefix, string entry) + : this(formatter, prefix, entry, 0) + { + } + + private TreeNode(Formatter formatter, string prefix, string entry, int depth) + { + _formatter = formatter; + formatter.RegisterEntry(prefix.Length, depth); + _prefix = prefix; + _entry = entry; + _depth = depth; + } + + public TreeNode AddChild(string prefix, string entry) + { + TreeNode child = new TreeNode(_formatter, prefix, entry, _depth + 1); + _children.Add(child); + return child; + } + + public override string ToString() + { + string self = _formatter.Format(_prefix, _entry, _depth); + + if (_children.Count == 0) + { + return self; + } + + return self + Environment.NewLine + string.Join(Environment.NewLine, _children); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.HttpRepl/Commands/UICommand.cs b/src/Microsoft.HttpRepl/Commands/UICommand.cs new file mode 100644 index 0000000000..ddf4ca4097 --- /dev/null +++ b/src/Microsoft.HttpRepl/Commands/UICommand.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Repl; +using Microsoft.Repl.Commanding; +using Microsoft.Repl.ConsoleHandling; +using Microsoft.Repl.Parsing; + +namespace Microsoft.HttpRepl.Commands +{ + public class UICommand : ICommand + { + private static readonly string Name = "ui"; + + public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + return parseResult.Sections.Count == 1 && string.Equals(parseResult.Sections[0], Name) + ? (bool?)true + : null; + } + + public Task ExecuteAsync(IShellState shellState, HttpState programState, ICoreParseResult parseResult, CancellationToken cancellationToken) + { + if (programState.BaseAddress == null) + { + shellState.ConsoleManager.Error.WriteLine("Must be connected to a server to launch Swagger UI".Bold().Red()); + return Task.CompletedTask; + } + + Uri uri = new Uri(programState.BaseAddress, "swagger"); + string agent = "cmd"; + string agentParam = $"/c {uri.AbsoluteUri}"; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + agent = "open"; + agentParam = uri.AbsoluteUri; + } + else if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + agent = "xdg-open"; + agentParam = uri.AbsoluteUri; + } + + Process.Start(new ProcessStartInfo(agent, agentParam) { CreateNoWindow = true }); + return Task.CompletedTask; + } + + public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + if (parseResult.Sections.Count == 1 && string.Equals(parseResult.Sections[0], Name)) + { + return "ui - Launches the Swagger UI page (if available) in the default browser"; + } + + return null; + } + + public string GetHelpSummary(IShellState shellState, HttpState programState) + { + return "ui - Launches the Swagger UI page (if available) in the default browser"; + } + + public IEnumerable Suggest(IShellState shellState, HttpState programState, ICoreParseResult parseResult) + { + if (parseResult.SelectedSection == 0 && + (string.IsNullOrEmpty(parseResult.Sections[parseResult.SelectedSection]) || Name.StartsWith(parseResult.Sections[0].Substring(0, parseResult.CaretPositionWithinSelectedSection), StringComparison.OrdinalIgnoreCase))) + { + return new[] { Name }; + } + + return null; + } + } +} diff --git a/src/Microsoft.HttpRepl/Diagnostics/ConfigItem.cs b/src/Microsoft.HttpRepl/Diagnostics/ConfigItem.cs new file mode 100644 index 0000000000..ba16701d58 --- /dev/null +++ b/src/Microsoft.HttpRepl/Diagnostics/ConfigItem.cs @@ -0,0 +1,9 @@ +namespace Microsoft.HttpRepl.Diagnostics +{ + public class ConfigItem + { + public string Key { get; set; } + + public string Value { get; set; } + } +} diff --git a/src/Microsoft.HttpRepl/Diagnostics/DiagEndpoint.cs b/src/Microsoft.HttpRepl/Diagnostics/DiagEndpoint.cs new file mode 100644 index 0000000000..80e619dcc3 --- /dev/null +++ b/src/Microsoft.HttpRepl/Diagnostics/DiagEndpoint.cs @@ -0,0 +1,9 @@ +namespace Microsoft.HttpRepl.Diagnostics +{ + public class DiagEndpoint + { + public string DisplayName { get; set; } + public string Url { get; set; } + public DiagEndpointMetadata[] Metadata { get; set; } + } +} diff --git a/src/Microsoft.HttpRepl/Diagnostics/DiagEndpointMetadata.cs b/src/Microsoft.HttpRepl/Diagnostics/DiagEndpointMetadata.cs new file mode 100644 index 0000000000..53e5aa3918 --- /dev/null +++ b/src/Microsoft.HttpRepl/Diagnostics/DiagEndpointMetadata.cs @@ -0,0 +1,9 @@ +namespace Microsoft.HttpRepl.Diagnostics +{ + public class DiagEndpointMetadata + { + public object Item { get; set; } + public string Type { get; set; } + public string[] Interfaces { get; set; } + } +} diff --git a/src/Microsoft.HttpRepl/Diagnostics/DiagItem.cs b/src/Microsoft.HttpRepl/Diagnostics/DiagItem.cs new file mode 100644 index 0000000000..c0fbf2df9c --- /dev/null +++ b/src/Microsoft.HttpRepl/Diagnostics/DiagItem.cs @@ -0,0 +1,11 @@ +namespace Microsoft.HttpRepl.Diagnostics +{ + public class DiagItem + { + public string DisplayName { get; set; } + + public string Description { get; set; } + + public string Url { get; set; } + } +} diff --git a/src/Microsoft.HttpRepl/Diagnostics/DiagnosticsState.cs b/src/Microsoft.HttpRepl/Diagnostics/DiagnosticsState.cs new file mode 100644 index 0000000000..3fe27cce19 --- /dev/null +++ b/src/Microsoft.HttpRepl/Diagnostics/DiagnosticsState.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace Microsoft.HttpRepl.Diagnostics +{ + public class DiagnosticsState + { + public string DiagnosticsEndpoint { get; set; } + + public IReadOnlyList DiagnosticItems { get; internal set; } + + public IDirectoryStructure DiagEndpointsStructure { get; set; } + } +} diff --git a/src/Microsoft.HttpRepl/DirectoryStructure.cs b/src/Microsoft.HttpRepl/DirectoryStructure.cs new file mode 100644 index 0000000000..f682488b9b --- /dev/null +++ b/src/Microsoft.HttpRepl/DirectoryStructure.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.HttpRepl +{ + public class DirectoryStructure : IDirectoryStructure + { + private readonly Dictionary _childDirectories = new Dictionary(StringComparer.OrdinalIgnoreCase); + + public DirectoryStructure(IDirectoryStructure parent) + { + Parent = parent; + } + + public IEnumerable DirectoryNames => _childDirectories.Keys; + + public IDirectoryStructure Parent { get; } + + public DirectoryStructure DeclareDirectory(string name) + { + if (_childDirectories.TryGetValue(name, out DirectoryStructure existing)) + { + return existing; + } + + return _childDirectories[name] = new DirectoryStructure(this); + } + + public IDirectoryStructure GetChildDirectory(string name) + { + if (_childDirectories.TryGetValue(name, out DirectoryStructure result)) + { + return result; + } + + IDirectoryStructure parameterizedTarget = _childDirectories.FirstOrDefault(x => x.Key.StartsWith('{') && x.Key.EndsWith('}')).Value; + + if (!(parameterizedTarget is null)) + { + return parameterizedTarget; + } + + return new DirectoryStructure(this); + } + + public IRequestInfo RequestInfo { get; set; } + } + + public class RequestInfo : IRequestInfo + { + private readonly HashSet _methods = new HashSet(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary> _requestBodiesByMethodByContentType = new Dictionary>(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary _fallbackBodyStringsByMethod = new Dictionary(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary> _contentTypesByMethod = new Dictionary>(StringComparer.OrdinalIgnoreCase); + + public IReadOnlyList Methods => _methods.ToList(); + + public IReadOnlyDictionary> ContentTypesByMethod => _contentTypesByMethod; + + public string GetRequestBodyForContentType(string contentType, string method) + { + if (_requestBodiesByMethodByContentType.TryGetValue(method, out Dictionary bodiesByContentType) + && bodiesByContentType.TryGetValue(contentType, out string body)) + { + return body; + } + + if (_fallbackBodyStringsByMethod.TryGetValue(method, out body)) + { + return body; + } + + return null; + } + + public void SetRequestBody(string method, string contentType, string body) + { + if (!_requestBodiesByMethodByContentType.TryGetValue(method, out Dictionary bodiesByContentType)) + { + _requestBodiesByMethodByContentType[method] = bodiesByContentType = new Dictionary(StringComparer.OrdinalIgnoreCase); + } + + if (!_contentTypesByMethod.TryGetValue(method, out IReadOnlyList contentTypesRaw)) + { + _contentTypesByMethod[method] = contentTypesRaw = new List(); + } + + List contentTypes = (List)contentTypesRaw; + contentTypes.Add(contentType); + + bodiesByContentType[contentType] = body; + } + + public void AddMethod(string method) + { + _methods.Add(method); + } + + public void SetFallbackRequestBody(string method, string fallbackBodyString) + { + _fallbackBodyStringsByMethod[method] = fallbackBodyString; + } + } +} diff --git a/src/Microsoft.HttpRepl/DirectoryStructureExtensions.cs b/src/Microsoft.HttpRepl/DirectoryStructureExtensions.cs new file mode 100644 index 0000000000..2b7ad5341a --- /dev/null +++ b/src/Microsoft.HttpRepl/DirectoryStructureExtensions.cs @@ -0,0 +1,57 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.HttpRepl +{ + public static class DirectoryStructureExtensions + { + public static IEnumerable GetDirectoryListingAtPath(this IDirectoryStructure structure, string path) + { + return structure.TraverseTo(path).DirectoryNames; + } + + public static IDirectoryStructure TraverseTo(this IDirectoryStructure structure, string path) + { + string[] parts = path.Replace('\\', '/').Split('/'); + return structure.TraverseTo(parts); + } + + public static IDirectoryStructure TraverseTo(this IDirectoryStructure structure, IEnumerable pathParts) + { + IDirectoryStructure s = structure; + IReadOnlyList parts = pathParts.ToList(); + + if (parts.Count == 0) + { + return s; + } + + if (parts[0] == string.Empty && parts.Count > 1) + { + while (s.Parent != null) + { + s = s.Parent; + } + } + + foreach (string part in parts) + { + if (part == ".") + { + continue; + } + + if (part == "..") + { + s = s.Parent ?? s; + } + else if (!string.IsNullOrEmpty(part)) + { + s = s.GetChildDirectory(part); + } + } + + return s; + } + } +} diff --git a/src/Microsoft.HttpRepl/Formatting/JsonVisitor.cs b/src/Microsoft.HttpRepl/Formatting/JsonVisitor.cs new file mode 100644 index 0000000000..fa40ee62ab --- /dev/null +++ b/src/Microsoft.HttpRepl/Formatting/JsonVisitor.cs @@ -0,0 +1,111 @@ +using System.IO; +using System.Text; +using Microsoft.HttpRepl.Preferences; +using Microsoft.Repl.ConsoleHandling; +using Newtonsoft.Json; + +namespace Microsoft.HttpRepl.Formatting +{ + public static class JsonVisitor + { + public static string FormatAndColorize(IJsonConfig config, string jsonData) + { + if (jsonData == null) + { + return string.Empty; + } + + StringBuilder result = new StringBuilder(); + JsonTextReader reader = new JsonTextReader(new StringReader(jsonData)); + bool isValuePosition = false; + bool isTerminalValue = false; + bool isFirstToken = true; + + while (reader.Read()) + { + if (!isValuePosition) + { + //If we're about to write an end object/array, we shouldn't have a comma + if (reader.TokenType != JsonToken.EndArray && reader.TokenType != JsonToken.EndObject + && isTerminalValue) + { + result.Append(",".SetColor(config.CommaColor)); + } + + if (!isFirstToken) + { + result.AppendLine(); + } + } + + isFirstToken = false; + + if (!isValuePosition) + { + result.Append("".PadLeft(reader.Depth * config.IndentSize)); + } + + isTerminalValue = false; + isValuePosition = false; + JsonToken type = reader.TokenType; + + switch (type) + { + case JsonToken.StartObject: + result.Append("{".SetColor(config.ObjectBraceColor)); + break; + case JsonToken.EndObject: + result.Append("}".SetColor(config.ObjectBraceColor)); + isTerminalValue = true; + break; + case JsonToken.StartArray: + result.Append("[".SetColor(config.ArrayBraceColor)); + break; + case JsonToken.EndArray: + result.Append("]".SetColor(config.ArrayBraceColor)); + isTerminalValue = true; + break; + case JsonToken.PropertyName: + result.Append((reader.QuoteChar.ToString() + reader.Value + reader.QuoteChar).SetColor(config.NameColor) + ": ".SetColor(config.NameSeparatorColor)); + isValuePosition = true; + break; + case JsonToken.Boolean: + result.Append(reader.Value.ToString().ToLowerInvariant().SetColor(config.BoolColor)); + isTerminalValue = true; + break; + case JsonToken.Integer: + case JsonToken.Float: + result.Append(reader.Value.ToString().ToLowerInvariant().SetColor(config.NumericColor)); + isTerminalValue = true; + break; + case JsonToken.Null: + result.Append("null".SetColor(config.NullColor)); + isTerminalValue = true; + break; + case JsonToken.Comment: + result.Append(("//" + reader.Value).SetColor(config.NumericColor)); + break; + case JsonToken.String: + result.Append((reader.QuoteChar.ToString() + reader.Value + reader.QuoteChar.ToString()).SetColor(config.StringColor)); + isTerminalValue = true; + break; + case JsonToken.Raw: + case JsonToken.Date: + case JsonToken.Bytes: + case JsonToken.Undefined: + case JsonToken.None: + result.Append(reader.Value.ToString().SetColor(config.DefaultColor)); + isTerminalValue = true; + break; + case JsonToken.EndConstructor: + case JsonToken.StartConstructor: + default: + result.Append(reader.Value.ToString().SetColor(config.DefaultColor)); + break; + } + } + + return result.ToString(); + } + } +} diff --git a/src/Microsoft.HttpRepl/HttpState.cs b/src/Microsoft.HttpRepl/HttpState.cs new file mode 100644 index 0000000000..55cfdd6188 --- /dev/null +++ b/src/Microsoft.HttpRepl/HttpState.cs @@ -0,0 +1,370 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Runtime.InteropServices; +using Microsoft.HttpRepl.Diagnostics; +using Microsoft.HttpRepl.Preferences; + +namespace Microsoft.HttpRepl +{ + public class HttpState + { + private string _userProfileDir; + private string _prefsFilePath; + + public HttpClient Client { get; } + + public Stack PathSections { get; } + + public IDirectoryStructure SwaggerStructure { get; set; } + + public IDirectoryStructure Structure => DiagnosticsState.DiagEndpointsStructure == null + ? SwaggerStructure + : SwaggerStructure == null + ? DiagnosticsState.DiagEndpointsStructure + : new AggregateDirectoryStructure(SwaggerStructure, DiagnosticsState.DiagEndpointsStructure); + + public Uri BaseAddress { get; set; } + + public bool EchoRequest { get; set; } + + public Dictionary Preferences { get; } + + public IReadOnlyDictionary DefaultPreferences { get; } + + public string UserProfileDir + { + get + { + if (_userProfileDir == null) + { + bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + + string profileDir = Environment.GetEnvironmentVariable(isWindows + ? "USERPROFILE" + : "HOME"); + + _userProfileDir = profileDir; + } + + return _userProfileDir; + } + } + + public string PrefsFilePath => _prefsFilePath ?? (_prefsFilePath = Path.Combine(UserProfileDir, ".httpreplprefs")); + + public Dictionary> Headers { get; } + + public DiagnosticsState DiagnosticsState { get; } + + public HttpState() + { + Client = new HttpClient(); + PathSections = new Stack(); + Preferences = new Dictionary(); + DefaultPreferences = CreateDefaultPreferencs(); + Headers = new Dictionary>(StringComparer.OrdinalIgnoreCase) + { + { "User-Agent", new[] { "HTTP-REPL" } } + }; + Preferences = new Dictionary(DefaultPreferences); + LoadPreferences(); + DiagnosticsState = new DiagnosticsState(); + } + + public string GetPrompt() + { + return $"{GetEffectivePath(new string[0], false, out int _)?.ToString() ?? "(Disconnected)"}~ "; + } + + private void LoadPreferences() + { + if (File.Exists(PrefsFilePath)) + { + string[] prefsFile = File.ReadAllLines(PrefsFilePath); + + foreach (string line in prefsFile) + { + int equalsIndex = line.IndexOf('='); + + if (equalsIndex < 0) + { + continue; + } + + Preferences[line.Substring(0, equalsIndex)] = line.Substring(equalsIndex + 1); + } + } + } + + private IReadOnlyDictionary CreateDefaultPreferencs() + { + return new Dictionary + { + { WellKnownPreference.ProtocolColor, "BoldGreen" }, + { WellKnownPreference.StatusColor, "BoldYellow" }, + + { WellKnownPreference.JsonArrayBraceColor, "BoldCyan" }, + { WellKnownPreference.JsonCommaColor, "BoldYellow" }, + { WellKnownPreference.JsonNameColor, "BoldMagenta" }, + { WellKnownPreference.JsonNameSeparatorColor, "BoldWhite" }, + { WellKnownPreference.JsonObjectBraceColor, "Cyan" }, + { WellKnownPreference.JsonColor, "Green" } + }; + } + + public bool SavePreferences() + { + List lines = new List(); + foreach (KeyValuePair entry in Preferences.OrderBy(x => x.Key)) + { + //If the value didn't exist in the defaults or the value's different, include it in the user's preferences file + if (!DefaultPreferences.TryGetValue(entry.Key, out string value) || !string.Equals(value, entry.Value, StringComparison.Ordinal)) + { + lines.Add($"{entry.Key}={entry.Value}"); + } + } + + try + { + File.WriteAllLines(PrefsFilePath, lines); + return true; + } + catch + { + return false; + } + } + + public string GetExampleBody(string path, string contentType, string method) + { + Uri effectivePath = GetEffectivePath(path); + string rootRelativePath = effectivePath.LocalPath.Substring(BaseAddress.LocalPath.Length).TrimStart('/'); + IDirectoryStructure structure = SwaggerStructure?.TraverseTo(rootRelativePath); + return structure?.RequestInfo?.GetRequestBodyForContentType(contentType, method); + } + + public IEnumerable GetApplicableContentTypes(string method, string path) + { + Uri effectivePath = GetEffectivePath(path); + string rootRelativePath = effectivePath.LocalPath.Substring(BaseAddress.LocalPath.Length).TrimStart('/'); + IDirectoryStructure structure = SwaggerStructure?.TraverseTo(rootRelativePath); + IReadOnlyDictionary> contentTypesByMethod = structure?.RequestInfo?.ContentTypesByMethod; + + if (contentTypesByMethod != null) + { + if (method is null) + { + return contentTypesByMethod.Values.SelectMany(x => x).Distinct(StringComparer.OrdinalIgnoreCase); + } + + if (contentTypesByMethod.TryGetValue(method, out IReadOnlyList contentTypes)) + { + return contentTypes; + } + } + + return null; + } + + public Uri GetEffectivePath(string commandSpecifiedPath) + { + if (Uri.TryCreate(commandSpecifiedPath, UriKind.Absolute, out Uri absoluteUri)) + { + return absoluteUri; + } + + UriBuilder builder = new UriBuilder(BaseAddress); + string path = string.Join('/', PathSections.Reverse()); + string[] parts = path.Split('?'); + string query = null; + string query2 = null; + + if (parts.Length > 1) + { + path = parts[0]; + query = string.Join('?', parts.Skip(1)); + } + + builder.Path += path; + + if (commandSpecifiedPath.Length > 0) + { + if (commandSpecifiedPath[0] != '/') + { + string argPath = commandSpecifiedPath; + if (builder.Path.Length > 0 && builder.Path[builder.Path.Length - 1] != '/') + { + argPath = "/" + argPath; + } + + int queryIndex = argPath.IndexOf('?'); + path = argPath; + + if (queryIndex > -1) + { + query2 = argPath.Substring(queryIndex + 1); + path = argPath.Substring(0, queryIndex); + } + + builder.Path += path; + } + else + { + int queryIndex = commandSpecifiedPath.IndexOf('?'); + path = commandSpecifiedPath; + + if (queryIndex > -1) + { + query2 = commandSpecifiedPath.Substring(queryIndex + 1); + path = commandSpecifiedPath.Substring(0, queryIndex); + } + + builder.Path = path; + } + } + else + { + + int queryIndex = commandSpecifiedPath.IndexOf('?'); + path = commandSpecifiedPath; + + if (queryIndex > -1) + { + query2 = commandSpecifiedPath.Substring(queryIndex + 1); + path = commandSpecifiedPath.Substring(0, queryIndex); + } + + builder.Path += path; + } + + if (query != null) + { + if (!string.IsNullOrEmpty(builder.Query)) + { + query = "&" + query; + } + + builder.Query += query; + } + + if (query2 != null) + { + if (!string.IsNullOrEmpty(builder.Query)) + { + query2 = "&" + query2; + } + + builder.Query += query2; + } + + return builder.Uri; + } + + public Uri GetEffectivePath(IReadOnlyList sections, bool requiresBody, out int filePathIndex) + { + filePathIndex = 1; + + if (BaseAddress == null) + { + return null; + } + + UriBuilder builder = new UriBuilder(BaseAddress); + string path = string.Join('/', PathSections.Reverse()); + string[] parts = path.Split('?'); + string query = null; + string query2 = null; + + if (parts.Length > 1) + { + path = parts[0]; + query = string.Join('?', parts.Skip(1)); + } + + builder.Path += path; + + if (sections.Count > 1) + { + if (!requiresBody || !File.Exists(sections[1])) + { + if (sections[1].Length > 0) + { + if (sections[1][0] != '/') + { + string argPath = sections[1]; + if (builder.Path.Length > 0 && builder.Path[builder.Path.Length - 1] != '/') + { + argPath = "/" + argPath; + } + + int queryIndex = argPath.IndexOf('?'); + path = argPath; + + if (queryIndex > -1) + { + query2 = argPath.Substring(queryIndex + 1); + path = argPath.Substring(0, queryIndex); + } + + builder.Path += path; + } + else + { + int queryIndex = sections[1].IndexOf('?'); + path = sections[1]; + + if (queryIndex > -1) + { + query2 = sections[1].Substring(queryIndex + 1); + path = sections[1].Substring(0, queryIndex); + } + + builder.Path = path; + } + } + else + { + + int queryIndex = sections[1].IndexOf('?'); + path = sections[1]; + + if (queryIndex > -1) + { + query2 = sections[1].Substring(queryIndex + 1); + path = sections[1].Substring(0, queryIndex); + } + + builder.Path += path; + } + + filePathIndex = 2; + } + } + + if (query != null) + { + if (!string.IsNullOrEmpty(builder.Query)) + { + query = "&" + query; + } + + builder.Query += query; + } + + if (query2 != null) + { + if (!string.IsNullOrEmpty(builder.Query)) + { + query2 = "&" + query2; + } + + builder.Query += query2; + } + + return builder.Uri; + } + } +} diff --git a/src/Microsoft.HttpRepl/IDirectoryStructure.cs b/src/Microsoft.HttpRepl/IDirectoryStructure.cs new file mode 100644 index 0000000000..5c02e8e476 --- /dev/null +++ b/src/Microsoft.HttpRepl/IDirectoryStructure.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; + +namespace Microsoft.HttpRepl +{ + public interface IDirectoryStructure + { + IEnumerable DirectoryNames { get; } + + IDirectoryStructure Parent { get; } + + IDirectoryStructure GetChildDirectory(string name); + + IRequestInfo RequestInfo { get; } + } + + public interface IRequestInfo + { + IReadOnlyDictionary> ContentTypesByMethod { get; } + + IReadOnlyList Methods { get; } + + string GetRequestBodyForContentType(string contentType, string method); + } +} diff --git a/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj b/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj new file mode 100644 index 0000000000..cec7ac17d5 --- /dev/null +++ b/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj @@ -0,0 +1,31 @@ + + + + Exe + netcoreapp2.2 + true + dotnet-httprepl + latest + Command line tool to for making HTTP calls and viewing their results. + dotnet;http;httprepl + + + true + + + + + + + + + + + + + + + + + + diff --git a/src/Microsoft.HttpRepl/OpenApi/Either.cs b/src/Microsoft.HttpRepl/OpenApi/Either.cs new file mode 100644 index 0000000000..f1e7dfacb3 --- /dev/null +++ b/src/Microsoft.HttpRepl/OpenApi/Either.cs @@ -0,0 +1,33 @@ +namespace Microsoft.HttpRepl.OpenApi +{ + public class Either + { + public Either(TOption1 option1) + { + Option1 = option1; + IsOption1 = true; + } + + public Either(TOption2 option2) + { + Option2 = option2; + IsOption1 = false; + } + + public bool IsOption1 { get; } + + public TOption1 Option1 { get; } + + public TOption2 Option2 { get; } + + public static implicit operator Either(TOption1 value) + { + return new Either(value); + } + + public static implicit operator Either(TOption2 value) + { + return new Either(value); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.HttpRepl/OpenApi/EitherConverter.cs b/src/Microsoft.HttpRepl/OpenApi/EitherConverter.cs new file mode 100644 index 0000000000..b89a85c9ef --- /dev/null +++ b/src/Microsoft.HttpRepl/OpenApi/EitherConverter.cs @@ -0,0 +1,32 @@ +using System; +using Newtonsoft.Json; + +namespace Microsoft.HttpRepl.OpenApi +{ + public class EitherConverter : JsonConverter + { + public override bool CanConvert(Type objectType) + { + return typeof(TOption1).IsAssignableFrom(objectType) || typeof(TOption2).IsAssignableFrom(objectType) || typeof(EitherConverter) == objectType; + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + try + { + TOption1 option1 = serializer.Deserialize(reader); + return new Either(option1); + } + catch + { + TOption2 option2 = serializer.Deserialize(reader); + return new Either(option2); + } + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.HttpRepl/OpenApi/EndpointMetadata.cs b/src/Microsoft.HttpRepl/OpenApi/EndpointMetadata.cs new file mode 100644 index 0000000000..e46387b3e0 --- /dev/null +++ b/src/Microsoft.HttpRepl/OpenApi/EndpointMetadata.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; + +namespace Microsoft.HttpRepl.OpenApi +{ + public class EndpointMetadata + { + public EndpointMetadata(string path, IReadOnlyDictionary>> requestsByMethodAndContentType) + { + Path = path; + AvailableRequests = requestsByMethodAndContentType ?? new Dictionary>>(); + } + + public string Path { get; } + + public IReadOnlyDictionary>> AvailableRequests { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.HttpRepl/OpenApi/EndpointMetadataReader.cs b/src/Microsoft.HttpRepl/OpenApi/EndpointMetadataReader.cs new file mode 100644 index 0000000000..8635d6fbee --- /dev/null +++ b/src/Microsoft.HttpRepl/OpenApi/EndpointMetadataReader.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using Newtonsoft.Json.Linq; + +namespace Microsoft.HttpRepl.OpenApi +{ + public class EndpointMetadataReader + { + private readonly List _readers = new List + { + new OpenApiV3EndpointMetadataReader(), + new SwaggerV2EndpointMetadataReader(), + new SwaggerV1EndpointMetadataReader() + }; + + public void RegisterReader(IEndpointMetadataReader reader) + { + _readers.Add(reader); + } + + public IEnumerable Read(JObject document) + { + foreach (IEndpointMetadataReader reader in _readers) + { + if (reader.CanHandle(document)) + { + IEnumerable result = reader.ReadMetadata(document); + + if (result != null) + { + return result; + } + } + } + + return null; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.HttpRepl/OpenApi/IEndpointMetadataReader.cs b/src/Microsoft.HttpRepl/OpenApi/IEndpointMetadataReader.cs new file mode 100644 index 0000000000..287740c7af --- /dev/null +++ b/src/Microsoft.HttpRepl/OpenApi/IEndpointMetadataReader.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using Newtonsoft.Json.Linq; + +namespace Microsoft.HttpRepl.OpenApi +{ + public interface IEndpointMetadataReader + { + bool CanHandle(JObject document); + + IEnumerable ReadMetadata(JObject document); + } +} \ No newline at end of file diff --git a/src/Microsoft.HttpRepl/OpenApi/OpenApiV3EndpointMetadataReader.cs b/src/Microsoft.HttpRepl/OpenApi/OpenApiV3EndpointMetadataReader.cs new file mode 100644 index 0000000000..5fa968efc6 --- /dev/null +++ b/src/Microsoft.HttpRepl/OpenApi/OpenApiV3EndpointMetadataReader.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json.Linq; + +namespace Microsoft.HttpRepl.OpenApi +{ + public class OpenApiV3EndpointMetadataReader : IEndpointMetadataReader + { + public bool CanHandle(JObject document) + { + return (document["openapi"]?.ToString() ?? "").StartsWith("3.", StringComparison.Ordinal); + } + + public IEnumerable ReadMetadata(JObject document) + { + List metadata = new List(); + + if (document["paths"] is JObject paths) + { + foreach (JProperty path in paths.Properties()) + { + if (!(path.Value is JObject pathBody)) + { + continue; + } + + Dictionary>> requestMethods = new Dictionary>>(StringComparer.OrdinalIgnoreCase); + + foreach (JProperty method in pathBody.Properties()) + { + List parameters = new List(); + + if (method.Value is JObject methodBody) + { + if (methodBody["parameters"] is JArray parametersArray) + { + foreach (JObject parameterObj in parametersArray.OfType()) + { + Parameter p = parameterObj.ToObject(); + p.Location = parameterObj["in"]?.ToString(); + + if (!(parameterObj["schema"] is JObject schemaObject)) + { + schemaObject = null; + } + + p.Schema = schemaObject?.ToObject() ?? parameterObj.ToObject(); + parameters.Add(p); + } + } + + if (methodBody["requestBody"] is JObject bodyObject) + { + if (!(bodyObject["content"] is JObject contentTypeLookup)) + { + continue; + } + + foreach (JProperty contentTypeEntry in contentTypeLookup.Properties()) + { + List parametersByContentType = new List(parameters); + Parameter p = bodyObject.ToObject(); + p.Location = "body"; + p.IsRequired = bodyObject["required"]?.ToObject() ?? false; + + if (!(bodyObject["schema"] is JObject schemaObject)) + { + schemaObject = null; + } + + p.Schema = schemaObject?.ToObject() ?? bodyObject.ToObject(); + parametersByContentType.Add(p); + + Dictionary> bucketByMethod; + if (!requestMethods.TryGetValue(method.Name, out IReadOnlyDictionary> bucketByMethodRaw)) + { + requestMethods[method.Name] = bucketByMethodRaw = new Dictionary>(StringComparer.OrdinalIgnoreCase) + { + { "", parametersByContentType } + }; + } + + bucketByMethod = (Dictionary>)bucketByMethodRaw; + bucketByMethod[contentTypeEntry.Name] = parametersByContentType; + } + } + } + } + + metadata.Add(new EndpointMetadata(path.Name, requestMethods)); + } + } + + return metadata; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.HttpRepl/OpenApi/Parameter.cs b/src/Microsoft.HttpRepl/OpenApi/Parameter.cs new file mode 100644 index 0000000000..faf21e5f9a --- /dev/null +++ b/src/Microsoft.HttpRepl/OpenApi/Parameter.cs @@ -0,0 +1,13 @@ +namespace Microsoft.HttpRepl.OpenApi +{ + public class Parameter + { + public string Name { get; set; } + + public string Location { get; set; } + + public bool IsRequired { get; set; } + + public Schema Schema { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs b/src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs new file mode 100644 index 0000000000..b01730b116 --- /dev/null +++ b/src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs @@ -0,0 +1,218 @@ +using System; +using System.Globalization; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using Newtonsoft.Json.Linq; + +namespace Microsoft.HttpRepl.OpenApi +{ + public static class PointerUtil + { + public static Task ResolvePointersAsync(Uri loadLocation, JToken root, HttpClient client) + { + return ResolvePointersAsync(loadLocation, root, root, client); + } + + private static async Task ResolvePointersAsync(Uri loadLocation, JToken root, JToken toResolve, HttpClient client) + { + if (toResolve is JArray arr) + { + for (int i = 0; i < arr.Count; ++i) + { + arr[i] = await ResolvePointersAsync(loadLocation, root, arr[i], client).ConfigureAwait(false); + } + } + else if (toResolve is JObject obj) + { + if (obj["$ref"] is JValue refVal && refVal.Type == JTokenType.String) + { + if (!Uri.TryCreate((string)refVal.Value, UriKind.RelativeOrAbsolute, out Uri loadTarget)) + { + //TODO: Error resolving pointer (pointer must be a valid URI) + return new JValue((object)null); + } + + if (!loadTarget.IsAbsoluteUri) + { + if (!Uri.TryCreate(loadLocation, loadTarget, out loadTarget)) + { + //TODO: Error resolving pointer (could not combine with base path) + return new JValue((object)null); + } + } + + //Check to see if we're changing source documents, if we are, get it + if (!string.Equals(loadLocation.Host, loadTarget.Host, StringComparison.OrdinalIgnoreCase) || !string.Equals(loadLocation.AbsolutePath, loadTarget.AbsolutePath, StringComparison.OrdinalIgnoreCase)) + { + HttpResponseMessage responseMessage = await client.GetAsync(loadTarget).ConfigureAwait(false); + + if (!responseMessage.IsSuccessStatusCode) + { + //TODO: Error resolving pointer (could not get referenced document) + return new JValue((object)null); + } + + string responseString = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false); + JToken newRoot; + + try + { + newRoot = JToken.Parse(responseString); + } + catch + { + //TODO: Error resolving pointer (referenced document is not valid JSON) + return new JValue((object)null); + } + + return await ResolvePointersAsync(loadTarget, newRoot, newRoot, client).ConfigureAwait(false); + } + + //We're in the right document, grab the bookmark (fragment) of the URI and get the element at that path + string fragment = loadTarget.Fragment; + + if (fragment.StartsWith('#')) + { + fragment = fragment.Substring(1); + } + + string[] parts = fragment.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + JToken cursor = root; + + for (int i = 0; i < parts.Length; ++i) + { + if (cursor is JArray ca) + { + if (!int.TryParse(parts[i], NumberStyles.Integer, CultureInfo.InvariantCulture, out int index)) + { + //TODO: Error resolving pointer, array index is non-integral + return new JValue((object)null); + } + + if (index < 0 || index >= ca.Count) + { + //TODO: Error resolving pointer, array index is out of bounds + return new JValue((object)null); + } + + JToken val = ca[index]; + if (val is JObject vo && vo.TryGetValue("$ref", out JToken vor) && vor is JValue vorv && vorv.Type == JTokenType.String) + { + cursor = await ResolvePointersAsync(loadLocation, root, val, client).ConfigureAwait(false); + } + else + { + cursor = val; + } + } + else if (cursor is JObject co) + { + if (!co.TryGetValue(parts[i], out JToken val)) + { + //TODO: Error resolving pointer, no such property on object + return new JValue((object)null); + } + + if (val is JObject vo && vo.TryGetValue("$ref", out JToken vor) && vor is JValue vorv && vorv.Type == JTokenType.String) + { + cursor = await ResolvePointersAsync(loadLocation, root, val, client).ConfigureAwait(false); + } + else + { + cursor = val; + } + } + else + { + //TODO: Error resolving pointer, cannot index into literal + return new JValue((object)null); + } + } + + cursor = await ResolvePointersAsync(loadLocation, root, cursor, client); + return cursor.DeepClone(); + } + + foreach (JProperty property in obj.Properties().ToList()) + { + obj[property.Name] = await ResolvePointersAsync(loadLocation, root, property.Value, client).ConfigureAwait(false); + } + } + + return toResolve; + } + + //public static async Task ResolvePointerAsync(this JToken root, HttpClient client, string pointer) + //{ + // if (!pointer.StartsWith("#/", StringComparison.Ordinal)) + // { + // HttpResponseMessage response = await client.GetAsync(pointer).ConfigureAwait(false); + + // if (!response.IsSuccessStatusCode) + // { + // //TODO: Failed to resolve pointer message + // return new JValue((object)null); + // } + + // string responseString = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + + // try + // { + // root = JToken.Parse(responseString); + // int hashIndex = pointer.IndexOf("#"); + + // if (hashIndex < 0) + // { + // return root; + // } + + // pointer = pointer.Substring(hashIndex); + // } + // catch (Exception ex) + // { + // //TODO: Failed to deserialize pointer message + // return new JValue((object)null); + // } + // } + + // string[] pointerParts = pointer.Split('/'); + + // for (int i = 1; !(root is null) && i < pointerParts.Length; ++i) + // { + // if (root is JArray arr) + // { + // if (!int.TryParse(pointerParts[i], System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out int result) || result < 0 || result >= arr.Count) + // { + // //TODO: Failed to resolve pointer part message (non-integer index to array or index out of range) + // return null; + // } + + // root = arr[result]; + // } + // else if (root is JObject obj) + // { + // root = obj[pointerParts[i]]; + + // if (root is null) + // { + // //TODO: Failed to resolve pointer part message (no such path in object) + // } + + // JToken nestedRef = root["$ref"]; + // if (nestedRef is JValue value && value.Type == JTokenType.String) + // { + // root = await ResolvePointerAsync(root, ) + // } + // } + // else + // { + // //TODO: Failed to resolve pointer part message (pathing into literal) + // return null; + // } + // } + + // return root; + //} + } +} \ No newline at end of file diff --git a/src/Microsoft.HttpRepl/OpenApi/Schema.cs b/src/Microsoft.HttpRepl/OpenApi/Schema.cs new file mode 100644 index 0000000000..028c0b13ca --- /dev/null +++ b/src/Microsoft.HttpRepl/OpenApi/Schema.cs @@ -0,0 +1,125 @@ +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Microsoft.HttpRepl.OpenApi +{ + public class Schema + { + public void PrepareForUsage(JToken document) + { + AdditionalProperties?.Option1?.PrepareForUsage(document); + + if (AllOf != null) + { + for (int i = 0; i < AllOf.Length; ++i) + { + AllOf[i].PrepareForUsage(document); + } + } + + if (AnyOf != null) + { + for (int i = 0; i < AnyOf.Length; ++i) + { + AnyOf[i].PrepareForUsage(document); + } + } + + if (OneOf != null) + { + for (int i = 0; i < OneOf.Length; ++i) + { + OneOf[i].PrepareForUsage(document); + } + } + + if (Properties != null) + { + IReadOnlyList keys = Properties.Keys.ToList(); + for (int i = 0; i < keys.Count; ++i) + { + Properties[keys[i]]?.PrepareForUsage(document); + } + } + + Items?.PrepareForUsage(document); + Not?.PrepareForUsage(document); + + if (Required?.Option1 != null) + { + if (Properties != null) + { + foreach (string propertyName in Required.Option1) + { + if (Properties.TryGetValue(propertyName, out Schema value)) + { + value.Required = true; + } + } + } + + Required = false; + } + } + + [JsonConverter(typeof(EitherConverter))] + public Either AdditionalProperties { get; set; } + + public Schema[] AllOf { get; set; } + + public Schema[] AnyOf { get; set; } + + public object Default { get; set; } + + public string Description { get; set; } + + public object[] Enum { get; set; } + + public object Example { get; set; } + + public bool ExclusiveMaximum { get; set; } + + public bool ExclusiveMinimum { get; set; } + + public string Format { get; set; } + + public Schema Items { get; set; } + + public double? Maximum { get; set; } + + public double? Minimum { get; set; } + + public int? MaxItems { get; set; } + + public int? MinItems { get; set; } + + public int? MaxLength { get; set; } + + public int? MinLength { get; set; } + + public int? MaxProperties { get; set; } + + public int? MinProperties { get; set; } + + public double? MultipleOf { get; set; } + + public Schema Not { get; set; } + + public Schema[] OneOf { get; set; } + + public string Pattern { get; set; } + + public Dictionary Properties { get; set; } + + [JsonConverter(typeof(EitherConverter))] + public Either Required { get; set; } + + public string Title { get; set; } + + public string Type { get; set; } + + public bool UniqueItems { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.HttpRepl/OpenApi/SwaggerV1EndpointMetadataReader.cs b/src/Microsoft.HttpRepl/OpenApi/SwaggerV1EndpointMetadataReader.cs new file mode 100644 index 0000000000..7f4fef4fb1 --- /dev/null +++ b/src/Microsoft.HttpRepl/OpenApi/SwaggerV1EndpointMetadataReader.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json.Linq; + +namespace Microsoft.HttpRepl.OpenApi +{ + public class SwaggerV1EndpointMetadataReader : IEndpointMetadataReader + { + public bool CanHandle(JObject document) + { + return (document["swaggerVersion"]?.ToString() ?? "").StartsWith("1.", StringComparison.Ordinal); + } + + public IEnumerable ReadMetadata(JObject document) + { + List metadata = new List(); + + if (!(document["consumes"] is JArray globalConsumes)) + { + globalConsumes = new JArray(); + } + + if (document["apis"] is JObject obj) + { + foreach (JProperty property in obj.Properties()) + { + string path = obj["path"]?.ToString(); + + if (path is null) + { + continue; + } + + Dictionary>> requestMethods = new Dictionary>>(StringComparer.Ordinal); + + if (obj["operations"] is JArray operations) + { + foreach (JObject operationObject in operations.OfType()) + { + string method = operationObject["method"]?.ToString(); + List parameters = new List(); + + if (operationObject["parameters"] is JArray parametersArray) + { + foreach (JObject parameterObj in parametersArray.OfType()) + { + Parameter p = parameterObj.ToObject(); + p.Location = parameterObj["paramType"]?.ToString(); + p.IsRequired = parameterObj["required"]?.ToObject() ?? false; + + string type = parameterObj["type"]?.ToString(); + + if (type is null) + { + continue; + } + + switch (type.ToUpperInvariant()) + { + case "INTEGER": + case "NUMBER": + case "STRING": + case "BOOLEAN": + p.Schema = new Schema { Type = type }; + break; + case "FILE": + break; + default: + if (document["models"]?[type] is JObject schemaObject) + { + //TODO: Handle subtypes (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/1.2.md#527-model-object) + p.Schema = schemaObject.ToObject(); + } + break; + } + + parameters.Add(p); + } + } + + if (!(operationObject["consumes"] is JArray consumes)) + { + consumes = globalConsumes; + } + + Dictionary> parametersByContentType = new Dictionary>(StringComparer.OrdinalIgnoreCase) + { + { "", parameters } + }; + + foreach (JValue value in consumes.OfType().Where(x => x.Type == JTokenType.String)) + { + parametersByContentType[value.ToString()] = parameters; + } + } + } + + metadata.Add(new EndpointMetadata(path, requestMethods)); + } + } + + return metadata; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.HttpRepl/OpenApi/SwaggerV2EndpointMetadataReader.cs b/src/Microsoft.HttpRepl/OpenApi/SwaggerV2EndpointMetadataReader.cs new file mode 100644 index 0000000000..5e7ecfe6aa --- /dev/null +++ b/src/Microsoft.HttpRepl/OpenApi/SwaggerV2EndpointMetadataReader.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json.Linq; + +namespace Microsoft.HttpRepl.OpenApi +{ + public class SwaggerV2EndpointMetadataReader : IEndpointMetadataReader + { + public bool CanHandle(JObject document) + { + return (document["swagger"]?.ToString() ?? "").StartsWith("2.", StringComparison.Ordinal); + } + + public IEnumerable ReadMetadata(JObject document) + { + List metadata = new List(); + + if (!(document["consumes"] is JArray globalConsumes)) + { + globalConsumes = new JArray(); + } + + if (document["paths"] is JObject obj) + { + foreach (JProperty property in obj.Properties()) + { + if (!(property.Value is JObject requestMethodInfos)) + { + continue; + } + + Dictionary>> requestMethods = new Dictionary>>(StringComparer.Ordinal); + + foreach (JProperty methodInfo in requestMethodInfos.Properties()) + { + List parameters = new List(); + + if (methodInfo.Value is JObject methodInfoDescription) + { + if (methodInfoDescription["parameters"] is JArray parametersArray) + { + foreach (JObject parameterObj in parametersArray.OfType()) + { + //TODO: Resolve refs here + + Parameter p = parameterObj.ToObject(); + p.Location = parameterObj["in"]?.ToString(); + p.IsRequired = parameterObj["required"]?.ToObject() ?? false; + + if (!(parameterObj["schema"] is JObject schemaObject)) + { + schemaObject = null; + } + + p.Schema = schemaObject?.ToObject() ?? parameterObj.ToObject(); + parameters.Add(p); + } + } + + if (!(methodInfoDescription["consumes"] is JArray consumes)) + { + consumes = globalConsumes; + } + + Dictionary> parametersByContentType = new Dictionary>(StringComparer.OrdinalIgnoreCase) + { + { "", parameters } + }; + + foreach (JValue value in consumes.OfType().Where(x => x.Type == JTokenType.String)) + { + parametersByContentType[value.ToString()] = parameters; + } + + requestMethods[methodInfo.Name] = parametersByContentType; + } + } + + metadata.Add(new EndpointMetadata(property.Name, requestMethods)); + } + } + + return metadata; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.HttpRepl/Preferences/IJsonConfig.cs b/src/Microsoft.HttpRepl/Preferences/IJsonConfig.cs new file mode 100644 index 0000000000..21918e44ef --- /dev/null +++ b/src/Microsoft.HttpRepl/Preferences/IJsonConfig.cs @@ -0,0 +1,29 @@ +using Microsoft.Repl.ConsoleHandling; + +namespace Microsoft.HttpRepl.Preferences +{ + public interface IJsonConfig + { + int IndentSize { get; } + + AllowedColors DefaultColor { get; } + + AllowedColors ArrayBraceColor { get; } + + AllowedColors ObjectBraceColor { get; } + + AllowedColors CommaColor { get; } + + AllowedColors NameColor { get; } + + AllowedColors NameSeparatorColor { get; } + + AllowedColors BoolColor { get; } + + AllowedColors NumericColor { get; } + + AllowedColors StringColor { get; } + + AllowedColors NullColor { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.HttpRepl/Preferences/JsonConfig.cs b/src/Microsoft.HttpRepl/Preferences/JsonConfig.cs new file mode 100644 index 0000000000..a1902e245e --- /dev/null +++ b/src/Microsoft.HttpRepl/Preferences/JsonConfig.cs @@ -0,0 +1,42 @@ +using Microsoft.Repl.ConsoleHandling; + +namespace Microsoft.HttpRepl.Preferences +{ + public class JsonConfig : IJsonConfig + { + private readonly HttpState _state; + + public int IndentSize => _state.GetIntPreference(WellKnownPreference.JsonIndentSize, 2); + + public AllowedColors DefaultColor => _state.GetColorPreference(WellKnownPreference.JsonColor); + + private AllowedColors DefaultBraceColor => _state.GetColorPreference(WellKnownPreference.JsonBraceColor, DefaultSyntaxColor); + + private AllowedColors DefaultSyntaxColor => _state.GetColorPreference(WellKnownPreference.JsonSyntaxColor, DefaultColor); + + private AllowedColors DefaultLiteralColor => _state.GetColorPreference(WellKnownPreference.JsonLiteralColor, DefaultColor); + + public AllowedColors ArrayBraceColor => _state.GetColorPreference(WellKnownPreference.JsonArrayBraceColor, DefaultBraceColor); + + public AllowedColors ObjectBraceColor => _state.GetColorPreference(WellKnownPreference.JsonObjectBraceColor, DefaultBraceColor); + + public AllowedColors CommaColor => _state.GetColorPreference(WellKnownPreference.JsonCommaColor, DefaultSyntaxColor); + + public AllowedColors NameColor => _state.GetColorPreference(WellKnownPreference.JsonNameColor, StringColor); + + public AllowedColors NameSeparatorColor => _state.GetColorPreference(WellKnownPreference.JsonNameSeparatorColor, DefaultSyntaxColor); + + public AllowedColors BoolColor => _state.GetColorPreference(WellKnownPreference.JsonBoolColor, DefaultLiteralColor); + + public AllowedColors NumericColor => _state.GetColorPreference(WellKnownPreference.JsonNumericColor, DefaultLiteralColor); + + public AllowedColors StringColor => _state.GetColorPreference(WellKnownPreference.JsonStringColor, DefaultLiteralColor); + + public AllowedColors NullColor => _state.GetColorPreference(WellKnownPreference.JsonNullColor, DefaultLiteralColor); + + public JsonConfig(HttpState state) + { + _state = state; + } + } +} diff --git a/src/Microsoft.HttpRepl/Preferences/RequestConfig.cs b/src/Microsoft.HttpRepl/Preferences/RequestConfig.cs new file mode 100644 index 0000000000..a3f9b55259 --- /dev/null +++ b/src/Microsoft.HttpRepl/Preferences/RequestConfig.cs @@ -0,0 +1,46 @@ +using Microsoft.Repl.ConsoleHandling; + +namespace Microsoft.HttpRepl.Preferences +{ + public class RequestConfig : RequestOrResponseConfig + { + public RequestConfig(HttpState state) + : base(state) + { + } + + public override AllowedColors BodyColor => State.GetColorPreference(WellKnownPreference.RequestBodyColor, base.BodyColor); + + public override AllowedColors SchemeColor => State.GetColorPreference(WellKnownPreference.RequestSchemeColor, base.SchemeColor); + + public override AllowedColors HeaderKeyColor => State.GetColorPreference(WellKnownPreference.RequestHeaderKeyColor, base.HeaderKeyColor); + + public override AllowedColors HeaderSeparatorColor => State.GetColorPreference(WellKnownPreference.RequestHeaderSeparatorColor, base.HeaderSeparatorColor); + + public override AllowedColors HeaderValueSeparatorColor => State.GetColorPreference(WellKnownPreference.RequestHeaderValueSeparatorColor, base.HeaderValueSeparatorColor); + + public override AllowedColors HeaderValueColor => State.GetColorPreference(WellKnownPreference.RequestHeaderValueColor, base.HeaderValueColor); + + public override AllowedColors HeaderColor => State.GetColorPreference(WellKnownPreference.RequestHeaderColor, base.HeaderColor); + + public override AllowedColors GeneralColor => State.GetColorPreference(WellKnownPreference.RequestColor, base.GeneralColor); + + public override AllowedColors ProtocolColor => State.GetColorPreference(WellKnownPreference.RequestProtocolColor, base.ProtocolColor); + + public override AllowedColors ProtocolNameColor => State.GetColorPreference(WellKnownPreference.RequestProtocolNameColor, base.ProtocolNameColor); + + public override AllowedColors ProtocolVersionColor => State.GetColorPreference(WellKnownPreference.RequestProtocolVersionColor, base.ProtocolVersionColor); + + public override AllowedColors ProtocolSeparatorColor => State.GetColorPreference(WellKnownPreference.RequestProtocolSeparatorColor, base.ProtocolSeparatorColor); + + public override AllowedColors StatusColor => State.GetColorPreference(WellKnownPreference.RequestStatusColor, base.StatusColor); + + public override AllowedColors StatusCodeColor => State.GetColorPreference(WellKnownPreference.RequestStatusCodeColor, base.StatusCodeColor); + + public override AllowedColors StatusReasonPhraseColor => State.GetColorPreference(WellKnownPreference.RequestStatusReaseonPhraseColor, base.StatusReasonPhraseColor); + + public AllowedColors MethodColor => State.GetColorPreference(WellKnownPreference.RequestMethodColor, GeneralColor); + + public AllowedColors AddressColor => State.GetColorPreference(WellKnownPreference.RequestAddressColor, GeneralColor); + } +} diff --git a/src/Microsoft.HttpRepl/Preferences/RequestOrResponseConfig.cs b/src/Microsoft.HttpRepl/Preferences/RequestOrResponseConfig.cs new file mode 100644 index 0000000000..c509a89f5e --- /dev/null +++ b/src/Microsoft.HttpRepl/Preferences/RequestOrResponseConfig.cs @@ -0,0 +1,44 @@ +using Microsoft.Repl.ConsoleHandling; + +namespace Microsoft.HttpRepl.Preferences +{ + public abstract class RequestOrResponseConfig + { + protected HttpState State { get; } + + protected RequestOrResponseConfig(HttpState state) + { + State = state; + } + + public virtual AllowedColors BodyColor => State.GetColorPreference(WellKnownPreference.BodyColor, GeneralColor); + + public virtual AllowedColors SchemeColor => State.GetColorPreference(WellKnownPreference.SchemeColor, GeneralColor); + + public virtual AllowedColors HeaderKeyColor => State.GetColorPreference(WellKnownPreference.HeaderKeyColor, HeaderColor); + + public virtual AllowedColors HeaderSeparatorColor => State.GetColorPreference(WellKnownPreference.HeaderSeparatorColor, HeaderColor); + + public virtual AllowedColors HeaderValueSeparatorColor => State.GetColorPreference(WellKnownPreference.HeaderValueSeparatorColor, HeaderSeparatorColor); + + public virtual AllowedColors HeaderValueColor => State.GetColorPreference(WellKnownPreference.HeaderValueColor, HeaderColor); + + public virtual AllowedColors HeaderColor => State.GetColorPreference(WellKnownPreference.HeaderColor, GeneralColor); + + public virtual AllowedColors GeneralColor => State.GetColorPreference(WellKnownPreference.RequestOrResponseColor); + + public virtual AllowedColors ProtocolColor => State.GetColorPreference(WellKnownPreference.ProtocolColor, GeneralColor); + + public virtual AllowedColors ProtocolNameColor => State.GetColorPreference(WellKnownPreference.ProtocolNameColor, ProtocolColor); + + public virtual AllowedColors ProtocolVersionColor => State.GetColorPreference(WellKnownPreference.ProtocolVersionColor, ProtocolColor); + + public virtual AllowedColors ProtocolSeparatorColor => State.GetColorPreference(WellKnownPreference.ProtocolSeparatorColor, ProtocolColor); + + public virtual AllowedColors StatusColor => State.GetColorPreference(WellKnownPreference.StatusColor, GeneralColor); + + public virtual AllowedColors StatusCodeColor => State.GetColorPreference(WellKnownPreference.StatusCodeColor, StatusColor); + + public virtual AllowedColors StatusReasonPhraseColor => State.GetColorPreference(WellKnownPreference.StatusReaseonPhraseColor, StatusColor); + } +} diff --git a/src/Microsoft.HttpRepl/Preferences/ResponseConfig.cs b/src/Microsoft.HttpRepl/Preferences/ResponseConfig.cs new file mode 100644 index 0000000000..123a86ff79 --- /dev/null +++ b/src/Microsoft.HttpRepl/Preferences/ResponseConfig.cs @@ -0,0 +1,42 @@ +using Microsoft.Repl.ConsoleHandling; + +namespace Microsoft.HttpRepl.Preferences +{ + public class ResponseConfig : RequestOrResponseConfig + { + public ResponseConfig(HttpState state) + : base(state) + { + } + + public override AllowedColors BodyColor => State.GetColorPreference(WellKnownPreference.ResponseBodyColor, base.BodyColor); + + public override AllowedColors SchemeColor => State.GetColorPreference(WellKnownPreference.ResponseSchemeColor, base.SchemeColor); + + public override AllowedColors HeaderKeyColor => State.GetColorPreference(WellKnownPreference.ResponseHeaderKeyColor, base.HeaderKeyColor); + + public override AllowedColors HeaderSeparatorColor => State.GetColorPreference(WellKnownPreference.ResponseHeaderSeparatorColor, base.HeaderSeparatorColor); + + public override AllowedColors HeaderValueSeparatorColor => State.GetColorPreference(WellKnownPreference.ResponseHeaderValueSeparatorColor, base.HeaderValueSeparatorColor); + + public override AllowedColors HeaderValueColor => State.GetColorPreference(WellKnownPreference.ResponseHeaderValueColor, base.HeaderValueColor); + + public override AllowedColors HeaderColor => State.GetColorPreference(WellKnownPreference.ResponseHeaderColor, base.HeaderColor); + + public override AllowedColors GeneralColor => State.GetColorPreference(WellKnownPreference.ResponseColor, base.GeneralColor); + + public override AllowedColors ProtocolColor => State.GetColorPreference(WellKnownPreference.ResponseProtocolColor, base.ProtocolColor); + + public override AllowedColors ProtocolNameColor => State.GetColorPreference(WellKnownPreference.ResponseProtocolNameColor, base.ProtocolNameColor); + + public override AllowedColors ProtocolVersionColor => State.GetColorPreference(WellKnownPreference.ResponseProtocolVersionColor, base.ProtocolVersionColor); + + public override AllowedColors ProtocolSeparatorColor => State.GetColorPreference(WellKnownPreference.ResponseProtocolSeparatorColor, base.ProtocolSeparatorColor); + + public override AllowedColors StatusColor => State.GetColorPreference(WellKnownPreference.ResponseStatusColor, base.StatusColor); + + public override AllowedColors StatusCodeColor => State.GetColorPreference(WellKnownPreference.ResponseStatusCodeColor, base.StatusCodeColor); + + public override AllowedColors StatusReasonPhraseColor => State.GetColorPreference(WellKnownPreference.ResponseStatusReaseonPhraseColor, base.StatusReasonPhraseColor); + } +} diff --git a/src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs b/src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs new file mode 100644 index 0000000000..a6c16a6da7 --- /dev/null +++ b/src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs @@ -0,0 +1,200 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using Microsoft.Repl.ConsoleHandling; + +namespace Microsoft.HttpRepl.Preferences +{ + public static class WellKnownPreference + { + public static class Catalog + { + private static IReadOnlyList _names; + + public static IReadOnlyList Names + { + get + { + if (_names != null) + { + return _names; + } + + List matchingProperties = new List(); + + foreach (PropertyInfo property in typeof(WellKnownPreference).GetProperties(BindingFlags.Public | BindingFlags.Static)) + { + if (property.PropertyType == typeof(string) && property.GetMethod != null && property.GetValue(null) is string val) + { + matchingProperties.Add(val); + } + } + + return _names = matchingProperties; + } + } + } + + #region JSON + public static string JsonArrayBraceColor { get; } = "colors.json.arrayBrace"; + + public static string JsonObjectBraceColor { get; } = "colors.json.objectBrace"; + + public static string JsonNameColor { get; } = "colors.json.name"; + + public static string JsonNameSeparatorColor { get; } = "colors.json.nameSeparator"; + + public static string JsonIndentSize { get; } = "formatting.json.indentSize"; + + public static string JsonCommaColor { get; } = "colors.json.comma"; + + public static string JsonLiteralColor { get; } = "colors.json.literal"; + + public static string JsonNullColor { get; } = "colors.json.null"; + + public static string JsonBoolColor { get; } = "colors.json.bool"; + + public static string JsonNumericColor { get; } = "colors.json.numeric"; + + public static string JsonStringColor { get; } = "colors.json.string"; + + public static string JsonColor { get; } = "colors.json"; + + public static string JsonSyntaxColor { get; } = "colors.json.syntax"; + + public static string JsonBraceColor { get; } = "colors.json.brace"; + #endregion JSON + + public static string RequestColor { get; } = "colors.request"; + + public static string RequestBodyColor { get; } = "colors.request.body"; + + public static string RequestSchemeColor { get; } = "colors.request.scheme"; + + public static string RequestHeaderKeyColor { get; } = "colors.request.header.key"; + + public static string RequestHeaderSeparatorColor { get; } = "colors.request.header.separator"; + + public static string RequestHeaderValueSeparatorColor { get; } = "colors.request.header.valueSeparator"; + + public static string RequestHeaderValueColor { get; } = "colors.request.header.value"; + + public static string RequestHeaderColor { get; } = "colors.request.header"; + + public static string RequestProtocolColor { get; } = "colors.request.protocol"; + + public static string RequestProtocolNameColor { get; } = "colors.request.protocol.name"; + + public static string RequestProtocolSeparatorColor { get; } = "colors.request.protocol.separator"; + + public static string RequestProtocolVersionColor { get; } = "colors.request.protocol.version"; + + public static string RequestStatusColor { get; } = "colors.request.status"; + + public static string RequestStatusCodeColor { get; } = "colors.request.status.code"; + + public static string RequestStatusReaseonPhraseColor { get; } = "colors.request.status.reasonPhrase"; + + public static string RequestMethodColor { get; } = "colors.request.method"; + + public static string RequestAddressColor { get; } = "colors.request.address"; + + + public static string ResponseColor { get; } = "colors.response"; + + public static string ResponseBodyColor { get; } = "colors.response.body"; + + public static string ResponseSchemeColor { get; } = "colors.response.scheme"; + + public static string ResponseHeaderKeyColor { get; } = "colors.response.header.key"; + + public static string ResponseHeaderSeparatorColor { get; } = "colors.response.header.separator"; + + public static string ResponseHeaderValueSeparatorColor { get; } = "colors.response.header.valueSeparator"; + + public static string ResponseHeaderValueColor { get; } = "colors.response.header.value"; + + public static string ResponseHeaderColor { get; } = "colors.response.header"; + + public static string ResponseProtocolColor { get; } = "colors.response.protocol"; + + public static string ResponseProtocolNameColor { get; } = "colors.response.protocol.name"; + + public static string ResponseProtocolSeparatorColor { get; } = "colors.response.protocol.separator"; + + public static string ResponseProtocolVersionColor { get; } = "colors.response.protocol.version"; + + public static string ResponseStatusColor { get; } = "colors.response.status"; + + public static string ResponseStatusCodeColor { get; } = "colors.response.status.code"; + + public static string ResponseStatusReaseonPhraseColor { get; } = "colors.response.status.reasonPhrase"; + + + public static string RequestOrResponseColor { get; } = "colors.requestOrResponse"; + + public static string BodyColor { get; } = "colors.body"; + + public static string SchemeColor { get; } = "colors.scheme"; + + public static string HeaderKeyColor { get; } = "colors.header.key"; + + public static string HeaderSeparatorColor { get; } = "colors.header.separator"; + + public static string HeaderValueSeparatorColor { get; } = "colors.header.valueSeparator"; + + public static string HeaderValueColor { get; } = "colors.header.value"; + + public static string HeaderColor { get; } = "colors.header"; + + public static string ProtocolColor { get; } = "colors.protocol"; + + public static string ProtocolNameColor { get; } = "colors.protocol.name"; + + public static string ProtocolSeparatorColor { get; } = "colors.protocol.separator"; + + public static string ProtocolVersionColor { get; } = "colors.protocol.version"; + + public static string StatusColor { get; } = "colors.status"; + + public static string StatusCodeColor { get; } = "colors.status.code"; + + public static string StatusReaseonPhraseColor { get; } = "colors.status.reasonPhrase"; + + + public static string DefaultEditorCommand { get; } = "editor.command.default"; + + public static string DefaultEditorArguments { get; } = "editor.command.default.arguments"; + + + public static AllowedColors GetColorPreference(this HttpState programState, string preference, AllowedColors defaultvalue = AllowedColors.None) + { + if (!programState.Preferences.TryGetValue(preference, out string preferenceValueString) || !Enum.TryParse(preferenceValueString, true, out AllowedColors result)) + { + result = defaultvalue; + } + + return result; + } + + public static int GetIntPreference(this HttpState programState, string preference, int defaultValue = 0) + { + if (!programState.Preferences.TryGetValue(preference, out string preferenceValueString) || !int.TryParse(preferenceValueString, out int result)) + { + result = defaultValue; + } + + return result; + } + + public static string GetStringPreference(this HttpState programState, string preference, string defaultValue = null) + { + if (!programState.Preferences.TryGetValue(preference, out string result)) + { + result = defaultValue; + } + + return result; + } + } +} diff --git a/src/Microsoft.HttpRepl/Program.cs b/src/Microsoft.HttpRepl/Program.cs new file mode 100644 index 0000000000..f64fcf377a --- /dev/null +++ b/src/Microsoft.HttpRepl/Program.cs @@ -0,0 +1,52 @@ +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Repl; +using Microsoft.Repl.Commanding; +using Microsoft.Repl.Parsing; +using Microsoft.HttpRepl.Commands; + +namespace Microsoft.HttpRepl +{ + class Program + { + static async Task Main(string[] args) + { + var state = new HttpState(); + var dispatcher = DefaultCommandDispatcher.Create(state.GetPrompt, state); + + dispatcher.AddCommand(new ChangeDirectoryCommand()); + dispatcher.AddCommand(new ClearCommand()); + //dispatcher.AddCommand(new ConfigCommand()); + dispatcher.AddCommand(new DeleteCommand()); + dispatcher.AddCommand(new EchoCommand()); + dispatcher.AddCommand(new ExitCommand()); + dispatcher.AddCommand(new HeadCommand()); + dispatcher.AddCommand(new HelpCommand()); + dispatcher.AddCommand(new GetCommand()); + dispatcher.AddCommand(new ListCommand()); + dispatcher.AddCommand(new OptionsCommand()); + dispatcher.AddCommand(new PatchCommand()); + dispatcher.AddCommand(new PrefCommand()); + dispatcher.AddCommand(new PostCommand()); + dispatcher.AddCommand(new PutCommand()); + dispatcher.AddCommand(new RunCommand()); + dispatcher.AddCommand(new SetBaseCommand()); + dispatcher.AddCommand(new SetDiagCommand()); + dispatcher.AddCommand(new SetHeaderCommand()); + dispatcher.AddCommand(new SetSwaggerCommand()); + dispatcher.AddCommand(new UICommand()); + + CancellationTokenSource source = new CancellationTokenSource(); + var shell = new Shell(dispatcher); + shell.ShellState.ConsoleManager.AddBreakHandler(() => source.Cancel()); + if (args.Length > 0) + { + shell.ShellState.CommandDispatcher.OnReady(shell.ShellState); + shell.ShellState.InputManager.SetInput(shell.ShellState, $"set base \"{args[0]}\""); + await shell.ShellState.CommandDispatcher.ExecuteCommandAsync(shell.ShellState, CancellationToken.None).ConfigureAwait(false); + } + Task result = shell.RunAsync(source.Token); + await result.ConfigureAwait(false); + } + } +} diff --git a/src/Microsoft.HttpRepl/Properties/launchSettings.json b/src/Microsoft.HttpRepl/Properties/launchSettings.json new file mode 100644 index 0000000000..dcce8f72a3 --- /dev/null +++ b/src/Microsoft.HttpRepl/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Microsoft.HttpRepl": { + "commandName": "Project", + "commandLineArgs": "http://localhost" + } + } +} \ No newline at end of file diff --git a/src/Microsoft.HttpRepl/Suggestions/HeaderCompletion.cs b/src/Microsoft.HttpRepl/Suggestions/HeaderCompletion.cs new file mode 100644 index 0000000000..05372d7bec --- /dev/null +++ b/src/Microsoft.HttpRepl/Suggestions/HeaderCompletion.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.HttpRepl.Suggestions +{ + public class HeaderCompletion + { + private static readonly IEnumerable CommonHeaders = new[] + { + "A-IM", + "Accept", + "Accept-Charset", + "Accept-Encoding", + "Accept-Language", + "Accept-Datetime", + "Access-Control-Request-Method", + "Access-Control-Request-Headers", + "Authorization", + "Cache-Control", + "Connection", + "Content-Length", + "Content-MD5", + "Content-Type", + "Cookie", + "Date", + "Expect", + "Forwarded", + "From", + "Host", + "If-Match", + "If-Modified-Since", + "If-None-Match", + "If-Range", + "If-Unmodified-Since", + "Max-Forwards", + "Origin", + "Pragma", + "Proxy-Authentication", + "Range", + "Referer", + "TE", + "User-Agent", + "Upgrade", + "Via", + "Warning", + //Non-standard + "Upgrade-Insecure-Requests", + "X-Requested-With", + "DNT", + "X-Forwarded-For", + "X-Forwarded-Host", + "X-Forwarded-Proto", + "Front-End-Https", + "X-Http-Method-Override", + "X-ATT-DeviceId", + "X-Wap-Profile", + "Proxy-Connection", + "X-UIDH", + "X-Csrf-Token", + "X-Request-ID", + "X-Correlation-ID" + }; + + private static readonly IReadOnlyList DefaultContentTypesList = null; + + public static IEnumerable GetCompletions(IReadOnlyCollection existingHeaders, string prefix) + { + List result = CommonHeaders.Where(x => x.StartsWith(prefix, StringComparison.OrdinalIgnoreCase) && !(existingHeaders?.Contains(x) ?? false)).ToList(); + + if (result.Count > 0) + { + return result; + } + + return null; + } + + public static IEnumerable GetValueCompletions(string method, string path, string header, string prefix, HttpState programState) + { + switch (header.ToUpperInvariant()) + { + case "CONTENT-TYPE": + IEnumerable results = programState.GetApplicableContentTypes(method, path) ?? DefaultContentTypesList; + + if (results is null) + { + return null; + } + + return results.Where(x => !string.IsNullOrEmpty(x) && x.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)); + default: + return null; + } + } + } +} diff --git a/src/Microsoft.HttpRepl/Suggestions/ServerPathCompletion.cs b/src/Microsoft.HttpRepl/Suggestions/ServerPathCompletion.cs new file mode 100644 index 0000000000..a50df8ae8d --- /dev/null +++ b/src/Microsoft.HttpRepl/Suggestions/ServerPathCompletion.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.HttpRepl.Suggestions +{ + public static class ServerPathCompletion + { + public static IEnumerable GetCompletions(HttpState programState, string normalCompletionString) + { + + //If it's an absolute URI, nothing to suggest + if (Uri.TryCreate(normalCompletionString, UriKind.Absolute, out Uri _)) + { + return null; + } + + string path = normalCompletionString.Replace('\\', '/'); + int searchFrom = normalCompletionString.Length - 1; + int lastSlash = path.LastIndexOf('/', searchFrom); + string prefix; + + if (lastSlash < 0) + { + path = string.Empty; + prefix = normalCompletionString; + } + else + { + path = path.Substring(0, lastSlash + 1); + prefix = normalCompletionString.Substring(lastSlash + 1); + } + + IDirectoryStructure s = programState.Structure.TraverseTo(programState.PathSections.Reverse()).TraverseTo(path); + + if (s?.DirectoryNames == null) + { + return null; + } + + List results = new List(); + + foreach (string child in s.DirectoryNames) + { + if (child.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) + { + results.Add(path + child); + } + } + + return results; + } + } +} diff --git a/src/Microsoft.Repl/Commanding/CommandHistory.cs b/src/Microsoft.Repl/Commanding/CommandHistory.cs new file mode 100644 index 0000000000..83c7206a9d --- /dev/null +++ b/src/Microsoft.Repl/Commanding/CommandHistory.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; + +namespace Microsoft.Repl.Commanding +{ + public class CommandHistory : ICommandHistory + { + private readonly int _maxEntries; + private readonly List _commandLines = new List(); + private int _currentCommand = -1; + private int _suspensionDepth; + + public CommandHistory(int maxEntries = 50) + { + _maxEntries = maxEntries; + } + + public void AddCommand(string command) + { + if (_suspensionDepth > 0) + { + return; + } + + _commandLines.Add(command); + if (_commandLines.Count > _maxEntries) + { + _commandLines.RemoveAt(0); + } + _currentCommand = -1; + } + + public string GetNextCommand() + { + if (_commandLines.Count == 0) + { + return string.Empty; + } + + if (_currentCommand == -1 || _currentCommand >= _commandLines.Count - 1) + { + _currentCommand = -1; + return string.Empty; + } + + return _commandLines[++_currentCommand]; + } + + public string GetPreviousCommand() + { + if (_commandLines.Count == 0) + { + return string.Empty; + } + + if (_currentCommand == -1) + { + _currentCommand = _commandLines.Count; + } + + if (_currentCommand > 0) + { + return _commandLines[--_currentCommand]; + } + + return _commandLines[0]; + } + + public IDisposable SuspendHistory() + { + ++_suspensionDepth; + return new Disposable(() => --_suspensionDepth); + } + } +} diff --git a/src/Microsoft.Repl/Commanding/CommandInputLocation.cs b/src/Microsoft.Repl/Commanding/CommandInputLocation.cs new file mode 100644 index 0000000000..1612384b61 --- /dev/null +++ b/src/Microsoft.Repl/Commanding/CommandInputLocation.cs @@ -0,0 +1,10 @@ +namespace Microsoft.Repl.Commanding +{ + public enum CommandInputLocation + { + CommandName, + Argument, + OptionName, + OptionValue + } +} \ No newline at end of file diff --git a/src/Microsoft.Repl/Commanding/CommandInputProcessingIssue.cs b/src/Microsoft.Repl/Commanding/CommandInputProcessingIssue.cs new file mode 100644 index 0000000000..501b4357da --- /dev/null +++ b/src/Microsoft.Repl/Commanding/CommandInputProcessingIssue.cs @@ -0,0 +1,15 @@ +namespace Microsoft.Repl.Commanding +{ + public class CommandInputProcessingIssue + { + public CommandInputProcessingIssueKind Kind { get; } + + public string Text { get; } + + public CommandInputProcessingIssue(CommandInputProcessingIssueKind kind, string text) + { + Kind = kind; + Text = text; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Repl/Commanding/CommandInputProcessingIssueKind.cs b/src/Microsoft.Repl/Commanding/CommandInputProcessingIssueKind.cs new file mode 100644 index 0000000000..cd69dccb85 --- /dev/null +++ b/src/Microsoft.Repl/Commanding/CommandInputProcessingIssueKind.cs @@ -0,0 +1,11 @@ +namespace Microsoft.Repl.Commanding +{ + public enum CommandInputProcessingIssueKind + { + CommandMismatch, + ArgumentCountOutOfRange, + UnknownOption, + OptionUseCountOutOfRange, + MissingRequiredOptionInput, + } +} \ No newline at end of file diff --git a/src/Microsoft.Repl/Commanding/CommandInputSpecification.cs b/src/Microsoft.Repl/Commanding/CommandInputSpecification.cs new file mode 100644 index 0000000000..370b9f3d34 --- /dev/null +++ b/src/Microsoft.Repl/Commanding/CommandInputSpecification.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; + +namespace Microsoft.Repl.Commanding +{ + public class CommandInputSpecification + { + public IReadOnlyList CommandName { get; } + + public char OptionPreamble { get; } + + public int MinimumArguments { get; } + + public int MaximumArguments { get; } + + public IReadOnlyList Options { get; } + + public CommandInputSpecification(IReadOnlyList name, char optionPreamble, IReadOnlyList options, int minimumArgs, int maximumArgs) + { + CommandName = name; + OptionPreamble = optionPreamble; + MinimumArguments = minimumArgs; + MaximumArguments = maximumArgs; + + if (MinimumArguments < 0) + { + MinimumArguments = 0; + } + + if (MaximumArguments < MinimumArguments) + { + MaximumArguments = MinimumArguments; + } + + Options = options; + } + + public static CommandInputSpecificationBuilder Create(string baseName, params string[] additionalNameParts) + { + List nameParts = new List {baseName}; + nameParts.AddRange(additionalNameParts); + return new CommandInputSpecificationBuilder(nameParts); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Repl/Commanding/CommandInputSpecificationBuilder.cs b/src/Microsoft.Repl/Commanding/CommandInputSpecificationBuilder.cs new file mode 100644 index 0000000000..5ad5edf345 --- /dev/null +++ b/src/Microsoft.Repl/Commanding/CommandInputSpecificationBuilder.cs @@ -0,0 +1,66 @@ +using System.Collections.Generic; + +namespace Microsoft.Repl.Commanding +{ + public class CommandInputSpecificationBuilder + { + private readonly IReadOnlyList _name; + private char _optionPreamble; + private int _minimumArgs; + private int _maximumArgs; + private readonly List _options = new List(); + + public CommandInputSpecificationBuilder(IReadOnlyList name) + { + _name = name; + _optionPreamble = '-'; + } + + public CommandInputSpecificationBuilder WithOptionPreamble(char optionChar) + { + _optionPreamble = optionChar; + return this; + } + + public CommandInputSpecificationBuilder ExactArgCount(int count) + { + _minimumArgs = count; + _maximumArgs = count; + return this; + } + + public CommandInputSpecificationBuilder MinimumArgCount(int count) + { + _minimumArgs = count; + if (_maximumArgs < count) + { + _maximumArgs = count; + } + + return this; + } + + public CommandInputSpecificationBuilder MaximumArgCount(int count) + { + _maximumArgs = count; + + if (_minimumArgs > count) + { + _minimumArgs = count; + } + + return this; + } + + public CommandInputSpecificationBuilder WithOption(CommandOptionSpecification option) + { + _options.Add(option); + return this; + } + + public CommandInputSpecification Finish() + { + return new CommandInputSpecification(_name, _optionPreamble, _options, _minimumArgs, _maximumArgs); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Repl/Commanding/CommandOptionSpecification.cs b/src/Microsoft.Repl/Commanding/CommandOptionSpecification.cs new file mode 100644 index 0000000000..d925e5b2c9 --- /dev/null +++ b/src/Microsoft.Repl/Commanding/CommandOptionSpecification.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; + +namespace Microsoft.Repl.Commanding +{ + public class CommandOptionSpecification + { + public string Id { get; } + + public IReadOnlyList Forms { get; } + + public int MaximumOccurrences { get; } + + public int MinimumOccurrences { get; } + + public bool AcceptsValue { get; } + + public bool RequiresValue { get; } + + public CommandOptionSpecification(string id, bool acceptsValue = false, bool requiresValue = false, int minimumOccurrences = 0, int maximumOccurrences = int.MaxValue, params string[] forms) + { + Id = id; + Forms = forms; + MinimumOccurrences = minimumOccurrences; + MaximumOccurrences = maximumOccurrences > minimumOccurrences ? maximumOccurrences : minimumOccurrences; + RequiresValue = requiresValue; + AcceptsValue = RequiresValue || acceptsValue; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Repl/Commanding/CommandWithStructuredInputBase.cs b/src/Microsoft.Repl/Commanding/CommandWithStructuredInputBase.cs new file mode 100644 index 0000000000..38443486e8 --- /dev/null +++ b/src/Microsoft.Repl/Commanding/CommandWithStructuredInputBase.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Repl.Parsing; + +namespace Microsoft.Repl.Commanding +{ + public abstract class CommandWithStructuredInputBase : ICommand + where TParseResult : ICoreParseResult + { + public abstract string GetHelpSummary(IShellState shellState, TProgramState programState); + + public string GetHelpDetails(IShellState shellState, TProgramState programState, TParseResult parseResult) + { + if (!DefaultCommandInput.TryProcess(InputSpec, parseResult, out DefaultCommandInput commandInput, out IReadOnlyList processingIssues) + && processingIssues.Any(x => x.Kind == CommandInputProcessingIssueKind.CommandMismatch)) + { + //If this is the right command, just not the right syntax, report the usage errors + return null; + } + + return GetHelpDetails(shellState, programState, commandInput, parseResult); + } + + protected abstract string GetHelpDetails(IShellState shellState, TProgramState programState, DefaultCommandInput commandInput, TParseResult parseResult); + + public IEnumerable Suggest(IShellState shellState, TProgramState programState, TParseResult parseResult) + { + DefaultCommandInput.TryProcess(InputSpec, parseResult, out DefaultCommandInput commandInput, out IReadOnlyList _); + + string normalCompletionString = parseResult.SelectedSection == parseResult.Sections.Count + ? string.Empty + : parseResult.Sections[parseResult.SelectedSection].Substring(0, parseResult.CaretPositionWithinSelectedSection); + + //If we're completing in a name position, offer completion for the command name + if (parseResult.SelectedSection < InputSpec.CommandName.Count) + { + for (int i = 0; i < parseResult.SelectedSection; ++i) + { + if (!string.Equals(InputSpec.CommandName[i], parseResult.Sections[i], StringComparison.OrdinalIgnoreCase)) + { + return null; + } + } + + if (InputSpec.CommandName[parseResult.SelectedSection].StartsWith(normalCompletionString, StringComparison.OrdinalIgnoreCase)) + { + return new[] {InputSpec.CommandName[parseResult.SelectedSection]}; + } + } + + if (commandInput is null) + { + return null; + } + + if (normalCompletionString.StartsWith(InputSpec.OptionPreamble)) + { + return GetOptionCompletions(commandInput, normalCompletionString); + } + + IEnumerable completions = Enumerable.Empty(); + CommandInputLocation? inputLocation = commandInput.SelectedElement?.Location; + + if (inputLocation != CommandInputLocation.OptionValue && commandInput.Arguments.Count < InputSpec.MaximumArguments) + { + IEnumerable results = GetArgumentSuggestionsForText(shellState, programState, parseResult, commandInput, normalCompletionString); + + if (results != null) + { + completions = results; + } + } + + switch (inputLocation) + { + case CommandInputLocation.OptionName: + { + IEnumerable results = GetOptionCompletions(commandInput, normalCompletionString); + + if (results != null) + { + completions = completions.Union(results); + } + + break; + } + case CommandInputLocation.OptionValue: + { + IEnumerable results = GetOptionValueCompletions(shellState, programState, commandInput.SelectedElement.Owner.NormalizedText, commandInput, parseResult, normalCompletionString); + + if (results != null) + { + completions = completions.Union(results); + } + + break; + } + case CommandInputLocation.Argument: + { + IEnumerable argumentResults = GetArgumentSuggestionsForText(shellState, programState, parseResult, commandInput, normalCompletionString); + + if (argumentResults != null) + { + completions = completions.Union(argumentResults); + } + + if (string.IsNullOrEmpty(normalCompletionString)) + { + IEnumerable results = GetOptionCompletions(commandInput, normalCompletionString); + + if (results != null) + { + completions = completions.Union(results); + } + } + + break; + } + } + + return completions; + } + + protected virtual IEnumerable GetOptionValueCompletions(IShellState shellState, TProgramState programState, string optionId, DefaultCommandInput commandInput, TParseResult parseResult, string normalizedCompletionText) + { + return null; + } + + protected virtual IEnumerable GetArgumentSuggestionsForText(IShellState shellState, TProgramState programState, TParseResult parseResult, DefaultCommandInput commandInput, string normalCompletionString) + { + return null; + } + + private IEnumerable GetOptionCompletions(DefaultCommandInput commandInput, string normalCompletionString) + { + return InputSpec.Options.Where(x => commandInput.Options[x.Id].Count < x.MaximumOccurrences) + .SelectMany(x => x.Forms) + .Where(x => x.StartsWith(normalCompletionString, StringComparison.OrdinalIgnoreCase)); + } + + public bool? CanHandle(IShellState shellState, TProgramState programState, TParseResult parseResult) + { + if (!DefaultCommandInput.TryProcess(InputSpec, parseResult, out DefaultCommandInput commandInput, out IReadOnlyList processingIssues)) + { + //If this is the right command, just not the right syntax, report the usage errors + if (processingIssues.All(x => x.Kind != CommandInputProcessingIssueKind.CommandMismatch)) + { + foreach (CommandInputProcessingIssue issue in processingIssues) + { + shellState.ConsoleManager.Error.WriteLine(GetStringForIssue(issue)); + } + + string help = GetHelpDetails(shellState, programState, parseResult); + shellState.ConsoleManager.WriteLine(help); + return false; + } + + //If there was a mismatch in the command name, this isn't our input to handle + return null; + } + + return CanHandle(shellState, programState, commandInput); + } + + protected virtual bool CanHandle(IShellState shellState, TProgramState programState, DefaultCommandInput commandInput) + { + return true; + } + + protected virtual string GetStringForIssue(CommandInputProcessingIssue issue) + { + //TODO: Make this nicer + return issue.Kind + " -- " + issue.Text; + } + + public Task ExecuteAsync(IShellState shellState, TProgramState programState, TParseResult parseResult, CancellationToken cancellationToken) + { + if (!DefaultCommandInput.TryProcess(InputSpec, parseResult, out DefaultCommandInput commandInput, out IReadOnlyList _)) + { + return Task.CompletedTask; + } + + return ExecuteAsync(shellState, programState, commandInput, parseResult, cancellationToken); + } + + protected abstract Task ExecuteAsync(IShellState shellState, TProgramState programState, DefaultCommandInput commandInput, TParseResult parseResult, CancellationToken cancellationToken); + + protected abstract CommandInputSpecification InputSpec { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs b/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs new file mode 100644 index 0000000000..932e8cdb1a --- /dev/null +++ b/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Repl.ConsoleHandling; +using Microsoft.Repl.Parsing; + +namespace Microsoft.Repl.Commanding +{ + public static class DefaultCommandDispatcher + { + public static DefaultCommandDispatcher Create(Func getPrompt, TProgramState programState) + { + return new DefaultCommandDispatcher(getPrompt, programState); + } + + public static DefaultCommandDispatcher Create(Action onReady, TProgramState programState) + { + return new DefaultCommandDispatcher(onReady, programState); + } + + public static DefaultCommandDispatcher Create(Func getPrompt, TProgramState programState, IParser parser) + where TParseResult : ICoreParseResult + { + return new DefaultCommandDispatcher(getPrompt, programState, parser); + } + + public static DefaultCommandDispatcher Create(Action onReady, TProgramState programState, IParser parser) + where TParseResult : ICoreParseResult + { + return new DefaultCommandDispatcher(onReady, programState, parser); + } + } + + public class DefaultCommandDispatcher : DefaultCommandDispatcher + { + public DefaultCommandDispatcher(Func getPrompt, TProgramState programState) + : base(getPrompt, programState, new CoreParser()) + { + } + + public DefaultCommandDispatcher(Action onReady, TProgramState programState) + : base(onReady, programState, new CoreParser()) + { + } + } + + public class DefaultCommandDispatcher : ICommandDispatcher + where TParseResult : ICoreParseResult + { + private readonly Action _onReady; + private readonly TProgramState _programState; + private readonly IParser _parser; + private readonly HashSet> _commands = new HashSet>(); + private bool _isReady; + + public DefaultCommandDispatcher(Func getPrompt, TProgramState programState, IParser parser) + : this(s => s.ConsoleManager.Write(getPrompt()), programState, parser) + { + } + + public DefaultCommandDispatcher(Action onReady, TProgramState programState, IParser parser) + { + _onReady = onReady; + _programState = programState; + _parser = parser; + } + + public void AddCommand(ICommand command) + { + _commands.Add(command); + } + + public IEnumerable> Commands => _commands; + + public IParser Parser => _parser; + + public IReadOnlyList CollectSuggesetions(IShellState shellState) + { + string line = shellState.InputManager.GetCurrentBuffer(); + TParseResult parseResult = _parser.Parse(line, shellState.ConsoleManager.CaretPosition); + HashSet suggestions = new HashSet(StringComparer.OrdinalIgnoreCase); + + foreach (ICommand command in _commands) + { + IEnumerable commandSuggestions = command.Suggest(shellState, _programState, parseResult); + + if (commandSuggestions != null) + { + suggestions.UnionWith(commandSuggestions); + } + } + + return suggestions.OrderBy(x => x, StringComparer.OrdinalIgnoreCase).ToList(); + } + + public async Task ExecuteCommandAsync(IShellState shellState, CancellationToken cancellationToken) + { + _isReady = false; + shellState.ConsoleManager.WriteLine(); + string commandText = shellState.InputManager.GetCurrentBuffer(); + + if (!string.IsNullOrWhiteSpace(commandText)) + { + shellState.CommandHistory.AddCommand(shellState.InputManager.GetCurrentBuffer()); + + try + { + await ExecuteCommandInternalAsync(shellState, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + shellState.ConsoleManager.Error.WriteLine(ex.ToString().Bold().Red()); + } + + if (cancellationToken.IsCancellationRequested) + { + shellState.ConsoleManager.Error.WriteLine("Execution was cancelled".Bold().Red()); + } + } + + if (!_isReady) + { + shellState.ConsoleManager.WriteLine(); + OnReady(shellState); + } + + shellState.InputManager.ResetInput(); + } + + private async Task ExecuteCommandInternalAsync(IShellState shellState, CancellationToken cancellationToken) + { + string line = shellState.InputManager.GetCurrentBuffer(); + TParseResult parseResult = _parser.Parse(line, shellState.ConsoleManager.CaretPosition); + + if (!string.IsNullOrWhiteSpace(parseResult.CommandText)) + { + foreach (ICommand command in _commands) + { + bool? result = command.CanHandle(shellState, _programState, parseResult); + + if (result.HasValue) + { + if (result.Value) + { + await command.ExecuteAsync(shellState, _programState, parseResult, cancellationToken); + } + + //If the handler returned non-null, the input would be directed to it, but it's not valid input + return; + } + } + + shellState.ConsoleManager.Error.WriteLine("No matching command found".Red().Bold()); + } + } + + public void OnReady(IShellState shellState) + { + if (!_isReady) + { + _onReady(shellState); + shellState.ConsoleManager.ResetCommandStart(); + _isReady = true; + } + } + } +} diff --git a/src/Microsoft.Repl/Commanding/DefaultCommandInput.cs b/src/Microsoft.Repl/Commanding/DefaultCommandInput.cs new file mode 100644 index 0000000000..0d3b97932e --- /dev/null +++ b/src/Microsoft.Repl/Commanding/DefaultCommandInput.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Repl.Parsing; + +namespace Microsoft.Repl.Commanding +{ + public class DefaultCommandInput + where TParseResult : ICoreParseResult + { + public DefaultCommandInput(IReadOnlyList commandName, IReadOnlyList arguments, IReadOnlyDictionary> options, InputElement selectedElement) + { + CommandName = commandName; + Arguments = arguments; + Options = options; + SelectedElement = selectedElement; + } + + public static bool TryProcess(CommandInputSpecification spec, TParseResult parseResult, out DefaultCommandInput result, out IReadOnlyList processingIssues) + { + List issues = new List(); + List commandNameElements = new List(); + + if (spec.CommandName.Count > parseResult.Sections.Count) + { + issues.Add(new CommandInputProcessingIssue(CommandInputProcessingIssueKind.CommandMismatch, spec.CommandName[parseResult.Sections.Count])); + } + + for (int i = 0; i < spec.CommandName.Count && i < parseResult.Sections.Count; ++i) + { + if (!string.Equals(spec.CommandName[i], parseResult.Sections[i], StringComparison.OrdinalIgnoreCase)) + { + issues.Add(new CommandInputProcessingIssue(CommandInputProcessingIssueKind.CommandMismatch, parseResult.Sections[i])); + } + + commandNameElements.Add(new InputElement(CommandInputLocation.CommandName, parseResult.Sections[i], spec.CommandName[i], i)); + } + + //If we have a command name mismatch, no point in continuing + if (issues.Count > 0) + { + result = null; + processingIssues = issues; + return false; + } + + List arguments = new List(); + Dictionary options = new Dictionary(); + InputElement currentOption = null; + CommandOptionSpecification currentOptionSpec = null; + InputElement selectedElement = null; + + for (int i = spec.CommandName.Count; i < parseResult.Sections.Count; ++i) + { + //If we're not looking at an option name + if (!parseResult.Sections[i].StartsWith(spec.OptionPreamble) || parseResult.IsQuotedSection(i)) + { + if (currentOption is null) + { + InputElement currentElement = new InputElement(CommandInputLocation.Argument, parseResult.Sections[i], parseResult.Sections[i], i); + + if (i == parseResult.SelectedSection) + { + selectedElement = currentElement; + } + + arguments.Add(currentElement); + } + else + { + //If the option isn't a defined one or it is and indicates that it accepts a value, add the section as an option value, + // otherwise add it as an argument + if (currentOptionSpec?.AcceptsValue ?? true) + { + InputElement currentElement = new InputElement(currentOption, CommandInputLocation.OptionValue, parseResult.Sections[i], parseResult.Sections[i], i); + + if (i == parseResult.SelectedSection) + { + selectedElement = currentElement; + } + + options[currentOption] = currentElement; + currentOption = null; + currentOptionSpec = null; + } + else + { + InputElement currentElement = new InputElement(CommandInputLocation.Argument, parseResult.Sections[i], parseResult.Sections[i], i); + + if (i == parseResult.SelectedSection) + { + selectedElement = currentElement; + } + + arguments.Add(currentElement); + } + } + } + //If we are looking at an option name + else + { + //Otherwise, check to see whether the previous option had a required argument before committing it + if (!(currentOption is null)) + { + options[currentOption] = null; + + if (currentOptionSpec?.RequiresValue ?? false) + { + issues.Add(new CommandInputProcessingIssue(CommandInputProcessingIssueKind.MissingRequiredOptionInput, currentOption.Text)); + } + } + + CommandOptionSpecification optionSpec = spec.Options.FirstOrDefault(x => x.Forms.Any(y => string.Equals(y, parseResult.Sections[i], StringComparison.Ordinal))); + + if (optionSpec is null) + { + issues.Add(new CommandInputProcessingIssue(CommandInputProcessingIssueKind.UnknownOption, parseResult.Sections[i])); + } + + currentOption = new InputElement(CommandInputLocation.OptionName, parseResult.Sections[i], optionSpec?.Id, i); + + if (i == parseResult.SelectedSection) + { + selectedElement = currentOption; + } + + currentOptionSpec = optionSpec; + } + } + + //Clear any option in progress + if (!(currentOption is null)) + { + options[currentOption] = null; + + if (currentOptionSpec?.RequiresValue ?? false) + { + issues.Add(new CommandInputProcessingIssue(CommandInputProcessingIssueKind.MissingRequiredOptionInput, currentOption.Text)); + } + } + + //Check to make sure our argument count is in range, if not add an issue + if (arguments.Count > spec.MaximumArguments || arguments.Count < spec.MinimumArguments) + { + issues.Add(new CommandInputProcessingIssue(CommandInputProcessingIssueKind.ArgumentCountOutOfRange, arguments.Count.ToString())); + } + + //Build up the dictionary of options by normal form, then validate counts for every option in the spec + Dictionary> optionsByNormalForm = new Dictionary>(StringComparer.Ordinal); + + foreach (KeyValuePair entry in options) + { + if (entry.Key.NormalizedText is null) + { + continue; + } + + if (!optionsByNormalForm.TryGetValue(entry.Key.NormalizedText, out IReadOnlyList rawBucket)) + { + optionsByNormalForm[entry.Key.NormalizedText] = rawBucket = new List(); + } + + List bucket = (List) rawBucket; + bucket.Add(entry.Value); + } + + foreach (CommandOptionSpecification optionSpec in spec.Options) + { + if (!optionsByNormalForm.TryGetValue(optionSpec.Id, out IReadOnlyList values)) + { + optionsByNormalForm[optionSpec.Id] = values = new List(); + } + + if (values.Count < optionSpec.MinimumOccurrences || values.Count > optionSpec.MaximumOccurrences) + { + issues.Add(new CommandInputProcessingIssue(CommandInputProcessingIssueKind.OptionUseCountOutOfRange, values.Count.ToString())); + } + } + + result = new DefaultCommandInput(commandNameElements, arguments, optionsByNormalForm, selectedElement); + processingIssues = issues; + return issues.Count == 0; + } + + public InputElement SelectedElement { get; } + + public IReadOnlyList CommandName { get; } + + public IReadOnlyList Arguments { get; } + + public IReadOnlyDictionary> Options { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.Repl/Commanding/ICommand.cs b/src/Microsoft.Repl/Commanding/ICommand.cs new file mode 100644 index 0000000000..be575437e2 --- /dev/null +++ b/src/Microsoft.Repl/Commanding/ICommand.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Repl.Parsing; + +namespace Microsoft.Repl.Commanding +{ + public interface ICommand + where TParseResult : ICoreParseResult + { + string GetHelpSummary(IShellState shellState, TProgramState programState); + + string GetHelpDetails(IShellState shellState, TProgramState programState, TParseResult parseResult); + + IEnumerable Suggest(IShellState shellState, TProgramState programState, TParseResult parseResult); + + bool? CanHandle(IShellState shellState, TProgramState programState, TParseResult parseResult); + + Task ExecuteAsync(IShellState shellState, TProgramState programState, TParseResult parseResult, CancellationToken cancellationToken); + } +} diff --git a/src/Microsoft.Repl/Commanding/ICommandDispatcher.cs b/src/Microsoft.Repl/Commanding/ICommandDispatcher.cs new file mode 100644 index 0000000000..c175490833 --- /dev/null +++ b/src/Microsoft.Repl/Commanding/ICommandDispatcher.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Repl.Parsing; + +namespace Microsoft.Repl.Commanding +{ + public interface ICommandDispatcher + { + IParser Parser { get; } + + IReadOnlyList CollectSuggesetions(IShellState shellState); + + void OnReady(IShellState shellState); + + Task ExecuteCommandAsync(IShellState shellState, CancellationToken cancellationToken); + } + + public interface ICommandDispatcher : ICommandDispatcher + where TParseResult : ICoreParseResult + { + IEnumerable> Commands { get; } + } +} diff --git a/src/Microsoft.Repl/Commanding/ICommandHistory.cs b/src/Microsoft.Repl/Commanding/ICommandHistory.cs new file mode 100644 index 0000000000..8e25db8906 --- /dev/null +++ b/src/Microsoft.Repl/Commanding/ICommandHistory.cs @@ -0,0 +1,15 @@ +using System; + +namespace Microsoft.Repl.Commanding +{ + public interface ICommandHistory + { + string GetPreviousCommand(); + + string GetNextCommand(); + + void AddCommand(string command); + + IDisposable SuspendHistory(); + } +} diff --git a/src/Microsoft.Repl/Commanding/InputElement.cs b/src/Microsoft.Repl/Commanding/InputElement.cs new file mode 100644 index 0000000000..c02c7f0f23 --- /dev/null +++ b/src/Microsoft.Repl/Commanding/InputElement.cs @@ -0,0 +1,29 @@ +namespace Microsoft.Repl.Commanding +{ + public class InputElement + { + public CommandInputLocation Location { get; } + + public string Text { get; } + + public string NormalizedText { get; } + + public InputElement Owner { get; } + + public int ParseResultSectionIndex { get; } + + public InputElement(CommandInputLocation location, string text, string normalizedText, int sectionIndex) + : this(null, location, text, normalizedText, sectionIndex) + { + } + + public InputElement(InputElement owner, CommandInputLocation location, string text, string normalizedText, int sectionIndex) + { + Owner = owner; + Location = location; + Text = text; + NormalizedText = normalizedText; + ParseResultSectionIndex = sectionIndex; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Repl/ConsoleHandling/AllowedColors.cs b/src/Microsoft.Repl/ConsoleHandling/AllowedColors.cs new file mode 100644 index 0000000000..a71dc2c8a4 --- /dev/null +++ b/src/Microsoft.Repl/ConsoleHandling/AllowedColors.cs @@ -0,0 +1,27 @@ +using System; + +namespace Microsoft.Repl.ConsoleHandling +{ + [Flags] + public enum AllowedColors + { + Black = 0x00, + BoldBlack = Bold | Black, + Red = 0x01, + BoldRed = Bold | Red, + Green = 0x02, + BoldGreen = Bold | Green, + Yellow = 0x03, + BoldYellow = Bold | Yellow, + Blue = 0x04, + BoldBlue = Bold | Blue, + Magenta = 0x05, + BoldMagenta = Bold | Magenta, + Cyan = 0x06, + BoldCyan = Bold | Cyan, + White = 0x07, + BoldWhite = White | Bold, + Bold = 0x100, + None = 0x99 + } +} \ No newline at end of file diff --git a/src/Microsoft.Repl/ConsoleHandling/AnsiColorExtensions.cs b/src/Microsoft.Repl/ConsoleHandling/AnsiColorExtensions.cs new file mode 100644 index 0000000000..cab5bc6f05 --- /dev/null +++ b/src/Microsoft.Repl/ConsoleHandling/AnsiColorExtensions.cs @@ -0,0 +1,80 @@ +namespace Microsoft.Repl.ConsoleHandling +{ + public static class AnsiColorExtensions + { + public static string Black(this string text) + { + return "\x1B[30m" + text + "\x1B[39m"; + } + + public static string Red(this string text) + { + return "\x1B[31m" + text + "\x1B[39m"; + } + public static string Green(this string text) + { + return "\x1B[32m" + text + "\x1B[39m"; + } + + public static string Yellow(this string text) + { + return "\x1B[33m" + text + "\x1B[39m"; + } + + public static string Blue(this string text) + { + return "\x1B[34m" + text + "\x1B[39m"; + } + + public static string Magenta(this string text) + { + return "\x1B[35m" + text + "\x1B[39m"; + } + + public static string Cyan(this string text) + { + return "\x1B[36m" + text + "\x1B[39m"; + } + + public static string White(this string text) + { + return "\x1B[37m" + text + "\x1B[39m"; + } + + public static string Bold(this string text) + { + return "\x1B[1m" + text + "\x1B[22m"; + } + + public static string SetColor(this string text, AllowedColors color) + { + if (color.HasFlag(AllowedColors.Bold)) + { + text = text.Bold(); + color = color & ~AllowedColors.Bold; + } + + switch (color) + { + case AllowedColors.Black: + return text.Black(); + case AllowedColors.Red: + return text.Red(); + case AllowedColors.Green: + return text.Green(); + case AllowedColors.Yellow: + return text.Yellow(); + case AllowedColors.Blue: + return text.Blue(); + case AllowedColors.Magenta: + return text.Magenta(); + case AllowedColors.Cyan: + return text.Cyan(); + case AllowedColors.White: + return text.White(); + default: + return text; + } + } + } +} diff --git a/src/Microsoft.Repl/ConsoleHandling/AnsiConsole.cs b/src/Microsoft.Repl/ConsoleHandling/AnsiConsole.cs new file mode 100644 index 0000000000..24944f8871 --- /dev/null +++ b/src/Microsoft.Repl/ConsoleHandling/AnsiConsole.cs @@ -0,0 +1,151 @@ +using System; +using System.IO; + +namespace Microsoft.Repl.ConsoleHandling +{ + public class AnsiConsole + { + private AnsiConsole(TextWriter writer) + { + Writer = writer; + + OriginalForegroundColor = Console.ForegroundColor; + } + + private int _boldRecursion; + + public static AnsiConsole GetOutput() + { + return new AnsiConsole(Console.Out); + } + + public static AnsiConsole GetError() + { + return new AnsiConsole(Console.Error); + } + + public TextWriter Writer { get; } + + public ConsoleColor OriginalForegroundColor { get; } + + private void SetColor(ConsoleColor color) + { + const int light = 0x08; + int c = (int)color; + + Console.ForegroundColor = + c < 0 ? color : // unknown, just use it + _boldRecursion > 0 ? (ConsoleColor)(c | light) : // ensure color is light + (ConsoleColor)(c & ~light); // ensure color is dark + } + + private void SetBold(bool bold) + { + _boldRecursion += bold ? 1 : -1; + if (_boldRecursion > 1 || (_boldRecursion == 1 && !bold)) + { + return; + } + + // switches on _boldRecursion to handle boldness + SetColor(Console.ForegroundColor); + } + + public void WriteLine(string message) + { + Write(message); + Writer.WriteLine(); + } + + public void Write(char message) + { + Writer.Write(message); + } + + public void Write(string message) + { + if (message is null) + { + return; + } + + var escapeScan = 0; + for (; ; ) + { + var escapeIndex = message.IndexOf("\x1b[", escapeScan, StringComparison.Ordinal); + if (escapeIndex == -1) + { + var text = message.Substring(escapeScan); + Writer.Write(text); + break; + } + else + { + var startIndex = escapeIndex + 2; + var endIndex = startIndex; + while (endIndex != message.Length && + message[endIndex] >= 0x20 && + message[endIndex] <= 0x3f) + { + endIndex += 1; + } + + var text = message.Substring(escapeScan, escapeIndex - escapeScan); + Writer.Write(text); + if (endIndex == message.Length) + { + break; + } + + switch (message[endIndex]) + { + case 'm': + if (int.TryParse(message.Substring(startIndex, endIndex - startIndex), out int value)) + { + switch (value) + { + case 1: + SetBold(true); + break; + case 22: + SetBold(false); + break; + case 30: + SetColor(ConsoleColor.Black); + break; + case 31: + SetColor(ConsoleColor.Red); + break; + case 32: + SetColor(ConsoleColor.Green); + break; + case 33: + SetColor(ConsoleColor.Yellow); + break; + case 34: + SetColor(ConsoleColor.Blue); + break; + case 35: + SetColor(ConsoleColor.Magenta); + break; + case 36: + SetColor(ConsoleColor.Cyan); + break; + case 37: + SetColor(ConsoleColor.Gray); + break; + case 39: + Console.ForegroundColor = OriginalForegroundColor; + break; + } + } + break; + } + + escapeScan = endIndex + 1; + } + } + } + } + +} diff --git a/src/Microsoft.Repl/ConsoleHandling/ConsoleManager.cs b/src/Microsoft.Repl/ConsoleHandling/ConsoleManager.cs new file mode 100644 index 0000000000..a15c1fd420 --- /dev/null +++ b/src/Microsoft.Repl/ConsoleHandling/ConsoleManager.cs @@ -0,0 +1,204 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; + +namespace Microsoft.Repl.ConsoleHandling +{ + public class ConsoleManager : IConsoleManager + { + private readonly List _breakHandlers = new List(); + + public Point Caret => new Point(Console.CursorLeft, Console.CursorTop); + + public Point CommandStart => new Point(Caret.X - CaretPosition % Console.BufferWidth, Caret.Y - CaretPosition / Console.BufferWidth); + + public int CaretPosition { get; private set; } + + public bool IsKeyAvailable => Console.KeyAvailable; + + public bool IsCaretVisible + { + get => Reporter.Output.IsCaretVisible; + set => Reporter.Output.IsCaretVisible = value; + } + + public ConsoleManager() + { + Error = new Writable(CaretUpdateScope, Reporter.Error); + Console.CancelKeyPress += OnCancelKeyPress; + } + + public void Clear() + { + using (CaretUpdateScope()) + { + Console.Clear(); + ResetCommandStart(); + } + } + + public void MoveCaret(int positions) + { + using (CaretUpdateScope()) + { + if (positions == 0) + { + return; + } + + while (positions < 0 && CaretPosition > 0) + { + if (-positions > Console.BufferWidth) + { + if (Console.CursorTop == 0) + { + Console.CursorLeft = 0; + positions = 0; + } + else + { + positions += Console.BufferWidth; + --Console.CursorTop; + } + } + else + { + int remaining = Console.CursorLeft + positions; + + if (remaining >= 0) + { + Console.CursorLeft = remaining; + } + else if (Console.CursorTop == 0) + { + Console.CursorLeft = 0; + } + else + { + --Console.CursorTop; + Console.CursorLeft = Console.BufferWidth + remaining; + } + + positions = 0; + } + } + + while (positions > 0) + { + if (positions > Console.BufferWidth) + { + positions -= Console.BufferWidth; + ++Console.CursorTop; + } + else + { + int spaceLeftOnLine = Console.BufferWidth - Console.CursorLeft - 1; + if (positions > spaceLeftOnLine) + { + ++Console.CursorTop; + Console.CursorLeft = positions - spaceLeftOnLine - 1; + } + else + { + Console.CursorLeft += positions; + } + + positions = 0; + } + } + } + } + + public ConsoleKeyInfo ReadKey(CancellationToken cancellationToken) + { + while (!Console.KeyAvailable && !cancellationToken.IsCancellationRequested) + { + Thread.Sleep(2); + } + + if (cancellationToken.IsCancellationRequested) + { + return default(ConsoleKeyInfo); + } + else + { + return Console.ReadKey(true); + } + } + + public void ResetCommandStart() + { + CaretPosition = 0; + } + + public void Write(char c) + { + using (CaretUpdateScope()) + { + Reporter.Output.Write(c); + } + } + + public void Write(string s) + { + using (CaretUpdateScope()) + { + Reporter.Output.Write(s); + } + } + + public void WriteLine() + { + using (CaretUpdateScope()) + { + Reporter.Output.WriteLine(); + } + } + + public void WriteLine(string s) + { + if (s is null) + { + return; + } + + using (CaretUpdateScope()) + { + Reporter.Output.WriteLine(s); + } + } + + public IDisposable AddBreakHandler(Action handler) + { + Disposable result = new Disposable(() => ReleaseBreakHandler(handler)); + _breakHandlers.Add(handler); + return result; + } + + private IDisposable CaretUpdateScope() + { + Point currentCaret = Caret; + return new Disposable(() => + { + int y = Caret.Y - currentCaret.Y; + int x = Caret.X - currentCaret.X; + CaretPosition += y * Console.BufferWidth + x; + }); + } + + private void OnCancelKeyPress(object sender, ConsoleCancelEventArgs e) + { + e.Cancel = true; + Action handler = _breakHandlers.LastOrDefault(); + handler?.Invoke(); + } + + private void ReleaseBreakHandler(Action handler) + { + _breakHandlers.Remove(handler); + } + + public IWritable Error { get; } + } +} diff --git a/src/Microsoft.Repl/ConsoleHandling/IConsoleManager.cs b/src/Microsoft.Repl/ConsoleHandling/IConsoleManager.cs new file mode 100644 index 0000000000..9ab7b26a15 --- /dev/null +++ b/src/Microsoft.Repl/ConsoleHandling/IConsoleManager.cs @@ -0,0 +1,28 @@ +using System; +using System.Threading; + +namespace Microsoft.Repl.ConsoleHandling +{ + public interface IConsoleManager : IWritable + { + Point Caret { get; } + + Point CommandStart { get; } + + int CaretPosition { get; } + + IWritable Error { get; } + + bool IsKeyAvailable { get; } + + void Clear(); + + void MoveCaret(int positions); + + ConsoleKeyInfo ReadKey(CancellationToken cancellationToken); + + void ResetCommandStart(); + + IDisposable AddBreakHandler(Action onBreak); + } +} diff --git a/src/Microsoft.Repl/ConsoleHandling/IWritable.cs b/src/Microsoft.Repl/ConsoleHandling/IWritable.cs new file mode 100644 index 0000000000..f18fa123a1 --- /dev/null +++ b/src/Microsoft.Repl/ConsoleHandling/IWritable.cs @@ -0,0 +1,15 @@ +namespace Microsoft.Repl.ConsoleHandling +{ + public interface IWritable + { + void Write(char c); + + void Write(string s); + + void WriteLine(); + + void WriteLine(string s); + + bool IsCaretVisible { get; set; } + } +} diff --git a/src/Microsoft.Repl/ConsoleHandling/Point.cs b/src/Microsoft.Repl/ConsoleHandling/Point.cs new file mode 100644 index 0000000000..4eeb68989d --- /dev/null +++ b/src/Microsoft.Repl/ConsoleHandling/Point.cs @@ -0,0 +1,50 @@ +namespace Microsoft.Repl.ConsoleHandling +{ + public struct Point + { + public readonly int X; + + public readonly int Y; + + public Point(int x, int y) + { + X = x; + Y = y; + } + + public static bool operator >(Point left, Point right) + { + return left.Y > right.Y || (left.Y == right.Y && right.X > left.X); + } + + public static bool operator <(Point left, Point right) + { + return left.Y < right.Y || (left.Y == right.Y && right.X < left.X); + } + + public static bool operator ==(Point left, Point right) + { + return left.X == right.X && left.Y == right.Y; + } + + public static bool operator !=(Point left, Point right) + { + return left.X != right.X || left.Y != right.Y; + } + + public override bool Equals(object obj) + { + return obj is Point other && other.X == X && other.Y == Y; + } + + public override int GetHashCode() + { + return X ^ Y; + } + + public override string ToString() + { + return $"(X={X}, Y={Y})"; + } + } +} diff --git a/src/Microsoft.Repl/ConsoleHandling/Reporter.cs b/src/Microsoft.Repl/ConsoleHandling/Reporter.cs new file mode 100644 index 0000000000..5b10d2be02 --- /dev/null +++ b/src/Microsoft.Repl/ConsoleHandling/Reporter.cs @@ -0,0 +1,115 @@ +using System; + +namespace Microsoft.Repl.ConsoleHandling +{ + public class Reporter : IWritable + { + private static readonly Reporter NullReporter = new Reporter(null); + private static readonly object Sync = new object(); + + private readonly AnsiConsole _console; + + static Reporter() + { + Reset(); + } + + private Reporter(AnsiConsole console) + { + _console = console; + } + + public static Reporter Output { get; private set; } + public static Reporter Error { get; private set; } + public static Reporter Verbose { get; private set; } + + /// + /// Resets the Reporters to write to the current Console Out/Error. + /// + public static void Reset() + { + lock (Sync) + { + Output = new Reporter(AnsiConsole.GetOutput()); + Error = new Reporter(AnsiConsole.GetError()); + Verbose = IsVerbose ? + new Reporter(AnsiConsole.GetOutput()) : + NullReporter; + } + } + + public void WriteLine(string message) + { + if (message is null) + { + return; + } + + lock (Sync) + { + if (ShouldPassAnsiCodesThrough) + { + _console?.Writer?.WriteLine(message); + } + else + { + _console?.WriteLine(message); + } + } + } + + public void WriteLine() + { + lock (Sync) + { + _console?.Writer?.WriteLine(); + } + } + + public void Write(char message) + { + lock (Sync) + { + if (ShouldPassAnsiCodesThrough) + { + _console?.Writer?.Write(message); + } + else + { + _console?.Write(message); + } + } + } + + public void Write(string message) + { + lock (Sync) + { + if (ShouldPassAnsiCodesThrough) + { + _console?.Writer?.Write(message); + } + else + { + _console?.Write(message); + } + } + } + + private static bool IsVerbose => bool.TryParse(Environment.GetEnvironmentVariable("DOTNET_CLI_CONTEXT_VERBOSE") ?? "false", out bool value) && value; + + private bool ShouldPassAnsiCodesThrough => bool.TryParse(Environment.GetEnvironmentVariable("DOTNET_CLI_CONTEXT_ANSI_PASS_THRU") ?? "false", out bool value) && value; + + private bool _isCaretVisible = true; + + public bool IsCaretVisible + { + get => _isCaretVisible; + set + { + Console.CursorVisible = value; + _isCaretVisible = value; + } + } + } +} diff --git a/src/Microsoft.Repl/ConsoleHandling/Writable.cs b/src/Microsoft.Repl/ConsoleHandling/Writable.cs new file mode 100644 index 0000000000..b12c2ad4e7 --- /dev/null +++ b/src/Microsoft.Repl/ConsoleHandling/Writable.cs @@ -0,0 +1,54 @@ +using System; + +namespace Microsoft.Repl.ConsoleHandling +{ + internal class Writable : IWritable + { + private readonly Func _caretUpdater; + private readonly Reporter _reporter; + + public Writable(Func caretUpdater, Reporter reporter) + { + _caretUpdater = caretUpdater; + _reporter = reporter; + } + + public bool IsCaretVisible + { + get => _reporter.IsCaretVisible; + set => _reporter.IsCaretVisible = value; + } + + public void Write(char c) + { + using (_caretUpdater()) + { + _reporter.Write(c); + } + } + + public void Write(string s) + { + using (_caretUpdater()) + { + _reporter.Write(s); + } + } + + public void WriteLine() + { + using (_caretUpdater()) + { + _reporter.WriteLine(); + } + } + + public void WriteLine(string s) + { + using (_caretUpdater()) + { + _reporter.WriteLine(s); + } + } + } +} diff --git a/src/Microsoft.Repl/Disposable.cs b/src/Microsoft.Repl/Disposable.cs new file mode 100644 index 0000000000..78002fb1d9 --- /dev/null +++ b/src/Microsoft.Repl/Disposable.cs @@ -0,0 +1,42 @@ +using System; + +namespace Microsoft.Repl +{ + public class Disposable : IDisposable + { + private Action _onDispose; + + public Disposable(Action onDispose) + { + _onDispose = onDispose; + } + public virtual void Dispose() + { + _onDispose?.Invoke(); + _onDispose = null; + } + } + + public class Disposable : Disposable + where T : class + { + public Disposable(T value, Action onDispose) + : base (onDispose) + { + Value = value; + } + + public T Value { get; private set; } + + public override void Dispose() + { + if (Value is IDisposable d) + { + d.Dispose(); + Value = null; + } + + base.Dispose(); + } + } +} diff --git a/src/Microsoft.Repl/IShellState.cs b/src/Microsoft.Repl/IShellState.cs new file mode 100644 index 0000000000..2ec1cb1514 --- /dev/null +++ b/src/Microsoft.Repl/IShellState.cs @@ -0,0 +1,22 @@ +using Microsoft.Repl.Commanding; +using Microsoft.Repl.ConsoleHandling; +using Microsoft.Repl.Input; +using Microsoft.Repl.Suggestions; + +namespace Microsoft.Repl +{ + public interface IShellState + { + IInputManager InputManager { get; } + + ICommandHistory CommandHistory { get; } + + IConsoleManager ConsoleManager { get; } + + ICommandDispatcher CommandDispatcher { get; } + + ISuggestionManager SuggestionManager { get; } + + bool IsExiting { get; set; } + } +} diff --git a/src/Microsoft.Repl/Input/AsyncKeyPressHandler.cs b/src/Microsoft.Repl/Input/AsyncKeyPressHandler.cs new file mode 100644 index 0000000000..616a749611 --- /dev/null +++ b/src/Microsoft.Repl/Input/AsyncKeyPressHandler.cs @@ -0,0 +1,8 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.Repl.Input +{ + public delegate Task AsyncKeyPressHandler(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken); +} diff --git a/src/Microsoft.Repl/Input/IInputManager.cs b/src/Microsoft.Repl/Input/IInputManager.cs new file mode 100644 index 0000000000..100dd22bea --- /dev/null +++ b/src/Microsoft.Repl/Input/IInputManager.cs @@ -0,0 +1,27 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.Repl.Input +{ + public interface IInputManager + { + bool IsOverwriteMode { get; set; } + + IInputManager RegisterKeyHandler(ConsoleKey key, AsyncKeyPressHandler handler); + + void ResetInput(); + + Task StartAsync(IShellState state, CancellationToken cancellationToken); + + void SetInput(IShellState state, string input); + + string GetCurrentBuffer(); + + void RemovePreviousCharacter(IShellState state); + + void RemoveCurrentCharacter(IShellState state); + + void Clear(IShellState state); + } +} diff --git a/src/Microsoft.Repl/Input/InputManager.cs b/src/Microsoft.Repl/Input/InputManager.cs new file mode 100644 index 0000000000..a635ccd37a --- /dev/null +++ b/src/Microsoft.Repl/Input/InputManager.cs @@ -0,0 +1,344 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.Repl.Input +{ + public class InputManager : IInputManager + { + private readonly Dictionary _handlers = new Dictionary(); + private readonly List _inputBuffer = new List(); + + public bool IsOverwriteMode { get; set; } + + public void Clear(IShellState state) + { + SetInput(state, string.Empty); + } + + public string GetCurrentBuffer() + { + return _inputBuffer.Stringify(); + } + + public IInputManager RegisterKeyHandler(ConsoleKey key, AsyncKeyPressHandler handler) + { + if (handler == null) + { + _handlers.Remove(key); + } + else + { + _handlers[key] = handler; + } + + return this; + } + + public void RemoveCurrentCharacter(IShellState state) + { + int caret = state.ConsoleManager.CaretPosition; + + if (caret == _inputBuffer.Count) + { + return; + } + + List update = _inputBuffer.ToList(); + update.RemoveAt(caret); + state.ConsoleManager.IsCaretVisible = false; + SetInput(state, update); + state.ConsoleManager.MoveCaret(caret - state.ConsoleManager.CaretPosition); + state.ConsoleManager.IsCaretVisible = true; + } + + public void RemovePreviousCharacter(IShellState state) + { + int caret = state.ConsoleManager.CaretPosition; + if (caret == 0) + { + return; + } + + List update = _inputBuffer.ToList(); + update.RemoveAt(caret - 1); + state.ConsoleManager.IsCaretVisible = false; + SetInput(state, update, false); + state.ConsoleManager.MoveCaret(caret - state.ConsoleManager.CaretPosition - 1); + state.ConsoleManager.IsCaretVisible = true; + } + + public void SetInput(IShellState state, string input) + { + SetInput(state, input.ToCharArray()); + } + + public void ResetInput() + { + _inputBuffer.Clear(); + } + + private string _ttyState; + + private void StashEchoState() + { + _ttyState = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.OSX) + ? GetTtyState() + : null; + + if (!string.IsNullOrEmpty(_ttyState)) + { + //"gfmt1:cflag=4300:iflag=6b02:lflag=200005c7:oflag=3:discard=f:dsusp=19:eof=4:eol=ff:eol2=ff:erase=7f:intr=3:kill=15:lnext=16:min=1:quit=1c:reprint=12:start=11:status=14:stop=13:susp=1a:time=0:werase=17:ispeed=38400:ospeed=38400\n" + ProcessStartInfo psi = new ProcessStartInfo("stty", "gfmt1:erase=08:werase=08 -echo"); + Process p = Process.Start(psi); + p?.WaitForExit(); + } + } + + private static string GetTtyState() + { + ProcessStartInfo psi = new ProcessStartInfo("stty", "-g") + { + RedirectStandardOutput = true + }; + Process p = Process.Start(psi); + p?.WaitForExit(); + string result = p?.StandardOutput.ReadToEnd(); + return result; + } + + private void RestoreTtyState() + { + if (!string.IsNullOrEmpty(_ttyState)) + { + ProcessStartInfo psi = new ProcessStartInfo("stty", _ttyState); + Process p = Process.Start(psi); + p?.WaitForExit(); + } + } + + private void SetInput(IShellState state, IReadOnlyList input, bool moveCaret = true) + { + bool oldCaretVisibility = state.ConsoleManager.IsCaretVisible; + state.ConsoleManager.IsCaretVisible = false; + int lastCommonPosition = 0; + + for (; lastCommonPosition < input.Count && lastCommonPosition < _inputBuffer.Count && _inputBuffer[lastCommonPosition] == input[lastCommonPosition]; ++lastCommonPosition) + { + } + + state.ConsoleManager.MoveCaret(-state.ConsoleManager.CaretPosition + lastCommonPosition); + string str = new string(input.Skip(lastCommonPosition).ToArray()); + int trailing = _inputBuffer.Count - input.Count; + + if (trailing > 0) + { + str = str.PadRight(trailing + str.Length); + } + + state.ConsoleManager.Write(str); + + if (trailing > 0 && moveCaret) + { + state.ConsoleManager.MoveCaret(-trailing); + } + + _inputBuffer.Clear(); + _inputBuffer.AddRange(input); + + if (oldCaretVisibility) + { + state.ConsoleManager.IsCaretVisible = true; + } + } + + public async Task StartAsync(IShellState state, CancellationToken cancellationToken) + { + StashEchoState(); + + try + { + List presses = null; + while (!state.IsExiting && !cancellationToken.IsCancellationRequested) + { + ConsoleKeyInfo keyPress = state.ConsoleManager.ReadKey(cancellationToken); + + if (_handlers.TryGetValue(keyPress.Key, out AsyncKeyPressHandler handler)) + { + using (CancellationTokenSource source = new CancellationTokenSource()) + using (state.ConsoleManager.AddBreakHandler(() => source.Cancel())) + { + if (presses != null) + { + FlushInput(state, ref presses); + } + + await handler(keyPress, state, source.Token).ConfigureAwait(false); + } + } + else if (!string.IsNullOrEmpty(_ttyState) && keyPress.Modifiers == ConsoleModifiers.Control) + { + if (presses != null) + { + FlushInput(state, ref presses); + } + + if (keyPress.Key == ConsoleKey.A) + { + state.ConsoleManager.MoveCaret(-state.ConsoleManager.CaretPosition); + } + else if (keyPress.Key == ConsoleKey.E) + { + state.ConsoleManager.MoveCaret(_inputBuffer.Count - state.ConsoleManager.CaretPosition); + } + } + else if (!string.IsNullOrEmpty(_ttyState) && keyPress.Modifiers == ConsoleModifiers.Alt) + { + if (presses != null) + { + FlushInput(state, ref presses); + } + + //Move back a word + if (keyPress.Key == ConsoleKey.B) + { + int i = state.ConsoleManager.CaretPosition - 1; + + if (i < 0) + { + continue; + } + + bool letterMode = char.IsLetterOrDigit(_inputBuffer[i]); + + for (; i > 0 && (char.IsLetterOrDigit(_inputBuffer[i]) == letterMode); --i) + { + } + + if (letterMode && i > 0) + { + ++i; + } + + if (i > -1) + { + state.ConsoleManager.MoveCaret(i - state.ConsoleManager.CaretPosition); + } + } + //Move forward a word + else if (keyPress.Key == ConsoleKey.F) + { + int i = state.ConsoleManager.CaretPosition + 1; + + if (i >= _inputBuffer.Count) + { + continue; + } + + bool letterMode = char.IsLetterOrDigit(_inputBuffer[i]); + + for (; i < _inputBuffer.Count && (char.IsLetterOrDigit(_inputBuffer[i]) == letterMode); ++i) + { + } + + if (letterMode && i < _inputBuffer.Count - 1 && i > 0) + { + --i; + } + + state.ConsoleManager.MoveCaret(i - state.ConsoleManager.CaretPosition); + } + } + else if (!keyPress.Modifiers.HasFlag(ConsoleModifiers.Alt) && !keyPress.Modifiers.HasFlag(ConsoleModifiers.Control)) + { + if (state.ConsoleManager.IsKeyAvailable) + { + if (presses == null) + { + presses = new List(); + } + + presses.Add(keyPress); + continue; + } + + if (presses != null) + { + presses.Add(keyPress); + FlushInput(state, ref presses); + continue; + } + + if (state.ConsoleManager.CaretPosition == _inputBuffer.Count) + { + _inputBuffer.Add(keyPress.KeyChar); + state.ConsoleManager.Write(keyPress.KeyChar); + } + else if (IsOverwriteMode) + { + _inputBuffer[state.ConsoleManager.CaretPosition] = keyPress.KeyChar; + state.ConsoleManager.Write(keyPress.KeyChar); + } + else + { + state.ConsoleManager.IsCaretVisible = false; + _inputBuffer.Insert(state.ConsoleManager.CaretPosition, keyPress.KeyChar); + int currentCaretPosition = state.ConsoleManager.CaretPosition; + string s = new string(_inputBuffer.ToArray(), state.ConsoleManager.CaretPosition, _inputBuffer.Count - state.ConsoleManager.CaretPosition); + state.ConsoleManager.Write(s); + state.ConsoleManager.MoveCaret(currentCaretPosition - state.ConsoleManager.CaretPosition + 1); + state.ConsoleManager.IsCaretVisible = true; + } + } + } + } + finally + { + RestoreTtyState(); + } + } + + private void FlushInput(IShellState state, ref List presses) + { + string str = new string(presses.Select(x => x.KeyChar).ToArray()); + + if (state.ConsoleManager.CaretPosition == _inputBuffer.Count) + { + _inputBuffer.AddRange(str); + state.ConsoleManager.Write(str); + } + else if (IsOverwriteMode) + { + for (int i = 0; i < str.Length; ++i) + { + if (state.ConsoleManager.CaretPosition + i < _inputBuffer.Count) + { + _inputBuffer[state.ConsoleManager.CaretPosition + i] = str[i]; + } + else + { + _inputBuffer.AddRange(str.Skip(i)); + break; + } + } + + state.ConsoleManager.Write(str); + } + else + { + state.ConsoleManager.IsCaretVisible = false; + _inputBuffer.InsertRange(state.ConsoleManager.CaretPosition, str); + int currentCaretPosition = state.ConsoleManager.CaretPosition; + string s = new string(_inputBuffer.ToArray(), state.ConsoleManager.CaretPosition, _inputBuffer.Count - state.ConsoleManager.CaretPosition); + state.ConsoleManager.Write(s); + state.ConsoleManager.MoveCaret(currentCaretPosition - state.ConsoleManager.CaretPosition + str.Length); + state.ConsoleManager.IsCaretVisible = true; + } + + presses = null; + } + } +} diff --git a/src/Microsoft.Repl/Input/KeyHandlers.cs b/src/Microsoft.Repl/Input/KeyHandlers.cs new file mode 100644 index 0000000000..7b23f08769 --- /dev/null +++ b/src/Microsoft.Repl/Input/KeyHandlers.cs @@ -0,0 +1,239 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Repl.Parsing; + +namespace Microsoft.Repl.Input +{ + public static class KeyHandlers + { + public static void RegisterDefaultKeyHandlers(IInputManager inputManager) + { + //Navigation in line + inputManager.RegisterKeyHandler(ConsoleKey.LeftArrow, LeftArrow); + inputManager.RegisterKeyHandler(ConsoleKey.RightArrow, RightArrow); + inputManager.RegisterKeyHandler(ConsoleKey.Home, Home); + inputManager.RegisterKeyHandler(ConsoleKey.End, End); + + //Command history + inputManager.RegisterKeyHandler(ConsoleKey.UpArrow, UpArrow); + inputManager.RegisterKeyHandler(ConsoleKey.DownArrow, DownArrow); + + //Completion + inputManager.RegisterKeyHandler(ConsoleKey.Tab, Tab); + + //Input manipulation + inputManager.RegisterKeyHandler(ConsoleKey.Escape, Escape); + inputManager.RegisterKeyHandler(ConsoleKey.Delete, Delete); + inputManager.RegisterKeyHandler(ConsoleKey.Backspace, Backspace); + + //Insert/Overwrite mode + inputManager.RegisterKeyHandler(ConsoleKey.Insert, Insert); + + //Execute command + inputManager.RegisterKeyHandler(ConsoleKey.Enter, Enter); + + //Map non-printable keys that aren't handled by default + inputManager.RegisterKeyHandler(ConsoleKey.F1, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F2, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F3, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F4, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F5, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F6, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F7, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F8, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F9, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F10, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F11, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F12, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F13, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F14, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F15, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F16, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F17, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F18, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F19, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F20, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F21, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F22, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F23, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.F24, Unhandled); + + inputManager.RegisterKeyHandler(ConsoleKey.Applications, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.Attention, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.BrowserBack, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.BrowserFavorites, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.BrowserForward, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.BrowserHome, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.BrowserRefresh, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.BrowserSearch, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.BrowserStop, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.Clear, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.CrSel, Unhandled); + + inputManager.RegisterKeyHandler(ConsoleKey.EraseEndOfFile, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.Execute, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.ExSel, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.Help, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.LaunchApp1, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.LaunchApp2, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.LaunchMail, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.LaunchMediaSelect, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.LeftWindows, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.MediaNext, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.MediaPlay, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.MediaPrevious, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.MediaStop, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.NoName, Unhandled); + + inputManager.RegisterKeyHandler(ConsoleKey.Pa1, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.Packet, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.PageDown, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.PageUp, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.Pause, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.Play, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.Print, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.PrintScreen, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.Process, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.RightWindows, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.Select, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.Separator, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.Sleep, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.VolumeDown, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.VolumeMute, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.VolumeUp, Unhandled); + inputManager.RegisterKeyHandler(ConsoleKey.Zoom, Unhandled); + } + + private static Task End(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken) + { + state.ConsoleManager.MoveCaret(state.InputManager.GetCurrentBuffer().Length - state.ConsoleManager.CaretPosition); + return Task.CompletedTask; + } + + public static Task Home(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken) + { + state.ConsoleManager.MoveCaret(-state.ConsoleManager.CaretPosition); + return Task.CompletedTask; + } + + public static Task LeftArrow(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken) + { + if (state.ConsoleManager.CaretPosition > 0) + { + if (!keyInfo.Modifiers.HasFlag(ConsoleModifiers.Control)) + { + state.ConsoleManager.MoveCaret(-1); + } + else + { + string line = state.InputManager.GetCurrentBuffer(); + ICoreParseResult parseResult = state.CommandDispatcher.Parser.Parse(line, state.ConsoleManager.CaretPosition); + int targetSection = parseResult.SelectedSection - (parseResult.CaretPositionWithinSelectedSection > 0 ? 0 : 1); + + if (targetSection < 0) + { + targetSection = 0; + } + + int desiredPosition = parseResult.SectionStartLookup[targetSection]; + state.ConsoleManager.MoveCaret(desiredPosition - state.ConsoleManager.CaretPosition); + } + } + + return Task.CompletedTask; + } + + public static Task RightArrow(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken) + { + string line = state.InputManager.GetCurrentBuffer(); + + if (state.ConsoleManager.CaretPosition < line.Length) + { + if (!keyInfo.Modifiers.HasFlag(ConsoleModifiers.Control)) + { + state.ConsoleManager.MoveCaret(1); + } + else + { + ICoreParseResult parseResult = state.CommandDispatcher.Parser.Parse(line, state.ConsoleManager.CaretPosition); + int targetSection = parseResult.SelectedSection + 1; + + if (targetSection >= parseResult.Sections.Count) + { + state.ConsoleManager.MoveCaret(line.Length - state.ConsoleManager.CaretPosition); + } + else + { + int desiredPosition = parseResult.SectionStartLookup[targetSection]; + state.ConsoleManager.MoveCaret(desiredPosition - state.ConsoleManager.CaretPosition); + } + } + } + + return Task.CompletedTask; + } + + public static Task UpArrow(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken) + { + string line = state.CommandHistory.GetPreviousCommand(); + state.InputManager.SetInput(state, line); + return Task.CompletedTask; + } + + public static Task DownArrow(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken) + { + string line = state.CommandHistory.GetNextCommand(); + state.InputManager.SetInput(state, line); + return Task.CompletedTask; + } + + public static Task Enter(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken) + { + return state.CommandDispatcher.ExecuteCommandAsync(state, cancellationToken); + } + + public static Task Backspace(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken) + { + state.InputManager.RemovePreviousCharacter(state); + return Task.CompletedTask; + } + + public static Task Unhandled(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken) + { + return Task.CompletedTask; + } + + public static Task Escape(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken) + { + state.InputManager.SetInput(state, string.Empty); + return Task.CompletedTask; + } + + public static Task Tab(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken) + { + if (keyInfo.Modifiers.HasFlag(ConsoleModifiers.Shift)) + { + state.SuggestionManager.PreviousSuggestion(state); + } + else + { + state.SuggestionManager.NextSuggestion(state); + } + + return Task.CompletedTask; + } + + public static Task Delete(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken) + { + state.InputManager.RemoveCurrentCharacter(state); + return Task.CompletedTask; + } + + public static Task Insert(ConsoleKeyInfo keyInfo, IShellState state, CancellationToken cancellationToken) + { + state.InputManager.IsOverwriteMode = !state.InputManager.IsOverwriteMode; + return Task.CompletedTask; + } + } +} diff --git a/src/Microsoft.Repl/Microsoft.Repl.csproj b/src/Microsoft.Repl/Microsoft.Repl.csproj new file mode 100644 index 0000000000..63af949be4 --- /dev/null +++ b/src/Microsoft.Repl/Microsoft.Repl.csproj @@ -0,0 +1,9 @@ + + + + netcoreapp2.2 + A framework for creating REPLs in .NET Core. + dotnet;repl + + + diff --git a/src/Microsoft.Repl/Parsing/CoreParseResult.cs b/src/Microsoft.Repl/Parsing/CoreParseResult.cs new file mode 100644 index 0000000000..8f345813f6 --- /dev/null +++ b/src/Microsoft.Repl/Parsing/CoreParseResult.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.Repl.Parsing +{ + public class CoreParseResult : ICoreParseResult + { + public CoreParseResult(int caretPositionWithinCommandText, int caretPositionWithinSelectedSection, string commandText, IReadOnlyList sections, int selectedSection, IReadOnlyDictionary sectionStartLookup, HashSet quotedSections) + { + CaretPositionWithinCommandText = caretPositionWithinCommandText; + CaretPositionWithinSelectedSection = caretPositionWithinSelectedSection; + CommandText = commandText; + Sections = sections; + SelectedSection = selectedSection; + SectionStartLookup = sectionStartLookup; + _quotedSections = quotedSections; + } + + public int CaretPositionWithinCommandText { get; } + + public int CaretPositionWithinSelectedSection { get; } + + public string CommandText { get; } + + public IReadOnlyList Sections { get; } + + public int SelectedSection { get; } + + public IReadOnlyDictionary SectionStartLookup { get; } + + private readonly HashSet _quotedSections; + + public bool IsQuotedSection(int index) + { + return _quotedSections.Contains(index); + } + + public virtual ICoreParseResult Slice(int numberOfLeadingSectionsToRemove) + { + if (numberOfLeadingSectionsToRemove == 0) + { + return this; + } + + if (numberOfLeadingSectionsToRemove >= Sections.Count) + { + return new CoreParseResult(0, 0, string.Empty, new[] { string.Empty }, 0, new Dictionary { { 0, 0 } }, new HashSet()); + } + + string commandText = CommandText.Substring(SectionStartLookup[numberOfLeadingSectionsToRemove]); + int caretPositionWithinCommandText = CaretPositionWithinCommandText - SectionStartLookup[numberOfLeadingSectionsToRemove]; + + if (caretPositionWithinCommandText < 0) + { + caretPositionWithinCommandText = 0; + } + + Dictionary sectionStartLookup = new Dictionary(); + List sections = new List(); + for (int i = 0; i < Sections.Count - numberOfLeadingSectionsToRemove; ++i) + { + sectionStartLookup[i] = SectionStartLookup[numberOfLeadingSectionsToRemove + i] - SectionStartLookup[numberOfLeadingSectionsToRemove]; + sections.Add(Sections[numberOfLeadingSectionsToRemove + i]); + } + + int selectedSection = SelectedSection - numberOfLeadingSectionsToRemove; + + if (selectedSection < 0) + { + selectedSection = 0; + } + + HashSet quotedSections = new HashSet(_quotedSections.Where(x => x > 0).Select(x => x - 1)); + return new CoreParseResult(caretPositionWithinCommandText, CaretPositionWithinSelectedSection, commandText, sections, selectedSection, sectionStartLookup, quotedSections); + } + } +} diff --git a/src/Microsoft.Repl/Parsing/CoreParser.cs b/src/Microsoft.Repl/Parsing/CoreParser.cs new file mode 100644 index 0000000000..35be4867a5 --- /dev/null +++ b/src/Microsoft.Repl/Parsing/CoreParser.cs @@ -0,0 +1,129 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.Repl.Parsing +{ + public class CoreParser : IParser + { + public ICoreParseResult Parse(string commandText, int caretPosition) + { + List sections = commandText.Split(' ').ToList(); + Dictionary sectionStartLookup = new Dictionary(); + HashSet quotedSections = new HashSet(); + int runningIndex = 0; + int selectedSection = -1; + int caretPositionWithinSelectedSection = 0; + bool isInQuotedSection = false; + + for (int i = 0; i < sections.Count; ++i) + { + int thisSectionLength = sections[i].Length; + bool isLastSection = i == sections.Count - 1; + + //If currently in a quoted section, combine with the previous section, check to see if this section closes the quotes + if (isInQuotedSection) + { + //Combine with the previous section + sections[i - 1] += " " + sections[i]; + sections.RemoveAt(i--); + + //Check for the closing quote + int sectionLength = sections[i].Length; + if (sections[i][sectionLength - 1] == '"') + { + if (sectionLength > 1 && sections[i][sectionLength - 2] != '\\') + { + isInQuotedSection = false; + } + } + } + //Not in a quoted section, check to see if we're starting one + else + { + sectionStartLookup[i] = runningIndex; + + if (sections[i].Length > 0) + { + if (sections[i][0] == '"') + { + isInQuotedSection = true; + } + } + } + + //Update the running index, adding one for all but the last element to account for the spaces between the sections + runningIndex += thisSectionLength + (isLastSection ? 0 : 1); + + //If the selected section hasn't been determined yet, and the end of the text is past the caret, set the selected + // section to the current section and set the initial value for the caret position within the selected section. + // Note that the caret position within the selected section, unlike the other positions, accounts for escape + // sequences and must be fixed up when escape sequences are removed + if (selectedSection == -1 && runningIndex > caretPosition) + { + selectedSection = i; + caretPositionWithinSelectedSection = caretPosition - sectionStartLookup[i]; + } + } + + //Unescape the sections + // Note that this isn't combined with the above loop to avoid additional complexity in the quoted section case + for (int i = 0; i < sections.Count; ++i) + { + string s = sections[i]; + + //Trim quotes if needed + if (s.Length > 1) + { + if (s[0] == s[s.Length - 1] && s[0] == '"') + { + s = s.Substring(1, s.Length - 2); + quotedSections.Add(i); + + //Fix up the caret position in the text + if (selectedSection == i) + { + //If the caret was on the closing quote, back up to the last character of the section + if (caretPositionWithinSelectedSection == s.Length - 1) + { + caretPositionWithinSelectedSection -= 2; + } + //If the caret was after the opening quote, back up one + else if (caretPositionWithinSelectedSection > 0) + { + --caretPositionWithinSelectedSection; + } + } + } + } + + for (int j = 0; j < s.Length - 1; ++j) + { + if (s[j] == '\\') + { + if (s[j + 1] == '\\' || s[j + 1] == '"') + { + s = s.Substring(0, j) + s.Substring(j + 1); + + //If we're changing the selected section, and we're removing a character + // from before the caret position, back the caret position up to account for it + if (selectedSection == i && j < caretPositionWithinSelectedSection) + { + --caretPositionWithinSelectedSection; + } + } + } + } + + sections[i] = s; + } + + if (selectedSection == -1) + { + selectedSection = sections.Count - 1; + caretPositionWithinSelectedSection = sections[selectedSection].Length; + } + + return new CoreParseResult(caretPosition, caretPositionWithinSelectedSection, commandText, sections, selectedSection, sectionStartLookup, quotedSections); + } + } +} diff --git a/src/Microsoft.Repl/Parsing/ICoreParseResult.cs b/src/Microsoft.Repl/Parsing/ICoreParseResult.cs new file mode 100644 index 0000000000..20ac2c7b4e --- /dev/null +++ b/src/Microsoft.Repl/Parsing/ICoreParseResult.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; + +namespace Microsoft.Repl.Parsing +{ + public interface ICoreParseResult + { + int CaretPositionWithinCommandText { get; } + + int CaretPositionWithinSelectedSection { get; } + + string CommandText { get; } + + IReadOnlyList Sections { get; } + + bool IsQuotedSection(int index); + + int SelectedSection { get; } + + IReadOnlyDictionary SectionStartLookup { get; } + + ICoreParseResult Slice(int numberOfLeadingSectionsToRemove); + } +} diff --git a/src/Microsoft.Repl/Parsing/IParser.cs b/src/Microsoft.Repl/Parsing/IParser.cs new file mode 100644 index 0000000000..c909f7d94f --- /dev/null +++ b/src/Microsoft.Repl/Parsing/IParser.cs @@ -0,0 +1,12 @@ +namespace Microsoft.Repl.Parsing +{ + public interface IParser + { + ICoreParseResult Parse(string commandText, int caretPosition); + } + + public interface IParser : IParser + { + new TParseResult Parse(string commandText, int caretPosition); + } +} diff --git a/src/Microsoft.Repl/Scripting/IScriptExecutor.cs b/src/Microsoft.Repl/Scripting/IScriptExecutor.cs new file mode 100644 index 0000000000..7d832d8306 --- /dev/null +++ b/src/Microsoft.Repl/Scripting/IScriptExecutor.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.Repl.Scripting +{ + public interface IScriptExecutor + { + Task ExecuteScriptAsync(IShellState shellState, IEnumerable commandTexts, CancellationToken cancellationToken); + } +} diff --git a/src/Microsoft.Repl/Scripting/ScriptExecutor.cs b/src/Microsoft.Repl/Scripting/ScriptExecutor.cs new file mode 100644 index 0000000000..3ec4bf5d21 --- /dev/null +++ b/src/Microsoft.Repl/Scripting/ScriptExecutor.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Repl.Commanding; +using Microsoft.Repl.Parsing; + +namespace Microsoft.Repl.Scripting +{ + public class ScriptExecutor : IScriptExecutor + where TParseResult : ICoreParseResult + { + private readonly bool _hideScriptLinesFromHistory; + + public ScriptExecutor(bool hideScriptLinesFromHistory = true) + { + _hideScriptLinesFromHistory = hideScriptLinesFromHistory; + } + + public async Task ExecuteScriptAsync(IShellState shellState, IEnumerable commandTexts, CancellationToken cancellationToken) + { + if (shellState.CommandDispatcher is ICommandDispatcher dispatcher) + { + IDisposable suppressor = _hideScriptLinesFromHistory ? shellState.CommandHistory.SuspendHistory() : null; + + using (suppressor) + { + foreach (string commandText in commandTexts) + { + if (string.IsNullOrWhiteSpace(commandText)) + { + continue; + } + + if (cancellationToken.IsCancellationRequested) + { + break; + } + + dispatcher.OnReady(shellState); + shellState.ConsoleManager.ResetCommandStart(); + shellState.InputManager.SetInput(shellState, commandText); + await dispatcher.ExecuteCommandAsync(shellState, cancellationToken).ConfigureAwait(false); + } + } + } + } + } +} diff --git a/src/Microsoft.Repl/Shell.cs b/src/Microsoft.Repl/Shell.cs new file mode 100644 index 0000000000..49f450eae0 --- /dev/null +++ b/src/Microsoft.Repl/Shell.cs @@ -0,0 +1,30 @@ +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Repl.Commanding; +using Microsoft.Repl.Input; +using Microsoft.Repl.Suggestions; + +namespace Microsoft.Repl +{ + public class Shell + { + public Shell(IShellState shellState) + { + KeyHandlers.RegisterDefaultKeyHandlers(shellState.InputManager); + ShellState = shellState; + } + + public Shell(ICommandDispatcher dispatcher, ISuggestionManager suggestionManager = null) + : this(new ShellState(dispatcher, suggestionManager)) + { + } + + public IShellState ShellState { get; } + + public Task RunAsync(CancellationToken cancellationToken) + { + ShellState.CommandDispatcher.OnReady(ShellState); + return ShellState.InputManager.StartAsync(ShellState, cancellationToken); + } + } +} diff --git a/src/Microsoft.Repl/ShellState.cs b/src/Microsoft.Repl/ShellState.cs new file mode 100644 index 0000000000..ef0ccf2a64 --- /dev/null +++ b/src/Microsoft.Repl/ShellState.cs @@ -0,0 +1,31 @@ +using Microsoft.Repl.Commanding; +using Microsoft.Repl.ConsoleHandling; +using Microsoft.Repl.Input; +using Microsoft.Repl.Suggestions; + +namespace Microsoft.Repl +{ + public class ShellState : IShellState + { + public ShellState(ICommandDispatcher commandDispatcher, ISuggestionManager suggestionManager = null, IInputManager inputManager = null, ICommandHistory commandHistory = null, IConsoleManager consoleManager = null) + { + InputManager = inputManager ?? new InputManager(); + CommandHistory = commandHistory ?? new CommandHistory(); + ConsoleManager = consoleManager ?? new ConsoleManager(); + CommandDispatcher = commandDispatcher; + SuggestionManager = suggestionManager ?? new SuggestionManager(); + } + + public IInputManager InputManager { get; } + + public ICommandHistory CommandHistory { get; } + + public IConsoleManager ConsoleManager { get; } + + public ICommandDispatcher CommandDispatcher { get; } + + public bool IsExiting { get; set; } + + public ISuggestionManager SuggestionManager { get; } + } +} diff --git a/src/Microsoft.Repl/Suggestions/FileSystemCompletion.cs b/src/Microsoft.Repl/Suggestions/FileSystemCompletion.cs new file mode 100644 index 0000000000..71237fcd27 --- /dev/null +++ b/src/Microsoft.Repl/Suggestions/FileSystemCompletion.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Microsoft.Repl.Suggestions +{ + public static class FileSystemCompletion + { + public static IEnumerable GetCompletions(string prefix) + { + if (prefix.StartsWith('\"')) + { + prefix = prefix.Substring(1); + + int lastQuote = prefix.LastIndexOf('\"'); + + if (lastQuote > -1) + { + prefix = prefix.Remove(lastQuote, 1); + } + + while (prefix.EndsWith($"{Path.DirectorySeparatorChar}{Path.DirectorySeparatorChar}")) + { + prefix = prefix.Substring(0, prefix.Length - 1); + } + } + + int lastPathIndex = prefix.LastIndexOfAny(new[] { '\\', '/' }); + if (lastPathIndex < 0) + { + return null; + } + + string dir = prefix.Substring(0, lastPathIndex + 1); + + if (dir.IndexOfAny(Path.GetInvalidPathChars()) > -1) + { + return null; + } + + string partPrefix = prefix.Substring(lastPathIndex + 1); + if (Directory.Exists(dir)) + { + return Directory.EnumerateDirectories(dir).Where(x => Path.GetFileName(x).StartsWith(partPrefix, StringComparison.OrdinalIgnoreCase)) + .Union(Directory.EnumerateFiles(dir).Where(x => Path.GetFileName(x).StartsWith(partPrefix, StringComparison.OrdinalIgnoreCase))).Select(x => x.IndexOf(' ') > -1 ? $"\"{x}\"" : x); + } + + return null; + } + } +} diff --git a/src/Microsoft.Repl/Suggestions/ISuggestionManager.cs b/src/Microsoft.Repl/Suggestions/ISuggestionManager.cs new file mode 100644 index 0000000000..f7e11a06fb --- /dev/null +++ b/src/Microsoft.Repl/Suggestions/ISuggestionManager.cs @@ -0,0 +1,9 @@ +namespace Microsoft.Repl.Suggestions +{ + public interface ISuggestionManager + { + void NextSuggestion(IShellState shellState); + + void PreviousSuggestion(IShellState shellState); + } +} diff --git a/src/Microsoft.Repl/Suggestions/SuggestionManager.cs b/src/Microsoft.Repl/Suggestions/SuggestionManager.cs new file mode 100644 index 0000000000..1fd9e861da --- /dev/null +++ b/src/Microsoft.Repl/Suggestions/SuggestionManager.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using Microsoft.Repl.Parsing; + +namespace Microsoft.Repl.Suggestions +{ + public class SuggestionManager : ISuggestionManager + { + private int _currentSuggestion; + private IReadOnlyList _suggestions; + private ICoreParseResult _expected; + + public void NextSuggestion(IShellState shellState) + { + string line = shellState.InputManager.GetCurrentBuffer(); + ICoreParseResult parseResult = shellState.CommandDispatcher.Parser.Parse(line, shellState.ConsoleManager.CaretPosition); + string currentSuggestion; + + //Check to see if we're continuing before querying for suggestions again + if (_expected != null + && string.Equals(_expected.CommandText, parseResult.CommandText, StringComparison.Ordinal) + && _expected.SelectedSection == parseResult.SelectedSection + && _expected.CaretPositionWithinSelectedSection == parseResult.CaretPositionWithinSelectedSection) + { + if (_suggestions == null || _suggestions.Count == 0) + { + return; + } + + _currentSuggestion = (_currentSuggestion + 1) % _suggestions.Count; + currentSuggestion = _suggestions[_currentSuggestion]; + } + else + { + _currentSuggestion = 0; + _suggestions = shellState.CommandDispatcher.CollectSuggesetions(shellState); + + if (_suggestions == null || _suggestions.Count == 0) + { + return; + } + + currentSuggestion = _suggestions[0]; + } + + //We now have a suggestion, take the command text leading up to the section being suggested for, + // concatenate that and the suggestion text, turn it in to keys, submit it to the input manager, + // reset the caret, store the parse result of the new text as what's expected for a continuation + string newText = parseResult.CommandText.Substring(0, parseResult.SectionStartLookup[parseResult.SelectedSection]) + currentSuggestion; + _expected = shellState.CommandDispatcher.Parser.Parse(newText, newText.Length); + shellState.InputManager.SetInput(shellState, newText); + } + + public void PreviousSuggestion(IShellState shellState) + { + string line = shellState.InputManager.GetCurrentBuffer(); + ICoreParseResult parseResult = shellState.CommandDispatcher.Parser.Parse(line, shellState.ConsoleManager.CaretPosition); + string currentSuggestion; + + //Check to see if we're continuing before querying for suggestions again + if (_expected != null + && string.Equals(_expected.CommandText, parseResult.CommandText, StringComparison.Ordinal) + && _expected.SelectedSection == parseResult.SelectedSection + && _expected.CaretPositionWithinSelectedSection == parseResult.CaretPositionWithinSelectedSection) + { + if (_suggestions == null || _suggestions.Count == 0) + { + return; + } + + _currentSuggestion = (_currentSuggestion - 1 + _suggestions.Count) % _suggestions.Count; + currentSuggestion = _suggestions[_currentSuggestion]; + } + else + { + _suggestions = shellState.CommandDispatcher.CollectSuggesetions(shellState); + _currentSuggestion = _suggestions.Count - 1; + + if (_suggestions == null || _suggestions.Count == 0) + { + return; + } + + currentSuggestion = _suggestions[_suggestions.Count - 1]; + } + + //We now have a suggestion, take the command text leading up to the section being suggested for, + // concatenate that and the suggestion text, turn it in to keys, submit it to the input manager, + // reset the caret, store the parse result of the new text as what's expected for a continuation + string newText = parseResult.CommandText.Substring(0, parseResult.SectionStartLookup[parseResult.SelectedSection]) + currentSuggestion; + _expected = shellState.CommandDispatcher.Parser.Parse(newText, newText.Length); + shellState.InputManager.SetInput(shellState, newText); + } + } +} diff --git a/src/Microsoft.Repl/Utils.cs b/src/Microsoft.Repl/Utils.cs new file mode 100644 index 0000000000..37ffcd97fb --- /dev/null +++ b/src/Microsoft.Repl/Utils.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +namespace Microsoft.Repl +{ + public static class Utils + { + public static string Stringify(this IReadOnlyList keys) + { + return string.Join("", keys); + } + } +} diff --git a/test/Microsoft.HttpRepl.Tests/JsonVisitorTests.cs b/test/Microsoft.HttpRepl.Tests/JsonVisitorTests.cs new file mode 100644 index 0000000000..30155b022f --- /dev/null +++ b/test/Microsoft.HttpRepl.Tests/JsonVisitorTests.cs @@ -0,0 +1,60 @@ +using Microsoft.HttpRepl.Formatting; +using Microsoft.HttpRepl.Preferences; +using Microsoft.Repl.ConsoleHandling; +using Xunit; + +namespace Microsoft.HttpRepl.Tests +{ + public class JsonVisitorTests + { + [Fact] + public void JsonVisitor_ObjectWithComments() + { + string testData = @"[ + { + //Object 1 + ""property"": ""value"", + ""and"": ""again"" + }, + { + //Object 2 + }, + [ + //An array + ], + null, + 1, + 3.2, + ""test"", + false +]"; + + string formatted = JsonVisitor.FormatAndColorize(new MockJsonConfig(), testData); + } + + private class MockJsonConfig : IJsonConfig + { + public int IndentSize => 2; + + public AllowedColors DefaultColor => AllowedColors.None; + + public AllowedColors ArrayBraceColor => AllowedColors.None; + + public AllowedColors ObjectBraceColor => AllowedColors.None; + + public AllowedColors CommaColor => AllowedColors.None; + + public AllowedColors NameColor => AllowedColors.None; + + public AllowedColors NameSeparatorColor => AllowedColors.None; + + public AllowedColors BoolColor => AllowedColors.None; + + public AllowedColors NumericColor => AllowedColors.None; + + public AllowedColors StringColor => AllowedColors.None; + + public AllowedColors NullColor => AllowedColors.None; + } + } +} diff --git a/test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj b/test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj new file mode 100644 index 0000000000..7a79d0121e --- /dev/null +++ b/test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj @@ -0,0 +1,21 @@ + + + + netcoreapp2.2 + + false + + + + + + + + + + + + + + + diff --git a/test/Microsoft.Repl.Tests/Microsoft.Repl.Tests.csproj b/test/Microsoft.Repl.Tests/Microsoft.Repl.Tests.csproj new file mode 100644 index 0000000000..52fbd0de16 --- /dev/null +++ b/test/Microsoft.Repl.Tests/Microsoft.Repl.Tests.csproj @@ -0,0 +1,19 @@ + + + + netcoreapp2.2 + + false + + + + + + + + + + + + + diff --git a/test/Microsoft.Repl.Tests/ParserTests.cs b/test/Microsoft.Repl.Tests/ParserTests.cs new file mode 100644 index 0000000000..422123db85 --- /dev/null +++ b/test/Microsoft.Repl.Tests/ParserTests.cs @@ -0,0 +1,26 @@ +using Microsoft.Repl.Parsing; +using Xunit; + +namespace Microsoft.Repl.Tests +{ + public class ParserTests + { + [Fact] + public void ParserTests_Basic() + { + string testString = "\"this is a test\" of \"Escape\\\\Sequences\\\"\""; + + CoreParser parser = new CoreParser(); + ICoreParseResult result = parser.Parse(testString, 29); + + Assert.Equal(3, result.Sections.Count); + Assert.Equal(2, result.SelectedSection); + Assert.Equal(0, result.SectionStartLookup[0]); + Assert.Equal(17, result.SectionStartLookup[1]); + Assert.Equal(20, result.SectionStartLookup[2]); + Assert.Equal(7, result.CaretPositionWithinSelectedSection); + Assert.Equal(29, result.CaretPositionWithinCommandText); + Assert.Equal(testString, result.CommandText); + } + } +} From 7f8f210a24fcebdd661037fd6cf6b1ed4bc1d06c Mon Sep 17 00:00:00 2001 From: Mike Lorbetske Date: Wed, 1 Aug 2018 12:35:27 -0700 Subject: [PATCH 0885/1029] Add license headers to all files Bump version of JSON.NET to 11.0.2 --- build/dependencies.props | 4 ++-- .../AggregateDirectoryStructure.cs | 5 ++++- .../Commands/BaseHttpCommand.cs | 5 ++++- .../Commands/ChangeDirectoryCommand.cs | 5 ++++- src/Microsoft.HttpRepl/Commands/ClearCommand.cs | 5 ++++- src/Microsoft.HttpRepl/Commands/ConfigCommand.cs | 5 ++++- src/Microsoft.HttpRepl/Commands/DeleteCommand.cs | 5 ++++- src/Microsoft.HttpRepl/Commands/EchoCommand.cs | 5 ++++- src/Microsoft.HttpRepl/Commands/ExitCommand.cs | 5 ++++- src/Microsoft.HttpRepl/Commands/Formatter.cs | 13 +++++-------- src/Microsoft.HttpRepl/Commands/GetCommand.cs | 5 ++++- src/Microsoft.HttpRepl/Commands/HeadCommand.cs | 5 ++++- src/Microsoft.HttpRepl/Commands/HelpCommand.cs | 5 ++++- src/Microsoft.HttpRepl/Commands/ListCommand.cs | 5 ++++- .../Commands/OptionsCommand.cs | 5 ++++- src/Microsoft.HttpRepl/Commands/PatchCommand.cs | 5 ++++- src/Microsoft.HttpRepl/Commands/PostCommand.cs | 5 ++++- src/Microsoft.HttpRepl/Commands/PrefCommand.cs | 5 ++++- src/Microsoft.HttpRepl/Commands/PutCommand.cs | 5 ++++- src/Microsoft.HttpRepl/Commands/RunCommand.cs | 5 ++++- .../Commands/SetBaseCommand.cs | 5 ++++- .../Commands/SetDiagCommand.cs | 5 ++++- .../Commands/SetHeaderCommand.cs | 5 ++++- .../Commands/SetSwaggerCommand.cs | 5 ++++- src/Microsoft.HttpRepl/Commands/TreeNode.cs | 7 +++++-- src/Microsoft.HttpRepl/Commands/UICommand.cs | 5 ++++- src/Microsoft.HttpRepl/Diagnostics/ConfigItem.cs | 5 ++++- .../Diagnostics/DiagEndpoint.cs | 5 ++++- .../Diagnostics/DiagEndpointMetadata.cs | 5 ++++- src/Microsoft.HttpRepl/Diagnostics/DiagItem.cs | 5 ++++- .../Diagnostics/DiagnosticsState.cs | 5 ++++- src/Microsoft.HttpRepl/DirectoryStructure.cs | 5 ++++- .../DirectoryStructureExtensions.cs | 5 ++++- src/Microsoft.HttpRepl/Formatting/JsonVisitor.cs | 5 ++++- src/Microsoft.HttpRepl/HttpState.cs | 5 ++++- src/Microsoft.HttpRepl/IDirectoryStructure.cs | 14 ++++---------- src/Microsoft.HttpRepl/IRequestInfo.cs | 16 ++++++++++++++++ src/Microsoft.HttpRepl/OpenApi/Either.cs | 5 ++++- .../OpenApi/EitherConverter.cs | 5 ++++- .../OpenApi/EndpointMetadata.cs | 5 ++++- .../OpenApi/EndpointMetadataReader.cs | 5 ++++- .../OpenApi/IEndpointMetadataReader.cs | 5 ++++- .../OpenApi/OpenApiV3EndpointMetadataReader.cs | 5 ++++- src/Microsoft.HttpRepl/OpenApi/Parameter.cs | 5 ++++- src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs | 5 ++++- src/Microsoft.HttpRepl/OpenApi/Schema.cs | 5 ++++- .../OpenApi/SwaggerV1EndpointMetadataReader.cs | 5 ++++- .../OpenApi/SwaggerV2EndpointMetadataReader.cs | 5 ++++- .../Preferences/IJsonConfig.cs | 7 +++++-- src/Microsoft.HttpRepl/Preferences/JsonConfig.cs | 5 ++++- .../Preferences/RequestConfig.cs | 5 ++++- .../Preferences/RequestOrResponseConfig.cs | 5 ++++- .../Preferences/ResponseConfig.cs | 5 ++++- .../Preferences/WellKnownPreference.cs | 5 ++++- src/Microsoft.HttpRepl/Program.cs | 5 ++++- .../Suggestions/HeaderCompletion.cs | 5 ++++- .../Suggestions/ServerPathCompletion.cs | 5 ++++- src/Microsoft.Repl/Commanding/CommandHistory.cs | 5 ++++- .../Commanding/CommandInputLocation.cs | 7 +++++-- .../Commanding/CommandInputProcessingIssue.cs | 7 +++++-- .../CommandInputProcessingIssueKind.cs | 7 +++++-- .../Commanding/CommandInputSpecification.cs | 7 +++++-- .../CommandInputSpecificationBuilder.cs | 7 +++++-- .../Commanding/CommandOptionSpecification.cs | 7 +++++-- .../Commanding/CommandWithStructuredInputBase.cs | 7 +++++-- .../Commanding/DefaultCommandDispatcher.cs | 5 ++++- .../Commanding/DefaultCommandInput.cs | 7 +++++-- src/Microsoft.Repl/Commanding/ICommand.cs | 5 ++++- .../Commanding/ICommandDispatcher.cs | 5 ++++- src/Microsoft.Repl/Commanding/ICommandHistory.cs | 5 ++++- src/Microsoft.Repl/Commanding/InputElement.cs | 7 +++++-- .../ConsoleHandling/AllowedColors.cs | 7 +++++-- .../ConsoleHandling/AnsiColorExtensions.cs | 5 ++++- .../ConsoleHandling/AnsiConsole.cs | 5 ++++- .../ConsoleHandling/ConsoleManager.cs | 5 ++++- .../ConsoleHandling/IConsoleManager.cs | 5 ++++- src/Microsoft.Repl/ConsoleHandling/IWritable.cs | 5 ++++- src/Microsoft.Repl/ConsoleHandling/Point.cs | 5 ++++- src/Microsoft.Repl/ConsoleHandling/Reporter.cs | 5 ++++- src/Microsoft.Repl/ConsoleHandling/Writable.cs | 5 ++++- src/Microsoft.Repl/Disposable.cs | 5 ++++- src/Microsoft.Repl/IShellState.cs | 5 ++++- src/Microsoft.Repl/Input/AsyncKeyPressHandler.cs | 5 ++++- src/Microsoft.Repl/Input/IInputManager.cs | 5 ++++- src/Microsoft.Repl/Input/InputManager.cs | 5 ++++- src/Microsoft.Repl/Input/KeyHandlers.cs | 5 ++++- src/Microsoft.Repl/Parsing/CoreParseResult.cs | 5 ++++- src/Microsoft.Repl/Parsing/CoreParser.cs | 5 ++++- src/Microsoft.Repl/Parsing/ICoreParseResult.cs | 5 ++++- src/Microsoft.Repl/Parsing/IParser.cs | 5 ++++- src/Microsoft.Repl/Scripting/IScriptExecutor.cs | 5 ++++- src/Microsoft.Repl/Scripting/ScriptExecutor.cs | 5 ++++- src/Microsoft.Repl/Shell.cs | 5 ++++- src/Microsoft.Repl/ShellState.cs | 5 ++++- .../Suggestions/FileSystemCompletion.cs | 5 ++++- .../Suggestions/ISuggestionManager.cs | 5 ++++- .../Suggestions/SuggestionManager.cs | 5 ++++- src/Microsoft.Repl/Utils.cs | 5 ++++- 98 files changed, 415 insertions(+), 126 deletions(-) create mode 100644 src/Microsoft.HttpRepl/IRequestInfo.cs diff --git a/build/dependencies.props b/build/dependencies.props index 0c7d2bca9d..ee0b0b8ccf 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,4 +1,4 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) @@ -17,7 +17,7 @@ 2.0.3 4.5.1 4.5.0 - 10.0.1 + 11.0.2 9.0.1 2.3.1 2.4.0 diff --git a/src/Microsoft.HttpRepl/AggregateDirectoryStructure.cs b/src/Microsoft.HttpRepl/AggregateDirectoryStructure.cs index ed763a3e8f..19dcb289f8 100644 --- a/src/Microsoft.HttpRepl/AggregateDirectoryStructure.cs +++ b/src/Microsoft.HttpRepl/AggregateDirectoryStructure.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Linq; diff --git a/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs b/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs index 3db2f39b7b..374544790b 100644 --- a/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; diff --git a/src/Microsoft.HttpRepl/Commands/ChangeDirectoryCommand.cs b/src/Microsoft.HttpRepl/Commands/ChangeDirectoryCommand.cs index 3a983698cf..c2baaf0de5 100644 --- a/src/Microsoft.HttpRepl/Commands/ChangeDirectoryCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/ChangeDirectoryCommand.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Linq; using System.Threading; diff --git a/src/Microsoft.HttpRepl/Commands/ClearCommand.cs b/src/Microsoft.HttpRepl/Commands/ClearCommand.cs index a695dfc544..4244946c95 100644 --- a/src/Microsoft.HttpRepl/Commands/ClearCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/ClearCommand.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; diff --git a/src/Microsoft.HttpRepl/Commands/ConfigCommand.cs b/src/Microsoft.HttpRepl/Commands/ConfigCommand.cs index 56003280ab..773bee0f04 100644 --- a/src/Microsoft.HttpRepl/Commands/ConfigCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/ConfigCommand.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; diff --git a/src/Microsoft.HttpRepl/Commands/DeleteCommand.cs b/src/Microsoft.HttpRepl/Commands/DeleteCommand.cs index a861b35142..7c9b789db3 100644 --- a/src/Microsoft.HttpRepl/Commands/DeleteCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/DeleteCommand.cs @@ -1,4 +1,7 @@ -namespace Microsoft.HttpRepl.Commands +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.HttpRepl.Commands { public class DeleteCommand : BaseHttpCommand { diff --git a/src/Microsoft.HttpRepl/Commands/EchoCommand.cs b/src/Microsoft.HttpRepl/Commands/EchoCommand.cs index 19eb33788b..691eb5679f 100644 --- a/src/Microsoft.HttpRepl/Commands/EchoCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/EchoCommand.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Linq; using System.Threading; diff --git a/src/Microsoft.HttpRepl/Commands/ExitCommand.cs b/src/Microsoft.HttpRepl/Commands/ExitCommand.cs index ebc0635876..af76ad95df 100644 --- a/src/Microsoft.HttpRepl/Commands/ExitCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/ExitCommand.cs @@ -1,4 +1,7 @@ -using System.Threading; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading; using System.Threading.Tasks; using Microsoft.Repl; using Microsoft.Repl.Commanding; diff --git a/src/Microsoft.HttpRepl/Commands/Formatter.cs b/src/Microsoft.HttpRepl/Commands/Formatter.cs index 5a450e3406..d1783dc357 100644 --- a/src/Microsoft.HttpRepl/Commands/Formatter.cs +++ b/src/Microsoft.HttpRepl/Commands/Formatter.cs @@ -1,18 +1,15 @@ -namespace Microsoft.HttpRepl.Commands +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.HttpRepl.Commands { public class Formatter { - //private readonly List _prefix = new List(); private int _prefix; private int _maxDepth; public void RegisterEntry(int prefixLength, int depth) { - //while (_prefix.Count < depth + 1) - //{ - // _prefix.Add(0); - //} - if (depth > _maxDepth) { _maxDepth = depth; @@ -30,4 +27,4 @@ return (indent + prefix).PadRight(_prefix + 3 + _maxDepth * 4) + entry; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.HttpRepl/Commands/GetCommand.cs b/src/Microsoft.HttpRepl/Commands/GetCommand.cs index 76765ce374..e5441cecd1 100644 --- a/src/Microsoft.HttpRepl/Commands/GetCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/GetCommand.cs @@ -1,4 +1,7 @@ -namespace Microsoft.HttpRepl.Commands +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.HttpRepl.Commands { public class GetCommand : BaseHttpCommand { diff --git a/src/Microsoft.HttpRepl/Commands/HeadCommand.cs b/src/Microsoft.HttpRepl/Commands/HeadCommand.cs index 97023f5860..fbd3de4971 100644 --- a/src/Microsoft.HttpRepl/Commands/HeadCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/HeadCommand.cs @@ -1,4 +1,7 @@ -namespace Microsoft.HttpRepl.Commands +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.HttpRepl.Commands { public class HeadCommand : BaseHttpCommand { diff --git a/src/Microsoft.HttpRepl/Commands/HelpCommand.cs b/src/Microsoft.HttpRepl/Commands/HelpCommand.cs index de909a4906..f205fc1243 100644 --- a/src/Microsoft.HttpRepl/Commands/HelpCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/HelpCommand.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Linq; using System.Threading; diff --git a/src/Microsoft.HttpRepl/Commands/ListCommand.cs b/src/Microsoft.HttpRepl/Commands/ListCommand.cs index 078a20d398..b1aa0718a3 100644 --- a/src/Microsoft.HttpRepl/Commands/ListCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/ListCommand.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Globalization; using System.Linq; diff --git a/src/Microsoft.HttpRepl/Commands/OptionsCommand.cs b/src/Microsoft.HttpRepl/Commands/OptionsCommand.cs index f6a3c8903c..5da5cadfaf 100644 --- a/src/Microsoft.HttpRepl/Commands/OptionsCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/OptionsCommand.cs @@ -1,4 +1,7 @@ -namespace Microsoft.HttpRepl.Commands +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.HttpRepl.Commands { public class OptionsCommand : BaseHttpCommand { diff --git a/src/Microsoft.HttpRepl/Commands/PatchCommand.cs b/src/Microsoft.HttpRepl/Commands/PatchCommand.cs index c5d9c875be..bfb9cc9192 100644 --- a/src/Microsoft.HttpRepl/Commands/PatchCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/PatchCommand.cs @@ -1,4 +1,7 @@ -namespace Microsoft.HttpRepl.Commands +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.HttpRepl.Commands { public class PatchCommand : BaseHttpCommand { diff --git a/src/Microsoft.HttpRepl/Commands/PostCommand.cs b/src/Microsoft.HttpRepl/Commands/PostCommand.cs index 216fe8ef1d..61edb6d4c8 100644 --- a/src/Microsoft.HttpRepl/Commands/PostCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/PostCommand.cs @@ -1,4 +1,7 @@ -namespace Microsoft.HttpRepl.Commands +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.HttpRepl.Commands { public class PostCommand : BaseHttpCommand { diff --git a/src/Microsoft.HttpRepl/Commands/PrefCommand.cs b/src/Microsoft.HttpRepl/Commands/PrefCommand.cs index 7f16af09b3..2a64d2f017 100644 --- a/src/Microsoft.HttpRepl/Commands/PrefCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/PrefCommand.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Linq; using System.Threading; diff --git a/src/Microsoft.HttpRepl/Commands/PutCommand.cs b/src/Microsoft.HttpRepl/Commands/PutCommand.cs index a65439dfb7..4f37e1776c 100644 --- a/src/Microsoft.HttpRepl/Commands/PutCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/PutCommand.cs @@ -1,4 +1,7 @@ -namespace Microsoft.HttpRepl.Commands +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.HttpRepl.Commands { public class PutCommand : BaseHttpCommand { diff --git a/src/Microsoft.HttpRepl/Commands/RunCommand.cs b/src/Microsoft.HttpRepl/Commands/RunCommand.cs index 6dd2f4a378..3228dbccf1 100644 --- a/src/Microsoft.HttpRepl/Commands/RunCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/RunCommand.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.IO; using System.Threading; diff --git a/src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs b/src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs index c346f541d4..77e5f0adde 100644 --- a/src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; diff --git a/src/Microsoft.HttpRepl/Commands/SetDiagCommand.cs b/src/Microsoft.HttpRepl/Commands/SetDiagCommand.cs index 4e86452b7c..535d1a2026 100644 --- a/src/Microsoft.HttpRepl/Commands/SetDiagCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/SetDiagCommand.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; diff --git a/src/Microsoft.HttpRepl/Commands/SetHeaderCommand.cs b/src/Microsoft.HttpRepl/Commands/SetHeaderCommand.cs index c95d22a6be..3db62f47b3 100644 --- a/src/Microsoft.HttpRepl/Commands/SetHeaderCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/SetHeaderCommand.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Linq; using System.Threading; diff --git a/src/Microsoft.HttpRepl/Commands/SetSwaggerCommand.cs b/src/Microsoft.HttpRepl/Commands/SetSwaggerCommand.cs index 9c9a1f36cc..be99891d5e 100644 --- a/src/Microsoft.HttpRepl/Commands/SetSwaggerCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/SetSwaggerCommand.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/src/Microsoft.HttpRepl/Commands/TreeNode.cs b/src/Microsoft.HttpRepl/Commands/TreeNode.cs index 256d5d9dae..1ae5db3cbc 100644 --- a/src/Microsoft.HttpRepl/Commands/TreeNode.cs +++ b/src/Microsoft.HttpRepl/Commands/TreeNode.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; namespace Microsoft.HttpRepl.Commands @@ -44,4 +47,4 @@ namespace Microsoft.HttpRepl.Commands return self + Environment.NewLine + string.Join(Environment.NewLine, _children); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.HttpRepl/Commands/UICommand.cs b/src/Microsoft.HttpRepl/Commands/UICommand.cs index ddf4ca4097..0eb02826f9 100644 --- a/src/Microsoft.HttpRepl/Commands/UICommand.cs +++ b/src/Microsoft.HttpRepl/Commands/UICommand.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; diff --git a/src/Microsoft.HttpRepl/Diagnostics/ConfigItem.cs b/src/Microsoft.HttpRepl/Diagnostics/ConfigItem.cs index ba16701d58..8e5c2943e4 100644 --- a/src/Microsoft.HttpRepl/Diagnostics/ConfigItem.cs +++ b/src/Microsoft.HttpRepl/Diagnostics/ConfigItem.cs @@ -1,4 +1,7 @@ -namespace Microsoft.HttpRepl.Diagnostics +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.HttpRepl.Diagnostics { public class ConfigItem { diff --git a/src/Microsoft.HttpRepl/Diagnostics/DiagEndpoint.cs b/src/Microsoft.HttpRepl/Diagnostics/DiagEndpoint.cs index 80e619dcc3..a38e50bada 100644 --- a/src/Microsoft.HttpRepl/Diagnostics/DiagEndpoint.cs +++ b/src/Microsoft.HttpRepl/Diagnostics/DiagEndpoint.cs @@ -1,4 +1,7 @@ -namespace Microsoft.HttpRepl.Diagnostics +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.HttpRepl.Diagnostics { public class DiagEndpoint { diff --git a/src/Microsoft.HttpRepl/Diagnostics/DiagEndpointMetadata.cs b/src/Microsoft.HttpRepl/Diagnostics/DiagEndpointMetadata.cs index 53e5aa3918..5989daf094 100644 --- a/src/Microsoft.HttpRepl/Diagnostics/DiagEndpointMetadata.cs +++ b/src/Microsoft.HttpRepl/Diagnostics/DiagEndpointMetadata.cs @@ -1,4 +1,7 @@ -namespace Microsoft.HttpRepl.Diagnostics +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.HttpRepl.Diagnostics { public class DiagEndpointMetadata { diff --git a/src/Microsoft.HttpRepl/Diagnostics/DiagItem.cs b/src/Microsoft.HttpRepl/Diagnostics/DiagItem.cs index c0fbf2df9c..a9d0692cfd 100644 --- a/src/Microsoft.HttpRepl/Diagnostics/DiagItem.cs +++ b/src/Microsoft.HttpRepl/Diagnostics/DiagItem.cs @@ -1,4 +1,7 @@ -namespace Microsoft.HttpRepl.Diagnostics +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.HttpRepl.Diagnostics { public class DiagItem { diff --git a/src/Microsoft.HttpRepl/Diagnostics/DiagnosticsState.cs b/src/Microsoft.HttpRepl/Diagnostics/DiagnosticsState.cs index 3fe27cce19..90033d9062 100644 --- a/src/Microsoft.HttpRepl/Diagnostics/DiagnosticsState.cs +++ b/src/Microsoft.HttpRepl/Diagnostics/DiagnosticsState.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; namespace Microsoft.HttpRepl.Diagnostics { diff --git a/src/Microsoft.HttpRepl/DirectoryStructure.cs b/src/Microsoft.HttpRepl/DirectoryStructure.cs index f682488b9b..8787f962fc 100644 --- a/src/Microsoft.HttpRepl/DirectoryStructure.cs +++ b/src/Microsoft.HttpRepl/DirectoryStructure.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Linq; diff --git a/src/Microsoft.HttpRepl/DirectoryStructureExtensions.cs b/src/Microsoft.HttpRepl/DirectoryStructureExtensions.cs index 2b7ad5341a..822fa41e6f 100644 --- a/src/Microsoft.HttpRepl/DirectoryStructureExtensions.cs +++ b/src/Microsoft.HttpRepl/DirectoryStructureExtensions.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; using System.Linq; namespace Microsoft.HttpRepl diff --git a/src/Microsoft.HttpRepl/Formatting/JsonVisitor.cs b/src/Microsoft.HttpRepl/Formatting/JsonVisitor.cs index fa40ee62ab..2538e2fdf2 100644 --- a/src/Microsoft.HttpRepl/Formatting/JsonVisitor.cs +++ b/src/Microsoft.HttpRepl/Formatting/JsonVisitor.cs @@ -1,4 +1,7 @@ -using System.IO; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; using System.Text; using Microsoft.HttpRepl.Preferences; using Microsoft.Repl.ConsoleHandling; diff --git a/src/Microsoft.HttpRepl/HttpState.cs b/src/Microsoft.HttpRepl/HttpState.cs index 55cfdd6188..d012a8fc45 100644 --- a/src/Microsoft.HttpRepl/HttpState.cs +++ b/src/Microsoft.HttpRepl/HttpState.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/src/Microsoft.HttpRepl/IDirectoryStructure.cs b/src/Microsoft.HttpRepl/IDirectoryStructure.cs index 5c02e8e476..e3641e3ca8 100644 --- a/src/Microsoft.HttpRepl/IDirectoryStructure.cs +++ b/src/Microsoft.HttpRepl/IDirectoryStructure.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; namespace Microsoft.HttpRepl { @@ -12,13 +15,4 @@ namespace Microsoft.HttpRepl IRequestInfo RequestInfo { get; } } - - public interface IRequestInfo - { - IReadOnlyDictionary> ContentTypesByMethod { get; } - - IReadOnlyList Methods { get; } - - string GetRequestBodyForContentType(string contentType, string method); - } } diff --git a/src/Microsoft.HttpRepl/IRequestInfo.cs b/src/Microsoft.HttpRepl/IRequestInfo.cs new file mode 100644 index 0000000000..24054f6142 --- /dev/null +++ b/src/Microsoft.HttpRepl/IRequestInfo.cs @@ -0,0 +1,16 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; + +namespace Microsoft.HttpRepl +{ + public interface IRequestInfo + { + IReadOnlyDictionary> ContentTypesByMethod { get; } + + IReadOnlyList Methods { get; } + + string GetRequestBodyForContentType(string contentType, string method); + } +} diff --git a/src/Microsoft.HttpRepl/OpenApi/Either.cs b/src/Microsoft.HttpRepl/OpenApi/Either.cs index f1e7dfacb3..8e3069de89 100644 --- a/src/Microsoft.HttpRepl/OpenApi/Either.cs +++ b/src/Microsoft.HttpRepl/OpenApi/Either.cs @@ -1,3 +1,6 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + namespace Microsoft.HttpRepl.OpenApi { public class Either @@ -30,4 +33,4 @@ namespace Microsoft.HttpRepl.OpenApi return new Either(value); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.HttpRepl/OpenApi/EitherConverter.cs b/src/Microsoft.HttpRepl/OpenApi/EitherConverter.cs index b89a85c9ef..a7197abc8b 100644 --- a/src/Microsoft.HttpRepl/OpenApi/EitherConverter.cs +++ b/src/Microsoft.HttpRepl/OpenApi/EitherConverter.cs @@ -1,3 +1,6 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + using System; using Newtonsoft.Json; @@ -29,4 +32,4 @@ namespace Microsoft.HttpRepl.OpenApi throw new NotImplementedException(); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.HttpRepl/OpenApi/EndpointMetadata.cs b/src/Microsoft.HttpRepl/OpenApi/EndpointMetadata.cs index e46387b3e0..27bb4d1b35 100644 --- a/src/Microsoft.HttpRepl/OpenApi/EndpointMetadata.cs +++ b/src/Microsoft.HttpRepl/OpenApi/EndpointMetadata.cs @@ -1,3 +1,6 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + using System.Collections.Generic; namespace Microsoft.HttpRepl.OpenApi @@ -14,4 +17,4 @@ namespace Microsoft.HttpRepl.OpenApi public IReadOnlyDictionary>> AvailableRequests { get; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.HttpRepl/OpenApi/EndpointMetadataReader.cs b/src/Microsoft.HttpRepl/OpenApi/EndpointMetadataReader.cs index 8635d6fbee..243b8fa92e 100644 --- a/src/Microsoft.HttpRepl/OpenApi/EndpointMetadataReader.cs +++ b/src/Microsoft.HttpRepl/OpenApi/EndpointMetadataReader.cs @@ -1,3 +1,6 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + using System.Collections.Generic; using Newtonsoft.Json.Linq; @@ -35,4 +38,4 @@ namespace Microsoft.HttpRepl.OpenApi return null; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.HttpRepl/OpenApi/IEndpointMetadataReader.cs b/src/Microsoft.HttpRepl/OpenApi/IEndpointMetadataReader.cs index 287740c7af..385f9dfce0 100644 --- a/src/Microsoft.HttpRepl/OpenApi/IEndpointMetadataReader.cs +++ b/src/Microsoft.HttpRepl/OpenApi/IEndpointMetadataReader.cs @@ -1,3 +1,6 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + using System.Collections.Generic; using Newtonsoft.Json.Linq; @@ -9,4 +12,4 @@ namespace Microsoft.HttpRepl.OpenApi IEnumerable ReadMetadata(JObject document); } -} \ No newline at end of file +} diff --git a/src/Microsoft.HttpRepl/OpenApi/OpenApiV3EndpointMetadataReader.cs b/src/Microsoft.HttpRepl/OpenApi/OpenApiV3EndpointMetadataReader.cs index 5fa968efc6..c009951608 100644 --- a/src/Microsoft.HttpRepl/OpenApi/OpenApiV3EndpointMetadataReader.cs +++ b/src/Microsoft.HttpRepl/OpenApi/OpenApiV3EndpointMetadataReader.cs @@ -1,3 +1,6 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + using System; using System.Collections.Generic; using System.Linq; @@ -95,4 +98,4 @@ namespace Microsoft.HttpRepl.OpenApi return metadata; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.HttpRepl/OpenApi/Parameter.cs b/src/Microsoft.HttpRepl/OpenApi/Parameter.cs index faf21e5f9a..0a44f489c5 100644 --- a/src/Microsoft.HttpRepl/OpenApi/Parameter.cs +++ b/src/Microsoft.HttpRepl/OpenApi/Parameter.cs @@ -1,3 +1,6 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + namespace Microsoft.HttpRepl.OpenApi { public class Parameter @@ -10,4 +13,4 @@ namespace Microsoft.HttpRepl.OpenApi public Schema Schema { get; set; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs b/src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs index b01730b116..db36c082bf 100644 --- a/src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs +++ b/src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs @@ -1,3 +1,6 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + using System; using System.Globalization; using System.Linq; @@ -215,4 +218,4 @@ namespace Microsoft.HttpRepl.OpenApi // return root; //} } -} \ No newline at end of file +} diff --git a/src/Microsoft.HttpRepl/OpenApi/Schema.cs b/src/Microsoft.HttpRepl/OpenApi/Schema.cs index 028c0b13ca..c84bbdda0f 100644 --- a/src/Microsoft.HttpRepl/OpenApi/Schema.cs +++ b/src/Microsoft.HttpRepl/OpenApi/Schema.cs @@ -1,3 +1,6 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; @@ -122,4 +125,4 @@ namespace Microsoft.HttpRepl.OpenApi public bool UniqueItems { get; set; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.HttpRepl/OpenApi/SwaggerV1EndpointMetadataReader.cs b/src/Microsoft.HttpRepl/OpenApi/SwaggerV1EndpointMetadataReader.cs index 7f4fef4fb1..d62fc8c3b1 100644 --- a/src/Microsoft.HttpRepl/OpenApi/SwaggerV1EndpointMetadataReader.cs +++ b/src/Microsoft.HttpRepl/OpenApi/SwaggerV1EndpointMetadataReader.cs @@ -1,3 +1,6 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + using System; using System.Collections.Generic; using System.Linq; @@ -103,4 +106,4 @@ namespace Microsoft.HttpRepl.OpenApi return metadata; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.HttpRepl/OpenApi/SwaggerV2EndpointMetadataReader.cs b/src/Microsoft.HttpRepl/OpenApi/SwaggerV2EndpointMetadataReader.cs index 5e7ecfe6aa..66b16d2ed5 100644 --- a/src/Microsoft.HttpRepl/OpenApi/SwaggerV2EndpointMetadataReader.cs +++ b/src/Microsoft.HttpRepl/OpenApi/SwaggerV2EndpointMetadataReader.cs @@ -1,3 +1,6 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + using System; using System.Collections.Generic; using System.Linq; @@ -84,4 +87,4 @@ namespace Microsoft.HttpRepl.OpenApi return metadata; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.HttpRepl/Preferences/IJsonConfig.cs b/src/Microsoft.HttpRepl/Preferences/IJsonConfig.cs index 21918e44ef..96d36ad7af 100644 --- a/src/Microsoft.HttpRepl/Preferences/IJsonConfig.cs +++ b/src/Microsoft.HttpRepl/Preferences/IJsonConfig.cs @@ -1,4 +1,7 @@ -using Microsoft.Repl.ConsoleHandling; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Repl.ConsoleHandling; namespace Microsoft.HttpRepl.Preferences { @@ -26,4 +29,4 @@ namespace Microsoft.HttpRepl.Preferences AllowedColors NullColor { get; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.HttpRepl/Preferences/JsonConfig.cs b/src/Microsoft.HttpRepl/Preferences/JsonConfig.cs index a1902e245e..67ce8aa2ed 100644 --- a/src/Microsoft.HttpRepl/Preferences/JsonConfig.cs +++ b/src/Microsoft.HttpRepl/Preferences/JsonConfig.cs @@ -1,4 +1,7 @@ -using Microsoft.Repl.ConsoleHandling; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Repl.ConsoleHandling; namespace Microsoft.HttpRepl.Preferences { diff --git a/src/Microsoft.HttpRepl/Preferences/RequestConfig.cs b/src/Microsoft.HttpRepl/Preferences/RequestConfig.cs index a3f9b55259..ae2b41e1fc 100644 --- a/src/Microsoft.HttpRepl/Preferences/RequestConfig.cs +++ b/src/Microsoft.HttpRepl/Preferences/RequestConfig.cs @@ -1,4 +1,7 @@ -using Microsoft.Repl.ConsoleHandling; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Repl.ConsoleHandling; namespace Microsoft.HttpRepl.Preferences { diff --git a/src/Microsoft.HttpRepl/Preferences/RequestOrResponseConfig.cs b/src/Microsoft.HttpRepl/Preferences/RequestOrResponseConfig.cs index c509a89f5e..c4385ad032 100644 --- a/src/Microsoft.HttpRepl/Preferences/RequestOrResponseConfig.cs +++ b/src/Microsoft.HttpRepl/Preferences/RequestOrResponseConfig.cs @@ -1,4 +1,7 @@ -using Microsoft.Repl.ConsoleHandling; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Repl.ConsoleHandling; namespace Microsoft.HttpRepl.Preferences { diff --git a/src/Microsoft.HttpRepl/Preferences/ResponseConfig.cs b/src/Microsoft.HttpRepl/Preferences/ResponseConfig.cs index 123a86ff79..d3a6c9c26f 100644 --- a/src/Microsoft.HttpRepl/Preferences/ResponseConfig.cs +++ b/src/Microsoft.HttpRepl/Preferences/ResponseConfig.cs @@ -1,4 +1,7 @@ -using Microsoft.Repl.ConsoleHandling; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Repl.ConsoleHandling; namespace Microsoft.HttpRepl.Preferences { diff --git a/src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs b/src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs index a6c16a6da7..1cd17a04ce 100644 --- a/src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs +++ b/src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Reflection; using Microsoft.Repl.ConsoleHandling; diff --git a/src/Microsoft.HttpRepl/Program.cs b/src/Microsoft.HttpRepl/Program.cs index f64fcf377a..a0e1c9addf 100644 --- a/src/Microsoft.HttpRepl/Program.cs +++ b/src/Microsoft.HttpRepl/Program.cs @@ -1,4 +1,7 @@ -using System.Threading; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading; using System.Threading.Tasks; using Microsoft.Repl; using Microsoft.Repl.Commanding; diff --git a/src/Microsoft.HttpRepl/Suggestions/HeaderCompletion.cs b/src/Microsoft.HttpRepl/Suggestions/HeaderCompletion.cs index 05372d7bec..74ceab2507 100644 --- a/src/Microsoft.HttpRepl/Suggestions/HeaderCompletion.cs +++ b/src/Microsoft.HttpRepl/Suggestions/HeaderCompletion.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Linq; diff --git a/src/Microsoft.HttpRepl/Suggestions/ServerPathCompletion.cs b/src/Microsoft.HttpRepl/Suggestions/ServerPathCompletion.cs index a50df8ae8d..2311b714b3 100644 --- a/src/Microsoft.HttpRepl/Suggestions/ServerPathCompletion.cs +++ b/src/Microsoft.HttpRepl/Suggestions/ServerPathCompletion.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Linq; diff --git a/src/Microsoft.Repl/Commanding/CommandHistory.cs b/src/Microsoft.Repl/Commanding/CommandHistory.cs index 83c7206a9d..27489df0d1 100644 --- a/src/Microsoft.Repl/Commanding/CommandHistory.cs +++ b/src/Microsoft.Repl/Commanding/CommandHistory.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; namespace Microsoft.Repl.Commanding diff --git a/src/Microsoft.Repl/Commanding/CommandInputLocation.cs b/src/Microsoft.Repl/Commanding/CommandInputLocation.cs index 1612384b61..e1ed19a50c 100644 --- a/src/Microsoft.Repl/Commanding/CommandInputLocation.cs +++ b/src/Microsoft.Repl/Commanding/CommandInputLocation.cs @@ -1,4 +1,7 @@ -namespace Microsoft.Repl.Commanding +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Repl.Commanding { public enum CommandInputLocation { @@ -7,4 +10,4 @@ OptionName, OptionValue } -} \ No newline at end of file +} diff --git a/src/Microsoft.Repl/Commanding/CommandInputProcessingIssue.cs b/src/Microsoft.Repl/Commanding/CommandInputProcessingIssue.cs index 501b4357da..f294718ff0 100644 --- a/src/Microsoft.Repl/Commanding/CommandInputProcessingIssue.cs +++ b/src/Microsoft.Repl/Commanding/CommandInputProcessingIssue.cs @@ -1,4 +1,7 @@ -namespace Microsoft.Repl.Commanding +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Repl.Commanding { public class CommandInputProcessingIssue { @@ -12,4 +15,4 @@ Text = text; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Repl/Commanding/CommandInputProcessingIssueKind.cs b/src/Microsoft.Repl/Commanding/CommandInputProcessingIssueKind.cs index cd69dccb85..dfc8a5f563 100644 --- a/src/Microsoft.Repl/Commanding/CommandInputProcessingIssueKind.cs +++ b/src/Microsoft.Repl/Commanding/CommandInputProcessingIssueKind.cs @@ -1,4 +1,7 @@ -namespace Microsoft.Repl.Commanding +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Repl.Commanding { public enum CommandInputProcessingIssueKind { @@ -8,4 +11,4 @@ OptionUseCountOutOfRange, MissingRequiredOptionInput, } -} \ No newline at end of file +} diff --git a/src/Microsoft.Repl/Commanding/CommandInputSpecification.cs b/src/Microsoft.Repl/Commanding/CommandInputSpecification.cs index 370b9f3d34..0e24c3fffa 100644 --- a/src/Microsoft.Repl/Commanding/CommandInputSpecification.cs +++ b/src/Microsoft.Repl/Commanding/CommandInputSpecification.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; namespace Microsoft.Repl.Commanding { @@ -41,4 +44,4 @@ namespace Microsoft.Repl.Commanding return new CommandInputSpecificationBuilder(nameParts); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Repl/Commanding/CommandInputSpecificationBuilder.cs b/src/Microsoft.Repl/Commanding/CommandInputSpecificationBuilder.cs index 5ad5edf345..019782d0b8 100644 --- a/src/Microsoft.Repl/Commanding/CommandInputSpecificationBuilder.cs +++ b/src/Microsoft.Repl/Commanding/CommandInputSpecificationBuilder.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; namespace Microsoft.Repl.Commanding { @@ -63,4 +66,4 @@ namespace Microsoft.Repl.Commanding return new CommandInputSpecification(_name, _optionPreamble, _options, _minimumArgs, _maximumArgs); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Repl/Commanding/CommandOptionSpecification.cs b/src/Microsoft.Repl/Commanding/CommandOptionSpecification.cs index d925e5b2c9..6f7e4469fe 100644 --- a/src/Microsoft.Repl/Commanding/CommandOptionSpecification.cs +++ b/src/Microsoft.Repl/Commanding/CommandOptionSpecification.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; namespace Microsoft.Repl.Commanding { @@ -26,4 +29,4 @@ namespace Microsoft.Repl.Commanding AcceptsValue = RequiresValue || acceptsValue; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Repl/Commanding/CommandWithStructuredInputBase.cs b/src/Microsoft.Repl/Commanding/CommandWithStructuredInputBase.cs index 38443486e8..1957205913 100644 --- a/src/Microsoft.Repl/Commanding/CommandWithStructuredInputBase.cs +++ b/src/Microsoft.Repl/Commanding/CommandWithStructuredInputBase.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -190,4 +193,4 @@ namespace Microsoft.Repl.Commanding protected abstract CommandInputSpecification InputSpec { get; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs b/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs index 932e8cdb1a..2b85c2bc57 100644 --- a/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs +++ b/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Linq; using System.Threading; diff --git a/src/Microsoft.Repl/Commanding/DefaultCommandInput.cs b/src/Microsoft.Repl/Commanding/DefaultCommandInput.cs index 0d3b97932e..ead59738b3 100644 --- a/src/Microsoft.Repl/Commanding/DefaultCommandInput.cs +++ b/src/Microsoft.Repl/Commanding/DefaultCommandInput.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Linq; using Microsoft.Repl.Parsing; @@ -190,4 +193,4 @@ namespace Microsoft.Repl.Commanding public IReadOnlyDictionary> Options { get; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Repl/Commanding/ICommand.cs b/src/Microsoft.Repl/Commanding/ICommand.cs index be575437e2..3b754924f0 100644 --- a/src/Microsoft.Repl/Commanding/ICommand.cs +++ b/src/Microsoft.Repl/Commanding/ICommand.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Microsoft.Repl.Parsing; diff --git a/src/Microsoft.Repl/Commanding/ICommandDispatcher.cs b/src/Microsoft.Repl/Commanding/ICommandDispatcher.cs index c175490833..d2d9000123 100644 --- a/src/Microsoft.Repl/Commanding/ICommandDispatcher.cs +++ b/src/Microsoft.Repl/Commanding/ICommandDispatcher.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Microsoft.Repl.Parsing; diff --git a/src/Microsoft.Repl/Commanding/ICommandHistory.cs b/src/Microsoft.Repl/Commanding/ICommandHistory.cs index 8e25db8906..cd506fb2b3 100644 --- a/src/Microsoft.Repl/Commanding/ICommandHistory.cs +++ b/src/Microsoft.Repl/Commanding/ICommandHistory.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; namespace Microsoft.Repl.Commanding { diff --git a/src/Microsoft.Repl/Commanding/InputElement.cs b/src/Microsoft.Repl/Commanding/InputElement.cs index c02c7f0f23..1f0c7cd764 100644 --- a/src/Microsoft.Repl/Commanding/InputElement.cs +++ b/src/Microsoft.Repl/Commanding/InputElement.cs @@ -1,4 +1,7 @@ -namespace Microsoft.Repl.Commanding +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Repl.Commanding { public class InputElement { @@ -26,4 +29,4 @@ ParseResultSectionIndex = sectionIndex; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Repl/ConsoleHandling/AllowedColors.cs b/src/Microsoft.Repl/ConsoleHandling/AllowedColors.cs index a71dc2c8a4..fd9245db28 100644 --- a/src/Microsoft.Repl/ConsoleHandling/AllowedColors.cs +++ b/src/Microsoft.Repl/ConsoleHandling/AllowedColors.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; namespace Microsoft.Repl.ConsoleHandling { @@ -24,4 +27,4 @@ namespace Microsoft.Repl.ConsoleHandling Bold = 0x100, None = 0x99 } -} \ No newline at end of file +} diff --git a/src/Microsoft.Repl/ConsoleHandling/AnsiColorExtensions.cs b/src/Microsoft.Repl/ConsoleHandling/AnsiColorExtensions.cs index cab5bc6f05..8d535bf15f 100644 --- a/src/Microsoft.Repl/ConsoleHandling/AnsiColorExtensions.cs +++ b/src/Microsoft.Repl/ConsoleHandling/AnsiColorExtensions.cs @@ -1,4 +1,7 @@ -namespace Microsoft.Repl.ConsoleHandling +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Repl.ConsoleHandling { public static class AnsiColorExtensions { diff --git a/src/Microsoft.Repl/ConsoleHandling/AnsiConsole.cs b/src/Microsoft.Repl/ConsoleHandling/AnsiConsole.cs index 24944f8871..205c7713b5 100644 --- a/src/Microsoft.Repl/ConsoleHandling/AnsiConsole.cs +++ b/src/Microsoft.Repl/ConsoleHandling/AnsiConsole.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.IO; namespace Microsoft.Repl.ConsoleHandling diff --git a/src/Microsoft.Repl/ConsoleHandling/ConsoleManager.cs b/src/Microsoft.Repl/ConsoleHandling/ConsoleManager.cs index a15c1fd420..ad4231ad5e 100644 --- a/src/Microsoft.Repl/ConsoleHandling/ConsoleManager.cs +++ b/src/Microsoft.Repl/ConsoleHandling/ConsoleManager.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Linq; using System.Threading; diff --git a/src/Microsoft.Repl/ConsoleHandling/IConsoleManager.cs b/src/Microsoft.Repl/ConsoleHandling/IConsoleManager.cs index 9ab7b26a15..ca93dbe88d 100644 --- a/src/Microsoft.Repl/ConsoleHandling/IConsoleManager.cs +++ b/src/Microsoft.Repl/ConsoleHandling/IConsoleManager.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Threading; namespace Microsoft.Repl.ConsoleHandling diff --git a/src/Microsoft.Repl/ConsoleHandling/IWritable.cs b/src/Microsoft.Repl/ConsoleHandling/IWritable.cs index f18fa123a1..fcb5441a69 100644 --- a/src/Microsoft.Repl/ConsoleHandling/IWritable.cs +++ b/src/Microsoft.Repl/ConsoleHandling/IWritable.cs @@ -1,4 +1,7 @@ -namespace Microsoft.Repl.ConsoleHandling +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Repl.ConsoleHandling { public interface IWritable { diff --git a/src/Microsoft.Repl/ConsoleHandling/Point.cs b/src/Microsoft.Repl/ConsoleHandling/Point.cs index 4eeb68989d..e705eada63 100644 --- a/src/Microsoft.Repl/ConsoleHandling/Point.cs +++ b/src/Microsoft.Repl/ConsoleHandling/Point.cs @@ -1,4 +1,7 @@ -namespace Microsoft.Repl.ConsoleHandling +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Repl.ConsoleHandling { public struct Point { diff --git a/src/Microsoft.Repl/ConsoleHandling/Reporter.cs b/src/Microsoft.Repl/ConsoleHandling/Reporter.cs index 5b10d2be02..a7da8d0060 100644 --- a/src/Microsoft.Repl/ConsoleHandling/Reporter.cs +++ b/src/Microsoft.Repl/ConsoleHandling/Reporter.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; namespace Microsoft.Repl.ConsoleHandling { diff --git a/src/Microsoft.Repl/ConsoleHandling/Writable.cs b/src/Microsoft.Repl/ConsoleHandling/Writable.cs index b12c2ad4e7..1b32e939f4 100644 --- a/src/Microsoft.Repl/ConsoleHandling/Writable.cs +++ b/src/Microsoft.Repl/ConsoleHandling/Writable.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; namespace Microsoft.Repl.ConsoleHandling { diff --git a/src/Microsoft.Repl/Disposable.cs b/src/Microsoft.Repl/Disposable.cs index 78002fb1d9..40b892ace1 100644 --- a/src/Microsoft.Repl/Disposable.cs +++ b/src/Microsoft.Repl/Disposable.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; namespace Microsoft.Repl { diff --git a/src/Microsoft.Repl/IShellState.cs b/src/Microsoft.Repl/IShellState.cs index 2ec1cb1514..1941fa65f9 100644 --- a/src/Microsoft.Repl/IShellState.cs +++ b/src/Microsoft.Repl/IShellState.cs @@ -1,4 +1,7 @@ -using Microsoft.Repl.Commanding; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Repl.Commanding; using Microsoft.Repl.ConsoleHandling; using Microsoft.Repl.Input; using Microsoft.Repl.Suggestions; diff --git a/src/Microsoft.Repl/Input/AsyncKeyPressHandler.cs b/src/Microsoft.Repl/Input/AsyncKeyPressHandler.cs index 616a749611..4ac3793979 100644 --- a/src/Microsoft.Repl/Input/AsyncKeyPressHandler.cs +++ b/src/Microsoft.Repl/Input/AsyncKeyPressHandler.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Threading; using System.Threading.Tasks; diff --git a/src/Microsoft.Repl/Input/IInputManager.cs b/src/Microsoft.Repl/Input/IInputManager.cs index 100dd22bea..b67f3e3936 100644 --- a/src/Microsoft.Repl/Input/IInputManager.cs +++ b/src/Microsoft.Repl/Input/IInputManager.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Threading; using System.Threading.Tasks; diff --git a/src/Microsoft.Repl/Input/InputManager.cs b/src/Microsoft.Repl/Input/InputManager.cs index a635ccd37a..e1d6055683 100644 --- a/src/Microsoft.Repl/Input/InputManager.cs +++ b/src/Microsoft.Repl/Input/InputManager.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; diff --git a/src/Microsoft.Repl/Input/KeyHandlers.cs b/src/Microsoft.Repl/Input/KeyHandlers.cs index 7b23f08769..192c55319c 100644 --- a/src/Microsoft.Repl/Input/KeyHandlers.cs +++ b/src/Microsoft.Repl/Input/KeyHandlers.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Threading; using System.Threading.Tasks; using Microsoft.Repl.Parsing; diff --git a/src/Microsoft.Repl/Parsing/CoreParseResult.cs b/src/Microsoft.Repl/Parsing/CoreParseResult.cs index 8f345813f6..1655e4a36a 100644 --- a/src/Microsoft.Repl/Parsing/CoreParseResult.cs +++ b/src/Microsoft.Repl/Parsing/CoreParseResult.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Linq; diff --git a/src/Microsoft.Repl/Parsing/CoreParser.cs b/src/Microsoft.Repl/Parsing/CoreParser.cs index 35be4867a5..7075f764a0 100644 --- a/src/Microsoft.Repl/Parsing/CoreParser.cs +++ b/src/Microsoft.Repl/Parsing/CoreParser.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; using System.Linq; namespace Microsoft.Repl.Parsing diff --git a/src/Microsoft.Repl/Parsing/ICoreParseResult.cs b/src/Microsoft.Repl/Parsing/ICoreParseResult.cs index 20ac2c7b4e..55bf5b2264 100644 --- a/src/Microsoft.Repl/Parsing/ICoreParseResult.cs +++ b/src/Microsoft.Repl/Parsing/ICoreParseResult.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; namespace Microsoft.Repl.Parsing { diff --git a/src/Microsoft.Repl/Parsing/IParser.cs b/src/Microsoft.Repl/Parsing/IParser.cs index c909f7d94f..86ce9ed940 100644 --- a/src/Microsoft.Repl/Parsing/IParser.cs +++ b/src/Microsoft.Repl/Parsing/IParser.cs @@ -1,4 +1,7 @@ -namespace Microsoft.Repl.Parsing +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Repl.Parsing { public interface IParser { diff --git a/src/Microsoft.Repl/Scripting/IScriptExecutor.cs b/src/Microsoft.Repl/Scripting/IScriptExecutor.cs index 7d832d8306..fcd5be2b53 100644 --- a/src/Microsoft.Repl/Scripting/IScriptExecutor.cs +++ b/src/Microsoft.Repl/Scripting/IScriptExecutor.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; diff --git a/src/Microsoft.Repl/Scripting/ScriptExecutor.cs b/src/Microsoft.Repl/Scripting/ScriptExecutor.cs index 3ec4bf5d21..6fafa6cbe4 100644 --- a/src/Microsoft.Repl/Scripting/ScriptExecutor.cs +++ b/src/Microsoft.Repl/Scripting/ScriptExecutor.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; diff --git a/src/Microsoft.Repl/Shell.cs b/src/Microsoft.Repl/Shell.cs index 49f450eae0..8d6cddb035 100644 --- a/src/Microsoft.Repl/Shell.cs +++ b/src/Microsoft.Repl/Shell.cs @@ -1,4 +1,7 @@ -using System.Threading; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading; using System.Threading.Tasks; using Microsoft.Repl.Commanding; using Microsoft.Repl.Input; diff --git a/src/Microsoft.Repl/ShellState.cs b/src/Microsoft.Repl/ShellState.cs index ef0ccf2a64..cb94bc63a2 100644 --- a/src/Microsoft.Repl/ShellState.cs +++ b/src/Microsoft.Repl/ShellState.cs @@ -1,4 +1,7 @@ -using Microsoft.Repl.Commanding; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Repl.Commanding; using Microsoft.Repl.ConsoleHandling; using Microsoft.Repl.Input; using Microsoft.Repl.Suggestions; diff --git a/src/Microsoft.Repl/Suggestions/FileSystemCompletion.cs b/src/Microsoft.Repl/Suggestions/FileSystemCompletion.cs index 71237fcd27..5b852a9b59 100644 --- a/src/Microsoft.Repl/Suggestions/FileSystemCompletion.cs +++ b/src/Microsoft.Repl/Suggestions/FileSystemCompletion.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/src/Microsoft.Repl/Suggestions/ISuggestionManager.cs b/src/Microsoft.Repl/Suggestions/ISuggestionManager.cs index f7e11a06fb..51e09c3a1c 100644 --- a/src/Microsoft.Repl/Suggestions/ISuggestionManager.cs +++ b/src/Microsoft.Repl/Suggestions/ISuggestionManager.cs @@ -1,4 +1,7 @@ -namespace Microsoft.Repl.Suggestions +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Repl.Suggestions { public interface ISuggestionManager { diff --git a/src/Microsoft.Repl/Suggestions/SuggestionManager.cs b/src/Microsoft.Repl/Suggestions/SuggestionManager.cs index 1fd9e861da..ba68ee9d46 100644 --- a/src/Microsoft.Repl/Suggestions/SuggestionManager.cs +++ b/src/Microsoft.Repl/Suggestions/SuggestionManager.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using Microsoft.Repl.Parsing; diff --git a/src/Microsoft.Repl/Utils.cs b/src/Microsoft.Repl/Utils.cs index 37ffcd97fb..eaf8160222 100644 --- a/src/Microsoft.Repl/Utils.cs +++ b/src/Microsoft.Repl/Utils.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; namespace Microsoft.Repl { From 7487da155f9272f46890d354be2dacf8912308c9 Mon Sep 17 00:00:00 2001 From: Mike Lorbetske Date: Wed, 1 Aug 2018 12:42:16 -0700 Subject: [PATCH 0886/1029] Switch signing certificate for Newtonsoft.JSON to Microsoft3rdPartyAppComponentDual --- src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj b/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj index cec7ac17d5..cf53e4b62e 100644 --- a/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj +++ b/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj @@ -23,8 +23,8 @@ - - + + From af5d8a824479f8a708447b8467e94b3282a75634 Mon Sep 17 00:00:00 2001 From: Mike Lorbetske Date: Fri, 3 Aug 2018 09:18:39 -0700 Subject: [PATCH 0887/1029] Address most code review comments Pagination hasn't been dealt with yet mac keybindings may be able to be simplified, pending some additional verification Fix 3rd party signing cert Bind a few common bash/zsh mappings Check for output redirection Make package version variable name consistent Add --help option for the command line Remove regions Remove old pointer resolution code Make command not found message more friendly Fix issue where base address was required for requests to absolute URIs Add options to suppress response formatting and streaming Turn off packing for the REPL project --- Directory.Build.props | 3 +- build/dependencies.props | 2 +- .../Commands/BaseHttpCommand.cs | 63 ++++++++-------- .../Commands/HelpCommand.cs | 23 +++--- .../Microsoft.HttpRepl.csproj | 4 +- src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs | 72 ------------------- .../Preferences/WellKnownPreference.cs | 2 - src/Microsoft.HttpRepl/Program.cs | 24 +++++++ .../Commanding/DefaultCommandDispatcher.cs | 1 + src/Microsoft.Repl/Input/IInputManager.cs | 2 + src/Microsoft.Repl/Input/InputManager.cs | 34 +++++++-- src/Microsoft.Repl/Input/KeyHandlers.cs | 6 ++ src/Microsoft.Repl/Microsoft.Repl.csproj | 1 + .../Microsoft.HttpRepl.Tests.csproj | 2 +- 14 files changed, 119 insertions(+), 120 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 8ca8a8757b..9921cb358e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,4 +1,4 @@ - + @@ -16,6 +16,7 @@ true MicrosoftNuGet Microsoft + Microsoft3rdPartyAppComponentDual true true diff --git a/build/dependencies.props b/build/dependencies.props index ee0b0b8ccf..bffcc722e2 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -17,7 +17,7 @@ 2.0.3 4.5.1 4.5.0 - 11.0.2 + 11.0.2 9.0.1 2.3.1 2.4.0 diff --git a/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs b/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs index 374544790b..ee9b4bcf0e 100644 --- a/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs @@ -31,6 +31,8 @@ namespace Microsoft.HttpRepl.Commands private const string ResponseFileOption = nameof(ResponseFileOption); private const string BodyFileOption = nameof(BodyFileOption); private const string NoBodyOption = nameof(NoBodyOption); + private const string NoFormattingOption = nameof(NoFormattingOption); + private const string NoStreamingOption = nameof(NoStreamingOption); private const string BodyContentOption = nameof(BodyContentOption); private static readonly char[] HeaderSeparatorChars = new[] { '=', ':' }; @@ -54,7 +56,9 @@ namespace Microsoft.HttpRepl.Commands .WithOption(new CommandOptionSpecification(HeaderOption, requiresValue: true, forms: new[] {"--header", "-h"})) .WithOption(new CommandOptionSpecification(ResponseFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] { "--response", })) .WithOption(new CommandOptionSpecification(ResponseHeadersFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] { "--response:headers", })) - .WithOption(new CommandOptionSpecification(ResponseBodyFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] { "--response:body", })); + .WithOption(new CommandOptionSpecification(ResponseBodyFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] { "--response:body", })) + .WithOption(new CommandOptionSpecification(NoFormattingOption, maximumOccurrences: 1, forms: new[] { "--no-formatting", "-F" })) + .WithOption(new CommandOptionSpecification(NoStreamingOption, maximumOccurrences: 1, forms: new[] { "--no-streaming", "-S" })); if (RequiresBody) { @@ -70,9 +74,9 @@ namespace Microsoft.HttpRepl.Commands protected override async Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) { - if (programState.BaseAddress == null) + if (programState.BaseAddress == null && (commandInput.Arguments.Count == 0 || !Uri.TryCreate(commandInput.Arguments[0].Text, UriKind.Absolute, out Uri _))) { - shellState.ConsoleManager.Error.WriteLine("'set base {url}' must be called before issuing requests".Bold().Red()); + shellState.ConsoleManager.Error.WriteLine("'set base {url}' must be called before issuing requests to a relative path".Bold().Red()); return; } @@ -203,10 +207,10 @@ namespace Microsoft.HttpRepl.Commands string bodyTarget = commandInput.Options[ResponseBodyFileOption].FirstOrDefault()?.Text ?? commandInput.Options[ResponseFileOption].FirstOrDefault()?.Text; HttpResponseMessage response = await programState.Client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - await HandleResponseAsync(programState, shellState.ConsoleManager, response, programState.EchoRequest, headersTarget, bodyTarget, cancellationToken).ConfigureAwait(false); + await HandleResponseAsync(programState, commandInput, shellState.ConsoleManager, response, programState.EchoRequest, headersTarget, bodyTarget, cancellationToken).ConfigureAwait(false); } - private static async Task HandleResponseAsync(HttpState programState, IConsoleManager consoleManager, HttpResponseMessage response, bool echoRequest, string headersTargetFile, string bodyTargetFile, CancellationToken cancellationToken) + private static async Task HandleResponseAsync(HttpState programState, DefaultCommandInput commandInput, IConsoleManager consoleManager, HttpResponseMessage response, bool echoRequest, string headersTargetFile, string bodyTargetFile, CancellationToken cancellationToken) { RequestConfig requestConfig = new RequestConfig(programState); ResponseConfig responseConfig = new ResponseConfig(programState); @@ -244,7 +248,7 @@ namespace Microsoft.HttpRepl.Commands { using (StreamWriter writer = new StreamWriter(new MemoryStream())) { - await FormatBodyAsync(programState, consoleManager, response.RequestMessage.Content, writer, cancellationToken).ConfigureAwait(false); + await FormatBodyAsync(commandInput, programState, consoleManager, response.RequestMessage.Content, writer, cancellationToken).ConfigureAwait(false); } } @@ -311,7 +315,7 @@ namespace Microsoft.HttpRepl.Commands if (response.Content != null) { - await FormatBodyAsync(programState, consoleManager, response.Content, bodyFileWriter, cancellationToken).ConfigureAwait(false); + await FormatBodyAsync(commandInput, programState, consoleManager, response.Content, bodyFileWriter, cancellationToken).ConfigureAwait(false); } bodyFileWriter.Flush(); @@ -321,7 +325,7 @@ namespace Microsoft.HttpRepl.Commands consoleManager.WriteLine(); } - private static async Task FormatBodyAsync(HttpState programState, IConsoleManager consoleManager, HttpContent content, StreamWriter bodyFileWriter, CancellationToken cancellationToken) + private static async Task FormatBodyAsync(DefaultCommandInput commandInput, HttpState programState, IConsoleManager consoleManager, HttpContent content, StreamWriter bodyFileWriter, CancellationToken cancellationToken) { string contentType = null; if (content.Headers.TryGetValues("Content-Type", out IEnumerable contentTypeValues)) @@ -331,33 +335,36 @@ namespace Microsoft.HttpRepl.Commands contentType = contentType?.ToUpperInvariant() ?? "text/plain"; - if (contentType.EndsWith("/JSON", StringComparison.OrdinalIgnoreCase) - || contentType.EndsWith("-JSON", StringComparison.OrdinalIgnoreCase) - || contentType.EndsWith("+JSON", StringComparison.OrdinalIgnoreCase) - || contentType.EndsWith("/JAVASCRIPT", StringComparison.OrdinalIgnoreCase) - || contentType.EndsWith("-JAVASCRIPT", StringComparison.OrdinalIgnoreCase) - || contentType.EndsWith("+JAVASCRIPT", StringComparison.OrdinalIgnoreCase)) + if (commandInput.Options[NoFormattingOption].Count == 0) { - if (await FormatJsonAsync(programState, consoleManager, content, bodyFileWriter)) + if (contentType.EndsWith("/JSON", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("-JSON", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("+JSON", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("/JAVASCRIPT", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("-JAVASCRIPT", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("+JAVASCRIPT", StringComparison.OrdinalIgnoreCase)) { - return; + if (await FormatJsonAsync(programState, consoleManager, content, bodyFileWriter)) + { + return; + } } - } - else if (contentType.EndsWith("/HTML", StringComparison.OrdinalIgnoreCase) - || contentType.EndsWith("-HTML", StringComparison.OrdinalIgnoreCase) - || contentType.EndsWith("+HTML", StringComparison.OrdinalIgnoreCase) - || contentType.EndsWith("/XML", StringComparison.OrdinalIgnoreCase) - || contentType.EndsWith("-XML", StringComparison.OrdinalIgnoreCase) - || contentType.EndsWith("+XML", StringComparison.OrdinalIgnoreCase)) - { - if (await FormatXmlAsync(consoleManager, content, bodyFileWriter)) + else if (contentType.EndsWith("/HTML", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("-HTML", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("+HTML", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("/XML", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("-XML", StringComparison.OrdinalIgnoreCase) + || contentType.EndsWith("+XML", StringComparison.OrdinalIgnoreCase)) { - return; + if (await FormatXmlAsync(consoleManager, content, bodyFileWriter)) + { + return; + } } } - //If we don't have content length, assume streaming - if (!content.Headers.TryGetValues("Content-Length", out IEnumerable _)) + //Unless the user has explicitly specified to not stream the response, if we don't have content length, assume streaming + if (commandInput.Options[NoStreamingOption].Count == 0 && !content.Headers.TryGetValues("Content-Length", out IEnumerable _)) { Memory buffer = new Memory(new char[2048]); Stream s = await content.ReadAsStreamAsync().ConfigureAwait(false); diff --git a/src/Microsoft.HttpRepl/Commands/HelpCommand.cs b/src/Microsoft.HttpRepl/Commands/HelpCommand.cs index f205fc1243..646dd4c544 100644 --- a/src/Microsoft.HttpRepl/Commands/HelpCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/HelpCommand.cs @@ -30,15 +30,7 @@ namespace Microsoft.HttpRepl.Commands { if (parseResult.Sections.Count == 1) { - foreach (ICommand command in dispatcher.Commands) - { - string help = command.GetHelpSummary(shellState, programState); - - if (!string.IsNullOrEmpty(help)) - { - shellState.ConsoleManager.WriteLine(help); - } - } + CoreGetHelp(shellState, dispatcher, programState); } else { @@ -171,5 +163,18 @@ namespace Microsoft.HttpRepl.Commands return null; } + + public void CoreGetHelp(IShellState shellState, ICommandDispatcher dispatcher, HttpState programState) + { + foreach (ICommand command in dispatcher.Commands) + { + string help = command.GetHelpSummary(shellState, programState); + + if (!string.IsNullOrEmpty(help)) + { + shellState.ConsoleManager.WriteLine(help); + } + } + } } } diff --git a/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj b/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj index cf53e4b62e..2dce88c68b 100644 --- a/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj +++ b/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj @@ -23,8 +23,8 @@ - - + + diff --git a/src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs b/src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs index db36c082bf..c8566095b7 100644 --- a/src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs +++ b/src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs @@ -145,77 +145,5 @@ namespace Microsoft.HttpRepl.OpenApi return toResolve; } - - //public static async Task ResolvePointerAsync(this JToken root, HttpClient client, string pointer) - //{ - // if (!pointer.StartsWith("#/", StringComparison.Ordinal)) - // { - // HttpResponseMessage response = await client.GetAsync(pointer).ConfigureAwait(false); - - // if (!response.IsSuccessStatusCode) - // { - // //TODO: Failed to resolve pointer message - // return new JValue((object)null); - // } - - // string responseString = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - - // try - // { - // root = JToken.Parse(responseString); - // int hashIndex = pointer.IndexOf("#"); - - // if (hashIndex < 0) - // { - // return root; - // } - - // pointer = pointer.Substring(hashIndex); - // } - // catch (Exception ex) - // { - // //TODO: Failed to deserialize pointer message - // return new JValue((object)null); - // } - // } - - // string[] pointerParts = pointer.Split('/'); - - // for (int i = 1; !(root is null) && i < pointerParts.Length; ++i) - // { - // if (root is JArray arr) - // { - // if (!int.TryParse(pointerParts[i], System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out int result) || result < 0 || result >= arr.Count) - // { - // //TODO: Failed to resolve pointer part message (non-integer index to array or index out of range) - // return null; - // } - - // root = arr[result]; - // } - // else if (root is JObject obj) - // { - // root = obj[pointerParts[i]]; - - // if (root is null) - // { - // //TODO: Failed to resolve pointer part message (no such path in object) - // } - - // JToken nestedRef = root["$ref"]; - // if (nestedRef is JValue value && value.Type == JTokenType.String) - // { - // root = await ResolvePointerAsync(root, ) - // } - // } - // else - // { - // //TODO: Failed to resolve pointer part message (pathing into literal) - // return null; - // } - // } - - // return root; - //} } } diff --git a/src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs b/src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs index 1cd17a04ce..424c0bb9a4 100644 --- a/src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs +++ b/src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs @@ -38,7 +38,6 @@ namespace Microsoft.HttpRepl.Preferences } } - #region JSON public static string JsonArrayBraceColor { get; } = "colors.json.arrayBrace"; public static string JsonObjectBraceColor { get; } = "colors.json.objectBrace"; @@ -66,7 +65,6 @@ namespace Microsoft.HttpRepl.Preferences public static string JsonSyntaxColor { get; } = "colors.json.syntax"; public static string JsonBraceColor { get; } = "colors.json.brace"; - #endregion JSON public static string RequestColor { get; } = "colors.request"; diff --git a/src/Microsoft.HttpRepl/Program.cs b/src/Microsoft.HttpRepl/Program.cs index a0e1c9addf..6509e7a38c 100644 --- a/src/Microsoft.HttpRepl/Program.cs +++ b/src/Microsoft.HttpRepl/Program.cs @@ -1,10 +1,12 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Threading; using System.Threading.Tasks; using Microsoft.Repl; using Microsoft.Repl.Commanding; +using Microsoft.Repl.ConsoleHandling; using Microsoft.Repl.Parsing; using Microsoft.HttpRepl.Commands; @@ -14,6 +16,12 @@ namespace Microsoft.HttpRepl { static async Task Main(string[] args) { + if(Console.IsOutputRedirected) + { + Reporter.Error.WriteLine("Cannot start the REPL when output is being redirected".Bold().Red()); + return; + } + var state = new HttpState(); var dispatcher = DefaultCommandDispatcher.Create(state.GetPrompt, state); @@ -44,6 +52,22 @@ namespace Microsoft.HttpRepl shell.ShellState.ConsoleManager.AddBreakHandler(() => source.Cancel()); if (args.Length > 0) { + if (string.Equals(args[0], "--help", StringComparison.OrdinalIgnoreCase)) + { + shell.ShellState.ConsoleManager.WriteLine("Usage: dotnet httprepl [] [options]"); + shell.ShellState.ConsoleManager.WriteLine(); + shell.ShellState.ConsoleManager.WriteLine("Arguments:"); + shell.ShellState.ConsoleManager.WriteLine(" - The initial base address for the REPL."); + shell.ShellState.ConsoleManager.WriteLine(); + shell.ShellState.ConsoleManager.WriteLine("Options:"); + shell.ShellState.ConsoleManager.WriteLine(" --help - Show help information."); + + shell.ShellState.ConsoleManager.WriteLine(); + shell.ShellState.ConsoleManager.WriteLine("REPL Commands:"); + new HelpCommand().CoreGetHelp(shell.ShellState, (ICommandDispatcher)shell.ShellState.CommandDispatcher, state); + return; + } + shell.ShellState.CommandDispatcher.OnReady(shell.ShellState); shell.ShellState.InputManager.SetInput(shell.ShellState, $"set base \"{args[0]}\""); await shell.ShellState.CommandDispatcher.ExecuteCommandAsync(shell.ShellState, CancellationToken.None).ConfigureAwait(false); diff --git a/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs b/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs index 2b85c2bc57..22be314827 100644 --- a/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs +++ b/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs @@ -156,6 +156,7 @@ namespace Microsoft.Repl.Commanding } shellState.ConsoleManager.Error.WriteLine("No matching command found".Red().Bold()); + shellState.ConsoleManager.Error.WriteLine("Execute 'help' to se available commands".Red().Bold()); } } diff --git a/src/Microsoft.Repl/Input/IInputManager.cs b/src/Microsoft.Repl/Input/IInputManager.cs index b67f3e3936..e8e98b2d54 100644 --- a/src/Microsoft.Repl/Input/IInputManager.cs +++ b/src/Microsoft.Repl/Input/IInputManager.cs @@ -13,6 +13,8 @@ namespace Microsoft.Repl.Input IInputManager RegisterKeyHandler(ConsoleKey key, AsyncKeyPressHandler handler); + IInputManager RegisterKeyHandler(ConsoleKey key, ConsoleModifiers modifiers, AsyncKeyPressHandler handler); + void ResetInput(); Task StartAsync(IShellState state, CancellationToken cancellationToken); diff --git a/src/Microsoft.Repl/Input/InputManager.cs b/src/Microsoft.Repl/Input/InputManager.cs index e1d6055683..cd1157c6ff 100644 --- a/src/Microsoft.Repl/Input/InputManager.cs +++ b/src/Microsoft.Repl/Input/InputManager.cs @@ -12,7 +12,7 @@ namespace Microsoft.Repl.Input { public class InputManager : IInputManager { - private readonly Dictionary _handlers = new Dictionary(); + private readonly Dictionary> _handlers = new Dictionary>(); private readonly List _inputBuffer = new List(); public bool IsOverwriteMode { get; set; } @@ -29,13 +29,37 @@ namespace Microsoft.Repl.Input public IInputManager RegisterKeyHandler(ConsoleKey key, AsyncKeyPressHandler handler) { + if (!_handlers.TryGetValue(key, out Dictionary handlers)) + { + _handlers[key] = handlers = new Dictionary(); + } + if (handler == null) { - _handlers.Remove(key); + handlers.Remove(default(ConsoleModifiers)); } else { - _handlers[key] = handler; + handlers[default(ConsoleModifiers)] = handler; + } + + return this; + } + + public IInputManager RegisterKeyHandler(ConsoleKey key, ConsoleModifiers modifiers, AsyncKeyPressHandler handler) + { + if (!_handlers.TryGetValue(key, out Dictionary handlers)) + { + _handlers[key] = handlers = new Dictionary(); + } + + if (handler == null) + { + handlers.Remove(modifiers); + } + else + { + handlers[modifiers] = handler; } return this; @@ -169,7 +193,7 @@ namespace Microsoft.Repl.Input { ConsoleKeyInfo keyPress = state.ConsoleManager.ReadKey(cancellationToken); - if (_handlers.TryGetValue(keyPress.Key, out AsyncKeyPressHandler handler)) + if (_handlers.TryGetValue(keyPress.Key, out Dictionary handlerLookup) && handlerLookup.TryGetValue(keyPress.Modifiers, out AsyncKeyPressHandler handler)) { using (CancellationTokenSource source = new CancellationTokenSource()) using (state.ConsoleManager.AddBreakHandler(() => source.Cancel())) @@ -189,6 +213,7 @@ namespace Microsoft.Repl.Input FlushInput(state, ref presses); } + //TODO: Verify on a mac whether these are still needed if (keyPress.Key == ConsoleKey.A) { state.ConsoleManager.MoveCaret(-state.ConsoleManager.CaretPosition); @@ -198,6 +223,7 @@ namespace Microsoft.Repl.Input state.ConsoleManager.MoveCaret(_inputBuffer.Count - state.ConsoleManager.CaretPosition); } } + //TODO: Register these like regular commands else if (!string.IsNullOrEmpty(_ttyState) && keyPress.Modifiers == ConsoleModifiers.Alt) { if (presses != null) diff --git a/src/Microsoft.Repl/Input/KeyHandlers.cs b/src/Microsoft.Repl/Input/KeyHandlers.cs index 192c55319c..750db8d2f6 100644 --- a/src/Microsoft.Repl/Input/KeyHandlers.cs +++ b/src/Microsoft.Repl/Input/KeyHandlers.cs @@ -14,9 +14,13 @@ namespace Microsoft.Repl.Input { //Navigation in line inputManager.RegisterKeyHandler(ConsoleKey.LeftArrow, LeftArrow); + inputManager.RegisterKeyHandler(ConsoleKey.LeftArrow, ConsoleModifiers.Control, LeftArrow); inputManager.RegisterKeyHandler(ConsoleKey.RightArrow, RightArrow); + inputManager.RegisterKeyHandler(ConsoleKey.RightArrow, ConsoleModifiers.Control, RightArrow); inputManager.RegisterKeyHandler(ConsoleKey.Home, Home); + inputManager.RegisterKeyHandler(ConsoleKey.A, ConsoleModifiers.Control, Home); inputManager.RegisterKeyHandler(ConsoleKey.End, End); + inputManager.RegisterKeyHandler(ConsoleKey.E, ConsoleModifiers.Control, End); //Command history inputManager.RegisterKeyHandler(ConsoleKey.UpArrow, UpArrow); @@ -24,9 +28,11 @@ namespace Microsoft.Repl.Input //Completion inputManager.RegisterKeyHandler(ConsoleKey.Tab, Tab); + inputManager.RegisterKeyHandler(ConsoleKey.Tab, ConsoleModifiers.Shift, Tab); //Input manipulation inputManager.RegisterKeyHandler(ConsoleKey.Escape, Escape); + inputManager.RegisterKeyHandler(ConsoleKey.U, ConsoleModifiers.Control, Escape); inputManager.RegisterKeyHandler(ConsoleKey.Delete, Delete); inputManager.RegisterKeyHandler(ConsoleKey.Backspace, Backspace); diff --git a/src/Microsoft.Repl/Microsoft.Repl.csproj b/src/Microsoft.Repl/Microsoft.Repl.csproj index 63af949be4..cb7311eeeb 100644 --- a/src/Microsoft.Repl/Microsoft.Repl.csproj +++ b/src/Microsoft.Repl/Microsoft.Repl.csproj @@ -4,6 +4,7 @@ netcoreapp2.2 A framework for creating REPLs in .NET Core. dotnet;repl + false diff --git a/test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj b/test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj index 7a79d0121e..a50dd1df30 100644 --- a/test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj +++ b/test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj @@ -10,7 +10,7 @@ - + From 8a9b407761436362c16b1de2b6d00e324273a6b9 Mon Sep 17 00:00:00 2001 From: Mike Lorbetske Date: Fri, 3 Aug 2018 12:27:02 -0700 Subject: [PATCH 0888/1029] Use netcoreapp2.1 instead of 2.2 --- src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj | 4 ++-- src/Microsoft.Repl/Microsoft.Repl.csproj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj b/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj index 2dce88c68b..99b86075c3 100644 --- a/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj +++ b/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj @@ -1,8 +1,8 @@ - + Exe - netcoreapp2.2 + netcoreapp2.1 true dotnet-httprepl latest diff --git a/src/Microsoft.Repl/Microsoft.Repl.csproj b/src/Microsoft.Repl/Microsoft.Repl.csproj index cb7311eeeb..d6cc6e83e6 100644 --- a/src/Microsoft.Repl/Microsoft.Repl.csproj +++ b/src/Microsoft.Repl/Microsoft.Repl.csproj @@ -1,7 +1,7 @@ - + - netcoreapp2.2 + netcoreapp2.1 A framework for creating REPLs in .NET Core. dotnet;repl false From 43c74cfa5360be63faaaf361e5d4385e2796e138 Mon Sep 17 00:00:00 2001 From: Mike Lorbetske Date: Fri, 3 Aug 2018 20:58:07 -0700 Subject: [PATCH 0889/1029] Respond to much of the feedback from review Default to requerying swagger for each exec Auto-set the content-type if not yet set for requests based on swagger Fix swagger UI command Make error and warning colors configurable Allow aliases to be specified in structured input based commands Have delete not require a body Show allowed methods for . and .. Show verbs on the announced path after CD Issue a request on set base and warn if there's a socket error --- .../Commands/BaseHttpCommand.cs | 98 ++++++++++--------- .../Commands/ChangeDirectoryCommand.cs | 8 +- .../Commands/ConfigCommand.cs | 8 +- .../Commands/DeleteCommand.cs | 2 +- .../Commands/EchoCommand.cs | 2 +- .../Commands/HelpCommand.cs | 16 ++- .../Commands/ListCommand.cs | 33 +++++-- .../Commands/PrefCommand.cs | 4 +- .../Commands/SetBaseCommand.cs | 13 ++- .../Commands/SetDiagCommand.cs | 6 +- .../Commands/SetSwaggerCommand.cs | 4 +- src/Microsoft.HttpRepl/Commands/UICommand.cs | 4 +- src/Microsoft.HttpRepl/HttpState.cs | 7 ++ .../Preferences/WellKnownPreference.cs | 7 +- src/Microsoft.HttpRepl/Program.cs | 8 +- .../Commanding/CommandInputSpecification.cs | 4 +- .../CommandInputSpecificationBuilder.cs | 13 ++- .../CommandWithStructuredInputBase.cs | 27 ++++- .../Commanding/DefaultCommandInput.cs | 54 +++++++--- 19 files changed, 219 insertions(+), 99 deletions(-) diff --git a/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs b/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs index ee9b4bcf0e..9a5eba8227 100644 --- a/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs @@ -32,7 +32,7 @@ namespace Microsoft.HttpRepl.Commands private const string BodyFileOption = nameof(BodyFileOption); private const string NoBodyOption = nameof(NoBodyOption); private const string NoFormattingOption = nameof(NoFormattingOption); - private const string NoStreamingOption = nameof(NoStreamingOption); + private const string StreamingOption = nameof(StreamingOption); private const string BodyContentOption = nameof(BodyContentOption); private static readonly char[] HeaderSeparatorChars = new[] { '=', ':' }; @@ -58,7 +58,7 @@ namespace Microsoft.HttpRepl.Commands .WithOption(new CommandOptionSpecification(ResponseHeadersFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] { "--response:headers", })) .WithOption(new CommandOptionSpecification(ResponseBodyFileOption, requiresValue: true, maximumOccurrences: 1, forms: new[] { "--response:body", })) .WithOption(new CommandOptionSpecification(NoFormattingOption, maximumOccurrences: 1, forms: new[] { "--no-formatting", "-F" })) - .WithOption(new CommandOptionSpecification(NoStreamingOption, maximumOccurrences: 1, forms: new[] { "--no-streaming", "-S" })); + .WithOption(new CommandOptionSpecification(StreamingOption, maximumOccurrences: 1, forms: new[] { "--streaming", "-s" })); if (RequiresBody) { @@ -76,10 +76,20 @@ namespace Microsoft.HttpRepl.Commands { if (programState.BaseAddress == null && (commandInput.Arguments.Count == 0 || !Uri.TryCreate(commandInput.Arguments[0].Text, UriKind.Absolute, out Uri _))) { - shellState.ConsoleManager.Error.WriteLine("'set base {url}' must be called before issuing requests to a relative path".Bold().Red()); + shellState.ConsoleManager.Error.WriteLine("'set base {url}' must be called before issuing requests to a relative path".SetColor(programState.ErrorColor)); return; } + if (programState.SwaggerEndpoint != null) + { + string swaggerRequeryBehaviorSetting = programState.GetStringPreference(WellKnownPreference.SwaggerRequeryBehavior, "auto"); + + if (swaggerRequeryBehaviorSetting.StartsWith("auto", StringComparison.OrdinalIgnoreCase)) + { + await SetSwaggerCommand.CreateDirectoryStructureForSwaggerEndpointAsync(shellState, programState, programState.SwaggerEndpoint, cancellationToken).ConfigureAwait(false); + } + } + Dictionary thisRequestHeaders = new Dictionary(); foreach (InputElement header in commandInput.Options[HeaderOption]) @@ -88,7 +98,7 @@ namespace Microsoft.HttpRepl.Commands if (equalsIndex < 0) { - shellState.ConsoleManager.Error.WriteLine("Headers must be formatted as {header}={value} or {header}:{value}".Bold().Red()); + shellState.ConsoleManager.Error.WriteLine("Headers must be formatted as {header}={value} or {header}:{value}".SetColor(programState.ErrorColor)); return; } @@ -114,7 +124,7 @@ namespace Microsoft.HttpRepl.Commands if (!File.Exists(filePath)) { - shellState.ConsoleManager.Error.WriteLine($"Content file {filePath} does not exist".Bold().Red()); + shellState.ConsoleManager.Error.WriteLine($"Content file {filePath} does not exist".SetColor(programState.ErrorColor)); return; } } @@ -127,7 +137,7 @@ namespace Microsoft.HttpRepl.Commands string defaultEditorCommand = programState.GetStringPreference(WellKnownPreference.DefaultEditorCommand); if (defaultEditorCommand == null) { - shellState.ConsoleManager.Error.WriteLine($"The default editor must be configured using the command `pref set {WellKnownPreference.DefaultEditorCommand} \"{{commandline}}\"`".Bold().Red()); + shellState.ConsoleManager.Error.WriteLine($"The default editor must be configured using the command `pref set {WellKnownPreference.DefaultEditorCommand} \"{{commandline}}\"`".SetColor(programState.ErrorColor)); return; } @@ -145,6 +155,7 @@ namespace Microsoft.HttpRepl.Commands } string exampleBody = programState.GetExampleBody(commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty, contentType, Verb); + request.Headers.TryAddWithoutValidation("Content-Type", contentType); if (!string.IsNullOrEmpty(exampleBody)) { @@ -224,7 +235,7 @@ namespace Microsoft.HttpRepl.Commands string method = response.RequestMessage.Method.ToString().ToUpperInvariant().SetColor(requestConfig.MethodColor); string pathAndQuery = response.RequestMessage.RequestUri.PathAndQuery.SetColor(requestConfig.AddressColor); - protocolInfo = $"{"HTTP".SetColor(requestConfig.ProtocolNameColor)}{"/".SetColor(requestConfig.ProtocolSeparatorColor)}{response.RequestMessage.Version.ToString().SetColor(requestConfig.ProtocolVersionColor)}"; + protocolInfo = $"{"HTTP".SetColor(requestConfig.ProtocolNameColor)}{"/".SetColor(requestConfig.ProtocolSeparatorColor)}{response.Version.ToString().SetColor(requestConfig.ProtocolVersionColor)}"; consoleManager.WriteLine($"{method} {pathAndQuery} {protocolInfo}"); IEnumerable>> requestHeaders = response.RequestMessage.Headers; @@ -327,6 +338,42 @@ namespace Microsoft.HttpRepl.Commands private static async Task FormatBodyAsync(DefaultCommandInput commandInput, HttpState programState, IConsoleManager consoleManager, HttpContent content, StreamWriter bodyFileWriter, CancellationToken cancellationToken) { + if (commandInput.Options[StreamingOption].Count > 0) + { + Memory buffer = new Memory(new char[2048]); + Stream s = await content.ReadAsStreamAsync().ConfigureAwait(false); + StreamReader reader = new StreamReader(s); + consoleManager.WriteLine("Streaming the response, press any key to stop...".SetColor(programState.WarningColor)); + + while (!cancellationToken.IsCancellationRequested) + { + try + { + ValueTask readTask = reader.ReadAsync(buffer, cancellationToken); + if (await WaitForCompletionAsync(readTask, cancellationToken).ConfigureAwait(false)) + { + if (readTask.Result == 0) + { + break; + } + + string str = new string(buffer.Span.Slice(0, readTask.Result)); + consoleManager.Write(str); + bodyFileWriter.Write(str); + } + else + { + break; + } + } + catch (OperationCanceledException) + { + } + } + + return; + } + string contentType = null; if (content.Headers.TryGetValues("Content-Type", out IEnumerable contentTypeValues)) { @@ -363,43 +410,6 @@ namespace Microsoft.HttpRepl.Commands } } - //Unless the user has explicitly specified to not stream the response, if we don't have content length, assume streaming - if (commandInput.Options[NoStreamingOption].Count == 0 && !content.Headers.TryGetValues("Content-Length", out IEnumerable _)) - { - Memory buffer = new Memory(new char[2048]); - Stream s = await content.ReadAsStreamAsync().ConfigureAwait(false); - StreamReader reader = new StreamReader(s); - consoleManager.WriteLine("Streaming the response, press any key to stop...".Bold().Yellow()); - - while (!cancellationToken.IsCancellationRequested) - { - try - { - ValueTask readTask = reader.ReadAsync(buffer, cancellationToken); - if (await WaitForCompletionAsync(readTask, cancellationToken).ConfigureAwait(false)) - { - if (readTask.Result == 0) - { - break; - } - - string str = new string(buffer.Span.Slice(0, readTask.Result)); - consoleManager.Write(str); - bodyFileWriter.Write(str); - } - else - { - break; - } - } - catch (OperationCanceledException) - { - } - } - - return; - } - string responseContent = await content.ReadAsStringAsync().ConfigureAwait(false); bodyFileWriter.WriteLine(responseContent); consoleManager.WriteLine(responseContent); diff --git a/src/Microsoft.HttpRepl/Commands/ChangeDirectoryCommand.cs b/src/Microsoft.HttpRepl/Commands/ChangeDirectoryCommand.cs index c2baaf0de5..a18aa2df9f 100644 --- a/src/Microsoft.HttpRepl/Commands/ChangeDirectoryCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/ChangeDirectoryCommand.cs @@ -48,7 +48,13 @@ namespace Microsoft.HttpRepl.Commands } } - shellState.ConsoleManager.WriteLine($"/{string.Join("/", programState.PathSections.Reverse())}"); + IDirectoryStructure s = programState.Structure.TraverseTo(programState.PathSections.Reverse()); + + string thisDirMethod = s.RequestInfo != null && s.RequestInfo.Methods.Count > 0 + ? "[" + string.Join("|", s.RequestInfo.Methods) + "]" + : "[]"; + + shellState.ConsoleManager.WriteLine($"/{string.Join("/", programState.PathSections.Reverse())} {thisDirMethod}"); } return Task.CompletedTask; diff --git a/src/Microsoft.HttpRepl/Commands/ConfigCommand.cs b/src/Microsoft.HttpRepl/Commands/ConfigCommand.cs index 773bee0f04..938936303f 100644 --- a/src/Microsoft.HttpRepl/Commands/ConfigCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/ConfigCommand.cs @@ -21,13 +21,13 @@ namespace Microsoft.HttpRepl.Commands { if (programState.BaseAddress == null) { - shellState.ConsoleManager.Error.WriteLine("Must be connected to a server to query configuration".Bold().Red()); + shellState.ConsoleManager.Error.WriteLine("Must be connected to a server to query configuration".SetColor(programState.ErrorColor)); return; } if (string.IsNullOrEmpty(programState.DiagnosticsState.DiagnosticsEndpoint)) { - shellState.ConsoleManager.Error.WriteLine("Diagnostics endpoint must be set to query configuration (see set diag)".Bold().Red()); + shellState.ConsoleManager.Error.WriteLine("Diagnostics endpoint must be set to query configuration (see set diag)".SetColor(programState.ErrorColor)); return; } @@ -35,7 +35,7 @@ namespace Microsoft.HttpRepl.Commands if (configUrl == null) { - shellState.ConsoleManager.Error.WriteLine("Diagnostics endpoint does not expose configuration information".Bold().Red()); + shellState.ConsoleManager.Error.WriteLine("Diagnostics endpoint does not expose configuration information".SetColor(programState.ErrorColor)); return; } @@ -43,7 +43,7 @@ namespace Microsoft.HttpRepl.Commands if (!response.IsSuccessStatusCode) { - shellState.ConsoleManager.Error.WriteLine("Unable to get configuration information from diagnostics endpoint".Bold().Red()); + shellState.ConsoleManager.Error.WriteLine("Unable to get configuration information from diagnostics endpoint".SetColor(programState.ErrorColor)); return; } diff --git a/src/Microsoft.HttpRepl/Commands/DeleteCommand.cs b/src/Microsoft.HttpRepl/Commands/DeleteCommand.cs index 7c9b789db3..aedef544c0 100644 --- a/src/Microsoft.HttpRepl/Commands/DeleteCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/DeleteCommand.cs @@ -7,6 +7,6 @@ namespace Microsoft.HttpRepl.Commands { protected override string Verb => "delete"; - protected override bool RequiresBody => true; + protected override bool RequiresBody => false; } } diff --git a/src/Microsoft.HttpRepl/Commands/EchoCommand.cs b/src/Microsoft.HttpRepl/Commands/EchoCommand.cs index 691eb5679f..e81ff810d4 100644 --- a/src/Microsoft.HttpRepl/Commands/EchoCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/EchoCommand.cs @@ -21,7 +21,7 @@ namespace Microsoft.HttpRepl.Commands { if (commandInput.Arguments.Count == 0 || !_allowedModes.Contains(commandInput.Arguments[0]?.Text)) { - shellState.ConsoleManager.Error.WriteLine("Allowed echo modes are 'on' and 'off'".Bold().Red()); + shellState.ConsoleManager.Error.WriteLine("Allowed echo modes are 'on' and 'off'".SetColor(programState.ErrorColor)); return false; } diff --git a/src/Microsoft.HttpRepl/Commands/HelpCommand.cs b/src/Microsoft.HttpRepl/Commands/HelpCommand.cs index 646dd4c544..6677bde928 100644 --- a/src/Microsoft.HttpRepl/Commands/HelpCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/HelpCommand.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.HttpRepl.Preferences; using Microsoft.HttpRepl.Suggestions; using Microsoft.Repl; using Microsoft.Repl.Commanding; @@ -24,7 +25,7 @@ namespace Microsoft.HttpRepl.Commands : null; } - public Task ExecuteAsync(IShellState shellState, HttpState programState, ICoreParseResult parseResult, CancellationToken cancellationToken) + public async Task ExecuteAsync(IShellState shellState, HttpState programState, ICoreParseResult parseResult, CancellationToken cancellationToken) { if (shellState.CommandDispatcher is ICommandDispatcher dispatcher) { @@ -55,6 +56,17 @@ namespace Microsoft.HttpRepl.Commands //Maybe the input is an URL if (parseResult.Sections.Count == 2) { + + if (programState.SwaggerEndpoint != null) + { + string swaggerRequeryBehaviorSetting = programState.GetStringPreference(WellKnownPreference.SwaggerRequeryBehavior, "auto"); + + if (swaggerRequeryBehaviorSetting.StartsWith("auto", StringComparison.OrdinalIgnoreCase)) + { + await SetSwaggerCommand.CreateDirectoryStructureForSwaggerEndpointAsync(shellState, programState, programState.SwaggerEndpoint, cancellationToken).ConfigureAwait(false); + } + } + IDirectoryStructure structure = programState.Structure.TraverseTo(parseResult.Sections[1]); if (structure.DirectoryNames.Any()) { @@ -101,8 +113,6 @@ namespace Microsoft.HttpRepl.Commands } } } - - return Task.CompletedTask; } public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult) diff --git a/src/Microsoft.HttpRepl/Commands/ListCommand.cs b/src/Microsoft.HttpRepl/Commands/ListCommand.cs index b1aa0718a3..b0641f186b 100644 --- a/src/Microsoft.HttpRepl/Commands/ListCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/ListCommand.cs @@ -7,6 +7,7 @@ using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.HttpRepl.Preferences; using Microsoft.Repl; using Microsoft.Repl.Commanding; using Microsoft.Repl.Parsing; @@ -17,11 +18,21 @@ namespace Microsoft.HttpRepl.Commands { private const string RecursiveOption = nameof(RecursiveOption); - protected override Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) + protected override async Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) { + if (programState.SwaggerEndpoint != null) + { + string swaggerRequeryBehaviorSetting = programState.GetStringPreference(WellKnownPreference.SwaggerRequeryBehavior, "auto"); + + if (swaggerRequeryBehaviorSetting.StartsWith("auto", StringComparison.OrdinalIgnoreCase)) + { + await SetSwaggerCommand.CreateDirectoryStructureForSwaggerEndpointAsync(shellState, programState, programState.SwaggerEndpoint, cancellationToken).ConfigureAwait(false); + } + } + if (programState.Structure == null || programState.BaseAddress == null) { - return Task.CompletedTask; + return; } string path = commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty; @@ -29,19 +40,27 @@ namespace Microsoft.HttpRepl.Commands //If it's an absolute URI, nothing to suggest if (Uri.TryCreate(path, UriKind.Absolute, out Uri _)) { - return Task.CompletedTask; + return; } IDirectoryStructure s = programState.Structure.TraverseTo(programState.PathSections.Reverse()).TraverseTo(path); + string thisDirMethod = s.RequestInfo != null && s.RequestInfo.Methods.Count > 0 + ? "[" + string.Join("|", s.RequestInfo.Methods) + "]" + : "[]"; + List roots = new List(); Formatter formatter = new Formatter(); - roots.Add(new TreeNode(formatter, ".", string.Empty)); + roots.Add(new TreeNode(formatter, ".", thisDirMethod)); if (s.Parent != null) { - roots.Add(new TreeNode(formatter, "..", string.Empty)); + string parentDirMethod = s.Parent.RequestInfo != null && s.Parent.RequestInfo.Methods.Count > 0 + ? "[" + string.Join("|", s.Parent.RequestInfo.Methods) + "]" + : "[]"; + + roots.Add(new TreeNode(formatter, "..", parentDirMethod)); } int recursionDepth = 1; @@ -75,8 +94,6 @@ namespace Microsoft.HttpRepl.Commands { shellState.ConsoleManager.WriteLine(node.ToString()); } - - return Task.CompletedTask; } private static void Recurse(TreeNode parentNode, IDirectoryStructure parent, int remainingDepth) @@ -101,7 +118,7 @@ namespace Microsoft.HttpRepl.Commands - protected override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("ls") + protected override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("ls").AlternateName("dir") .MaximumArgCount(1) .WithOption(new CommandOptionSpecification(RecursiveOption, maximumOccurrences: 1, acceptsValue: true, forms: new[] {"-r", "--recursive"})) .Finish(); diff --git a/src/Microsoft.HttpRepl/Commands/PrefCommand.cs b/src/Microsoft.HttpRepl/Commands/PrefCommand.cs index 2a64d2f017..d4d5d19b4a 100644 --- a/src/Microsoft.HttpRepl/Commands/PrefCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/PrefCommand.cs @@ -90,7 +90,7 @@ namespace Microsoft.HttpRepl.Commands if (!programState.SavePreferences()) { - shellState.ConsoleManager.Error.WriteLine("Error saving preferences".Bold().Red()); + shellState.ConsoleManager.Error.WriteLine("Error saving preferences".SetColor(programState.ErrorColor)); } return Task.CompletedTask; @@ -109,7 +109,7 @@ namespace Microsoft.HttpRepl.Commands } else { - shellState.ConsoleManager.Error.WriteLine((commandInput.Arguments[1].Text + " does not have a configured value").Bold().Red()); + shellState.ConsoleManager.Error.WriteLine((commandInput.Arguments[1].Text + " does not have a configured value").SetColor(programState.ErrorColor)); } } else diff --git a/src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs b/src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs index 77e5f0adde..76166d5c53 100644 --- a/src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs @@ -3,6 +3,8 @@ using System; using System.Collections.Generic; +using System.Net.Http; +using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; using Microsoft.Repl; @@ -34,11 +36,20 @@ namespace Microsoft.HttpRepl.Commands } else if (parseResult.Sections.Count != 3 || string.IsNullOrEmpty(parseResult.Sections[2]) || !Uri.TryCreate(EnsureTrailingSlash(parseResult.Sections[2]), UriKind.Absolute, out Uri serverUri)) { - shellState.ConsoleManager.Error.WriteLine("Must specify a server".Bold().Red()); + shellState.ConsoleManager.Error.WriteLine("Must specify a server".SetColor(state.ErrorColor)); } else { state.BaseAddress = serverUri; + try + { + await state.Client.SendAsync(new HttpRequestMessage(HttpMethod.Head, serverUri)).ConfigureAwait(false); + } + catch (Exception ex) when (ex.InnerException is SocketException se) + { + shellState.ConsoleManager.Error.WriteLine($"Warning: HEAD request to the specified address was unsuccessful ({se.Message})".SetColor(state.WarningColor)); + } + catch { } } if (state.BaseAddress == null || !Uri.TryCreate(state.BaseAddress, "/swagger/v1/swagger.json", out Uri result)) diff --git a/src/Microsoft.HttpRepl/Commands/SetDiagCommand.cs b/src/Microsoft.HttpRepl/Commands/SetDiagCommand.cs index 535d1a2026..4adb208de3 100644 --- a/src/Microsoft.HttpRepl/Commands/SetDiagCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/SetDiagCommand.cs @@ -41,7 +41,7 @@ namespace Microsoft.HttpRepl.Commands if (parseResult.Sections.Count != 3 || string.IsNullOrEmpty(parseResult.Sections[2]) || !Uri.TryCreate(parseResult.Sections[2], UriKind.Relative, out Uri _)) { - shellState.ConsoleManager.Error.WriteLine("Must specify a relative path".Bold().Red()); + shellState.ConsoleManager.Error.WriteLine("Must specify a relative path".SetColor(programState.ErrorColor)); } else { @@ -50,7 +50,7 @@ namespace Microsoft.HttpRepl.Commands if (!response.IsSuccessStatusCode) { - shellState.ConsoleManager.Error.WriteLine("Unable to access diagnostics endpoint".Bold().Red()); + shellState.ConsoleManager.Error.WriteLine("Unable to access diagnostics endpoint".SetColor(programState.ErrorColor)); programState.DiagnosticsState.DiagnosticsEndpoint = null; programState.DiagnosticsState.DiagnosticItems = null; } @@ -66,7 +66,7 @@ namespace Microsoft.HttpRepl.Commands if (!endpointsResponse.IsSuccessStatusCode) { - shellState.ConsoleManager.Error.WriteLine("Unable to get endpoints information from diagnostics endpoint".Bold().Red()); + shellState.ConsoleManager.Error.WriteLine("Unable to get endpoints information from diagnostics endpoint".SetColor(programState.ErrorColor)); return; } diff --git a/src/Microsoft.HttpRepl/Commands/SetSwaggerCommand.cs b/src/Microsoft.HttpRepl/Commands/SetSwaggerCommand.cs index be99891d5e..41c1564a99 100644 --- a/src/Microsoft.HttpRepl/Commands/SetSwaggerCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/SetSwaggerCommand.cs @@ -243,7 +243,7 @@ namespace Microsoft.HttpRepl.Commands if (parseResult.Sections.Count != 3 || string.IsNullOrEmpty(parseResult.Sections[2]) || !Uri.TryCreate(parseResult.Sections[2], UriKind.Absolute, out Uri serverUri)) { - shellState.ConsoleManager.Error.WriteLine("Must specify a swagger document".Bold().Red()); + shellState.ConsoleManager.Error.WriteLine("Must specify a swagger document".SetColor(programState.ErrorColor)); } else { @@ -253,6 +253,8 @@ namespace Microsoft.HttpRepl.Commands internal static async Task CreateDirectoryStructureForSwaggerEndpointAsync(IShellState shellState, HttpState programState, Uri serverUri, CancellationToken cancellationToken) { + programState.SwaggerEndpoint = serverUri; + try { IEnumerable doc = await GetSwaggerDocAsync(programState.Client, serverUri).ConfigureAwait(false); diff --git a/src/Microsoft.HttpRepl/Commands/UICommand.cs b/src/Microsoft.HttpRepl/Commands/UICommand.cs index 0eb02826f9..ac03d53d29 100644 --- a/src/Microsoft.HttpRepl/Commands/UICommand.cs +++ b/src/Microsoft.HttpRepl/Commands/UICommand.cs @@ -29,13 +29,13 @@ namespace Microsoft.HttpRepl.Commands { if (programState.BaseAddress == null) { - shellState.ConsoleManager.Error.WriteLine("Must be connected to a server to launch Swagger UI".Bold().Red()); + shellState.ConsoleManager.Error.WriteLine("Must be connected to a server to launch Swagger UI".SetColor(programState.ErrorColor)); return Task.CompletedTask; } Uri uri = new Uri(programState.BaseAddress, "swagger"); string agent = "cmd"; - string agentParam = $"/c {uri.AbsoluteUri}"; + string agentParam = $"/c start {uri.AbsoluteUri}"; if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { diff --git a/src/Microsoft.HttpRepl/HttpState.cs b/src/Microsoft.HttpRepl/HttpState.cs index d012a8fc45..9104e4e02c 100644 --- a/src/Microsoft.HttpRepl/HttpState.cs +++ b/src/Microsoft.HttpRepl/HttpState.cs @@ -9,6 +9,7 @@ using System.Net.Http; using System.Runtime.InteropServices; using Microsoft.HttpRepl.Diagnostics; using Microsoft.HttpRepl.Preferences; +using Microsoft.Repl.ConsoleHandling; namespace Microsoft.HttpRepl { @@ -19,6 +20,10 @@ namespace Microsoft.HttpRepl public HttpClient Client { get; } + public AllowedColors ErrorColor => this.GetColorPreference(WellKnownPreference.ErrorColor, AllowedColors.BoldRed); + + public AllowedColors WarningColor => this.GetColorPreference(WellKnownPreference.WarningColor, AllowedColors.BoldYellow); + public Stack PathSections { get; } public IDirectoryStructure SwaggerStructure { get; set; } @@ -62,6 +67,8 @@ namespace Microsoft.HttpRepl public DiagnosticsState DiagnosticsState { get; } + public Uri SwaggerEndpoint { get; set; } + public HttpState() { Client = new HttpClient(); diff --git a/src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs b/src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs index 424c0bb9a4..a0456bb99f 100644 --- a/src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs +++ b/src/Microsoft.HttpRepl/Preferences/WellKnownPreference.cs @@ -131,9 +131,12 @@ namespace Microsoft.HttpRepl.Preferences public static string ResponseStatusReaseonPhraseColor { get; } = "colors.response.status.reasonPhrase"; - public static string RequestOrResponseColor { get; } = "colors.requestOrResponse"; + public static string ErrorColor { get; } = "colors.error"; + + public static string WarningColor { get; } = "colors.warning"; + public static string BodyColor { get; } = "colors.body"; public static string SchemeColor { get; } = "colors.scheme"; @@ -167,6 +170,8 @@ namespace Microsoft.HttpRepl.Preferences public static string DefaultEditorArguments { get; } = "editor.command.default.arguments"; + public static string SwaggerRequeryBehavior { get; } = "swagger.requery"; + public static AllowedColors GetColorPreference(this HttpState programState, string preference, AllowedColors defaultvalue = AllowedColors.None) { diff --git a/src/Microsoft.HttpRepl/Program.cs b/src/Microsoft.HttpRepl/Program.cs index 6509e7a38c..e41a36ff21 100644 --- a/src/Microsoft.HttpRepl/Program.cs +++ b/src/Microsoft.HttpRepl/Program.cs @@ -16,15 +16,15 @@ namespace Microsoft.HttpRepl { static async Task Main(string[] args) { - if(Console.IsOutputRedirected) + var state = new HttpState(); + + if (Console.IsOutputRedirected) { - Reporter.Error.WriteLine("Cannot start the REPL when output is being redirected".Bold().Red()); + Reporter.Error.WriteLine("Cannot start the REPL when output is being redirected".SetColor(state.ErrorColor)); return; } - var state = new HttpState(); var dispatcher = DefaultCommandDispatcher.Create(state.GetPrompt, state); - dispatcher.AddCommand(new ChangeDirectoryCommand()); dispatcher.AddCommand(new ClearCommand()); //dispatcher.AddCommand(new ConfigCommand()); diff --git a/src/Microsoft.Repl/Commanding/CommandInputSpecification.cs b/src/Microsoft.Repl/Commanding/CommandInputSpecification.cs index 0e24c3fffa..05a14e8641 100644 --- a/src/Microsoft.Repl/Commanding/CommandInputSpecification.cs +++ b/src/Microsoft.Repl/Commanding/CommandInputSpecification.cs @@ -7,7 +7,7 @@ namespace Microsoft.Repl.Commanding { public class CommandInputSpecification { - public IReadOnlyList CommandName { get; } + public IReadOnlyList> CommandName { get; } public char OptionPreamble { get; } @@ -17,7 +17,7 @@ namespace Microsoft.Repl.Commanding public IReadOnlyList Options { get; } - public CommandInputSpecification(IReadOnlyList name, char optionPreamble, IReadOnlyList options, int minimumArgs, int maximumArgs) + public CommandInputSpecification(IReadOnlyList> name, char optionPreamble, IReadOnlyList options, int minimumArgs, int maximumArgs) { CommandName = name; OptionPreamble = optionPreamble; diff --git a/src/Microsoft.Repl/Commanding/CommandInputSpecificationBuilder.cs b/src/Microsoft.Repl/Commanding/CommandInputSpecificationBuilder.cs index 019782d0b8..7b5b529e3c 100644 --- a/src/Microsoft.Repl/Commanding/CommandInputSpecificationBuilder.cs +++ b/src/Microsoft.Repl/Commanding/CommandInputSpecificationBuilder.cs @@ -1,13 +1,14 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; namespace Microsoft.Repl.Commanding { public class CommandInputSpecificationBuilder { - private readonly IReadOnlyList _name; + private readonly List> _name; private char _optionPreamble; private int _minimumArgs; private int _maximumArgs; @@ -15,7 +16,7 @@ namespace Microsoft.Repl.Commanding public CommandInputSpecificationBuilder(IReadOnlyList name) { - _name = name; + _name = new List> { name }; _optionPreamble = '-'; } @@ -65,5 +66,13 @@ namespace Microsoft.Repl.Commanding { return new CommandInputSpecification(_name, _optionPreamble, _options, _minimumArgs, _maximumArgs); } + + public CommandInputSpecificationBuilder AlternateName(string baseName, params string[] additionalNameParts) + { + List nameParts = new List { baseName }; + nameParts.AddRange(additionalNameParts); + _name.Add(nameParts); + return this; + } } } diff --git a/src/Microsoft.Repl/Commanding/CommandWithStructuredInputBase.cs b/src/Microsoft.Repl/Commanding/CommandWithStructuredInputBase.cs index 1957205913..a7e07b3cee 100644 --- a/src/Microsoft.Repl/Commanding/CommandWithStructuredInputBase.cs +++ b/src/Microsoft.Repl/Commanding/CommandWithStructuredInputBase.cs @@ -40,17 +40,34 @@ namespace Microsoft.Repl.Commanding //If we're completing in a name position, offer completion for the command name if (parseResult.SelectedSection < InputSpec.CommandName.Count) { - for (int i = 0; i < parseResult.SelectedSection; ++i) + IReadOnlyList commandName = null; + for (int j = 0; j < InputSpec.CommandName.Count; ++j) { - if (!string.Equals(InputSpec.CommandName[i], parseResult.Sections[i], StringComparison.OrdinalIgnoreCase)) + bool success = true; + for (int i = 0; i < parseResult.SelectedSection; ++i) { - return null; + if (!string.Equals(InputSpec.CommandName[j][i], parseResult.Sections[i], StringComparison.OrdinalIgnoreCase)) + { + success = false; + break; + } + } + + if (success) + { + commandName = InputSpec.CommandName[j]; + break; } } - if (InputSpec.CommandName[parseResult.SelectedSection].StartsWith(normalCompletionString, StringComparison.OrdinalIgnoreCase)) + if (commandName is null) { - return new[] {InputSpec.CommandName[parseResult.SelectedSection]}; + return null; + } + + if (commandName[parseResult.SelectedSection].StartsWith(normalCompletionString, StringComparison.OrdinalIgnoreCase)) + { + return new[] {commandName[parseResult.SelectedSection]}; } } diff --git a/src/Microsoft.Repl/Commanding/DefaultCommandInput.cs b/src/Microsoft.Repl/Commanding/DefaultCommandInput.cs index ead59738b3..8ddaa031dc 100644 --- a/src/Microsoft.Repl/Commanding/DefaultCommandInput.cs +++ b/src/Microsoft.Repl/Commanding/DefaultCommandInput.cs @@ -21,26 +21,19 @@ namespace Microsoft.Repl.Commanding public static bool TryProcess(CommandInputSpecification spec, TParseResult parseResult, out DefaultCommandInput result, out IReadOnlyList processingIssues) { - List issues = new List(); - List commandNameElements = new List(); + List issues = null; + List commandNameElements = null; - if (spec.CommandName.Count > parseResult.Sections.Count) + foreach (IReadOnlyList commandName in spec.CommandName) { - issues.Add(new CommandInputProcessingIssue(CommandInputProcessingIssueKind.CommandMismatch, spec.CommandName[parseResult.Sections.Count])); - } - - for (int i = 0; i < spec.CommandName.Count && i < parseResult.Sections.Count; ++i) - { - if (!string.Equals(spec.CommandName[i], parseResult.Sections[i], StringComparison.OrdinalIgnoreCase)) + if (TryProcessCommandName(commandName, parseResult, out List nameElements, out issues)) { - issues.Add(new CommandInputProcessingIssue(CommandInputProcessingIssueKind.CommandMismatch, parseResult.Sections[i])); + commandNameElements = nameElements; + break; } - - commandNameElements.Add(new InputElement(CommandInputLocation.CommandName, parseResult.Sections[i], spec.CommandName[i], i)); } - //If we have a command name mismatch, no point in continuing - if (issues.Count > 0) + if (commandNameElements is null) { result = null; processingIssues = issues; @@ -185,6 +178,39 @@ namespace Microsoft.Repl.Commanding return issues.Count == 0; } + private static bool TryProcessCommandName(IReadOnlyList commandName, TParseResult parseResult, out List nameElements, out List processingIssues) + { + List issues = new List(); + List commandNameElements = new List(); + + if (commandName.Count > parseResult.Sections.Count) + { + issues.Add(new CommandInputProcessingIssue(CommandInputProcessingIssueKind.CommandMismatch, commandName[parseResult.Sections.Count])); + } + + for (int i = 0; i < commandName.Count && i < parseResult.Sections.Count; ++i) + { + if (!string.Equals(commandName[i], parseResult.Sections[i], StringComparison.OrdinalIgnoreCase)) + { + issues.Add(new CommandInputProcessingIssue(CommandInputProcessingIssueKind.CommandMismatch, parseResult.Sections[i])); + } + + commandNameElements.Add(new InputElement(CommandInputLocation.CommandName, parseResult.Sections[i], commandName[i], i)); + } + + processingIssues = issues; + + //If we have a command name mismatch, no point in continuing + if (issues.Count > 0) + { + nameElements = null; + return false; + } + + nameElements = commandNameElements; + return true; + } + public InputElement SelectedElement { get; } public IReadOnlyList CommandName { get; } From 6d106bee9290f79ae0ee5be895dc46ab565d5fb0 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 5 Aug 2018 19:11:25 +0000 Subject: [PATCH 0890/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 0f57ae33b0..83d1dc944d 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17102 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 + 2.2.0-preview1-20180731.1 + 2.2.0-preview1-34882 + 2.2.0-preview1-34882 + 2.2.0-preview1-34882 + 2.2.0-preview1-34882 + 2.2.0-preview1-34882 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 28cd6a5b03..b6efc7cfcb 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17102 -commithash:e7e2b5a97ca92cfc6acc4def534cb0901a6d1eb9 +version:2.2.0-preview1-20180731.1 +commithash:29fde58465439f4bb9df40830635ed758e063daf From 2f2027fe5fe90190eca3df7a43adf9924abee4f8 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 5 Aug 2018 19:14:38 +0000 Subject: [PATCH 0891/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 09d37136bd..4aa84ba6c2 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,11 +3,11 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17102 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 - 2.2.0-preview1-34823 + 2.2.0-preview1-20180731.1 + 2.2.0-preview1-34882 + 2.2.0-preview1-34882 + 2.2.0-preview1-34882 + 2.2.0-preview1-34882 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 6b8da29e6b..c7af2292c7 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17102 -commithash:e7e2b5a97ca92cfc6acc4def534cb0901a6d1eb9 +version:2.2.0-preview1-20180731.1 +commithash:29fde58465439f4bb9df40830635ed758e063daf From 91188201eea719cae1e58c07c486193ce5737932 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 5 Aug 2018 19:20:10 +0000 Subject: [PATCH 0892/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 6 +++--- korebuild-lock.txt | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 5b45506395..f6d57f9ae8 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-17102 - 2.2.0-preview1-34823 + 2.2.0-preview1-20180731.1 + 2.2.0-preview1-34882 4.5.0 - 2.2.0-preview1-34823 + 2.2.0-preview1-34882 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 6b8da29e6b..c7af2292c7 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-17102 -commithash:e7e2b5a97ca92cfc6acc4def534cb0901a6d1eb9 +version:2.2.0-preview1-20180731.1 +commithash:29fde58465439f4bb9df40830635ed758e063daf From 8655da7e1efb941d63bebdc528286df3c3f81b63 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 5 Aug 2018 19:49:49 +0000 Subject: [PATCH 0893/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 8da79df136..380b8d2342 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,13 +3,13 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-10015 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-preview1-26727-03 + 3.0.0-alpha1-20180731.2 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-preview1-26731-01 15.6.1 2.0.3 4.6.0-preview1-26727-04 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 8c70cbad9f..fe0f897b25 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-10015 -commithash:3f36e5c2f061712f76f2766c435d2555681d5c55 +version:3.0.0-alpha1-20180731.2 +commithash:1179f1083695ac9213c8a70a4d1d6c45a52caf41 From 34ebc51d5fcf3c53d7d91acf11222e0d1a92027c Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 5 Aug 2018 19:53:08 +0000 Subject: [PATCH 0894/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 7c3160369c..0172ee1e9f 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,11 +3,11 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-10015 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 - 3.0.0-alpha1-10173 + 3.0.0-alpha1-20180731.2 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 + 3.0.0-alpha1-10221 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 1e75dc3a23..8f9f6066ef 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-10015 -commithash:3f36e5c2f061712f76f2766c435d2555681d5c55 +version:3.0.0-alpha1-20180731.2 +commithash:1179f1083695ac9213c8a70a4d1d6c45a52caf41 From 9605408ce3db9ae4c64f0f3c2f7213e931b6bb67 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 5 Aug 2018 19:56:10 +0000 Subject: [PATCH 0895/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 6 +++--- korebuild-lock.txt | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 1fec5379c4..903b5af79e 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-10015 - 3.0.0-alpha1-10173 + 3.0.0-alpha1-20180731.2 + 3.0.0-alpha1-10221 4.6.0-preview1-26727-04 - 3.0.0-alpha1-10173 + 3.0.0-alpha1-10221 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 1e75dc3a23..8f9f6066ef 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-10015 -commithash:3f36e5c2f061712f76f2766c435d2555681d5c55 +version:3.0.0-alpha1-20180731.2 +commithash:1179f1083695ac9213c8a70a4d1d6c45a52caf41 From b242704bda1dbef522d6be69f7b1d4b2aa2b258e Mon Sep 17 00:00:00 2001 From: Mike Lorbetske Date: Sun, 5 Aug 2018 13:55:29 -0700 Subject: [PATCH 0896/1029] Remove unnecessary exclusions from NuGetPackageVerifier.json --- NuGetPackageVerifier.json | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index 4167e36811..fb43448889 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -24,33 +24,12 @@ "DotnetTool" ] }, - "dotnet-httprepl": { - "packageTypes": [ - "DotnetTool" - ], - "Exclusions": { - "ASSEMBLY_DESCRIPTION": { - "tools/netcoreapp2.2/any/System.Net.Http.Formatting.dll": "Referenced assembly, not built as part of this process" - }, - "VERSION_INFORMATIONALVERSION": { - "tools/netcoreapp2.2/any/Newtonsoft.Json.dll": "Referenced assembly, not built as part of this process", - "tools/netcoreapp2.2/any/Newtonsoft.Json.Bson.dll": "Referenced assembly, not built as part of this process" - } - } - }, "Microsoft.AspNetCore.DeveloperCertificates.XPlat": { "Exclusions": { "DOC_MISSING": { "lib/netcoreapp2.2/Microsoft.AspNetCore.DeveloperCertificates.XPlat.dll": "Docs not required to shipoob package" } } - }, - "Microsoft.Repl": { - "Exclusions": { - "DOC_MISSING": { - "lib/netcoreapp2.2/Microsoft.Repl.dll": "Docs not required to shipoob package" - } - } } } }, From eb591fb29dfc87c9815eba024038788c731afcbc Mon Sep 17 00:00:00 2001 From: Mike Lorbetske Date: Sun, 5 Aug 2018 14:13:08 -0700 Subject: [PATCH 0897/1029] Attempt to fix exclusions in NuGetPackageVerifier.json again --- NuGetPackageVerifier.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index fb43448889..63b866c8ed 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -24,6 +24,20 @@ "DotnetTool" ] }, + "dotnet-httprepl": { + "packageTypes": [ + "DotnetTool" + ], + "Exclusions": { + "ASSEMBLY_DESCRIPTION": { + "tools/netcoreapp2.1/any/System.Net.Http.Formatting.dll": "Referenced assembly, not built as part of this process" + }, + "VERSION_INFORMATIONALVERSION": { + "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Referenced assembly, not built as part of this process", + "tools/netcoreapp2.1/any/Newtonsoft.Json.Bson.dll": "Referenced assembly, not built as part of this process" + } + } + }, "Microsoft.AspNetCore.DeveloperCertificates.XPlat": { "Exclusions": { "DOC_MISSING": { From dbad34cdef766fc06877cb28d862eeff0c55377a Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Mon, 6 Aug 2018 20:33:37 +0000 Subject: [PATCH 0898/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 83d1dc944d..b6107e7202 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,11 +4,11 @@ 2.2.0-preview1-20180731.1 - 2.2.0-preview1-34882 - 2.2.0-preview1-34882 - 2.2.0-preview1-34882 - 2.2.0-preview1-34882 - 2.2.0-preview1-34882 + 2.2.0-preview1-34896 + 2.2.0-preview1-34896 + 2.2.0-preview1-34896 + 2.2.0-preview1-34896 + 2.2.0-preview1-34896 2.0.9 2.1.2 2.2.0-preview1-26618-02 From 04d476a729642e6d4304029ecef88bab98e4abd8 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Mon, 6 Aug 2018 20:36:56 +0000 Subject: [PATCH 0899/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 4aa84ba6c2..b6626fdf05 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,10 +4,10 @@ 2.2.0-preview1-20180731.1 - 2.2.0-preview1-34882 - 2.2.0-preview1-34882 - 2.2.0-preview1-34882 - 2.2.0-preview1-34882 + 2.2.0-preview1-34896 + 2.2.0-preview1-34896 + 2.2.0-preview1-34896 + 2.2.0-preview1-34896 2.0.9 2.1.2 2.2.0-preview1-26618-02 From 8100421d2fe65d160044b3204151f6f5e5b323d2 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Mon, 6 Aug 2018 20:42:45 +0000 Subject: [PATCH 0900/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index f6d57f9ae8..85c8596f07 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,9 +4,9 @@ 2.2.0-preview1-20180731.1 - 2.2.0-preview1-34882 + 2.2.0-preview1-34896 4.5.0 - 2.2.0-preview1-34882 + 2.2.0-preview1-34896 2.0.9 2.1.2 2.2.0-preview1-26618-02 From b53d50f6f0fb79f5c4794f090d6c80382a7e9d98 Mon Sep 17 00:00:00 2001 From: Mike Lorbetske Date: Tue, 7 Aug 2018 16:16:33 -0700 Subject: [PATCH 0901/1029] Fix incorrectly resolved cross-document pointers --- src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs b/src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs index c8566095b7..5bff058b95 100644 --- a/src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs +++ b/src/Microsoft.HttpRepl/OpenApi/PointerUtil.cs @@ -19,6 +19,8 @@ namespace Microsoft.HttpRepl.OpenApi private static async Task ResolvePointersAsync(Uri loadLocation, JToken root, JToken toResolve, HttpClient client) { + JToken cursor = root; + if (toResolve is JArray arr) { for (int i = 0; i < arr.Count; ++i) @@ -69,7 +71,7 @@ namespace Microsoft.HttpRepl.OpenApi return new JValue((object)null); } - return await ResolvePointersAsync(loadTarget, newRoot, newRoot, client).ConfigureAwait(false); + cursor = await ResolvePointersAsync(loadTarget, newRoot, newRoot, client).ConfigureAwait(false); } //We're in the right document, grab the bookmark (fragment) of the URI and get the element at that path @@ -81,7 +83,6 @@ namespace Microsoft.HttpRepl.OpenApi } string[] parts = fragment.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); - JToken cursor = root; for (int i = 0; i < parts.Length; ++i) { From a9bdf718e532b87bac5ec6f5532e75c1f0b84036 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 12 Aug 2018 19:10:29 +0000 Subject: [PATCH 0902/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index b6107e7202..54c03037c6 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180731.1 - 2.2.0-preview1-34896 - 2.2.0-preview1-34896 - 2.2.0-preview1-34896 - 2.2.0-preview1-34896 - 2.2.0-preview1-34896 + 2.2.0-preview1-20180807.2 + 2.2.0-preview1-34967 + 2.2.0-preview1-34967 + 2.2.0-preview1-34967 + 2.2.0-preview1-34967 + 2.2.0-preview1-34967 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index b6efc7cfcb..29a57027f1 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180731.1 -commithash:29fde58465439f4bb9df40830635ed758e063daf +version:2.2.0-preview1-20180807.2 +commithash:11495dbd236104434e08cb1152fcb58cf2a20923 From b4b9d5b0af1ac654157e30b81e09b9a889fc717b Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 12 Aug 2018 19:13:50 +0000 Subject: [PATCH 0903/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index b6626fdf05..1f8d7ce1dc 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,11 +3,11 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180731.1 - 2.2.0-preview1-34896 - 2.2.0-preview1-34896 - 2.2.0-preview1-34896 - 2.2.0-preview1-34896 + 2.2.0-preview1-20180807.2 + 2.2.0-preview1-34967 + 2.2.0-preview1-34967 + 2.2.0-preview1-34967 + 2.2.0-preview1-34967 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index c7af2292c7..3fbcc80189 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180731.1 -commithash:29fde58465439f4bb9df40830635ed758e063daf +version:2.2.0-preview1-20180807.2 +commithash:11495dbd236104434e08cb1152fcb58cf2a20923 From 06d1a535b3153efc0ca24adc4f68ea42eec70755 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 12 Aug 2018 19:19:45 +0000 Subject: [PATCH 0904/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 6 +++--- korebuild-lock.txt | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 85c8596f07..d4e5106db9 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180731.1 - 2.2.0-preview1-34896 + 2.2.0-preview1-20180807.2 + 2.2.0-preview1-34967 4.5.0 - 2.2.0-preview1-34896 + 2.2.0-preview1-34967 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index c7af2292c7..3fbcc80189 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180731.1 -commithash:29fde58465439f4bb9df40830635ed758e063daf +version:2.2.0-preview1-20180807.2 +commithash:11495dbd236104434e08cb1152fcb58cf2a20923 From 854556408a15f765a3dcbd5ed3c8a19e2753abfb Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 12 Aug 2018 19:56:59 +0000 Subject: [PATCH 0905/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 380b8d2342..c560193114 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-20180731.2 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-preview1-26731-01 + 3.0.0-alpha1-20180810.1 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-preview1-26810-02 15.6.1 2.0.3 - 4.6.0-preview1-26727-04 - 4.6.0-preview1-26727-04 + 4.6.0-preview1-26807-04 + 4.6.0-preview1-26807-04 9.0.1 2.3.1 2.4.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index fe0f897b25..c53be3fca9 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180731.2 -commithash:1179f1083695ac9213c8a70a4d1d6c45a52caf41 +version:3.0.0-alpha1-20180810.1 +commithash:45c32b4f020e14a9295be31866051a18d293309d From c7aaa655db1435537071514f1d8f0867f79bbd65 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 12 Aug 2018 20:00:15 +0000 Subject: [PATCH 0906/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 0172ee1e9f..2c0eaa0377 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-20180731.2 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 - 3.0.0-alpha1-10221 + 3.0.0-alpha1-20180810.1 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 + 3.0.0-alpha1-10275 2.0.9 2.1.2 2.2.0-preview1-26618-02 15.6.1 2.0.3 - 4.6.0-preview1-26727-04 + 4.6.0-preview1-26807-04 2.3.1 2.4.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 8f9f6066ef..e417a01b52 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180731.2 -commithash:1179f1083695ac9213c8a70a4d1d6c45a52caf41 +version:3.0.0-alpha1-20180810.1 +commithash:45c32b4f020e14a9295be31866051a18d293309d From f3fc41e294f28db4dbbde20198abd9d4adaefe41 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 12 Aug 2018 20:06:05 +0000 Subject: [PATCH 0907/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 8 ++++---- korebuild-lock.txt | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 903b5af79e..be9cae25a3 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-20180731.2 - 3.0.0-alpha1-10221 - 4.6.0-preview1-26727-04 - 3.0.0-alpha1-10221 + 3.0.0-alpha1-20180810.1 + 3.0.0-alpha1-10275 + 4.6.0-preview1-26807-04 + 3.0.0-alpha1-10275 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 8f9f6066ef..e417a01b52 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180731.2 -commithash:1179f1083695ac9213c8a70a4d1d6c45a52caf41 +version:3.0.0-alpha1-20180810.1 +commithash:45c32b4f020e14a9295be31866051a18d293309d From 734ddf9c1007181e4c6dcd7ca49e2f512b2cd4ae Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 15 Aug 2018 10:35:12 -0700 Subject: [PATCH 0908/1029] Restrict build to only use VS 2017 --- korebuild.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/korebuild.json b/korebuild.json index 7002d25ca1..6cff0cf67e 100644 --- a/korebuild.json +++ b/korebuild.json @@ -7,7 +7,7 @@ "windows" ], "includePrerelease": true, - "minVersion": "15.0.26730.03", + "versionRange": "[15.0.26730.03, 16.0)", "requiredWorkloads": [ "Microsoft.VisualStudio.Component.VSSDK" ] From 14a19d4acbde76516df0e466a6d46f2f678ad1bc Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 19 Aug 2018 19:11:20 +0000 Subject: [PATCH 0909/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index c560193114..d60339d79d 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-20180810.1 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-preview1-26810-02 + 3.0.0-alpha1-20180817.3 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-preview1-26817-04 15.6.1 2.0.3 - 4.6.0-preview1-26807-04 - 4.6.0-preview1-26807-04 + 4.6.0-preview1-26816-01 + 4.6.0-preview1-26816-01 9.0.1 2.3.1 2.4.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index c53be3fca9..7abb5ed14d 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180810.1 -commithash:45c32b4f020e14a9295be31866051a18d293309d +version:3.0.0-alpha1-20180817.3 +commithash:134cdbee9bee29dd3ccb654c67663b27b9ffa6c8 From 7a9e70ac681d85905923a4cbf4467f5f72cab889 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 19 Aug 2018 19:14:47 +0000 Subject: [PATCH 0910/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 2c0eaa0377..fc7b9a69a6 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-20180810.1 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 - 3.0.0-alpha1-10275 + 3.0.0-alpha1-20180817.3 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 + 3.0.0-alpha1-10321 2.0.9 2.1.2 2.2.0-preview1-26618-02 15.6.1 2.0.3 - 4.6.0-preview1-26807-04 + 4.6.0-preview1-26816-01 2.3.1 2.4.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index e417a01b52..e5330b3d33 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180810.1 -commithash:45c32b4f020e14a9295be31866051a18d293309d +version:3.0.0-alpha1-20180817.3 +commithash:134cdbee9bee29dd3ccb654c67663b27b9ffa6c8 From 1c710b905b3e46dc355fd3259c211966f80630bf Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 19 Aug 2018 19:20:47 +0000 Subject: [PATCH 0911/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 8 ++++---- korebuild-lock.txt | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index be9cae25a3..d6e580a39c 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-20180810.1 - 3.0.0-alpha1-10275 - 4.6.0-preview1-26807-04 - 3.0.0-alpha1-10275 + 3.0.0-alpha1-20180817.3 + 3.0.0-alpha1-10321 + 4.6.0-preview1-26816-01 + 3.0.0-alpha1-10321 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index e417a01b52..e5330b3d33 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180810.1 -commithash:45c32b4f020e14a9295be31866051a18d293309d +version:3.0.0-alpha1-20180817.3 +commithash:134cdbee9bee29dd3ccb654c67663b27b9ffa6c8 From b3f6477a49e1ebdd6d0f8a8933cacd7b0b916b88 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 21 Aug 2018 13:33:49 -0700 Subject: [PATCH 0912/1029] Update package branding for 2.2.0-preview2 --- build/dependencies.props | 2 +- version.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 54c03037c6..c3fb6054b3 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -20,6 +20,6 @@ 2.3.1 2.4.0 - + diff --git a/version.props b/version.props index 4c749bb5d2..91190966fa 100644 --- a/version.props +++ b/version.props @@ -2,7 +2,7 @@ 2.2.0 15.6 - preview1 + preview2 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final $(VsixVersion).$(BuildNumber) From 386c024198d5b7b3dbb9c632df49479770d882b0 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 21 Aug 2018 13:33:50 -0700 Subject: [PATCH 0913/1029] Update package branding for 2.2.0-preview2 --- build/dependencies.props | 2 +- version.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 1f8d7ce1dc..e40e4c54a1 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -17,6 +17,6 @@ 2.3.1 2.4.0 - + diff --git a/version.props b/version.props index 44985cedb3..15637ba785 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ 2.2.0 - preview1 + preview2 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From bd559b7966bd2a647e53c46697dbc39c87f29694 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 21 Aug 2018 13:33:50 -0700 Subject: [PATCH 0914/1029] Update package branding for 2.2.0-preview2 --- build/dependencies.props | 2 +- version.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index d4e5106db9..68adbeafb8 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -18,6 +18,6 @@ 2.3.1 2.4.0 - + diff --git a/version.props b/version.props index 44985cedb3..15637ba785 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ 2.2.0 - preview1 + preview2 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From 4ced217d23a398f391d331360fed11cbd1bda268 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 26 Aug 2018 19:10:41 +0000 Subject: [PATCH 0915/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index d60339d79d..12e9bde1cc 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-20180817.3 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-preview1-26817-04 + 3.0.0-alpha1-20180821.3 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-preview1-26821-04 15.6.1 2.0.3 - 4.6.0-preview1-26816-01 - 4.6.0-preview1-26816-01 + 4.6.0-preview1-26817-04 + 4.6.0-preview1-26817-04 9.0.1 2.3.1 2.4.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 7abb5ed14d..74c82096f1 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180817.3 -commithash:134cdbee9bee29dd3ccb654c67663b27b9ffa6c8 +version:3.0.0-alpha1-20180821.3 +commithash:0939a90812deb1c604eb9a4768869687495fc1dd From 630bcb94cbb2a5a4401013f01983b13324e30771 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 26 Aug 2018 19:14:12 +0000 Subject: [PATCH 0916/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index fc7b9a69a6..57a5796716 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-20180817.3 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 - 3.0.0-alpha1-10321 + 3.0.0-alpha1-20180821.3 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 + 3.0.0-alpha1-10352 2.0.9 2.1.2 2.2.0-preview1-26618-02 15.6.1 2.0.3 - 4.6.0-preview1-26816-01 + 4.6.0-preview1-26817-04 2.3.1 2.4.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index e5330b3d33..767a471795 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180817.3 -commithash:134cdbee9bee29dd3ccb654c67663b27b9ffa6c8 +version:3.0.0-alpha1-20180821.3 +commithash:0939a90812deb1c604eb9a4768869687495fc1dd From b76ab6743a507698b8192c0762c1e888eb6a086f Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 26 Aug 2018 19:20:27 +0000 Subject: [PATCH 0917/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 8 ++++---- korebuild-lock.txt | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index d6e580a39c..5c61498e5b 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-20180817.3 - 3.0.0-alpha1-10321 - 4.6.0-preview1-26816-01 - 3.0.0-alpha1-10321 + 3.0.0-alpha1-20180821.3 + 3.0.0-alpha1-10352 + 4.6.0-preview1-26817-04 + 3.0.0-alpha1-10352 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index e5330b3d33..767a471795 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180817.3 -commithash:134cdbee9bee29dd3ccb654c67663b27b9ffa6c8 +version:3.0.0-alpha1-20180821.3 +commithash:0939a90812deb1c604eb9a4768869687495fc1dd From 9a0ab9df630e19f63d26604bd8e24b3c6aa8b2ef Mon Sep 17 00:00:00 2001 From: Mike Lorbetske Date: Tue, 28 Aug 2018 15:11:46 -0700 Subject: [PATCH 0918/1029] Update HttpRepl project to target 3.0 --- src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj b/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj index 99b86075c3..9e8a0b343c 100644 --- a/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj +++ b/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp2.1 + netcoreapp3.0 true dotnet-httprepl latest From c3c634aa1e230d667e38388bf9a5c2e69e33911d Mon Sep 17 00:00:00 2001 From: Mike Lorbetske Date: Tue, 28 Aug 2018 15:12:16 -0700 Subject: [PATCH 0919/1029] Update Repl project to target 3.0 --- src/Microsoft.Repl/Microsoft.Repl.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Repl/Microsoft.Repl.csproj b/src/Microsoft.Repl/Microsoft.Repl.csproj index d6cc6e83e6..1615d686ad 100644 --- a/src/Microsoft.Repl/Microsoft.Repl.csproj +++ b/src/Microsoft.Repl/Microsoft.Repl.csproj @@ -1,7 +1,7 @@  - netcoreapp2.1 + netcoreapp3.0 A framework for creating REPLs in .NET Core. dotnet;repl false From d93d6bf7514646006a6fcbaa039a6a8a1c758a9b Mon Sep 17 00:00:00 2001 From: Mike Lorbetske Date: Tue, 28 Aug 2018 15:12:42 -0700 Subject: [PATCH 0920/1029] Update HttpRepl test project to target 3.0 --- test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj b/test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj index a50dd1df30..409c13f325 100644 --- a/test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj +++ b/test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp3.0 false From b8daa4ae5cebbf4b97cc056c024e8cc26cc52731 Mon Sep 17 00:00:00 2001 From: Mike Lorbetske Date: Tue, 28 Aug 2018 15:13:00 -0700 Subject: [PATCH 0921/1029] Update Repl test project to target 3.0 --- test/Microsoft.Repl.Tests/Microsoft.Repl.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.Repl.Tests/Microsoft.Repl.Tests.csproj b/test/Microsoft.Repl.Tests/Microsoft.Repl.Tests.csproj index 52fbd0de16..62a1e3b306 100644 --- a/test/Microsoft.Repl.Tests/Microsoft.Repl.Tests.csproj +++ b/test/Microsoft.Repl.Tests/Microsoft.Repl.Tests.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.0 false From 207bdec61c2ce51b25509363831e57c82372c264 Mon Sep 17 00:00:00 2001 From: Mike Lorbetske Date: Tue, 28 Aug 2018 15:27:21 -0700 Subject: [PATCH 0922/1029] Fix NuGetPackageVerifier.json --- NuGetPackageVerifier.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index eed02c9d95..6ea6e98cc5 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -30,11 +30,11 @@ ], "Exclusions": { "ASSEMBLY_DESCRIPTION": { - "tools/netcoreapp2.1/any/System.Net.Http.Formatting.dll": "Referenced assembly, not built as part of this process" + "tools/netcoreapp3.0/any/System.Net.Http.Formatting.dll": "Referenced assembly, not built as part of this process" }, "VERSION_INFORMATIONALVERSION": { - "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Referenced assembly, not built as part of this process", - "tools/netcoreapp2.1/any/Newtonsoft.Json.Bson.dll": "Referenced assembly, not built as part of this process" + "tools/netcoreapp3.0/any/Newtonsoft.Json.dll": "Referenced assembly, not built as part of this process", + "tools/netcoreapp3.0/any/Newtonsoft.Json.Bson.dll": "Referenced assembly, not built as part of this process" } } }, From 64c572c8a58a088626d61326ba77f453e5f7199b Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 2 Sep 2018 12:09:51 -0700 Subject: [PATCH 0923/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 16 ++++++++-------- korebuild-lock.txt | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 029957e745..cf1be76701 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,23 +1,23 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180807.2 - 2.2.0-preview1-34967 - 2.2.0-preview1-34967 - 2.2.0-preview1-34967 - 2.2.0-preview1-34967 - 2.2.0-preview1-34967 + 2.2.0-preview1-20180821.1 + 2.2.0-preview2-35143 + 2.2.0-preview2-35143 + 2.2.0-preview2-35143 + 2.2.0-preview2-35143 + 2.2.0-preview2-35143 2.0.9 2.1.2 2.2.0-preview1-26618-02 15.6.1 5.2.6 2.0.3 + 11.0.2 4.5.1 4.5.0 - 11.0.2 9.0.1 2.3.1 2.4.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 29a57027f1..524a2323d0 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180807.2 -commithash:11495dbd236104434e08cb1152fcb58cf2a20923 +version:2.2.0-preview1-20180821.1 +commithash:c8d0cc52cd1abb697be24e288ffd54f8fae8bf17 From 78c9594075ca5198b6e376a17fa1298235a15171 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 2 Sep 2018 19:10:34 +0000 Subject: [PATCH 0924/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index da982434a6..c7dd858e0e 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,21 +1,21 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 3.0.0-alpha1-20180821.3 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-preview1-26821-04 + 3.0.0-alpha1-10393 + 3.0.0-alpha1-10393 + 3.0.0-alpha1-10393 + 3.0.0-alpha1-10393 + 3.0.0-alpha1-10393 + 3.0.0-preview1-26830-01 15.6.1 5.2.6 2.0.3 - 4.6.0-preview1-26817-04 - 4.6.0-preview1-26817-04 11.0.2 + 4.6.0-preview1-26829-04 + 4.6.0-preview1-26829-04 9.0.1 2.3.1 2.4.0 From 8d5b123c611a6df427624e5c7499f14061646577 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 2 Sep 2018 12:13:02 -0700 Subject: [PATCH 0925/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index e40e4c54a1..da718d7433 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,11 +3,11 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180807.2 - 2.2.0-preview1-34967 - 2.2.0-preview1-34967 - 2.2.0-preview1-34967 - 2.2.0-preview1-34967 + 2.2.0-preview1-20180821.1 + 2.2.0-preview2-35143 + 2.2.0-preview2-35143 + 2.2.0-preview2-35143 + 2.2.0-preview2-35143 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 3fbcc80189..ad704918df 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180807.2 -commithash:11495dbd236104434e08cb1152fcb58cf2a20923 +version:2.2.0-preview1-20180821.1 +commithash:c8d0cc52cd1abb697be24e288ffd54f8fae8bf17 From 1d83b14b526fcd4e8207b0a618749cee4182dec6 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 2 Sep 2018 19:14:14 +0000 Subject: [PATCH 0926/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 57a5796716..c3a1eb2e75 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,16 +4,16 @@ 3.0.0-alpha1-20180821.3 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 - 3.0.0-alpha1-10352 + 3.0.0-alpha1-10393 + 3.0.0-alpha1-10393 + 3.0.0-alpha1-10393 + 3.0.0-alpha1-10393 2.0.9 2.1.2 2.2.0-preview1-26618-02 15.6.1 2.0.3 - 4.6.0-preview1-26817-04 + 4.6.0-preview1-26829-04 2.3.1 2.4.0 From cb569de67201c566b680f71a7a0bb7f0cac34600 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 2 Sep 2018 12:18:41 -0700 Subject: [PATCH 0927/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 6 +++--- korebuild-lock.txt | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 68adbeafb8..c19ec5d60d 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180807.2 - 2.2.0-preview1-34967 + 2.2.0-preview1-20180821.1 + 2.2.0-preview2-35143 4.5.0 - 2.2.0-preview1-34967 + 2.2.0-preview2-35143 2.0.9 2.1.2 2.2.0-preview1-26618-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 3fbcc80189..ad704918df 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180807.2 -commithash:11495dbd236104434e08cb1152fcb58cf2a20923 +version:2.2.0-preview1-20180821.1 +commithash:c8d0cc52cd1abb697be24e288ffd54f8fae8bf17 From 64d1780047d0b1ab935ce6de610767a849c56b4a Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 2 Sep 2018 19:20:27 +0000 Subject: [PATCH 0928/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 5c61498e5b..aed2325db4 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,14 +4,14 @@ 3.0.0-alpha1-20180821.3 - 3.0.0-alpha1-10352 - 4.6.0-preview1-26817-04 - 3.0.0-alpha1-10352 + 3.0.0-alpha1-10393 + 4.6.0-preview1-26829-04 + 3.0.0-alpha1-10393 2.0.9 2.1.2 2.2.0-preview1-26618-02 15.6.1 - 4.7.49 + 4.9.0 2.0.3 11.0.2 0.10.0 From 64a2c3ab46274613935a7a2a87c76b4b320d14b0 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Wed, 5 Sep 2018 16:34:06 -0700 Subject: [PATCH 0929/1029] Update branding to 2.2.0-preview3 --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 91190966fa..07833713f2 100644 --- a/version.props +++ b/version.props @@ -2,7 +2,7 @@ 2.2.0 15.6 - preview2 + preview3 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final $(VsixVersion).$(BuildNumber) From eade194b39088b91c84c8c1aebd46d2ce7c85507 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Wed, 5 Sep 2018 16:34:28 -0700 Subject: [PATCH 0930/1029] Update branding to 2.2.0-preview3 --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 15637ba785..704cac087b 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ 2.2.0 - preview2 + preview3 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From bb31ceee59fa27b52908bef651636247e1fce481 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Wed, 5 Sep 2018 16:35:05 -0700 Subject: [PATCH 0931/1029] Update branding to 2.2.0-preview3 --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 15637ba785..704cac087b 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ 2.2.0 - preview2 + preview3 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From 7277826fdeeafbd6dfa05b26609f74fd54733acf Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Wed, 5 Sep 2018 23:42:50 +0000 Subject: [PATCH 0932/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index c7dd858e0e..f1dad2d5eb 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,18 +4,18 @@ 3.0.0-alpha1-20180821.3 - 3.0.0-alpha1-10393 - 3.0.0-alpha1-10393 - 3.0.0-alpha1-10393 - 3.0.0-alpha1-10393 - 3.0.0-alpha1-10393 - 3.0.0-preview1-26830-01 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-preview1-26905-03 15.6.1 5.2.6 2.0.3 11.0.2 - 4.6.0-preview1-26829-04 - 4.6.0-preview1-26829-04 + 4.6.0-preview1-26831-06 + 4.6.0-preview1-26831-06 9.0.1 2.3.1 2.4.0 From 6a4619a26975a15f636febd6741c7ef5554def91 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Wed, 5 Sep 2018 23:46:23 +0000 Subject: [PATCH 0933/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index c3a1eb2e75..074ac8b042 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,16 +4,16 @@ 3.0.0-alpha1-20180821.3 - 3.0.0-alpha1-10393 - 3.0.0-alpha1-10393 - 3.0.0-alpha1-10393 - 3.0.0-alpha1-10393 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 + 3.0.0-alpha1-10400 2.0.9 - 2.1.2 - 2.2.0-preview1-26618-02 + 2.1.3 + 2.2.0-preview2-26905-02 15.6.1 2.0.3 - 4.6.0-preview1-26829-04 + 4.6.0-preview1-26831-06 2.3.1 2.4.0 From 08a0c7fa7d05f4eb8c3d8de687e087de8d952907 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Wed, 5 Sep 2018 23:52:38 +0000 Subject: [PATCH 0934/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index aed2325db4..8f315c5a6b 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,12 +4,12 @@ 3.0.0-alpha1-20180821.3 - 3.0.0-alpha1-10393 - 4.6.0-preview1-26829-04 - 3.0.0-alpha1-10393 + 3.0.0-alpha1-10400 + 4.6.0-preview1-26831-06 + 3.0.0-alpha1-10400 2.0.9 - 2.1.2 - 2.2.0-preview1-26618-02 + 2.1.3 + 2.2.0-preview2-26905-02 15.6.1 4.9.0 2.0.3 From aa93edcee29acea037694d2a71ad02232836f69c Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 7 Sep 2018 10:01:52 -0700 Subject: [PATCH 0935/1029] Remove Microsoft.DotNet.GlobalTools.Sdk These targets are now part of Microsoft.NET.Sdk --- NuGet.config | 6 +----- build/dependencies.props | 2 +- korebuild-lock.txt | 4 ++-- src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj | 7 +++---- src/dotnet-dev-certs/dotnet-dev-certs.csproj | 4 +--- src/dotnet-sql-cache/dotnet-sql-cache.csproj | 7 ++----- src/dotnet-user-secrets/dotnet-user-secrets.csproj | 7 ++----- src/dotnet-watch/dotnet-watch.csproj | 7 ++----- 8 files changed, 14 insertions(+), 30 deletions(-) diff --git a/NuGet.config b/NuGet.config index 8c30f1c84e..e32bddfd51 100644 --- a/NuGet.config +++ b/NuGet.config @@ -2,10 +2,6 @@ - - + diff --git a/build/dependencies.props b/build/dependencies.props index cf1be76701..fbf093bdf8 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,7 +3,7 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180821.1 + 2.2.0-preview1-20180907.3 2.2.0-preview2-35143 2.2.0-preview2-35143 2.2.0-preview2-35143 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 524a2323d0..be535d1f04 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180821.1 -commithash:c8d0cc52cd1abb697be24e288ffd54f8fae8bf17 +version:2.2.0-preview1-20180907.3 +commithash:2315030c7f3de2af0f16cf64502321937b6c4315 diff --git a/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj b/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj index 99b86075c3..72f3e8fc1e 100644 --- a/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj +++ b/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj @@ -1,4 +1,4 @@ - + Exe @@ -8,9 +8,8 @@ latest Command line tool to for making HTTP calls and viewing their results. dotnet;http;httprepl - - true + win-x64;win-x86 @@ -20,7 +19,7 @@ - + diff --git a/src/dotnet-dev-certs/dotnet-dev-certs.csproj b/src/dotnet-dev-certs/dotnet-dev-certs.csproj index b785b60c42..343025749a 100644 --- a/src/dotnet-dev-certs/dotnet-dev-certs.csproj +++ b/src/dotnet-dev-certs/dotnet-dev-certs.csproj @@ -1,6 +1,5 @@ - netcoreapp2.2 @@ -9,9 +8,8 @@ Microsoft.AspNetCore.DeveloperCertificates.Tools dotnet;developercertificates true - - true + win-x64;win-x86 diff --git a/src/dotnet-sql-cache/dotnet-sql-cache.csproj b/src/dotnet-sql-cache/dotnet-sql-cache.csproj index 4ab0f3425c..3f9ce05717 100644 --- a/src/dotnet-sql-cache/dotnet-sql-cache.csproj +++ b/src/dotnet-sql-cache/dotnet-sql-cache.csproj @@ -1,6 +1,4 @@ - - - + netcoreapp2.2 @@ -8,9 +6,8 @@ Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching. cache;distributedcache;sqlserver true - - true + win-x64;win-x86 diff --git a/src/dotnet-user-secrets/dotnet-user-secrets.csproj b/src/dotnet-user-secrets/dotnet-user-secrets.csproj index bcb37e37b2..ae77d9bffd 100644 --- a/src/dotnet-user-secrets/dotnet-user-secrets.csproj +++ b/src/dotnet-user-secrets/dotnet-user-secrets.csproj @@ -1,6 +1,4 @@ - - - + netcoreapp2.2 @@ -10,9 +8,8 @@ Microsoft.Extensions.SecretManager.Tools configuration;secrets;usersecrets true - - true + win-x64;win-x86 diff --git a/src/dotnet-watch/dotnet-watch.csproj b/src/dotnet-watch/dotnet-watch.csproj index c5210a0cd2..d5012267f8 100644 --- a/src/dotnet-watch/dotnet-watch.csproj +++ b/src/dotnet-watch/dotnet-watch.csproj @@ -1,6 +1,4 @@ - - - + netcoreapp2.2 @@ -9,9 +7,8 @@ Microsoft.DotNet.Watcher.Tools dotnet;watch true - - true + win-x64;win-x86 From 4bcfbe4d404a3e3fed76a548618ca6d698547ced Mon Sep 17 00:00:00 2001 From: Glenn Condron Date: Fri, 7 Sep 2018 15:21:42 -0700 Subject: [PATCH 0936/1029] [REPL] Help improvements for repl (#478) * Beginning of help additions. Fixed a nullref. * Standardized help with options displayed as appropriate. --- .../Commands/BaseHttpCommand.cs | 15 +- .../Commands/ChangeDirectoryCommand.cs | 15 +- .../Commands/ConfigCommand.cs | 2 +- .../Commands/EchoCommand.cs | 10 +- .../Commands/ExitCommand.cs | 11 +- .../Commands/HelpCommand.cs | 134 +++++++++++++----- .../Commands/ListCommand.cs | 13 +- .../Commands/PrefCommand.cs | 80 ++++++++++- src/Microsoft.HttpRepl/Commands/RunCommand.cs | 15 +- .../Commands/SetBaseCommand.cs | 8 +- .../Commands/SetHeaderCommand.cs | 16 ++- .../CommandWithStructuredInputBase.cs | 2 +- 12 files changed, 250 insertions(+), 71 deletions(-) diff --git a/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs b/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs index 9a5eba8227..a8ad52fc24 100644 --- a/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs @@ -42,7 +42,7 @@ namespace Microsoft.HttpRepl.Commands protected abstract bool RequiresBody { get; } - protected override CommandInputSpecification InputSpec + public override CommandInputSpecification InputSpec { get { @@ -469,7 +469,18 @@ namespace Microsoft.HttpRepl.Commands protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult) { - return $"Issues a {Verb.ToUpperInvariant()} request"; + var helpText = new StringBuilder(); + helpText.Append("Usage: ".Bold()); + helpText.AppendLine($"{Verb.ToUpperInvariant()} [Options]"); + helpText.AppendLine(); + helpText.AppendLine($"Issues a {Verb.ToUpperInvariant()} request."); + + if (RequiresBody) + { + helpText.AppendLine("Your default editor will be opened with a sample body if no options are provided."); + } + + return helpText.ToString(); } public override string GetHelpSummary(IShellState shellState, HttpState programState) diff --git a/src/Microsoft.HttpRepl/Commands/ChangeDirectoryCommand.cs b/src/Microsoft.HttpRepl/Commands/ChangeDirectoryCommand.cs index a18aa2df9f..4fd011d182 100644 --- a/src/Microsoft.HttpRepl/Commands/ChangeDirectoryCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/ChangeDirectoryCommand.cs @@ -4,11 +4,13 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.HttpRepl.Suggestions; using Microsoft.Repl; using Microsoft.Repl.Commanding; +using Microsoft.Repl.ConsoleHandling; using Microsoft.Repl.Parsing; namespace Microsoft.HttpRepl.Commands @@ -60,18 +62,19 @@ namespace Microsoft.HttpRepl.Commands return Task.CompletedTask; } - protected override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("cd") + public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("cd") .MaximumArgCount(1) .Finish(); protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult) { - if (commandInput.Arguments.Count == 1 && !string.IsNullOrEmpty(commandInput.Arguments[0]?.Text)) - { - return "Prints the current directory if no argument is specified, otherwise changes to the specified directory"; - } + var help = new StringBuilder(); + help.Append("Usage:".Bold()); + help.AppendLine("cd [directory]"); + help.AppendLine(); + help.AppendLine("Prints the current directory if no argument is specified, otherwise changes to the specified directory"); - return "Changes to the directory " + commandInput.Arguments[0].Text; + return help.ToString(); } public override string GetHelpSummary(IShellState shellState, HttpState programState) diff --git a/src/Microsoft.HttpRepl/Commands/ConfigCommand.cs b/src/Microsoft.HttpRepl/Commands/ConfigCommand.cs index 938936303f..9ad71ea15d 100644 --- a/src/Microsoft.HttpRepl/Commands/ConfigCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/ConfigCommand.cs @@ -55,7 +55,7 @@ namespace Microsoft.HttpRepl.Commands } } - protected override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("config").Finish(); + public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("config").Finish(); protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult) { diff --git a/src/Microsoft.HttpRepl/Commands/EchoCommand.cs b/src/Microsoft.HttpRepl/Commands/EchoCommand.cs index e81ff810d4..e4c0ace75a 100644 --- a/src/Microsoft.HttpRepl/Commands/EchoCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/EchoCommand.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Repl; @@ -37,11 +38,16 @@ namespace Microsoft.HttpRepl.Commands return Task.CompletedTask; } - protected override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("echo").ExactArgCount(1).Finish(); + public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("echo").ExactArgCount(1).Finish(); protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult) { - return "Turns request echoing on or off"; + var helpText = new StringBuilder(); + helpText.Append("Usage: ".Bold()); + helpText.AppendLine($"echo [on|off]"); + helpText.AppendLine(); + helpText.AppendLine($"Turns request echoing on or off. When request echoing is on we will display a text representation of requests made by the CLI."); + return helpText.ToString(); } public override string GetHelpSummary(IShellState shellState, HttpState programState) diff --git a/src/Microsoft.HttpRepl/Commands/ExitCommand.cs b/src/Microsoft.HttpRepl/Commands/ExitCommand.cs index af76ad95df..ea6bf74b68 100644 --- a/src/Microsoft.HttpRepl/Commands/ExitCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/ExitCommand.cs @@ -1,10 +1,12 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Repl; using Microsoft.Repl.Commanding; +using Microsoft.Repl.ConsoleHandling; using Microsoft.Repl.Parsing; namespace Microsoft.HttpRepl.Commands @@ -17,11 +19,16 @@ namespace Microsoft.HttpRepl.Commands return Task.CompletedTask; } - protected override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("exit").ExactArgCount(0).Finish(); + public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("exit").ExactArgCount(0).Finish(); protected override string GetHelpDetails(IShellState shellState, object programState, DefaultCommandInput commandInput, ICoreParseResult parseResult) { - return "Exits the shell"; + var helpText = new StringBuilder(); + helpText.Append("Usage: ".Bold()); + helpText.AppendLine($"exit"); + helpText.AppendLine(); + helpText.AppendLine($"Exits the shell"); + return helpText.ToString(); } public override string GetHelpSummary(IShellState shellState, object programState) diff --git a/src/Microsoft.HttpRepl/Commands/HelpCommand.cs b/src/Microsoft.HttpRepl/Commands/HelpCommand.cs index 6677bde928..26e4468e8a 100644 --- a/src/Microsoft.HttpRepl/Commands/HelpCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/HelpCommand.cs @@ -10,6 +10,7 @@ using Microsoft.HttpRepl.Preferences; using Microsoft.HttpRepl.Suggestions; using Microsoft.Repl; using Microsoft.Repl.Commanding; +using Microsoft.Repl.ConsoleHandling; using Microsoft.Repl.Parsing; namespace Microsoft.HttpRepl.Commands @@ -46,7 +47,30 @@ namespace Microsoft.HttpRepl.Commands if (!string.IsNullOrEmpty(help)) { anyHelp = true; + shellState.ConsoleManager.WriteLine(); shellState.ConsoleManager.WriteLine(help); + + var structuredCommand = command as CommandWithStructuredInputBase; + if (structuredCommand != null && structuredCommand.InputSpec.Options.Any()) + { + shellState.ConsoleManager.WriteLine(); + shellState.ConsoleManager.WriteLine("Options:".Bold()); + foreach (var option in structuredCommand.InputSpec.Options) + { + var optionText = string.Empty; + foreach (var form in option.Forms) + { + if (!string.IsNullOrEmpty(optionText)) + { + optionText += "|"; + } + optionText += form; + } + shellState.ConsoleManager.WriteLine($" {optionText}"); + } + } + + break; } } } @@ -67,39 +91,42 @@ namespace Microsoft.HttpRepl.Commands } } - IDirectoryStructure structure = programState.Structure.TraverseTo(parseResult.Sections[1]); - if (structure.DirectoryNames.Any()) + //Structure is null because, for example, SwaggerEndpoint exists but is not reachable. + if (programState.Structure != null) { - shellState.ConsoleManager.WriteLine("Child directories:"); - - foreach (string name in structure.DirectoryNames) + IDirectoryStructure structure = programState.Structure.TraverseTo(parseResult.Sections[1]); + if (structure.DirectoryNames.Any()) { - shellState.ConsoleManager.WriteLine(" " + name + "/"); + shellState.ConsoleManager.WriteLine("Child directories:"); + + foreach (string name in structure.DirectoryNames) + { + shellState.ConsoleManager.WriteLine(" " + name + "/"); + } + anyHelp = true; } - anyHelp = true; - } - - if (structure.RequestInfo != null) - { - if (structure.RequestInfo.Methods.Count > 0) + if (structure.RequestInfo != null) { - if (anyHelp) + if (structure.RequestInfo.Methods.Count > 0) { - shellState.ConsoleManager.WriteLine(); - } - - anyHelp = true; - shellState.ConsoleManager.WriteLine("Available methods:"); - - foreach (string method in structure.RequestInfo.Methods) - { - shellState.ConsoleManager.WriteLine(" " + method.ToUpperInvariant()); - IReadOnlyList accepts = structure.RequestInfo.ContentTypesByMethod[method]; - string acceptsString = string.Join(", ", accepts.Where(x => !string.IsNullOrEmpty(x))); - if (!string.IsNullOrEmpty(acceptsString)) + if (anyHelp) { - shellState.ConsoleManager.WriteLine(" Accepts: " + acceptsString); + shellState.ConsoleManager.WriteLine(); + } + + anyHelp = true; + shellState.ConsoleManager.WriteLine("Available methods:"); + + foreach (string method in structure.RequestInfo.Methods) + { + shellState.ConsoleManager.WriteLine(" " + method.ToUpperInvariant()); + IReadOnlyList accepts = structure.RequestInfo.ContentTypesByMethod[method]; + string acceptsString = string.Join(", ", accepts.Where(x => !string.IsNullOrEmpty(x))); + if (!string.IsNullOrEmpty(acceptsString)) + { + shellState.ConsoleManager.WriteLine(" Accepts: " + acceptsString); + } } } } @@ -176,15 +203,54 @@ namespace Microsoft.HttpRepl.Commands public void CoreGetHelp(IShellState shellState, ICommandDispatcher dispatcher, HttpState programState) { - foreach (ICommand command in dispatcher.Commands) - { - string help = command.GetHelpSummary(shellState, programState); + shellState.ConsoleManager.WriteLine(); + shellState.ConsoleManager.WriteLine("HTTP Commands:".Bold().Cyan()); + shellState.ConsoleManager.WriteLine("Use these commands to execute requests against your application."); + shellState.ConsoleManager.WriteLine(); - if (!string.IsNullOrEmpty(help)) - { - shellState.ConsoleManager.WriteLine(help); - } - } + const int navCommandColumn = -15; + + shellState.ConsoleManager.WriteLine($"{"GET",navCommandColumn}{"Issues a GET request."}"); + shellState.ConsoleManager.WriteLine($"{"POST",navCommandColumn}{"Issues a POST request."}"); + shellState.ConsoleManager.WriteLine($"{"PUT",navCommandColumn}{"Issues a PUT request."}"); + shellState.ConsoleManager.WriteLine($"{"DELETE",navCommandColumn}{"Issues a DELETE request."}"); + shellState.ConsoleManager.WriteLine($"{"PATCH",navCommandColumn}{"Issues a PATCH request."}"); + shellState.ConsoleManager.WriteLine($"{"HEAD",navCommandColumn}{"Issues a HEAD request."}"); + shellState.ConsoleManager.WriteLine($"{"OPTIONS",navCommandColumn}{"Issues an OPTIONS request."}"); + shellState.ConsoleManager.WriteLine(); + shellState.ConsoleManager.WriteLine($"{"set header",navCommandColumn}{"Sets or clears a header for all requests. e.g. `set header content-type:application/json`"}"); + shellState.ConsoleManager.WriteLine(); + + shellState.ConsoleManager.WriteLine(); + shellState.ConsoleManager.WriteLine("Navigation Commands:".Bold().Cyan()); + shellState.ConsoleManager.WriteLine("The REPL allows you to navigate your URL space and focus on specific APIS that you are working on."); + shellState.ConsoleManager.WriteLine(); + + shellState.ConsoleManager.WriteLine($"{"set base",navCommandColumn}{"Set the base URI. e.g. `set base http://locahost:5000`"}"); + shellState.ConsoleManager.WriteLine($"{"set swagger",navCommandColumn}{"Set the URI, relative to your base if set, of the Swagger document for this API. e.g. `set swagger /swagger/v1/swagger.json`"}"); + shellState.ConsoleManager.WriteLine($"{"ls",navCommandColumn}{"Show all endpoints for the current path."}"); + shellState.ConsoleManager.WriteLine($"{"cd",navCommandColumn}{"Append the given directory to the currently selected path, or move up a path when using `cd ..`."}"); + + shellState.ConsoleManager.WriteLine(); + shellState.ConsoleManager.WriteLine("Shell Commands:".Bold().Cyan()); + shellState.ConsoleManager.WriteLine("Use these commands to interact with the REPL shell."); + shellState.ConsoleManager.WriteLine(); + + shellState.ConsoleManager.WriteLine($"{"clear",navCommandColumn}{"Removes all text from the shell."}"); + shellState.ConsoleManager.WriteLine($"{"echo [on/off]",navCommandColumn}{"Turns request echoing on or off, show the request that was mode when using request commands."}"); + shellState.ConsoleManager.WriteLine($"{"exit",navCommandColumn}{"Exit the shell."}"); + + shellState.ConsoleManager.WriteLine(); + shellState.ConsoleManager.WriteLine("REPL Customization Commands:".Bold().Cyan()); + shellState.ConsoleManager.WriteLine("Use these commands to customize the REPL behavior.."); + shellState.ConsoleManager.WriteLine(); + + shellState.ConsoleManager.WriteLine($"{"pref [get/set]",navCommandColumn}{"Allows viewing or changing preferences, e.g. 'pref set editor.command.default 'C:\\Program Files\\Microsoft VS Code\\Code.exe'`"}"); + shellState.ConsoleManager.WriteLine($"{"run",navCommandColumn}{"Runs the script at the given path. A script is a set of commands that can be typed with one command per line."}"); + shellState.ConsoleManager.WriteLine($"{"ui",navCommandColumn}{"Displays the swagger UI page, if available, in the default browser."}"); + shellState.ConsoleManager.WriteLine(); + shellState.ConsoleManager.WriteLine("Use help to learn more details about individual commands. e.g. `help get`".Bold().Cyan()); + shellState.ConsoleManager.WriteLine(); } } } diff --git a/src/Microsoft.HttpRepl/Commands/ListCommand.cs b/src/Microsoft.HttpRepl/Commands/ListCommand.cs index b0641f186b..ff604e9fe3 100644 --- a/src/Microsoft.HttpRepl/Commands/ListCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/ListCommand.cs @@ -5,11 +5,13 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.HttpRepl.Preferences; using Microsoft.Repl; using Microsoft.Repl.Commanding; +using Microsoft.Repl.ConsoleHandling; using Microsoft.Repl.Parsing; namespace Microsoft.HttpRepl.Commands @@ -118,19 +120,24 @@ namespace Microsoft.HttpRepl.Commands - protected override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("ls").AlternateName("dir") + public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("ls").AlternateName("dir") .MaximumArgCount(1) .WithOption(new CommandOptionSpecification(RecursiveOption, maximumOccurrences: 1, acceptsValue: true, forms: new[] {"-r", "--recursive"})) .Finish(); protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult) { - return "Lists the contents of a directory"; + var helpText = new StringBuilder(); + helpText.Append("Usage: ".Bold()); + helpText.AppendLine($"ls [Options]"); + helpText.AppendLine(); + helpText.AppendLine($"Displays the known routes at the current location. Requires a Swagger document to be set."); + return helpText.ToString(); } public override string GetHelpSummary(IShellState shellState, HttpState programState) { - return "ls - Performs a directory listing"; + return "ls - List known routes for the current location"; } protected override IEnumerable GetArgumentSuggestionsForText(IShellState shellState, HttpState programState, ICoreParseResult parseResult, DefaultCommandInput commandInput, string normalCompletionString) diff --git a/src/Microsoft.HttpRepl/Commands/PrefCommand.cs b/src/Microsoft.HttpRepl/Commands/PrefCommand.cs index d4d5d19b4a..02df9eef47 100644 --- a/src/Microsoft.HttpRepl/Commands/PrefCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/PrefCommand.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.HttpRepl.Preferences; @@ -42,19 +43,86 @@ namespace Microsoft.HttpRepl.Commands protected override string GetHelpDetails(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult) { + var helpText = new StringBuilder(); + helpText.Append("Usage: ".Bold()); + if (commandInput.Arguments.Count == 0 || !_allowedSubcommands.Contains(commandInput.Arguments[0]?.Text)) { - return "pref [get/set] {setting} [{value}] - Get or sets a preference to a particular value"; + helpText.AppendLine("pref [get/set] {setting} [{value}] - Get or sets a preference to a particular value"); } - - if (string.Equals(commandInput.Arguments[0].Text, "get", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(commandInput.Arguments[0].Text, "get", StringComparison.OrdinalIgnoreCase)) { - return "pref get [{setting}] - Gets the value of the specified preference or lists all preferences if no preference is specified"; + helpText.AppendLine("pref get [{setting}] - Gets the value of the specified preference or lists all preferences if no preference is specified"); } else { - return "pref set {setting} [{value}] - Sets (or clears if value is not specified) the value of the specified preference"; + helpText.AppendLine("pref set {setting} [{value}] - Sets (or clears if value is not specified) the value of the specified preference"); } + + helpText.AppendLine(); + helpText.AppendLine("Current Default Preferences:"); + foreach (var pref in programState.DefaultPreferences) + { + var val = pref.Value; + if (pref.Key.Contains("colors")) + { + val = GetColor(val); + } + helpText.AppendLine($"{pref.Key,-50}{val}"); + } + helpText.AppendLine(); + helpText.AppendLine("Current Preferences:"); + foreach (var pref in programState.Preferences) + { + var val = pref.Value; + if (pref.Key.Contains("colors")) + { + val = GetColor(val); + } + helpText.AppendLine($"{pref.Key,-50}{val}"); + } + + return helpText.ToString(); + } + + private static string GetColor(string value) + { + if (value.Contains("Bold")) + { + value = value.Bold(); + } + + if (value.Contains("Yellow")) + { + value = value.Yellow(); + } + + if (value.Contains("Cyan")) + { + value = value.Cyan(); + } + + if (value.Contains("Magenta")) + { + value = value.Magenta(); + } + + if (value.Contains("Green")) + { + value = value.Green(); + } + + if (value.Contains("White")) + { + value = value.White(); + } + + if (value.Contains("Black")) + { + value = value.Black(); + } + + return value; } protected override Task ExecuteAsync(IShellState shellState, HttpState programState, DefaultCommandInput commandInput, ICoreParseResult parseResult, CancellationToken cancellationToken) @@ -123,7 +191,7 @@ namespace Microsoft.HttpRepl.Commands return Task.CompletedTask; } - protected override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("pref") + public override CommandInputSpecification InputSpec { get; } = CommandInputSpecification.Create("pref") .MinimumArgCount(1) .MaximumArgCount(3) .Finish(); diff --git a/src/Microsoft.HttpRepl/Commands/RunCommand.cs b/src/Microsoft.HttpRepl/Commands/RunCommand.cs index 3228dbccf1..09f4649812 100644 --- a/src/Microsoft.HttpRepl/Commands/RunCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/RunCommand.cs @@ -4,10 +4,12 @@ using System; using System.Collections.Generic; using System.IO; +using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Repl; using Microsoft.Repl.Commanding; +using Microsoft.Repl.ConsoleHandling; using Microsoft.Repl.Parsing; using Microsoft.Repl.Scripting; using Microsoft.Repl.Suggestions; @@ -48,12 +50,13 @@ namespace Microsoft.HttpRepl.Commands { if (parseResult.Sections.Count > 0 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase)) { - if (parseResult.Sections.Count == 1) - { - return "Runs the specified script"; - } - - return "Runs the script " + parseResult.Sections[1]; + var helpText = new StringBuilder(); + helpText.Append("Usage: ".Bold()); + helpText.AppendLine("run {path to script}"); + helpText.AppendLine(); + helpText.AppendLine("Runs the specified script."); + helpText.AppendLine("A script is a text file containing one CLI command per line. Each line will be run as if it was typed into the CLI."); + return helpText.ToString(); } return null; diff --git a/src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs b/src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs index 76166d5c53..aa12ec819e 100644 --- a/src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Net.Http; using System.Net.Sockets; +using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Repl; @@ -80,7 +81,12 @@ namespace Microsoft.HttpRepl.Commands { if (parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase)) { - return Description; + var helpText = new StringBuilder(); + helpText.Append("Usage: ".Bold()); + helpText.AppendLine($"set base [uri]"); + helpText.AppendLine(); + helpText.AppendLine(Description); + return helpText.ToString(); } return null; diff --git a/src/Microsoft.HttpRepl/Commands/SetHeaderCommand.cs b/src/Microsoft.HttpRepl/Commands/SetHeaderCommand.cs index 3db62f47b3..7c46906358 100644 --- a/src/Microsoft.HttpRepl/Commands/SetHeaderCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/SetHeaderCommand.cs @@ -4,11 +4,13 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.HttpRepl.Suggestions; using Microsoft.Repl; using Microsoft.Repl.Commanding; +using Microsoft.Repl.ConsoleHandling; using Microsoft.Repl.Parsing; namespace Microsoft.HttpRepl.Commands @@ -18,7 +20,7 @@ namespace Microsoft.HttpRepl.Commands private static readonly string Name = "set"; private static readonly string SubCommand = "header"; - public string Description => "set header {name} [{{value}}] - Sets or clears a header"; + public string Description => "set header {name} [value] - Sets or clears a header"; public bool? CanHandle(IShellState shellState, HttpState programState, ICoreParseResult parseResult) { @@ -43,12 +45,12 @@ namespace Microsoft.HttpRepl.Commands public string GetHelpDetails(IShellState shellState, HttpState programState, ICoreParseResult parseResult) { - if (parseResult.Sections.Count > 1 && string.Equals(parseResult.Sections[0], Name, StringComparison.OrdinalIgnoreCase) && string.Equals(parseResult.Sections[1], SubCommand, StringComparison.OrdinalIgnoreCase)) - { - return Description; - } - - return null; + var helpText = new StringBuilder(); + helpText.Append("Usage: ".Bold()); + helpText.AppendLine("set header {name} [value]"); + helpText.AppendLine(); + helpText.AppendLine("Sets or clears a header. When [value] is empty the header is cleared."); + return Description; } public string GetHelpSummary(IShellState shellState, HttpState programState) diff --git a/src/Microsoft.Repl/Commanding/CommandWithStructuredInputBase.cs b/src/Microsoft.Repl/Commanding/CommandWithStructuredInputBase.cs index a7e07b3cee..d087d4cea6 100644 --- a/src/Microsoft.Repl/Commanding/CommandWithStructuredInputBase.cs +++ b/src/Microsoft.Repl/Commanding/CommandWithStructuredInputBase.cs @@ -208,6 +208,6 @@ namespace Microsoft.Repl.Commanding protected abstract Task ExecuteAsync(IShellState shellState, TProgramState programState, DefaultCommandInput commandInput, TParseResult parseResult, CancellationToken cancellationToken); - protected abstract CommandInputSpecification InputSpec { get; } + public abstract CommandInputSpecification InputSpec { get; } } } From e975b87b91a16233e55426ca232d62df4267bd54 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 9 Sep 2018 12:10:33 -0700 Subject: [PATCH 0937/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index fbf093bdf8..4f54bb78c9 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,20 +3,20 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180907.3 - 2.2.0-preview2-35143 - 2.2.0-preview2-35143 - 2.2.0-preview2-35143 - 2.2.0-preview2-35143 - 2.2.0-preview2-35143 + 2.2.0-preview1-20180907.8 + 2.2.0-preview3-35202 + 2.2.0-preview3-35202 + 2.2.0-preview3-35202 + 2.2.0-preview3-35202 + 2.2.0-preview3-35202 2.0.9 - 2.1.2 - 2.2.0-preview1-26618-02 + 2.1.3 + 2.2.0-preview2-26905-02 15.6.1 5.2.6 2.0.3 11.0.2 - 4.5.1 + 4.6.0-preview2-26905-02 4.5.0 9.0.1 2.3.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index be535d1f04..552300b0ce 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180907.3 -commithash:2315030c7f3de2af0f16cf64502321937b6c4315 +version:2.2.0-preview1-20180907.8 +commithash:078918eb5c1f176ee1da351c584fb4a4d7491aa0 From 89dedd068c0fccf80850f825c20e7c72754386dc Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 9 Sep 2018 19:11:42 +0000 Subject: [PATCH 0938/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 1ad634bd36..63a379c30a 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,19 +3,19 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-20180907.5 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-preview1-26905-03 + 3.0.0-alpha1-20180907.9 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-preview1-26907-04 15.6.1 5.2.6 2.0.3 11.0.2 - 4.6.0-preview1-26831-06 - 4.6.0-preview1-26831-06 + 4.6.0-preview1-26905-03 + 4.6.0-preview1-26905-03 9.0.1 2.3.1 2.4.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index dc3466e65d..86de522933 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180907.5 -commithash:49785528468590252ade5a7ed91f1e6de466b89f +version:3.0.0-alpha1-20180907.9 +commithash:f997365a8832ff0a3cbd9a98df45734ac2723fa0 From 05a34009e8184ae3a48bada25d9681f310746301 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 9 Sep 2018 12:13:56 -0700 Subject: [PATCH 0939/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 14 +++++++------- korebuild-lock.txt | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index da718d7433..0c12fec871 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,14 +3,14 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180821.1 - 2.2.0-preview2-35143 - 2.2.0-preview2-35143 - 2.2.0-preview2-35143 - 2.2.0-preview2-35143 + 2.2.0-preview1-20180907.8 + 2.2.0-preview3-35202 + 2.2.0-preview3-35202 + 2.2.0-preview3-35202 + 2.2.0-preview3-35202 2.0.9 - 2.1.2 - 2.2.0-preview1-26618-02 + 2.1.3 + 2.2.0-preview2-26905-02 15.6.1 2.0.3 4.5.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index ad704918df..312f82f9a5 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180821.1 -commithash:c8d0cc52cd1abb697be24e288ffd54f8fae8bf17 +version:2.2.0-preview1-20180907.8 +commithash:078918eb5c1f176ee1da351c584fb4a4d7491aa0 From 999f0724174123be49e7f7f58f920ef2d6f5c3e5 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 9 Sep 2018 19:14:59 +0000 Subject: [PATCH 0940/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 074ac8b042..ed37b88510 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-20180821.3 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 - 3.0.0-alpha1-10400 + 3.0.0-alpha1-20180907.9 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 + 3.0.0-alpha1-10419 2.0.9 2.1.3 2.2.0-preview2-26905-02 15.6.1 2.0.3 - 4.6.0-preview1-26831-06 + 4.6.0-preview1-26905-03 2.3.1 2.4.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 767a471795..b614cab6e8 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180821.3 -commithash:0939a90812deb1c604eb9a4768869687495fc1dd +version:3.0.0-alpha1-20180907.9 +commithash:f997365a8832ff0a3cbd9a98df45734ac2723fa0 From 3d0502f947a3ff8283d451ac140fa9d9f783b931 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 9 Sep 2018 12:21:00 -0700 Subject: [PATCH 0941/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index c19ec5d60d..d36bf72206 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,13 +3,13 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180821.1 - 2.2.0-preview2-35143 + 2.2.0-preview1-20180907.8 + 2.2.0-preview3-35202 4.5.0 - 2.2.0-preview2-35143 + 2.2.0-preview3-35202 2.0.9 - 2.1.2 - 2.2.0-preview1-26618-02 + 2.1.3 + 2.2.0-preview2-26905-02 15.6.1 4.7.49 2.0.3 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index ad704918df..312f82f9a5 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180821.1 -commithash:c8d0cc52cd1abb697be24e288ffd54f8fae8bf17 +version:2.2.0-preview1-20180907.8 +commithash:078918eb5c1f176ee1da351c584fb4a4d7491aa0 From 6e7a133d7781d716776cc83c16d7c3928a70d13a Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 9 Sep 2018 19:22:30 +0000 Subject: [PATCH 0942/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 8 ++++---- korebuild-lock.txt | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 8f315c5a6b..f72fe1cf90 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-20180821.3 - 3.0.0-alpha1-10400 - 4.6.0-preview1-26831-06 - 3.0.0-alpha1-10400 + 3.0.0-alpha1-20180907.9 + 3.0.0-alpha1-10419 + 4.6.0-preview1-26905-03 + 3.0.0-alpha1-10419 2.0.9 2.1.3 2.2.0-preview2-26905-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 767a471795..b614cab6e8 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180821.3 -commithash:0939a90812deb1c604eb9a4768869687495fc1dd +version:3.0.0-alpha1-20180907.9 +commithash:f997365a8832ff0a3cbd9a98df45734ac2723fa0 From 7517263bd4d089680757272dc665d4e94d51950b Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 16 Sep 2018 12:09:26 -0700 Subject: [PATCH 0943/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 4f54bb78c9..deb0947864 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180907.8 - 2.2.0-preview3-35202 - 2.2.0-preview3-35202 - 2.2.0-preview3-35202 - 2.2.0-preview3-35202 - 2.2.0-preview3-35202 + 2.2.0-preview1-20180911.1 + 2.2.0-preview3-35252 + 2.2.0-preview3-35252 + 2.2.0-preview3-35252 + 2.2.0-preview3-35252 + 2.2.0-preview3-35252 2.0.9 2.1.3 2.2.0-preview2-26905-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 552300b0ce..1090ad6a92 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180907.8 -commithash:078918eb5c1f176ee1da351c584fb4a4d7491aa0 +version:2.2.0-preview1-20180911.1 +commithash:ddfecdfc6e8e4859db5a0daea578070b862aac65 From ac9106c9a1358fc0e380afb550fc161f45bd4d3a Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 16 Sep 2018 19:10:24 +0000 Subject: [PATCH 0944/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 18 +++++++++--------- korebuild-lock.txt | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 63a379c30a..022053637b 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,19 +3,19 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-20180907.9 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-preview1-26907-04 + 3.0.0-alpha1-20180911.2 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-preview1-26907-05 15.6.1 5.2.6 2.0.3 11.0.2 - 4.6.0-preview1-26905-03 - 4.6.0-preview1-26905-03 + 4.6.0-preview1-26907-04 + 4.6.0-preview1-26907-04 9.0.1 2.3.1 2.4.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 86de522933..a3511df82d 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180907.9 -commithash:f997365a8832ff0a3cbd9a98df45734ac2723fa0 +version:3.0.0-alpha1-20180911.2 +commithash:2a2b7dbea1b247930c41da497f4ea0b2bb756818 From 89a2849126c5e06116dca8cb629af3c6ab44bf56 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 16 Sep 2018 12:12:38 -0700 Subject: [PATCH 0945/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 0c12fec871..e49c4108ac 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,11 +3,11 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180907.8 - 2.2.0-preview3-35202 - 2.2.0-preview3-35202 - 2.2.0-preview3-35202 - 2.2.0-preview3-35202 + 2.2.0-preview1-20180911.1 + 2.2.0-preview3-35252 + 2.2.0-preview3-35252 + 2.2.0-preview3-35252 + 2.2.0-preview3-35252 2.0.9 2.1.3 2.2.0-preview2-26905-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 312f82f9a5..7124f37441 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180907.8 -commithash:078918eb5c1f176ee1da351c584fb4a4d7491aa0 +version:2.2.0-preview1-20180911.1 +commithash:ddfecdfc6e8e4859db5a0daea578070b862aac65 From 4d94ef727a7d5fee371c83e7f511a0581b4fa4f7 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 16 Sep 2018 19:13:58 +0000 Subject: [PATCH 0946/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index ed37b88510..6f10728c12 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,17 +3,17 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-20180907.9 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 - 3.0.0-alpha1-10419 + 3.0.0-alpha1-20180911.2 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 + 3.0.0-alpha1-10454 2.0.9 2.1.3 2.2.0-preview2-26905-02 15.6.1 2.0.3 - 4.6.0-preview1-26905-03 + 4.6.0-preview1-26907-04 2.3.1 2.4.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index b614cab6e8..a817c10d28 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180907.9 -commithash:f997365a8832ff0a3cbd9a98df45734ac2723fa0 +version:3.0.0-alpha1-20180911.2 +commithash:2a2b7dbea1b247930c41da497f4ea0b2bb756818 From 41614badf9bfac6265ea395b090a58ddcbcde067 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 16 Sep 2018 12:19:33 -0700 Subject: [PATCH 0947/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 6 +++--- korebuild-lock.txt | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index d36bf72206..6500ecf53f 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180907.8 - 2.2.0-preview3-35202 + 2.2.0-preview1-20180911.1 + 2.2.0-preview3-35252 4.5.0 - 2.2.0-preview3-35202 + 2.2.0-preview3-35252 2.0.9 2.1.3 2.2.0-preview2-26905-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 312f82f9a5..7124f37441 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180907.8 -commithash:078918eb5c1f176ee1da351c584fb4a4d7491aa0 +version:2.2.0-preview1-20180911.1 +commithash:ddfecdfc6e8e4859db5a0daea578070b862aac65 From 09171963e0fb48740ca5394ad9cfc8c12e3508cd Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 16 Sep 2018 19:21:30 +0000 Subject: [PATCH 0948/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 8 ++++---- korebuild-lock.txt | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index f72fe1cf90..457862baaa 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-20180907.9 - 3.0.0-alpha1-10419 - 4.6.0-preview1-26905-03 - 3.0.0-alpha1-10419 + 3.0.0-alpha1-20180911.2 + 3.0.0-alpha1-10454 + 4.6.0-preview1-26907-04 + 3.0.0-alpha1-10454 2.0.9 2.1.3 2.2.0-preview2-26905-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index b614cab6e8..a817c10d28 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180907.9 -commithash:f997365a8832ff0a3cbd9a98df45734ac2723fa0 +version:3.0.0-alpha1-20180911.2 +commithash:2a2b7dbea1b247930c41da497f4ea0b2bb756818 From 986d9d48c945daff106dbe85d936862e61ca6c92 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Sat, 8 Sep 2018 12:10:37 -0700 Subject: [PATCH 0949/1029] Fix typo --- src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs b/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs index 22be314827..3ed30f4a35 100644 --- a/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs +++ b/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs @@ -156,7 +156,7 @@ namespace Microsoft.Repl.Commanding } shellState.ConsoleManager.Error.WriteLine("No matching command found".Red().Bold()); - shellState.ConsoleManager.Error.WriteLine("Execute 'help' to se available commands".Red().Bold()); + shellState.ConsoleManager.Error.WriteLine("Execute 'help' to see available commands".Red().Bold()); } } From 46aefb86dd227b3b45ee1e2fc620764487edfeaa Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 23 Sep 2018 12:10:04 -0700 Subject: [PATCH 0950/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 022053637b..2074d0ffa2 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-20180911.2 - 3.0.0-alpha1-10454 - 3.0.0-alpha1-10454 - 3.0.0-alpha1-10454 - 3.0.0-alpha1-10454 - 3.0.0-alpha1-10454 + 3.0.0-alpha1-20180919.1 + 3.0.0-alpha1-10495 + 3.0.0-alpha1-10495 + 3.0.0-alpha1-10495 + 3.0.0-alpha1-10495 + 3.0.0-alpha1-10495 3.0.0-preview1-26907-05 15.6.1 5.2.6 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index a3511df82d..9a87e4ccb7 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180911.2 -commithash:2a2b7dbea1b247930c41da497f4ea0b2bb756818 +version:3.0.0-alpha1-20180919.1 +commithash:3066ae0a230870ea07e3f132605b5e5493f8bbd4 From 6c39b06a5988e0b17c685024b0ba26cefe6b3208 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 23 Sep 2018 19:11:11 +0000 Subject: [PATCH 0951/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index deb0947864..53c1c40ecb 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180911.1 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 + 2.2.0-preview1-20180918.1 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 2.0.9 2.1.3 2.2.0-preview2-26905-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 1090ad6a92..8491de70e6 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180911.1 -commithash:ddfecdfc6e8e4859db5a0daea578070b862aac65 +version:2.2.0-preview1-20180918.1 +commithash:ad5e3fc53442741a0dd49bce437d2ac72f4b5800 From fa8ba9d220d19f2d1825c9f203395e2eb2dc254e Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 23 Sep 2018 12:13:24 -0700 Subject: [PATCH 0952/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 6f10728c12..d34ed3bd56 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,11 +3,11 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-20180911.2 - 3.0.0-alpha1-10454 - 3.0.0-alpha1-10454 - 3.0.0-alpha1-10454 - 3.0.0-alpha1-10454 + 3.0.0-alpha1-20180919.1 + 3.0.0-alpha1-10495 + 3.0.0-alpha1-10495 + 3.0.0-alpha1-10495 + 3.0.0-alpha1-10495 2.0.9 2.1.3 2.2.0-preview2-26905-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index a817c10d28..d66a13bdc7 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180911.2 -commithash:2a2b7dbea1b247930c41da497f4ea0b2bb756818 +version:3.0.0-alpha1-20180919.1 +commithash:3066ae0a230870ea07e3f132605b5e5493f8bbd4 From e18cef609ece13d17a7e8880d8dc466e02c73fac Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 23 Sep 2018 19:14:47 +0000 Subject: [PATCH 0953/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- korebuild-lock.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index e49c4108ac..3d199851a2 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,11 +3,11 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180911.1 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 - 2.2.0-preview3-35252 + 2.2.0-preview1-20180918.1 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 + 2.2.0-preview3-35301 2.0.9 2.1.3 2.2.0-preview2-26905-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 7124f37441..649bf2ba0b 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180911.1 -commithash:ddfecdfc6e8e4859db5a0daea578070b862aac65 +version:2.2.0-preview1-20180918.1 +commithash:ad5e3fc53442741a0dd49bce437d2ac72f4b5800 From a7056ce4e68b871d24d08da7f496c3d95629edc8 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 23 Sep 2018 12:20:22 -0700 Subject: [PATCH 0954/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 6 +++--- korebuild-lock.txt | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 457862baaa..11381ccbfb 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-20180911.2 - 3.0.0-alpha1-10454 + 3.0.0-alpha1-20180919.1 + 3.0.0-alpha1-10495 4.6.0-preview1-26907-04 - 3.0.0-alpha1-10454 + 3.0.0-alpha1-10495 2.0.9 2.1.3 2.2.0-preview2-26905-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index a817c10d28..d66a13bdc7 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180911.2 -commithash:2a2b7dbea1b247930c41da497f4ea0b2bb756818 +version:3.0.0-alpha1-20180919.1 +commithash:3066ae0a230870ea07e3f132605b5e5493f8bbd4 From 2fcf2215d8b7b450954475d899b682dd9aa3e9fe Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 23 Sep 2018 19:22:14 +0000 Subject: [PATCH 0955/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 6 +++--- korebuild-lock.txt | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 6500ecf53f..b6ca4ad584 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,10 +3,10 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180911.1 - 2.2.0-preview3-35252 + 2.2.0-preview1-20180918.1 + 2.2.0-preview3-35301 4.5.0 - 2.2.0-preview3-35252 + 2.2.0-preview3-35301 2.0.9 2.1.3 2.2.0-preview2-26905-02 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 7124f37441..649bf2ba0b 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180911.1 -commithash:ddfecdfc6e8e4859db5a0daea578070b862aac65 +version:2.2.0-preview1-20180918.1 +commithash:ad5e3fc53442741a0dd49bce437d2ac72f4b5800 From c601038484606dab00000ed9bf7581a5659b2215 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 26 Sep 2018 14:24:22 -0700 Subject: [PATCH 0956/1029] Remove duplicate PackageReferences --- test/Microsoft.Repl.Tests/Microsoft.Repl.Tests.csproj | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/Microsoft.Repl.Tests/Microsoft.Repl.Tests.csproj b/test/Microsoft.Repl.Tests/Microsoft.Repl.Tests.csproj index 52fbd0de16..31a83d818e 100644 --- a/test/Microsoft.Repl.Tests/Microsoft.Repl.Tests.csproj +++ b/test/Microsoft.Repl.Tests/Microsoft.Repl.Tests.csproj @@ -2,16 +2,8 @@ netcoreapp2.2 - - false - - - - - - From 0157e38a23bbe7ef827a34c221bc3cd268f242a7 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 26 Sep 2018 15:05:40 -0700 Subject: [PATCH 0957/1029] Fix the path for SignedPackageFile and include the VSIX .dll in signing --- build/VSIX.targets | 1 + .../Microsoft.HttpRepl.csproj | 8 ++++---- .../dotnet-user-secrets.csproj | 20 +++++++++---------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/build/VSIX.targets b/build/VSIX.targets index 687fd72b24..058c4dd0fd 100644 --- a/build/VSIX.targets +++ b/build/VSIX.targets @@ -41,6 +41,7 @@ + diff --git a/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj b/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj index 72f3e8fc1e..821e7398b5 100644 --- a/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj +++ b/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj @@ -21,10 +21,10 @@ - - - - + + + + diff --git a/src/dotnet-user-secrets/dotnet-user-secrets.csproj b/src/dotnet-user-secrets/dotnet-user-secrets.csproj index ae77d9bffd..5bcc7e7f57 100644 --- a/src/dotnet-user-secrets/dotnet-user-secrets.csproj +++ b/src/dotnet-user-secrets/dotnet-user-secrets.csproj @@ -24,18 +24,18 @@ - - - - - - - - - + + + + + + + + + - + From 4baa07ccae9665416044bee78cc98cd9bebef2b3 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 27 Sep 2018 12:53:38 -0700 Subject: [PATCH 0958/1029] Update code signing properties and configuration --- Directory.Build.props | 4 ---- build/VSIX.targets | 2 +- .../Microsoft.HttpRepl.csproj | 2 +- src/dotnet-sql-cache/dotnet-sql-cache.csproj | 18 +++++++------- .../dotnet-user-secrets.csproj | 24 +++++++++---------- 5 files changed, 22 insertions(+), 28 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 9921cb358e..80d6cc1543 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -14,10 +14,6 @@ $(MSBuildThisFileDirectory) $(MSBuildThisFileDirectory)build\Key.snk true - MicrosoftNuGet - Microsoft - Microsoft3rdPartyAppComponentDual - true true diff --git a/build/VSIX.targets b/build/VSIX.targets index 058c4dd0fd..af61b649a4 100644 --- a/build/VSIX.targets +++ b/build/VSIX.targets @@ -41,7 +41,7 @@ - + diff --git a/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj b/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj index 821e7398b5..d2552ef1e4 100644 --- a/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj +++ b/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj @@ -24,7 +24,7 @@ - + diff --git a/src/dotnet-sql-cache/dotnet-sql-cache.csproj b/src/dotnet-sql-cache/dotnet-sql-cache.csproj index 3f9ce05717..59017c22ff 100644 --- a/src/dotnet-sql-cache/dotnet-sql-cache.csproj +++ b/src/dotnet-sql-cache/dotnet-sql-cache.csproj @@ -21,15 +21,15 @@ - - - - - - - - - + + + + + + + + + diff --git a/src/dotnet-user-secrets/dotnet-user-secrets.csproj b/src/dotnet-user-secrets/dotnet-user-secrets.csproj index 5bcc7e7f57..15ce1c1d5a 100644 --- a/src/dotnet-user-secrets/dotnet-user-secrets.csproj +++ b/src/dotnet-user-secrets/dotnet-user-secrets.csproj @@ -23,22 +23,20 @@ - - - - - - - - - - - - - + + + + + + + + + + + From ba676a9f624b2ce6aee2d89cedc76c8d950a5f8b Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Thu, 27 Sep 2018 15:28:53 -0700 Subject: [PATCH 0959/1029] Update LICENSE.txt --- LICENSE.txt | 207 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 197 insertions(+), 10 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 7b2956ecee..b3b180cd51 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,14 +1,201 @@ -Copyright (c) .NET Foundation and Contributors + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -All rights reserved. + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -Licensed under the Apache License, Version 2.0 (the "License"); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at + 1. Definitions. - http://www.apache.org/licenses/LICENSE-2.0 + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -Unless required by applicable law or agreed to in writing, software distributed -under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -CONDITIONS OF ANY KIND, either express or implied. See the License for the -specific language governing permissions and limitations under the License. + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright (c) .NET Foundation and Contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From f21eca33e21f0b7d92aa163a54e7f91bb525557e Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Thu, 27 Sep 2018 15:32:20 -0700 Subject: [PATCH 0960/1029] Update LICENSE.txt --- LICENSE.txt | 207 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 197 insertions(+), 10 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 7b2956ecee..b3b180cd51 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,14 +1,201 @@ -Copyright (c) .NET Foundation and Contributors + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -All rights reserved. + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -Licensed under the Apache License, Version 2.0 (the "License"); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at + 1. Definitions. - http://www.apache.org/licenses/LICENSE-2.0 + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -Unless required by applicable law or agreed to in writing, software distributed -under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -CONDITIONS OF ANY KIND, either express or implied. See the License for the -specific language governing permissions and limitations under the License. + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright (c) .NET Foundation and Contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From 212465673ee9cff7b3e714eabf8257db5bd250e5 Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Thu, 27 Sep 2018 15:44:54 -0700 Subject: [PATCH 0961/1029] Update LICENSE.txt --- LICENSE.txt | 207 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 197 insertions(+), 10 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 7b2956ecee..b3b180cd51 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,14 +1,201 @@ -Copyright (c) .NET Foundation and Contributors + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -All rights reserved. + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -Licensed under the Apache License, Version 2.0 (the "License"); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at + 1. Definitions. - http://www.apache.org/licenses/LICENSE-2.0 + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -Unless required by applicable law or agreed to in writing, software distributed -under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -CONDITIONS OF ANY KIND, either express or implied. See the License for the -specific language governing permissions and limitations under the License. + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright (c) .NET Foundation and Contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From b88c6fcd192130778ba654219b41e4e8cc0270e2 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 28 Sep 2018 17:10:32 -0700 Subject: [PATCH 0962/1029] automated: bulk infrastructure updates. Update bootstrapper scripts and remove unnecessary signing properties --- run.ps1 | 6 +++--- run.sh | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/run.ps1 b/run.ps1 index 3b27382468..34604c7175 100644 --- a/run.ps1 +++ b/run.ps1 @@ -52,8 +52,8 @@ in the file are overridden by command line parameters. Example config file: ```json { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev", + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", + "channel": "master", "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" } ``` @@ -192,7 +192,7 @@ if (!$DotNetHome) { else { Join-Path $PSScriptRoot '.dotnet'} } -if (!$Channel) { $Channel = 'dev' } +if (!$Channel) { $Channel = 'master' } if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } # Execute diff --git a/run.sh b/run.sh index 02aac15874..4c1fed5646 100755 --- a/run.sh +++ b/run.sh @@ -220,7 +220,7 @@ if [ -f "$config_file" ]; then config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")" else - _error "$config_file contains invalid JSON." + __error "$config_file contains invalid JSON." exit 1 fi elif __machine_has python ; then @@ -228,7 +228,7 @@ if [ -f "$config_file" ]; then config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" else - _error "$config_file contains invalid JSON." + __error "$config_file contains invalid JSON." exit 1 fi elif __machine_has python3 ; then @@ -236,11 +236,11 @@ if [ -f "$config_file" ]; then config_channel="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" config_tools_source="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" else - _error "$config_file contains invalid JSON." + __error "$config_file contains invalid JSON." exit 1 fi else - _error 'Missing required command: jq or python. Could not parse the JSON file.' + __error 'Missing required command: jq or python. Could not parse the JSON file.' exit 1 fi @@ -248,7 +248,7 @@ if [ -f "$config_file" ]; then [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" fi -[ -z "$channel" ] && channel='dev' +[ -z "$channel" ] && channel='master' [ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' get_korebuild From 2c486604d7ff11ab83020aa29e5a3bc4b0fbb4d4 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 28 Sep 2018 17:10:34 -0700 Subject: [PATCH 0963/1029] automated: bulk infrastructure updates. Update bootstrapper scripts and remove unnecessary signing properties --- Directory.Build.props | 3 --- run.ps1 | 6 +++--- run.sh | 10 +++++----- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index d5b8bf3650..08fa9d2e3b 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,9 +13,6 @@ $(MSBuildThisFileDirectory) $(MSBuildThisFileDirectory)build\Key.snk true - Microsoft - MicrosoftNuGet - true true diff --git a/run.ps1 b/run.ps1 index 3b27382468..34604c7175 100644 --- a/run.ps1 +++ b/run.ps1 @@ -52,8 +52,8 @@ in the file are overridden by command line parameters. Example config file: ```json { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev", + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", + "channel": "master", "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" } ``` @@ -192,7 +192,7 @@ if (!$DotNetHome) { else { Join-Path $PSScriptRoot '.dotnet'} } -if (!$Channel) { $Channel = 'dev' } +if (!$Channel) { $Channel = 'master' } if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } # Execute diff --git a/run.sh b/run.sh index 02aac15874..4c1fed5646 100755 --- a/run.sh +++ b/run.sh @@ -220,7 +220,7 @@ if [ -f "$config_file" ]; then config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")" else - _error "$config_file contains invalid JSON." + __error "$config_file contains invalid JSON." exit 1 fi elif __machine_has python ; then @@ -228,7 +228,7 @@ if [ -f "$config_file" ]; then config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" else - _error "$config_file contains invalid JSON." + __error "$config_file contains invalid JSON." exit 1 fi elif __machine_has python3 ; then @@ -236,11 +236,11 @@ if [ -f "$config_file" ]; then config_channel="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" config_tools_source="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" else - _error "$config_file contains invalid JSON." + __error "$config_file contains invalid JSON." exit 1 fi else - _error 'Missing required command: jq or python. Could not parse the JSON file.' + __error 'Missing required command: jq or python. Could not parse the JSON file.' exit 1 fi @@ -248,7 +248,7 @@ if [ -f "$config_file" ]; then [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" fi -[ -z "$channel" ] && channel='dev' +[ -z "$channel" ] && channel='master' [ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' get_korebuild From 05b58f826367946013d890735e1326c20d391aa8 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 28 Sep 2018 17:10:36 -0700 Subject: [PATCH 0964/1029] automated: bulk infrastructure updates. Update bootstrapper scripts and remove unnecessary signing properties --- Directory.Build.props | 3 --- run.ps1 | 6 +++--- run.sh | 10 +++++----- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 0c6cb2e37f..4c54defe04 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -14,9 +14,6 @@ $(MSBuildThisFileDirectory) $(MSBuildThisFileDirectory)build\Key.snk true - Microsoft - MicrosoftNuGet - true true diff --git a/run.ps1 b/run.ps1 index 3b27382468..34604c7175 100644 --- a/run.ps1 +++ b/run.ps1 @@ -52,8 +52,8 @@ in the file are overridden by command line parameters. Example config file: ```json { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev", + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", + "channel": "master", "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" } ``` @@ -192,7 +192,7 @@ if (!$DotNetHome) { else { Join-Path $PSScriptRoot '.dotnet'} } -if (!$Channel) { $Channel = 'dev' } +if (!$Channel) { $Channel = 'master' } if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } # Execute diff --git a/run.sh b/run.sh index 02aac15874..4c1fed5646 100755 --- a/run.sh +++ b/run.sh @@ -220,7 +220,7 @@ if [ -f "$config_file" ]; then config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")" else - _error "$config_file contains invalid JSON." + __error "$config_file contains invalid JSON." exit 1 fi elif __machine_has python ; then @@ -228,7 +228,7 @@ if [ -f "$config_file" ]; then config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" else - _error "$config_file contains invalid JSON." + __error "$config_file contains invalid JSON." exit 1 fi elif __machine_has python3 ; then @@ -236,11 +236,11 @@ if [ -f "$config_file" ]; then config_channel="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" config_tools_source="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" else - _error "$config_file contains invalid JSON." + __error "$config_file contains invalid JSON." exit 1 fi else - _error 'Missing required command: jq or python. Could not parse the JSON file.' + __error 'Missing required command: jq or python. Could not parse the JSON file.' exit 1 fi @@ -248,7 +248,7 @@ if [ -f "$config_file" ]; then [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" fi -[ -z "$channel" ] && channel='dev' +[ -z "$channel" ] && channel='master' [ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' get_korebuild From 978d76d7613d457c84d8b932fededdca746b150b Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 30 Sep 2018 12:10:48 -0700 Subject: [PATCH 0965/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 2074d0ffa2..38d799449f 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,11 +4,11 @@ 3.0.0-alpha1-20180919.1 - 3.0.0-alpha1-10495 - 3.0.0-alpha1-10495 - 3.0.0-alpha1-10495 - 3.0.0-alpha1-10495 - 3.0.0-alpha1-10495 + 3.0.0-alpha1-10549 + 3.0.0-alpha1-10549 + 3.0.0-alpha1-10549 + 3.0.0-alpha1-10549 + 3.0.0-alpha1-10549 3.0.0-preview1-26907-05 15.6.1 5.2.6 From 37bdb72c5d35a5712c46e8f4af2cf5bf3efae9bb Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 30 Sep 2018 12:11:26 -0700 Subject: [PATCH 0966/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 16 ++++++++-------- korebuild-lock.txt | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 53c1c40ecb..1b90e37de1 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,20 +3,20 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180918.1 - 2.2.0-preview3-35301 - 2.2.0-preview3-35301 - 2.2.0-preview3-35301 - 2.2.0-preview3-35301 - 2.2.0-preview3-35301 + 2.2.0-preview1-20180928.5 + 2.2.0-preview3-35359 + 2.2.0-preview3-35359 + 2.2.0-preview3-35359 + 2.2.0-preview3-35359 + 2.2.0-preview3-35359 2.0.9 2.1.3 - 2.2.0-preview2-26905-02 + 2.2.0-preview3-26927-02 15.6.1 5.2.6 2.0.3 11.0.2 - 4.6.0-preview2-26905-02 + 4.6.0-preview3-26927-02 4.5.0 9.0.1 2.3.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 8491de70e6..0507680073 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180918.1 -commithash:ad5e3fc53442741a0dd49bce437d2ac72f4b5800 +version:2.2.0-preview1-20180928.5 +commithash:43faa29f679f47b88689d645b39e6be5e0055d70 From 45b7e2ddb796f0cb909d8f04bc4b5a5cf13b5e46 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 30 Sep 2018 12:14:04 -0700 Subject: [PATCH 0967/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index d34ed3bd56..a416795877 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,10 +4,10 @@ 3.0.0-alpha1-20180919.1 - 3.0.0-alpha1-10495 - 3.0.0-alpha1-10495 - 3.0.0-alpha1-10495 - 3.0.0-alpha1-10495 + 3.0.0-alpha1-10549 + 3.0.0-alpha1-10549 + 3.0.0-alpha1-10549 + 3.0.0-alpha1-10549 2.0.9 2.1.3 2.2.0-preview2-26905-02 From 49e982cc658c65db432db2768ce6a4ba3706bcf3 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 30 Sep 2018 12:14:58 -0700 Subject: [PATCH 0968/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 3d199851a2..7465761b22 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,14 +3,14 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180918.1 - 2.2.0-preview3-35301 - 2.2.0-preview3-35301 - 2.2.0-preview3-35301 - 2.2.0-preview3-35301 + 2.2.0-preview1-20180928.5 + 2.2.0-preview3-35359 + 2.2.0-preview3-35359 + 2.2.0-preview3-35359 + 2.2.0-preview3-35359 2.0.9 2.1.3 - 2.2.0-preview2-26905-02 + 2.2.0-preview3-26927-02 15.6.1 2.0.3 4.5.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 649bf2ba0b..26697a21fa 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180918.1 -commithash:ad5e3fc53442741a0dd49bce437d2ac72f4b5800 +version:2.2.0-preview1-20180928.5 +commithash:43faa29f679f47b88689d645b39e6be5e0055d70 From e842973c71a702287a5255a1ff6ac6b5352c61a4 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 30 Sep 2018 12:20:58 -0700 Subject: [PATCH 0969/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 11381ccbfb..b32b5bbbc4 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -4,9 +4,9 @@ 3.0.0-alpha1-20180919.1 - 3.0.0-alpha1-10495 + 3.0.0-alpha1-10549 4.6.0-preview1-26907-04 - 3.0.0-alpha1-10495 + 3.0.0-alpha1-10549 2.0.9 2.1.3 2.2.0-preview2-26905-02 From ed49a91b675390bb1f1d7b0c3d94243c9b83ea22 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 30 Sep 2018 12:22:27 -0700 Subject: [PATCH 0970/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 8 ++++---- korebuild-lock.txt | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index b6ca4ad584..9937fc7b36 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,13 +3,13 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180918.1 - 2.2.0-preview3-35301 + 2.2.0-preview1-20180928.5 + 2.2.0-preview3-35359 4.5.0 - 2.2.0-preview3-35301 + 2.2.0-preview3-35359 2.0.9 2.1.3 - 2.2.0-preview2-26905-02 + 2.2.0-preview3-26927-02 15.6.1 4.7.49 2.0.3 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 649bf2ba0b..26697a21fa 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180918.1 -commithash:ad5e3fc53442741a0dd49bce437d2ac72f4b5800 +version:2.2.0-preview1-20180928.5 +commithash:43faa29f679f47b88689d645b39e6be5e0055d70 From 4c49d5ce80f4515ac0549016822db04bbd647bb2 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 2 Oct 2018 09:17:04 -0700 Subject: [PATCH 0971/1029] Resolve flaky tests (#497) 1. Prevent an ObjectDisposedException in dotnet-watch on slower machines 2. Fix flakiness caused by PID reuse 3. Fix flakiness in tests that await the restart of dotnet-watch. The `.TimeoutAfter` method doesn't cancel the long-running task. This left 2 readers running on dotnet-watch output which caused indeterminate test outcome. --- .../Internal/FileWatcher/DotnetFileWatcher.cs | 43 ++++++++++++++----- .../AwaitableProcess.cs | 27 +++++++----- .../DotNetWatcherTests.cs | 6 ++- .../GlobbingAppTests.cs | 5 ++- .../NoDepsAppTests.cs | 3 -- 5 files changed, 58 insertions(+), 26 deletions(-) diff --git a/src/dotnet-watch/Internal/FileWatcher/DotnetFileWatcher.cs b/src/dotnet-watch/Internal/FileWatcher/DotnetFileWatcher.cs index d1103c41e6..0372327819 100644 --- a/src/dotnet-watch/Internal/FileWatcher/DotnetFileWatcher.cs +++ b/src/dotnet-watch/Internal/FileWatcher/DotnetFileWatcher.cs @@ -10,6 +10,8 @@ namespace Microsoft.DotNet.Watcher.Internal { internal class DotnetFileWatcher : IFileSystemWatcher { + private volatile bool _disposed; + private readonly Func _watcherFactory; private FileSystemWatcher _fileSystemWatcher; @@ -46,6 +48,11 @@ namespace Microsoft.DotNet.Watcher.Internal private void WatcherErrorHandler(object sender, ErrorEventArgs e) { + if (_disposed) + { + return; + } + var exception = e.GetException(); // Win32Exception may be triggered when setting EnableRaisingEvents on a file system type @@ -62,6 +69,11 @@ namespace Microsoft.DotNet.Watcher.Internal private void WatcherRenameHandler(object sender, RenamedEventArgs e) { + if (_disposed) + { + return; + } + NotifyChange(e.OldFullPath); NotifyChange(e.FullPath); @@ -79,6 +91,11 @@ namespace Microsoft.DotNet.Watcher.Internal private void WatcherChangeHandler(object sender, FileSystemEventArgs e) { + if (_disposed) + { + return; + } + NotifyChange(e.FullPath); } @@ -98,15 +115,7 @@ namespace Microsoft.DotNet.Watcher.Internal { enableEvents = _fileSystemWatcher.EnableRaisingEvents; - _fileSystemWatcher.EnableRaisingEvents = false; - - _fileSystemWatcher.Created -= WatcherChangeHandler; - _fileSystemWatcher.Deleted -= WatcherChangeHandler; - _fileSystemWatcher.Changed -= WatcherChangeHandler; - _fileSystemWatcher.Renamed -= WatcherRenameHandler; - _fileSystemWatcher.Error -= WatcherErrorHandler; - - _fileSystemWatcher.Dispose(); + DisposeInnerWatcher(); } _fileSystemWatcher = _watcherFactory(BasePath); @@ -122,6 +131,19 @@ namespace Microsoft.DotNet.Watcher.Internal } } + private void DisposeInnerWatcher() + { + _fileSystemWatcher.EnableRaisingEvents = false; + + _fileSystemWatcher.Created -= WatcherChangeHandler; + _fileSystemWatcher.Deleted -= WatcherChangeHandler; + _fileSystemWatcher.Changed -= WatcherChangeHandler; + _fileSystemWatcher.Renamed -= WatcherRenameHandler; + _fileSystemWatcher.Error -= WatcherErrorHandler; + + _fileSystemWatcher.Dispose(); + } + public bool EnableRaisingEvents { get => _fileSystemWatcher.EnableRaisingEvents; @@ -130,7 +152,8 @@ namespace Microsoft.DotNet.Watcher.Internal public void Dispose() { - _fileSystemWatcher.Dispose(); + _disposed = true; + DisposeInnerWatcher(); } } } diff --git a/test/dotnet-watch.FunctionalTests/AwaitableProcess.cs b/test/dotnet-watch.FunctionalTests/AwaitableProcess.cs index 86e2f90f79..3e22d53245 100644 --- a/test/dotnet-watch.FunctionalTests/AwaitableProcess.cs +++ b/test/dotnet-watch.FunctionalTests/AwaitableProcess.cs @@ -4,9 +4,9 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; -using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.Internal; using Microsoft.Extensions.CommandLineUtils; using Xunit.Abstractions; @@ -80,25 +80,30 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public async Task GetOutputLineAsync(string message, TimeSpan timeout) { _logger.WriteLine($"Waiting for output line [msg == '{message}']. Will wait for {timeout.TotalSeconds} sec."); - return await GetOutputLineAsync(m => string.Equals(m, message, StringComparison.Ordinal)).TimeoutAfter(timeout); + var cts = new CancellationTokenSource(); + cts.CancelAfter(timeout); + return await GetOutputLineAsync($"[msg == '{message}']", m => string.Equals(m, message, StringComparison.Ordinal), cts.Token); } public async Task GetOutputLineStartsWithAsync(string message, TimeSpan timeout) { _logger.WriteLine($"Waiting for output line [msg.StartsWith('{message}')]. Will wait for {timeout.TotalSeconds} sec."); - return await GetOutputLineAsync(m => m != null && m.StartsWith(message, StringComparison.Ordinal)).TimeoutAfter(timeout); + var cts = new CancellationTokenSource(); + cts.CancelAfter(timeout); + return await GetOutputLineAsync($"[msg.StartsWith('{message}')]", m => m != null && m.StartsWith(message, StringComparison.Ordinal), cts.Token); } - private async Task GetOutputLineAsync(Predicate predicate) + private async Task GetOutputLineAsync(string predicateName, Predicate predicate, CancellationToken cancellationToken) { while (!_source.Completion.IsCompleted) { - while (await _source.OutputAvailableAsync()) + while (await _source.OutputAvailableAsync(cancellationToken)) { - var next = await _source.ReceiveAsync(); + var next = await _source.ReceiveAsync(cancellationToken); _lines.Add(next); - _logger.WriteLine($"{DateTime.Now}: recv: '{next}'"); - if (predicate(next)) + var match = predicate(next); + _logger.WriteLine($"{DateTime.Now}: recv: '{next}'. {(match ? "Matches" : "Does not match")} condition '{predicateName}'."); + if (match) { return next; } @@ -108,14 +113,14 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests return null; } - public async Task> GetAllOutputLines() + public async Task> GetAllOutputLinesAsync(CancellationToken cancellationToken) { var lines = new List(); while (!_source.Completion.IsCompleted) { - while (await _source.OutputAvailableAsync()) + while (await _source.OutputAvailableAsync(cancellationToken)) { - var next = await _source.ReceiveAsync(); + var next = await _source.ReceiveAsync(cancellationToken); _logger.WriteLine($"{DateTime.Now}: recv: '{next}'"); lines.Add(next); } diff --git a/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs b/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs index 65ff6416e2..d31f650aa6 100644 --- a/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs +++ b/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs @@ -13,10 +13,12 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { public class DotNetWatcherTests : IDisposable { + private readonly ITestOutputHelper _logger; private readonly KitchenSinkApp _app; public DotNetWatcherTests(ITestOutputHelper logger) { + _logger = logger; _app = new KitchenSinkApp(logger); } @@ -52,8 +54,10 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests File.SetLastWriteTime(source, DateTime.Now); await _app.HasRestarted(); } - catch + catch (Exception ex) { + _logger.WriteLine("Retrying. First attempt to restart app failed: " + ex.Message); + // retry File.SetLastWriteTime(source, DateTime.Now); await _app.HasRestarted(); diff --git a/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs b/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs index a01a28e7d8..3658261049 100644 --- a/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs +++ b/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs @@ -4,6 +4,7 @@ using System; using System.IO; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Microsoft.DotNet.Watcher.Tools.Tests; using Xunit; @@ -101,7 +102,9 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests { await _app.PrepareAsync(); _app.Start(new [] { "--list" }); - var lines = await _app.Process.GetAllOutputLines(); + var cts = new CancellationTokenSource(); + cts.CancelAfter(TimeSpan.FromSeconds(30)); + var lines = await _app.Process.GetAllOutputLinesAsync(cts.Token); var files = lines.Where(l => !l.StartsWith("watch :")); AssertEx.EqualFileList( diff --git a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs index 55d0441552..d1eead9048 100644 --- a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs +++ b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs @@ -39,9 +39,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests var pid2 = await _app.GetProcessId(); Assert.NotEqual(pid, pid2); - - // first app should have shut down - Assert.Throws(() => Process.GetProcessById(pid)); } [Fact] From 581b3160f422180b3411d84b4458c10128c8cacb Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 7 Oct 2018 12:10:59 -0700 Subject: [PATCH 0972/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 12 ++++++------ korebuild-lock.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 38d799449f..c2a53cebd4 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,12 +3,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.0.0-alpha1-20180919.1 - 3.0.0-alpha1-10549 - 3.0.0-alpha1-10549 - 3.0.0-alpha1-10549 - 3.0.0-alpha1-10549 - 3.0.0-alpha1-10549 + 3.0.0-alpha1-20181004.7 + 3.0.0-alpha1-10584 + 3.0.0-alpha1-10584 + 3.0.0-alpha1-10584 + 3.0.0-alpha1-10584 + 3.0.0-alpha1-10584 3.0.0-preview1-26907-05 15.6.1 5.2.6 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 9a87e4ccb7..14c4ea8ed3 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180919.1 -commithash:3066ae0a230870ea07e3f132605b5e5493f8bbd4 +version:3.0.0-alpha1-20181004.7 +commithash:27fabdaf2b1d4753c3d2749581694ca65d78f7f2 From b473a0d76ce0c255962d97e22d45904c6b62fe5d Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 7 Oct 2018 19:11:55 +0000 Subject: [PATCH 0973/1029] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 16 ++++++++-------- korebuild-lock.txt | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 1b90e37de1..825e82f2e3 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,20 +3,20 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview1-20180928.5 - 2.2.0-preview3-35359 - 2.2.0-preview3-35359 - 2.2.0-preview3-35359 - 2.2.0-preview3-35359 - 2.2.0-preview3-35359 + 2.2.0-preview2-20181004.6 + 2.2.0-preview3-35425 + 2.2.0-preview3-35425 + 2.2.0-preview3-35425 + 2.2.0-preview3-35425 + 2.2.0-preview3-35425 2.0.9 2.1.3 - 2.2.0-preview3-26927-02 + 2.2.0-preview3-27001-02 15.6.1 5.2.6 2.0.3 11.0.2 - 4.6.0-preview3-26927-02 + 4.6.0-preview3-27001-02 4.5.0 9.0.1 2.3.1 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 0507680073..3e92dd5543 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview1-20180928.5 -commithash:43faa29f679f47b88689d645b39e6be5e0055d70 +version:2.2.0-preview2-20181004.6 +commithash:c04c4b2f5018632647f96210ab01876661302dac From 0b76599c31b3fa367dc172272e81cee87a634ba9 Mon Sep 17 00:00:00 2001 From: David Date: Mon, 2 Oct 2017 09:54:55 +0100 Subject: [PATCH 0974/1029] Improve conformance of replace operations to spec This ensures that JSON patch "replace" operations are functionally equivalent to "remove" operations followed by "add" operations at the same path, as RFC 6902 specifies. Addresses #110 --- .../Internal/DynamicObjectAdapter.cs | 5 + .../Internal/DynamicObjectAdapterTest.cs | 4 +- .../WriteOnceDynamicTestObject.cs | 117 ++++++++++++++++++ 3 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/WriteOnceDynamicTestObject.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs index dc3c48266f..5b3d7d8bdd 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs @@ -96,6 +96,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal return false; } + if (!TryRemove(target, segment, contractResolver, out errorMessage)) + { + return false; + } + if (!TrySetDynamicObjectProperty(target, contractResolver, segment, convertedValue, out errorMessage)) { return false; diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/DynamicObjectAdapterTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/DynamicObjectAdapterTest.cs index 96b1aee935..9d5eb2595c 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/DynamicObjectAdapterTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/DynamicObjectAdapterTest.cs @@ -130,11 +130,11 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal } [Fact] - public void TryReplace_ReplacesPropertyValue() + public void TryReplace_RemovesExistingValue_BeforeAddingNewValue() { // Arrange var adapter = new DynamicObjectAdapter(); - dynamic target = new DynamicTestObject(); + dynamic target = new WriteOnceDynamicTestObject(); target.NewProperty = new object(); var segment = "NewProperty"; var resolver = new DefaultContractResolver(); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/WriteOnceDynamicTestObject.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/WriteOnceDynamicTestObject.cs new file mode 100644 index 0000000000..769ddcc154 --- /dev/null +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/WriteOnceDynamicTestObject.cs @@ -0,0 +1,117 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Dynamic; + +namespace Microsoft.AspNetCore.JsonPatch.Internal +{ + /// + /// + /// This class is used specifically to test that JSON patch "replace" operations are functionally equivalent to + /// "add" and "remove" operations applied sequentially using the same path. + /// + /// + /// This is done by asserting that no value exists for a particular key before setting its value. To replace the + /// value for a key, the key must first be removed, and then re-added with the new value. + /// + /// + /// See JsonPatch#110 for further details. + /// + /// + public class WriteOnceDynamicTestObject : DynamicObject + { + private Dictionary _dictionary = new Dictionary(); + + public object this[string key] { get => ((IDictionary)_dictionary)[key]; set => SetValueForKey(key, value); } + + public ICollection Keys => ((IDictionary)_dictionary).Keys; + + public ICollection Values => ((IDictionary)_dictionary).Values; + + public int Count => ((IDictionary)_dictionary).Count; + + public bool IsReadOnly => ((IDictionary)_dictionary).IsReadOnly; + + public void Add(string key, object value) + { + SetValueForKey(key, value); + } + + public void Add(KeyValuePair item) + { + SetValueForKey(item.Key, item.Value); + } + + public void Clear() + { + ((IDictionary)_dictionary).Clear(); + } + + public bool Contains(KeyValuePair item) + { + return ((IDictionary)_dictionary).Contains(item); + } + + public bool ContainsKey(string key) + { + return ((IDictionary)_dictionary).ContainsKey(key); + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + ((IDictionary)_dictionary).CopyTo(array, arrayIndex); + } + + public IEnumerator> GetEnumerator() + { + return ((IDictionary)_dictionary).GetEnumerator(); + } + + public bool Remove(string key) + { + return ((IDictionary)_dictionary).Remove(key); + } + + public bool Remove(KeyValuePair item) + { + return ((IDictionary)_dictionary).Remove(item); + } + + public bool TryGetValue(string key, out object value) + { + return ((IDictionary)_dictionary).TryGetValue(key, out value); + } + + public override bool TryGetMember(GetMemberBinder binder, out object result) + { + var name = binder.Name; + + return TryGetValue(name, out result); + } + + public override bool TrySetMember(SetMemberBinder binder, object value) + { + SetValueForKey(binder.Name, value); + + return true; + } + + private void SetValueForKey(string key, object value) + { + if (value == null) + { + _dictionary.Remove(key); + return; + } + + if (_dictionary.ContainsKey(key)) + { + throw new ArgumentException($"Value for {key} already exists"); + } + + _dictionary[key] = value; + } + } +} From 98f7829b5c5f5738f15f3863205547e35901bbe1 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 16 Oct 2018 12:48:13 -0700 Subject: [PATCH 0975/1029] Update package branding for 2.2 RTM --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 07833713f2..0d0c8979e6 100644 --- a/version.props +++ b/version.props @@ -2,7 +2,7 @@ 2.2.0 15.6 - preview3 + rtm $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final $(VsixVersion).$(BuildNumber) From 6c5ca90d81f9013a8652da4c1752bd0b4d18e908 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 16 Oct 2018 12:48:14 -0700 Subject: [PATCH 0976/1029] Update package branding for 2.2 RTM --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 704cac087b..4889a26987 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ 2.2.0 - preview3 + rtm $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From aeb5c578e7d59cf9b100352f55f05f55c7cfebd1 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 16 Oct 2018 12:48:16 -0700 Subject: [PATCH 0977/1029] Update package branding for 2.2 RTM --- version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.props b/version.props index 704cac087b..4889a26987 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ 2.2.0 - preview3 + rtm $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final t000 From e75dc563279c3ec622e4dd9dc3ad22fabbc111e7 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 16 Oct 2018 14:29:10 -0700 Subject: [PATCH 0978/1029] Sign Newtonsoft.Json with AssemblySigning3rdPartyCertName --- src/dotnet-user-secrets/dotnet-user-secrets.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotnet-user-secrets/dotnet-user-secrets.csproj b/src/dotnet-user-secrets/dotnet-user-secrets.csproj index 15ce1c1d5a..133f303006 100644 --- a/src/dotnet-user-secrets/dotnet-user-secrets.csproj +++ b/src/dotnet-user-secrets/dotnet-user-secrets.csproj @@ -24,7 +24,7 @@ - + From 572aadf149fad6f19691e922926c11bdb2a74fb1 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 17 Oct 2018 13:15:14 -0700 Subject: [PATCH 0979/1029] Remove duplicate package references (#501) --- test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj b/test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj index a50dd1df30..981a7e8bdd 100644 --- a/test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj +++ b/test/Microsoft.HttpRepl.Tests/Microsoft.HttpRepl.Tests.csproj @@ -7,9 +7,6 @@ - - - From 1db0f18ab3dedca44df4587accbc7ef76a3a653d Mon Sep 17 00:00:00 2001 From: Anton Piskunov Date: Tue, 23 Oct 2018 15:37:04 -0700 Subject: [PATCH 0980/1029] Update CPS packages with breaking changes --- .../Microsoft.VisualStudio.SecretManager.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj b/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj index b178075251..8cd9e0e314 100644 --- a/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj +++ b/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj @@ -79,10 +79,10 @@ - - - - + + + + From c556be949de6be508f33798e8f2ae94521cf26d5 Mon Sep 17 00:00:00 2001 From: Anton Piskunov Date: Tue, 23 Oct 2018 16:21:11 -0700 Subject: [PATCH 0981/1029] Change vsix version to 16 and add CPS feed --- build/sources.props | 1 + version.props | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/build/sources.props b/build/sources.props index cada42ba91..4c4748d85a 100644 --- a/build/sources.props +++ b/build/sources.props @@ -9,6 +9,7 @@ https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; https://vside.myget.org/F/vssdk/api/v3/index.json; + https://vside.myget.org/F/devcore/api/v3/index.json $(RestoreSources); diff --git a/version.props b/version.props index 0b4b9416cf..4a7d610604 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@  3.0.0 - 15.6 + 16.0 alpha1 $(VersionPrefix) $(VersionPrefix)-$(VersionSuffix)-final From 01f9af21c533df2b3961b7900ca0b656ee38a588 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 24 Oct 2018 13:02:25 -0700 Subject: [PATCH 0982/1029] Temporarily stop producing a package for dotnet-httprepl (#505) This package isn't quite ship-shape yet, so we're delaying this from shipping with 2.2 RTM. Setting IsPackable=false so we avoid accidentally building a 2.2.0 RTM version of this package along with the rest of the 2.2.0 RTM tools in this repo, like dotnet-watch. --- NuGetPackageVerifier.json | 14 -------------- src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj | 3 +++ 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index 63b866c8ed..fb43448889 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -24,20 +24,6 @@ "DotnetTool" ] }, - "dotnet-httprepl": { - "packageTypes": [ - "DotnetTool" - ], - "Exclusions": { - "ASSEMBLY_DESCRIPTION": { - "tools/netcoreapp2.1/any/System.Net.Http.Formatting.dll": "Referenced assembly, not built as part of this process" - }, - "VERSION_INFORMATIONALVERSION": { - "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Referenced assembly, not built as part of this process", - "tools/netcoreapp2.1/any/Newtonsoft.Json.Bson.dll": "Referenced assembly, not built as part of this process" - } - } - }, "Microsoft.AspNetCore.DeveloperCertificates.XPlat": { "Exclusions": { "DOC_MISSING": { diff --git a/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj b/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj index d2552ef1e4..d367892325 100644 --- a/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj +++ b/src/Microsoft.HttpRepl/Microsoft.HttpRepl.csproj @@ -10,6 +10,9 @@ dotnet;http;httprepl win-x64;win-x86 + + + false From d957ac9da0e250d38d826bbc489b6882ff157eaa Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Sat, 27 Oct 2018 01:28:14 -0700 Subject: [PATCH 0983/1029] Remove Microsoft.DotNet.GlobalTools.Sdk, upgrade BuildTools, and change VSIX signing cert name --- build/VSIX.targets | 2 +- build/dependencies.props | 9 ++++----- build/repo.props | 4 +--- korebuild-lock.txt | 4 ++-- src/dotnet-dev-certs/dotnet-dev-certs.csproj | 7 ++----- src/dotnet-sql-cache/dotnet-sql-cache.csproj | 7 ++----- src/dotnet-user-secrets/dotnet-user-secrets.csproj | 7 ++----- src/dotnet-watch/dotnet-watch.csproj | 7 ++----- 8 files changed, 16 insertions(+), 31 deletions(-) diff --git a/build/VSIX.targets b/build/VSIX.targets index 687fd72b24..558570b7bb 100644 --- a/build/VSIX.targets +++ b/build/VSIX.targets @@ -40,7 +40,7 @@ full - + diff --git a/build/dependencies.props b/build/dependencies.props index cf3681c3c2..2ffa03acd5 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -5,21 +5,20 @@ - 2.1.3-rtm-15802 + 2.1.3-rtm-15833 2.1.1 2.1.0 2.1.1 2.1.1 2.1.1 - 2.0.0 2.1.2 - 15.6.1 + 15.9.0 2.0.3 4.5.1 4.5.0 9.0.1 - 2.3.1 - 2.4.0-beta.1.build3945 + 2.4.0 + 2.4.0 diff --git a/build/repo.props b/build/repo.props index 129e1465c8..571c6712c0 100644 --- a/build/repo.props +++ b/build/repo.props @@ -2,15 +2,13 @@ - - Internal.AspNetCore.Universe.Lineup - 2.1.0-rc1-* + 2.1.0-* https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 1dfc352a0a..04cce2fca7 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.3-rtm-15802 -commithash:a7c08b45b440a7d2058a0aa1eaa3eb6ba811976a +version:2.1.3-rtm-15833 +commithash:42bee65743476deedda53948fa3e84a0ac4c0360 diff --git a/src/dotnet-dev-certs/dotnet-dev-certs.csproj b/src/dotnet-dev-certs/dotnet-dev-certs.csproj index 024cc705d2..59dc5b5eab 100644 --- a/src/dotnet-dev-certs/dotnet-dev-certs.csproj +++ b/src/dotnet-dev-certs/dotnet-dev-certs.csproj @@ -1,6 +1,4 @@ - - - + netcoreapp2.1 @@ -9,9 +7,8 @@ Microsoft.AspNetCore.DeveloperCertificates.Tools dotnet;developercertificates true - - true + win-x64;win-x86 diff --git a/src/dotnet-sql-cache/dotnet-sql-cache.csproj b/src/dotnet-sql-cache/dotnet-sql-cache.csproj index ad1105f2b8..da0ce30a21 100644 --- a/src/dotnet-sql-cache/dotnet-sql-cache.csproj +++ b/src/dotnet-sql-cache/dotnet-sql-cache.csproj @@ -1,6 +1,4 @@ - - - + netcoreapp2.1 @@ -8,9 +6,8 @@ Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching. cache;distributedcache;sqlserver true - - true + win-x64;win-x86 diff --git a/src/dotnet-user-secrets/dotnet-user-secrets.csproj b/src/dotnet-user-secrets/dotnet-user-secrets.csproj index f431447a01..6624e89809 100644 --- a/src/dotnet-user-secrets/dotnet-user-secrets.csproj +++ b/src/dotnet-user-secrets/dotnet-user-secrets.csproj @@ -1,6 +1,4 @@ - - - + netcoreapp2.1 @@ -10,9 +8,8 @@ Microsoft.Extensions.SecretManager.Tools configuration;secrets;usersecrets true - - true + win-x64;win-x86 diff --git a/src/dotnet-watch/dotnet-watch.csproj b/src/dotnet-watch/dotnet-watch.csproj index f20ea3ebc5..fa2f617f41 100644 --- a/src/dotnet-watch/dotnet-watch.csproj +++ b/src/dotnet-watch/dotnet-watch.csproj @@ -1,6 +1,4 @@ - - - + netcoreapp2.1 @@ -9,9 +7,8 @@ Microsoft.DotNet.Watcher.Tools dotnet;watch true - - true + win-x64;win-x86 From c6130df988524145848dd347a9006929c1374c8b Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Sat, 27 Oct 2018 01:47:18 -0700 Subject: [PATCH 0984/1029] Upgrade dependencies and build tools --- build/dependencies.props | 16 ++++++++-------- korebuild-lock.txt | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index add83e237b..3be7610a3d 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -3,19 +3,19 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 2.2.0-preview2-20181004.6 - 2.2.0-preview3-35425 - 2.2.0-preview3-35425 - 2.2.0-preview3-35425 - 2.2.0-preview3-35425 - 2.2.0-preview3-35425 + 2.2.0-preview2-20181026.4 + 2.2.0-rtm-35542 + 2.2.0-rtm-35542 + 2.2.0-rtm-35542 + 2.2.0-rtm-35545 + 2.2.0-rtm-35542 2.1.3 - 2.2.0-preview3-27001-02 + 2.2.0-rtm-27023-02 15.9.0 5.2.6 2.0.3 11.0.2 - 4.6.0-preview3-27001-02 + 4.6.0-rtm-27023-03 4.5.0 9.0.1 2.4.0 diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 3e92dd5543..a60356d3e0 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview2-20181004.6 -commithash:c04c4b2f5018632647f96210ab01876661302dac +version:2.2.0-preview2-20181026.4 +commithash:f05a283e6c1eb66ef29a32526f75f8b567a986c9 From eba014d534ef34ea88ce6c3879b92743b825a7fe Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Sat, 27 Oct 2018 01:59:37 -0700 Subject: [PATCH 0985/1029] Add additional signing configuration for external assemblies in the tools packages --- .vsts-pipelines/builds/ci-internal.yml | 13 ++++++ .vsts-pipelines/builds/ci-public.yml | 15 +++++++ Directory.Build.props | 2 - build/VSIX.targets | 1 + run.ps1 | 32 ++++++++++----- run.sh | 40 ++++++++++++++++--- src/dotnet-sql-cache/dotnet-sql-cache.csproj | 13 ++++++ .../dotnet-user-secrets.csproj | 17 ++++++++ 8 files changed, 116 insertions(+), 17 deletions(-) create mode 100644 .vsts-pipelines/builds/ci-internal.yml create mode 100644 .vsts-pipelines/builds/ci-public.yml diff --git a/.vsts-pipelines/builds/ci-internal.yml b/.vsts-pipelines/builds/ci-internal.yml new file mode 100644 index 0000000000..3693598d93 --- /dev/null +++ b/.vsts-pipelines/builds/ci-internal.yml @@ -0,0 +1,13 @@ +trigger: +- master +- release/* + +resources: + repositories: + - repository: buildtools + type: git + name: aspnet-BuildTools + ref: refs/heads/release/2.1 + +phases: +- template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/.vsts-pipelines/builds/ci-public.yml b/.vsts-pipelines/builds/ci-public.yml new file mode 100644 index 0000000000..c459e62eb6 --- /dev/null +++ b/.vsts-pipelines/builds/ci-public.yml @@ -0,0 +1,15 @@ +trigger: +- master +- release/* + +# See https://github.com/aspnet/BuildTools +resources: + repositories: + - repository: buildtools + type: github + endpoint: DotNet-Bot GitHub Connection + name: aspnet/BuildTools + ref: refs/heads/release/2.1 + +phases: +- template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/Directory.Build.props b/Directory.Build.props index 29d623306f..8c12d37b2d 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -14,8 +14,6 @@ $(MSBuildThisFileDirectory) $(MSBuildThisFileDirectory)build\Key.snk true - true - Microsoft true diff --git a/build/VSIX.targets b/build/VSIX.targets index 558570b7bb..ccafe5bf76 100644 --- a/build/VSIX.targets +++ b/build/VSIX.targets @@ -41,6 +41,7 @@ + diff --git a/run.ps1 b/run.ps1 index 27dcf848f8..2f892843e0 100644 --- a/run.ps1 +++ b/run.ps1 @@ -26,12 +26,18 @@ The base url where build tools can be downloaded. Overrides the value from the c .PARAMETER Update Updates KoreBuild to the latest version even if a lock file is present. +.PARAMETER Reinstall +Re-installs KoreBuild + .PARAMETER ConfigFile The path to the configuration file that stores values. Defaults to korebuild.json. .PARAMETER ToolsSourceSuffix The Suffix to append to the end of the ToolsSource. Useful for query strings in blob stores. +.PARAMETER CI +Sets up CI specific settings and variables. + .PARAMETER Arguments Arguments to be passed to the command @@ -46,8 +52,8 @@ in the file are overridden by command line parameters. Example config file: ```json { - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev", + "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", + "channel": "master", "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" } ``` @@ -65,8 +71,10 @@ param( [string]$ToolsSource, [Alias('u')] [switch]$Update, - [string]$ConfigFile, + [switch]$Reinstall, [string]$ToolsSourceSuffix, + [string]$ConfigFile = $null, + [switch]$CI, [Parameter(ValueFromRemainingArguments = $true)] [string[]]$Arguments ) @@ -93,6 +101,10 @@ function Get-KoreBuild { $version = $version.TrimStart('version:').Trim() $korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version) + if ($Reinstall -and (Test-Path $korebuildPath)) { + Remove-Item -Force -Recurse $korebuildPath + } + if (!(Test-Path $korebuildPath)) { Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version" New-Item -ItemType Directory -Path $korebuildPath | Out-Null @@ -101,9 +113,9 @@ function Get-KoreBuild { try { $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip" Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix - if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) { + if (Get-Command -Name 'Microsoft.PowerShell.Archive\Expand-Archive' -ErrorAction Ignore) { # Use built-in commands where possible as they are cross-plat compatible - Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath + Microsoft.PowerShell.Archive\Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath } else { # Fallback to old approach for old installations of PowerShell @@ -167,19 +179,21 @@ if (Test-Path $ConfigFile) { } } catch { - Write-Warning "$ConfigFile could not be read. Its settings will be ignored." - Write-Warning $Error[0] + Write-Host -ForegroundColor Red $Error[0] + Write-Error "$ConfigFile contains invalid JSON." + exit 1 } } if (!$DotNetHome) { $DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } ` + elseif ($CI) { Join-Path $PSScriptRoot '.dotnet' } ` elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} ` elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}` else { Join-Path $PSScriptRoot '.dotnet'} } -if (!$Channel) { $Channel = 'dev' } +if (!$Channel) { $Channel = 'master' } if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } # Execute @@ -188,7 +202,7 @@ $korebuildPath = Get-KoreBuild Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1') try { - Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile + Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile -CI:$CI Invoke-KoreBuildCommand $Command @Arguments } finally { diff --git a/run.sh b/run.sh index 834961fc3a..129b0b9576 100755 --- a/run.sh +++ b/run.sh @@ -11,13 +11,14 @@ RED="\033[0;31m" YELLOW="\033[0;33m" MAGENTA="\033[0;95m" DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" verbose=false update=false +reinstall=false repo_path="$DIR" channel='' tools_source='' tools_source_suffix='' +ci=false # # Functions @@ -38,6 +39,8 @@ __usage() { echo " -s|--tools-source|-ToolsSource The base url where build tools can be downloaded. Overrides the value from the config file." echo " --tools-source-suffix|-ToolsSourceSuffix The suffix to append to tools-source. Useful for query strings." echo " -u|--update Update to the latest KoreBuild even if the lock file is present." + echo " --reinstall Reinstall KoreBuild." + echo " --ci Apply CI specific settings and environment variables." echo "" echo "Description:" echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." @@ -62,6 +65,10 @@ get_korebuild() { version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" + if [ "$reinstall" = true ] && [ -d "$korebuild_path" ]; then + rm -rf "$korebuild_path" + fi + { if [ ! -d "$korebuild_path" ]; then mkdir -p "$korebuild_path" @@ -175,6 +182,15 @@ while [[ $# -gt 0 ]]; do -u|--update|-Update) update=true ;; + --reinstall|-[Rr]einstall) + reinstall=true + ;; + --ci|-[Cc][Ii]) + ci=true + if [[ -z "${DOTNET_HOME:-}" ]]; then + DOTNET_HOME="$DIR/.dotnet" + fi + ;; --verbose|-Verbose) verbose=true ;; @@ -206,26 +222,38 @@ if [ -f "$config_file" ]; then config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")" else - __warn "$config_file is invalid JSON. Its settings will be ignored." + __error "$config_file contains invalid JSON." + exit 1 fi elif __machine_has python ; then if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" else - __warn "$config_file is invalid JSON. Its settings will be ignored." + __error "$config_file contains invalid JSON." + exit 1 + fi + elif __machine_has python3 ; then + if python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then + config_channel="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" + config_tools_source="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" + else + __error "$config_file contains invalid JSON." + exit 1 fi else - __warn 'Missing required command: jq or pyton. Could not parse the JSON file. Its settings will be ignored.' + __error 'Missing required command: jq or python. Could not parse the JSON file.' + exit 1 fi [ ! -z "${config_channel:-}" ] && channel="$config_channel" [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" fi -[ -z "$channel" ] && channel='dev' +[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" +[ -z "$channel" ] && channel='master' [ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' get_korebuild -set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file" +set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file" "$ci" invoke_korebuild_command "$command" "$@" diff --git a/src/dotnet-sql-cache/dotnet-sql-cache.csproj b/src/dotnet-sql-cache/dotnet-sql-cache.csproj index da0ce30a21..15c3229544 100644 --- a/src/dotnet-sql-cache/dotnet-sql-cache.csproj +++ b/src/dotnet-sql-cache/dotnet-sql-cache.csproj @@ -19,4 +19,17 @@ + + + + + + + + + + + + + diff --git a/src/dotnet-user-secrets/dotnet-user-secrets.csproj b/src/dotnet-user-secrets/dotnet-user-secrets.csproj index 6624e89809..99258ea0f6 100644 --- a/src/dotnet-user-secrets/dotnet-user-secrets.csproj +++ b/src/dotnet-user-secrets/dotnet-user-secrets.csproj @@ -22,4 +22,21 @@ + + + + + + + + + + + + + + + + + From 3b485909ebec98d9437058dbcf45dac3ccd1f157 Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Wed, 31 Oct 2018 13:59:20 -0700 Subject: [PATCH 0986/1029] Fix aspnet/AspNetCore#3634 --- .../Internal/ObjectVisitor.cs | 8 +++++- .../SimpleObjectIntegrationTest.cs | 27 +++++++++++++++++++ .../Internal/ObjectVisitorTest.cs | 16 +++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs index a988afa300..6cb4d7450c 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections; using Microsoft.AspNetCore.JsonPatch.Adapters; using Newtonsoft.Json.Serialization; @@ -56,6 +55,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal adapter = null; return false; } + + // If we hit a null on an interior segment then we need to stop traversing. + if (next == null) + { + adapter = null; + return false; + } target = next; adapter = SelectAdapter(target); diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/SimpleObjectIntegrationTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/SimpleObjectIntegrationTest.cs index 669c6d7af4..4672d9c97b 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/SimpleObjectIntegrationTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/SimpleObjectIntegrationTest.cs @@ -2,6 +2,8 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Dynamic; +using Microsoft.AspNetCore.JsonPatch.Exceptions; using Xunit; namespace Microsoft.AspNetCore.JsonPatch.IntegrationTests @@ -124,5 +126,30 @@ namespace Microsoft.AspNetCore.JsonPatch.IntegrationTests Assert.Equal(newGuid, targetObject.GuidValue); } + // https://github.com/aspnet/AspNetCore/issues/3634 + [Fact] + public void Regression_AspNetCore3634() + { + // Assert + var document = new JsonPatchDocument(); + document.Move("/Object", "/Object/goodbye"); + + dynamic @object = new ExpandoObject(); + @object.hello = "world"; + + var target = new Regression_AspNetCore3634_Object(); + target.Object = @object; + + // Act + var ex = Assert.Throws(() => document.ApplyTo(target)); + + // Assert + Assert.Equal("For operation 'move', the target location specified by path '/Object/goodbye' was not found.", ex.Message); + } + + private class Regression_AspNetCore3634_Object + { + public dynamic Object { get; set; } + } } } diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ObjectVisitorTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ObjectVisitorTest.cs index cb299cf0dc..44f6fc81ae 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ObjectVisitorTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ObjectVisitorTest.cs @@ -205,6 +205,22 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal Assert.IsType(adapter); } + [Fact] + public void Visit_NullInteriorTarget_ReturnsFalse() + { + // Arrange + var visitor = new ObjectVisitor(new ParsedPath("/States/0"), new DefaultContractResolver()); + + // Act + object target = new Class1() { States = null, }; + var visitStatus = visitor.TryVisit(ref target, out var adapter, out var message); + + // Assert + Assert.False(visitStatus); + Assert.Null(adapter); + Assert.Null(message); + } + [Fact] public void Visit_NullTarget_ReturnsNullAdapter() { From fbca8be4042533db160704324e4f095efe77583d Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 1 Nov 2018 10:01:42 -0700 Subject: [PATCH 0987/1029] Disable building the VSIX in 2.2 by default (#508) We don't release the UserSecrets VSIX from this branch --- build/VSIX.targets | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/VSIX.targets b/build/VSIX.targets index ccafe5bf76..a761a9bc13 100644 --- a/build/VSIX.targets +++ b/build/VSIX.targets @@ -1,6 +1,7 @@ - true + + false $(RestoreDependsOn);RestoreVSIX $(PackageDependsOn);PackageVSIX $(GetArtifactInfoDependsOn);GetVSIXArtifactInfo From 22a32500ac53283bb0db681ec1f22a95091eb717 Mon Sep 17 00:00:00 2001 From: Mike Lorbetske Date: Wed, 31 Oct 2018 12:40:16 -0700 Subject: [PATCH 0988/1029] Fix several issues Fix #502 Fix #492 Fix #491 Fix #486 Improves #489 --- .../Commands/BaseHttpCommand.cs | 30 +++++++------ .../Commands/HelpCommand.cs | 2 +- .../Commands/SetBaseCommand.cs | 17 +++++++- .../Commands/SetSwaggerCommand.cs | 2 +- src/Microsoft.HttpRepl/DirectoryStructure.cs | 11 ++++- src/Microsoft.HttpRepl/HttpState.cs | 4 +- src/Microsoft.HttpRepl/IRequestInfo.cs | 2 +- .../Commanding/DefaultCommandDispatcher.cs | 2 +- .../Commanding/ICommandDispatcher.cs | 2 +- .../ConsoleHandling/ConsoleManager.cs | 42 +++++++++++-------- src/Microsoft.Repl/Input/InputManager.cs | 26 ++++++++---- .../Suggestions/SuggestionManager.cs | 4 +- 12 files changed, 93 insertions(+), 51 deletions(-) diff --git a/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs b/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs index a8ad52fc24..30191306e4 100644 --- a/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/BaseHttpCommand.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Net.Http; +using System.Net.Http.Headers; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -116,8 +117,18 @@ namespace Microsoft.HttpRepl.Commands bool deleteFile = false; noBody = commandInput.Options[NoBodyOption].Count > 0; + if (!thisRequestHeaders.TryGetValue("content-type", out string contentType) && programState.Headers.TryGetValue("content-type", out IEnumerable contentTypes)) + { + contentType = contentTypes.FirstOrDefault(); + } + if (!noBody) { + if (string.IsNullOrEmpty(contentType)) + { + contentType = "application/json"; + } + if (commandInput.Options[BodyFileOption].Count > 0) { filePath = commandInput.Options[BodyFileOption][0].Text; @@ -144,18 +155,7 @@ namespace Microsoft.HttpRepl.Commands deleteFile = true; filePath = Path.GetTempFileName(); - if (!thisRequestHeaders.TryGetValue("content-type", out string contentType) && programState.Headers.TryGetValue("content-type", out IEnumerable contentTypes)) - { - contentType = contentTypes.FirstOrDefault(); - } - - if (contentType == null) - { - contentType = "application/json"; - } - - string exampleBody = programState.GetExampleBody(commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty, contentType, Verb); - request.Headers.TryAddWithoutValidation("Content-Type", contentType); + string exampleBody = programState.GetExampleBody(commandInput.Arguments.Count > 0 ? commandInput.Arguments[0].Text : string.Empty, ref contentType, Verb); if (!string.IsNullOrEmpty(exampleBody)) { @@ -179,6 +179,11 @@ namespace Microsoft.HttpRepl.Commands } } + if (string.IsNullOrEmpty(contentType)) + { + contentType = "application/json"; + } + byte[] data = noBody ? new byte[0] : string.IsNullOrEmpty(bodyContent) @@ -186,6 +191,7 @@ namespace Microsoft.HttpRepl.Commands : Encoding.UTF8.GetBytes(bodyContent); HttpContent content = new ByteArrayContent(data); + content.Headers.ContentType = new MediaTypeHeaderValue(contentType); request.Content = content; if (deleteFile) diff --git a/src/Microsoft.HttpRepl/Commands/HelpCommand.cs b/src/Microsoft.HttpRepl/Commands/HelpCommand.cs index 26e4468e8a..17dbef4d1f 100644 --- a/src/Microsoft.HttpRepl/Commands/HelpCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/HelpCommand.cs @@ -218,7 +218,7 @@ namespace Microsoft.HttpRepl.Commands shellState.ConsoleManager.WriteLine($"{"HEAD",navCommandColumn}{"Issues a HEAD request."}"); shellState.ConsoleManager.WriteLine($"{"OPTIONS",navCommandColumn}{"Issues an OPTIONS request."}"); shellState.ConsoleManager.WriteLine(); - shellState.ConsoleManager.WriteLine($"{"set header",navCommandColumn}{"Sets or clears a header for all requests. e.g. `set header content-type:application/json`"}"); + shellState.ConsoleManager.WriteLine($"{"set header",navCommandColumn}{"Sets or clears a header for all requests. e.g. `set header content-type application/json`"}"); shellState.ConsoleManager.WriteLine(); shellState.ConsoleManager.WriteLine(); diff --git a/src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs b/src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs index aa12ec819e..70e829a891 100644 --- a/src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/SetBaseCommand.cs @@ -53,7 +53,7 @@ namespace Microsoft.HttpRepl.Commands catch { } } - if (state.BaseAddress == null || !Uri.TryCreate(state.BaseAddress, "/swagger/v1/swagger.json", out Uri result)) + if (state.BaseAddress == null || !Uri.TryCreate(state.BaseAddress, "swagger.json", out Uri result)) { state.SwaggerStructure = null; } @@ -64,6 +64,21 @@ namespace Microsoft.HttpRepl.Commands { shellState.ConsoleManager.WriteLine("Using swagger metadata from " + result); } + else + { + if (state.BaseAddress == null || !Uri.TryCreate(state.BaseAddress, "swagger/v1/swagger.json", out result)) + { + state.SwaggerStructure = null; + } + else + { + await SetSwaggerCommand.CreateDirectoryStructureForSwaggerEndpointAsync(shellState, state, result, cancellationToken).ConfigureAwait(false); + if (state.SwaggerStructure != null) + { + shellState.ConsoleManager.WriteLine("Using swagger metadata from " + result); + } + } + } } } diff --git a/src/Microsoft.HttpRepl/Commands/SetSwaggerCommand.cs b/src/Microsoft.HttpRepl/Commands/SetSwaggerCommand.cs index 41c1564a99..53d3743d6d 100644 --- a/src/Microsoft.HttpRepl/Commands/SetSwaggerCommand.cs +++ b/src/Microsoft.HttpRepl/Commands/SetSwaggerCommand.cs @@ -47,7 +47,7 @@ namespace Microsoft.HttpRepl.Commands { if (string.IsNullOrEmpty(parameterSetsByContentType.Key)) { - dirRequestInfo.SetFallbackRequestBody(method, GetBodyString(null, parameterSetsByContentType.Value)); + dirRequestInfo.SetFallbackRequestBody(method, parameterSetsByContentType.Key, GetBodyString(null, parameterSetsByContentType.Value)); } dirRequestInfo.SetRequestBody(method, parameterSetsByContentType.Key, GetBodyString(parameterSetsByContentType.Key, parameterSetsByContentType.Value)); diff --git a/src/Microsoft.HttpRepl/DirectoryStructure.cs b/src/Microsoft.HttpRepl/DirectoryStructure.cs index 8787f962fc..7587327de0 100644 --- a/src/Microsoft.HttpRepl/DirectoryStructure.cs +++ b/src/Microsoft.HttpRepl/DirectoryStructure.cs @@ -55,13 +55,14 @@ namespace Microsoft.HttpRepl private readonly HashSet _methods = new HashSet(StringComparer.OrdinalIgnoreCase); private readonly Dictionary> _requestBodiesByMethodByContentType = new Dictionary>(StringComparer.OrdinalIgnoreCase); private readonly Dictionary _fallbackBodyStringsByMethod = new Dictionary(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary _fallbackContentTypeStringsByMethod = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly Dictionary> _contentTypesByMethod = new Dictionary>(StringComparer.OrdinalIgnoreCase); public IReadOnlyList Methods => _methods.ToList(); public IReadOnlyDictionary> ContentTypesByMethod => _contentTypesByMethod; - public string GetRequestBodyForContentType(string contentType, string method) + public string GetRequestBodyForContentType(ref string contentType, string method) { if (_requestBodiesByMethodByContentType.TryGetValue(method, out Dictionary bodiesByContentType) && bodiesByContentType.TryGetValue(contentType, out string body)) @@ -71,6 +72,11 @@ namespace Microsoft.HttpRepl if (_fallbackBodyStringsByMethod.TryGetValue(method, out body)) { + if (_fallbackContentTypeStringsByMethod.TryGetValue(method, out string newContentType)) + { + contentType = newContentType; + } + return body; } @@ -100,9 +106,10 @@ namespace Microsoft.HttpRepl _methods.Add(method); } - public void SetFallbackRequestBody(string method, string fallbackBodyString) + public void SetFallbackRequestBody(string method, string contentType, string fallbackBodyString) { _fallbackBodyStringsByMethod[method] = fallbackBodyString; + _fallbackContentTypeStringsByMethod[method] = contentType; } } } diff --git a/src/Microsoft.HttpRepl/HttpState.cs b/src/Microsoft.HttpRepl/HttpState.cs index 9104e4e02c..4ac8e09ed4 100644 --- a/src/Microsoft.HttpRepl/HttpState.cs +++ b/src/Microsoft.HttpRepl/HttpState.cs @@ -148,12 +148,12 @@ namespace Microsoft.HttpRepl } } - public string GetExampleBody(string path, string contentType, string method) + public string GetExampleBody(string path, ref string contentType, string method) { Uri effectivePath = GetEffectivePath(path); string rootRelativePath = effectivePath.LocalPath.Substring(BaseAddress.LocalPath.Length).TrimStart('/'); IDirectoryStructure structure = SwaggerStructure?.TraverseTo(rootRelativePath); - return structure?.RequestInfo?.GetRequestBodyForContentType(contentType, method); + return structure?.RequestInfo?.GetRequestBodyForContentType(ref contentType, method); } public IEnumerable GetApplicableContentTypes(string method, string path) diff --git a/src/Microsoft.HttpRepl/IRequestInfo.cs b/src/Microsoft.HttpRepl/IRequestInfo.cs index 24054f6142..d420d36d2a 100644 --- a/src/Microsoft.HttpRepl/IRequestInfo.cs +++ b/src/Microsoft.HttpRepl/IRequestInfo.cs @@ -11,6 +11,6 @@ namespace Microsoft.HttpRepl IReadOnlyList Methods { get; } - string GetRequestBodyForContentType(string contentType, string method); + string GetRequestBodyForContentType(ref string contentType, string method); } } diff --git a/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs b/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs index 22be314827..bdd9426868 100644 --- a/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs +++ b/src/Microsoft.Repl/Commanding/DefaultCommandDispatcher.cs @@ -79,7 +79,7 @@ namespace Microsoft.Repl.Commanding public IParser Parser => _parser; - public IReadOnlyList CollectSuggesetions(IShellState shellState) + public IReadOnlyList CollectSuggestions(IShellState shellState) { string line = shellState.InputManager.GetCurrentBuffer(); TParseResult parseResult = _parser.Parse(line, shellState.ConsoleManager.CaretPosition); diff --git a/src/Microsoft.Repl/Commanding/ICommandDispatcher.cs b/src/Microsoft.Repl/Commanding/ICommandDispatcher.cs index d2d9000123..b02dd830a7 100644 --- a/src/Microsoft.Repl/Commanding/ICommandDispatcher.cs +++ b/src/Microsoft.Repl/Commanding/ICommandDispatcher.cs @@ -12,7 +12,7 @@ namespace Microsoft.Repl.Commanding { IParser Parser { get; } - IReadOnlyList CollectSuggesetions(IShellState shellState); + IReadOnlyList CollectSuggestions(IShellState shellState); void OnReady(IShellState shellState); diff --git a/src/Microsoft.Repl/ConsoleHandling/ConsoleManager.cs b/src/Microsoft.Repl/ConsoleHandling/ConsoleManager.cs index ad4231ad5e..b6d471ad52 100644 --- a/src/Microsoft.Repl/ConsoleHandling/ConsoleManager.cs +++ b/src/Microsoft.Repl/ConsoleHandling/ConsoleManager.cs @@ -50,37 +50,41 @@ namespace Microsoft.Repl.ConsoleHandling return; } + int bufferWidth = Console.BufferWidth; + int cursorTop = Console.CursorTop; + int cursorLeft = Console.CursorLeft; + while (positions < 0 && CaretPosition > 0) { - if (-positions > Console.BufferWidth) + if (-positions > bufferWidth) { - if (Console.CursorTop == 0) + if (cursorTop == 0) { - Console.CursorLeft = 0; + cursorLeft = 0; positions = 0; } else { - positions += Console.BufferWidth; - --Console.CursorTop; + positions += bufferWidth; + --cursorTop; } } else { - int remaining = Console.CursorLeft + positions; + int remaining = cursorLeft + positions; if (remaining >= 0) { - Console.CursorLeft = remaining; + cursorLeft = remaining; } - else if (Console.CursorTop == 0) + else if (cursorTop == 0) { - Console.CursorLeft = 0; + cursorLeft = 0; } else { - --Console.CursorTop; - Console.CursorLeft = Console.BufferWidth + remaining; + --cursorTop; + cursorLeft = bufferWidth + remaining; } positions = 0; @@ -89,27 +93,29 @@ namespace Microsoft.Repl.ConsoleHandling while (positions > 0) { - if (positions > Console.BufferWidth) + if (positions > bufferWidth) { - positions -= Console.BufferWidth; - ++Console.CursorTop; + positions -= bufferWidth; + ++cursorTop; } else { - int spaceLeftOnLine = Console.BufferWidth - Console.CursorLeft - 1; + int spaceLeftOnLine = bufferWidth - cursorLeft - 1; if (positions > spaceLeftOnLine) { - ++Console.CursorTop; - Console.CursorLeft = positions - spaceLeftOnLine - 1; + ++cursorTop; + cursorLeft = positions - spaceLeftOnLine - 1; } else { - Console.CursorLeft += positions; + cursorLeft += positions; } positions = 0; } } + + Console.SetCursorPosition(cursorLeft, cursorTop); } } diff --git a/src/Microsoft.Repl/Input/InputManager.cs b/src/Microsoft.Repl/Input/InputManager.cs index cd1157c6ff..b35633ad4e 100644 --- a/src/Microsoft.Repl/Input/InputManager.cs +++ b/src/Microsoft.Repl/Input/InputManager.cs @@ -112,14 +112,22 @@ namespace Microsoft.Repl.Input private void StashEchoState() { - _ttyState = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.OSX) - ? GetTtyState() - : null; - - if (!string.IsNullOrEmpty(_ttyState)) + string sttyFlags = null; + if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.OSX)) { - //"gfmt1:cflag=4300:iflag=6b02:lflag=200005c7:oflag=3:discard=f:dsusp=19:eof=4:eol=ff:eol2=ff:erase=7f:intr=3:kill=15:lnext=16:min=1:quit=1c:reprint=12:start=11:status=14:stop=13:susp=1a:time=0:werase=17:ispeed=38400:ospeed=38400\n" - ProcessStartInfo psi = new ProcessStartInfo("stty", "gfmt1:erase=08:werase=08 -echo"); + _ttyState = GetTtyState(); + sttyFlags = "gfmt1:erase=08:werase=08 -echo"; + } + //If it's any of the ubuntu variants on 18.x, stty tweaks are required + else if (System.Runtime.InteropServices.RuntimeInformation.OSDescription.IndexOf("buntu", StringComparison.OrdinalIgnoreCase) > -1) + { + _ttyState = GetTtyState(); + sttyFlags = "erase 0x08 werase 0x08 -echo"; + } + + if (!string.IsNullOrEmpty(sttyFlags)) + { + ProcessStartInfo psi = new ProcessStartInfo("stty", sttyFlags); Process p = Process.Start(psi); p?.WaitForExit(); } @@ -133,7 +141,7 @@ namespace Microsoft.Repl.Input }; Process p = Process.Start(psi); p?.WaitForExit(); - string result = p?.StandardOutput.ReadToEnd(); + string result = p?.StandardOutput.ReadToEnd().Trim(); return result; } @@ -331,7 +339,7 @@ namespace Microsoft.Repl.Input } private void FlushInput(IShellState state, ref List presses) - { + { string str = new string(presses.Select(x => x.KeyChar).ToArray()); if (state.ConsoleManager.CaretPosition == _inputBuffer.Count) diff --git a/src/Microsoft.Repl/Suggestions/SuggestionManager.cs b/src/Microsoft.Repl/Suggestions/SuggestionManager.cs index ba68ee9d46..5080e6ae6f 100644 --- a/src/Microsoft.Repl/Suggestions/SuggestionManager.cs +++ b/src/Microsoft.Repl/Suggestions/SuggestionManager.cs @@ -36,7 +36,7 @@ namespace Microsoft.Repl.Suggestions else { _currentSuggestion = 0; - _suggestions = shellState.CommandDispatcher.CollectSuggesetions(shellState); + _suggestions = shellState.CommandDispatcher.CollectSuggestions(shellState); if (_suggestions == null || _suggestions.Count == 0) { @@ -76,7 +76,7 @@ namespace Microsoft.Repl.Suggestions } else { - _suggestions = shellState.CommandDispatcher.CollectSuggesetions(shellState); + _suggestions = shellState.CommandDispatcher.CollectSuggestions(shellState); _currentSuggestion = _suggestions.Count - 1; if (_suggestions == null || _suggestions.Count == 0) From d745b8c161d42665ceb51597888062336fec7764 Mon Sep 17 00:00:00 2001 From: Mike Lorbetske Date: Wed, 31 Oct 2018 12:45:45 -0700 Subject: [PATCH 0989/1029] Fix #485 --- src/Microsoft.HttpRepl/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.HttpRepl/Program.cs b/src/Microsoft.HttpRepl/Program.cs index e41a36ff21..308996ff2c 100644 --- a/src/Microsoft.HttpRepl/Program.cs +++ b/src/Microsoft.HttpRepl/Program.cs @@ -52,7 +52,7 @@ namespace Microsoft.HttpRepl shell.ShellState.ConsoleManager.AddBreakHandler(() => source.Cancel()); if (args.Length > 0) { - if (string.Equals(args[0], "--help", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(args[0], "--help", StringComparison.OrdinalIgnoreCase) || string.Equals(args[0], "-h", StringComparison.OrdinalIgnoreCase)) { shell.ShellState.ConsoleManager.WriteLine("Usage: dotnet httprepl [] [options]"); shell.ShellState.ConsoleManager.WriteLine(); From 9de04520e05b9458e376e8c0780fdff4dd7bade4 Mon Sep 17 00:00:00 2001 From: Liam Dawson Date: Tue, 6 Nov 2018 05:44:50 +1100 Subject: [PATCH 0990/1029] Add `user-secret init` command for adding a UserSecretsId to a project file (#500) --- src/dotnet-user-secrets/CommandLineOptions.cs | 1 + .../Internal/InitCommand.cs | 126 ++++++++++++++++++ src/dotnet-user-secrets/Program.cs | 6 + .../Properties/Resources.Designer.cs | 122 +++++++++-------- src/dotnet-user-secrets/Resources.resx | 63 +++++---- .../InitCommandTest.cs | 119 +++++++++++++++++ .../SecretManagerTests.cs | 15 ++- 7 files changed, 370 insertions(+), 82 deletions(-) create mode 100644 src/dotnet-user-secrets/Internal/InitCommand.cs create mode 100644 test/dotnet-user-secrets.Tests/InitCommandTest.cs diff --git a/src/dotnet-user-secrets/CommandLineOptions.cs b/src/dotnet-user-secrets/CommandLineOptions.cs index 6ce543cc00..8495b6de9d 100644 --- a/src/dotnet-user-secrets/CommandLineOptions.cs +++ b/src/dotnet-user-secrets/CommandLineOptions.cs @@ -50,6 +50,7 @@ namespace Microsoft.Extensions.SecretManager.Tools app.Command("remove", c => RemoveCommand.Configure(c, options)); app.Command("list", c => ListCommand.Configure(c, options)); app.Command("clear", c => ClearCommand.Configure(c, options)); + app.Command("init", c => InitCommandFactory.Configure(c, options)); // Show help information if no subcommand/option was specified. app.OnExecute(() => app.ShowHelp()); diff --git a/src/dotnet-user-secrets/Internal/InitCommand.cs b/src/dotnet-user-secrets/Internal/InitCommand.cs new file mode 100644 index 0000000000..670da42c4e --- /dev/null +++ b/src/dotnet-user-secrets/Internal/InitCommand.cs @@ -0,0 +1,126 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Linq; +using System.Xml.Linq; +using System.Xml.XPath; +using Microsoft.Extensions.CommandLineUtils; + +namespace Microsoft.Extensions.SecretManager.Tools.Internal +{ + // Workaround used to handle the fact that the options have not been parsed at configuration time + public class InitCommandFactory : ICommand + { + public CommandLineOptions Options { get; } + + internal static void Configure(CommandLineApplication command, CommandLineOptions options) + { + command.Description = "Set a user secrets ID to enable secret storage"; + command.HelpOption(); + + command.OnExecute(() => + { + options.Command = new InitCommandFactory(options); + }); + } + + public InitCommandFactory(CommandLineOptions options) + { + Options = options; + } + + public void Execute(CommandContext context) + { + new InitCommand(Options.Id, Options.Project).Execute(context); + } + + public void Execute(CommandContext context, string workingDirectory) + { + new InitCommand(Options.Id, Options.Project).Execute(context, workingDirectory); + } + } + + public class InitCommand : ICommand + { + public string OverrideId { get; } + public string ProjectPath { get; } + public string WorkingDirectory { get; private set; } = Directory.GetCurrentDirectory(); + + public InitCommand(string id, string project) + { + OverrideId = id; + ProjectPath = project; + } + + public void Execute(CommandContext context, string workingDirectory) + { + WorkingDirectory = workingDirectory; + Execute(context); + } + + public void Execute(CommandContext context) + { + var projectPath = ResolveProjectPath(ProjectPath, WorkingDirectory); + + // Load the project file as XML + var projectDocument = XDocument.Load(projectPath); + + // Accept the `--id` CLI option to the main app + string newSecretsId = string.IsNullOrWhiteSpace(OverrideId) + ? Guid.NewGuid().ToString() + : OverrideId; + + // Confirm secret ID does not contain invalid characters + if (Path.GetInvalidPathChars().Any(invalidChar => newSecretsId.Contains(invalidChar))) + { + throw new ArgumentException(Resources.FormatError_InvalidSecretsId(newSecretsId)); + } + + var existingUserSecretsId = projectDocument.XPathSelectElements("//UserSecretsId").FirstOrDefault(); + + // Check if a UserSecretsId is already set + if (existingUserSecretsId != default) + { + // Only set the UserSecretsId if the user specified an explicit value + if (string.IsNullOrWhiteSpace(OverrideId)) + { + context.Reporter.Output(Resources.FormatMessage_ProjectAlreadyInitialized(projectPath)); + return; + } + + existingUserSecretsId.SetValue(newSecretsId); + } + else + { + // Find the first non-conditional PropertyGroup + var propertyGroup = projectDocument.Root.DescendantNodes() + .FirstOrDefault(node => node is XElement el + && el.Name == "PropertyGroup" + && el.Attributes().All(attr => + attr.Name != "Condition")) as XElement; + + // No valid property group, create a new one + if (propertyGroup == null) + { + propertyGroup = new XElement("PropertyGroup"); + projectDocument.Root.AddFirst(propertyGroup); + } + + // Add UserSecretsId element + propertyGroup.Add(new XElement("UserSecretsId", newSecretsId)); + } + + projectDocument.Save(projectPath); + + context.Reporter.Output(Resources.FormatMessage_SetUserSecretsIdForProject(newSecretsId, projectPath)); + } + + private static string ResolveProjectPath(string name, string path) + { + var finder = new MsBuildProjectFinder(path); + return finder.FindMsBuildProject(name); + } + } +} diff --git a/src/dotnet-user-secrets/Program.cs b/src/dotnet-user-secrets/Program.cs index 187e40128f..710756eb88 100644 --- a/src/dotnet-user-secrets/Program.cs +++ b/src/dotnet-user-secrets/Program.cs @@ -71,6 +71,12 @@ namespace Microsoft.Extensions.SecretManager.Tools var reporter = CreateReporter(options.IsVerbose); + if (options.Command is InitCommandFactory initCmd) + { + initCmd.Execute(new CommandContext(null, reporter, _console), _workingDirectory); + return 0; + } + string userSecretsId; try { diff --git a/src/dotnet-user-secrets/Properties/Resources.Designer.cs b/src/dotnet-user-secrets/Properties/Resources.Designer.cs index a75fc0108f..8ee2a8f38e 100644 --- a/src/dotnet-user-secrets/Properties/Resources.Designer.cs +++ b/src/dotnet-user-secrets/Properties/Resources.Designer.cs @@ -15,16 +15,14 @@ namespace Microsoft.Extensions.SecretManager.Tools /// internal static string Error_Command_Failed { - get { return GetString("Error_Command_Failed"); } + get => GetString("Error_Command_Failed"); } /// /// Command failed : {message} /// internal static string FormatError_Command_Failed(object message) - { - return string.Format(CultureInfo.CurrentCulture, GetString("Error_Command_Failed", "message"), message); - } + => string.Format(CultureInfo.CurrentCulture, GetString("Error_Command_Failed", "message"), message); /// /// Missing parameter value for '{name}'. @@ -32,7 +30,7 @@ namespace Microsoft.Extensions.SecretManager.Tools /// internal static string Error_MissingArgument { - get { return GetString("Error_MissingArgument"); } + get => GetString("Error_MissingArgument"); } /// @@ -40,202 +38,218 @@ namespace Microsoft.Extensions.SecretManager.Tools /// Use the '--help' flag to see info. /// internal static string FormatError_MissingArgument(object name) - { - return string.Format(CultureInfo.CurrentCulture, GetString("Error_MissingArgument", "name"), name); - } + => string.Format(CultureInfo.CurrentCulture, GetString("Error_MissingArgument", "name"), name); /// /// Cannot find '{key}' in the secret store. /// internal static string Error_Missing_Secret { - get { return GetString("Error_Missing_Secret"); } + get => GetString("Error_Missing_Secret"); } /// /// Cannot find '{key}' in the secret store. /// internal static string FormatError_Missing_Secret(object key) - { - return string.Format(CultureInfo.CurrentCulture, GetString("Error_Missing_Secret", "key"), key); - } + => string.Format(CultureInfo.CurrentCulture, GetString("Error_Missing_Secret", "key"), key); /// /// Multiple MSBuild project files found in '{projectPath}'. Specify which to use with the --project option. /// internal static string Error_MultipleProjectsFound { - get { return GetString("Error_MultipleProjectsFound"); } + get => GetString("Error_MultipleProjectsFound"); } /// /// Multiple MSBuild project files found in '{projectPath}'. Specify which to use with the --project option. /// internal static string FormatError_MultipleProjectsFound(object projectPath) - { - return string.Format(CultureInfo.CurrentCulture, GetString("Error_MultipleProjectsFound", "projectPath"), projectPath); - } + => string.Format(CultureInfo.CurrentCulture, GetString("Error_MultipleProjectsFound", "projectPath"), projectPath); /// /// No secrets configured for this application. /// internal static string Error_No_Secrets_Found { - get { return GetString("Error_No_Secrets_Found"); } + get => GetString("Error_No_Secrets_Found"); } /// /// No secrets configured for this application. /// internal static string FormatError_No_Secrets_Found() - { - return GetString("Error_No_Secrets_Found"); - } + => GetString("Error_No_Secrets_Found"); /// /// Could not find a MSBuild project file in '{projectPath}'. Specify which project to use with the --project option. /// internal static string Error_NoProjectsFound { - get { return GetString("Error_NoProjectsFound"); } + get => GetString("Error_NoProjectsFound"); } /// /// Could not find a MSBuild project file in '{projectPath}'. Specify which project to use with the --project option. /// internal static string FormatError_NoProjectsFound(object projectPath) - { - return string.Format(CultureInfo.CurrentCulture, GetString("Error_NoProjectsFound", "projectPath"), projectPath); - } + => string.Format(CultureInfo.CurrentCulture, GetString("Error_NoProjectsFound", "projectPath"), projectPath); /// /// Could not find the global property 'UserSecretsId' in MSBuild project '{project}'. Ensure this property is set in the project or use the '--id' command line option. /// internal static string Error_ProjectMissingId { - get { return GetString("Error_ProjectMissingId"); } + get => GetString("Error_ProjectMissingId"); } /// /// Could not find the global property 'UserSecretsId' in MSBuild project '{project}'. Ensure this property is set in the project or use the '--id' command line option. /// internal static string FormatError_ProjectMissingId(object project) - { - return string.Format(CultureInfo.CurrentCulture, GetString("Error_ProjectMissingId", "project"), project); - } + => string.Format(CultureInfo.CurrentCulture, GetString("Error_ProjectMissingId", "project"), project); /// /// The project file '{path}' does not exist. /// internal static string Error_ProjectPath_NotFound { - get { return GetString("Error_ProjectPath_NotFound"); } + get => GetString("Error_ProjectPath_NotFound"); } /// /// The project file '{path}' does not exist. /// internal static string FormatError_ProjectPath_NotFound(object path) - { - return string.Format(CultureInfo.CurrentCulture, GetString("Error_ProjectPath_NotFound", "path"), path); - } + => string.Format(CultureInfo.CurrentCulture, GetString("Error_ProjectPath_NotFound", "path"), path); /// /// Could not load the MSBuild project '{project}'. /// internal static string Error_ProjectFailedToLoad { - get { return GetString("Error_ProjectFailedToLoad"); } + get => GetString("Error_ProjectFailedToLoad"); } /// /// Could not load the MSBuild project '{project}'. /// internal static string FormatError_ProjectFailedToLoad(object project) - { - return string.Format(CultureInfo.CurrentCulture, GetString("Error_ProjectFailedToLoad", "project"), project); - } + => string.Format(CultureInfo.CurrentCulture, GetString("Error_ProjectFailedToLoad", "project"), project); /// /// Project file path {project}. /// internal static string Message_Project_File_Path { - get { return GetString("Message_Project_File_Path"); } + get => GetString("Message_Project_File_Path"); } /// /// Project file path {project}. /// internal static string FormatMessage_Project_File_Path(object project) - { - return string.Format(CultureInfo.CurrentCulture, GetString("Message_Project_File_Path", "project"), project); - } + => string.Format(CultureInfo.CurrentCulture, GetString("Message_Project_File_Path", "project"), project); /// /// Successfully saved {key} = {value} to the secret store. /// internal static string Message_Saved_Secret { - get { return GetString("Message_Saved_Secret"); } + get => GetString("Message_Saved_Secret"); } /// /// Successfully saved {key} = {value} to the secret store. /// internal static string FormatMessage_Saved_Secret(object key, object value) - { - return string.Format(CultureInfo.CurrentCulture, GetString("Message_Saved_Secret", "key", "value"), key, value); - } + => string.Format(CultureInfo.CurrentCulture, GetString("Message_Saved_Secret", "key", "value"), key, value); /// /// Successfully saved {number} secrets to the secret store. /// internal static string Message_Saved_Secrets { - get { return GetString("Message_Saved_Secrets"); } + get => GetString("Message_Saved_Secrets"); } /// /// Successfully saved {number} secrets to the secret store. /// internal static string FormatMessage_Saved_Secrets(object number) - { - return string.Format(CultureInfo.CurrentCulture, GetString("Message_Saved_Secrets", "number"), number); - } + => string.Format(CultureInfo.CurrentCulture, GetString("Message_Saved_Secrets", "number"), number); /// /// Secrets file path {secretsFilePath}. /// internal static string Message_Secret_File_Path { - get { return GetString("Message_Secret_File_Path"); } + get => GetString("Message_Secret_File_Path"); } /// /// Secrets file path {secretsFilePath}. /// internal static string FormatMessage_Secret_File_Path(object secretsFilePath) - { - return string.Format(CultureInfo.CurrentCulture, GetString("Message_Secret_File_Path", "secretsFilePath"), secretsFilePath); - } + => string.Format(CultureInfo.CurrentCulture, GetString("Message_Secret_File_Path", "secretsFilePath"), secretsFilePath); /// /// {key} = {value} /// internal static string Message_Secret_Value_Format { - get { return GetString("Message_Secret_Value_Format"); } + get => GetString("Message_Secret_Value_Format"); } /// /// {key} = {value} /// internal static string FormatMessage_Secret_Value_Format(object key, object value) + => string.Format(CultureInfo.CurrentCulture, GetString("Message_Secret_Value_Format", "key", "value"), key, value); + + /// + /// The UserSecretsId '{userSecretsId}' cannot contain any characters that cannot be used in a file path. + /// + internal static string Error_InvalidSecretsId { - return string.Format(CultureInfo.CurrentCulture, GetString("Message_Secret_Value_Format", "key", "value"), key, value); + get => GetString("Error_InvalidSecretsId"); } + /// + /// The UserSecretsId '{userSecretsId}' cannot contain any characters that cannot be used in a file path. + /// + internal static string FormatError_InvalidSecretsId(object userSecretsId) + => string.Format(CultureInfo.CurrentCulture, GetString("Error_InvalidSecretsId", "userSecretsId"), userSecretsId); + + /// + /// The MSBuild project '{project}' has already been initialized with a UserSecretsId. + /// + internal static string Message_ProjectAlreadyInitialized + { + get => GetString("Message_ProjectAlreadyInitialized"); + } + + /// + /// The MSBuild project '{project}' has already been initialized with a UserSecretsId. + /// + internal static string FormatMessage_ProjectAlreadyInitialized(object project) + => string.Format(CultureInfo.CurrentCulture, GetString("Message_ProjectAlreadyInitialized", "project"), project); + + /// + /// Set UserSecretsId to '{userSecretsId}' for MSBuild project '{project}'. + /// + internal static string Message_SetUserSecretsIdForProject + { + get => GetString("Message_SetUserSecretsIdForProject"); + } + + /// + /// Set UserSecretsId to '{userSecretsId}' for MSBuild project '{project}'. + /// + internal static string FormatMessage_SetUserSecretsIdForProject(object userSecretsId, object project) + => string.Format(CultureInfo.CurrentCulture, GetString("Message_SetUserSecretsIdForProject", "userSecretsId", "project"), userSecretsId, project); + private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); diff --git a/src/dotnet-user-secrets/Resources.resx b/src/dotnet-user-secrets/Resources.resx index c9222930fc..bfcdf99c2a 100644 --- a/src/dotnet-user-secrets/Resources.resx +++ b/src/dotnet-user-secrets/Resources.resx @@ -1,17 +1,17 @@  - @@ -160,4 +160,13 @@ Use the '--help' flag to see info. {key} = {value} + + The UserSecretsId '{userSecretsId}' cannot contain any characters that cannot be used in a file path. + + + The MSBuild project '{project}' has already been initialized with a UserSecretsId. + + + Set UserSecretsId to '{userSecretsId}' for MSBuild project '{project}'. + \ No newline at end of file diff --git a/test/dotnet-user-secrets.Tests/InitCommandTest.cs b/test/dotnet-user-secrets.Tests/InitCommandTest.cs new file mode 100644 index 0000000000..d1558e8811 --- /dev/null +++ b/test/dotnet-user-secrets.Tests/InitCommandTest.cs @@ -0,0 +1,119 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Text; +using Microsoft.Extensions.Configuration.UserSecrets.Tests; +using Microsoft.Extensions.SecretManager.Tools.Internal; +using Microsoft.Extensions.Tools.Internal; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.Extensions.SecretManager.Tools.Tests +{ + public class InitCommandTests : IClassFixture + { + private UserSecretsTestFixture _fixture; + private ITestOutputHelper _output; + private TestConsole _console; + private StringBuilder _textOutput; + + public InitCommandTests(UserSecretsTestFixture fixture, ITestOutputHelper output) + { + _fixture = fixture; + _output = output; + _textOutput = new StringBuilder(); + + _console = new TestConsole(output) + { + Error = new StringWriter(_textOutput), + Out = new StringWriter(_textOutput), + }; + } + + private CommandContext MakeCommandContext() => new CommandContext(null, new TestReporter(_output), _console); + + [Fact] + public void AddsSecretIdToProject() + { + var projectDir = _fixture.CreateProject(null); + + new InitCommand(null, null).Execute(MakeCommandContext(), projectDir); + + var idResolver = new ProjectIdResolver(MakeCommandContext().Reporter, projectDir); + + Assert.False(string.IsNullOrWhiteSpace(idResolver.Resolve(null, null))); + } + + [Fact] + public void AddsSpecificSecretIdToProject() + { + const string SecretId = "TestSecretId"; + + var projectDir = _fixture.CreateProject(null); + + new InitCommand(SecretId, null).Execute(MakeCommandContext(), projectDir); + + var idResolver = new ProjectIdResolver(MakeCommandContext().Reporter, projectDir); + + Assert.Equal(SecretId, idResolver.Resolve(null, null)); + } + + [Fact] + public void AddsEscapedSpecificSecretIdToProject() + { + const string SecretId = @"&"; + + var projectDir = _fixture.CreateProject(null); + + new InitCommand(SecretId, null).Execute(MakeCommandContext(), projectDir); + + var idResolver = new ProjectIdResolver(MakeCommandContext().Reporter, projectDir); + + Assert.Equal(SecretId, idResolver.Resolve(null, null)); + } + + [Fact] + public void DoesNotGenerateIdForProjectWithSecretId() + { + const string SecretId = "AlreadyExists"; + + var projectDir = _fixture.CreateProject(SecretId); + + new InitCommand(null, null).Execute(MakeCommandContext(), projectDir); + + var idResolver = new ProjectIdResolver(MakeCommandContext().Reporter, projectDir); + + Assert.Equal(SecretId, idResolver.Resolve(null, null)); + } + + [Fact] + public void OverridesIdForProjectWithSecretId() + { + const string SecretId = "AlreadyExists"; + const string NewId = "TestValue"; + + var projectDir = _fixture.CreateProject(SecretId); + + new InitCommand(NewId, null).Execute(MakeCommandContext(), projectDir); + + var idResolver = new ProjectIdResolver(MakeCommandContext().Reporter, projectDir); + + Assert.Equal(NewId, idResolver.Resolve(null, null)); + } + + [Fact] + public void FailsForInvalidId() + { + string secretId = $"invalid{Path.GetInvalidPathChars()[0]}secret-id"; + + var projectDir = _fixture.CreateProject(null); + + Assert.Throws(() => + { + new InitCommand(secretId, null).Execute(MakeCommandContext(), projectDir); + }); + } + } +} diff --git a/test/dotnet-user-secrets.Tests/SecretManagerTests.cs b/test/dotnet-user-secrets.Tests/SecretManagerTests.cs index ee7ca55247..3a390d4439 100644 --- a/test/dotnet-user-secrets.Tests/SecretManagerTests.cs +++ b/test/dotnet-user-secrets.Tests/SecretManagerTests.cs @@ -323,5 +323,18 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests secretManager.RunInternal(args); Assert.Contains(Resources.Error_No_Secrets_Found, _output.ToString()); } + + [Fact] + public void Init_When_Project_Has_No_Secrets_Id() + { + var projectPath = _fixture.CreateProject(null); + var project = Path.Combine(projectPath, "TestProject.csproj"); + var secretManager = new Program(_console, projectPath); + + secretManager.RunInternal("init", "-p", project); + + Assert.DoesNotContain(Resources.FormatError_ProjectMissingId(project), _output.ToString()); + Assert.DoesNotContain("--help", _output.ToString()); + } } -} \ No newline at end of file +} From a24b4ee4598b425d9e8b2f041be508c32eb41cf5 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 6 Nov 2018 09:57:17 -0800 Subject: [PATCH 0991/1029] Reduce flakiness in tests caused by the OS re-using the PID on test processes (#512) We were using PID to assert that dotnet-watch had restarted processes. The OS does not guaranteed the uniqueness of PID, so I've changed tests to use PID + process start time to distinguish between processes. --- test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs | 12 ++++++------ .../Scenario/WatchableApp.cs | 9 +++++---- .../TestProjects/AppWithDeps/Program.cs | 3 ++- .../TestProjects/GlobbingApp/Program.cs | 3 ++- .../TestProjects/KitchenSink/Program.cs | 3 ++- .../TestProjects/NoDepsApp/Program.cs | 3 ++- 6 files changed, 19 insertions(+), 14 deletions(-) diff --git a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs index d1eead9048..812f4ca755 100644 --- a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs +++ b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs @@ -27,7 +27,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public async Task RestartProcessOnFileChange() { await _app.StartWatcherAsync(new[] { "--no-exit" }); - var pid = await _app.GetProcessId(); + var processIdentifier = await _app.GetProcessIdentifier(); // Then wait for it to restart when we change a file var fileToChange = Path.Combine(_app.SourceDirectory, "Program.cs"); @@ -37,15 +37,15 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests await _app.HasRestarted(); Assert.DoesNotContain(_app.Process.Output, l => l.StartsWith("Exited with error code")); - var pid2 = await _app.GetProcessId(); - Assert.NotEqual(pid, pid2); + var processIdentifier2 = await _app.GetProcessIdentifier(); + Assert.NotEqual(processIdentifier, processIdentifier2); } [Fact] public async Task RestartProcessThatTerminatesAfterFileChange() { await _app.StartWatcherAsync(); - var pid = await _app.GetProcessId(); + var processIdentifier = await _app.GetProcessIdentifier(); await _app.HasExited(); // process should exit after run await _app.IsWaitingForFileChange(); @@ -63,8 +63,8 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests await _app.HasRestarted(); } - var pid2 = await _app.GetProcessId(); - Assert.NotEqual(pid, pid2); + var processIdentifier2 = await _app.GetProcessIdentifier(); + Assert.NotEqual(processIdentifier, processIdentifier2); await _app.HasExited(); // process should exit after run } diff --git a/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs b/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs index 4f2d575f01..c6983a314c 100644 --- a/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs +++ b/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs @@ -57,11 +57,12 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public bool UsePollingWatcher { get; set; } - public async Task GetProcessId() + public async Task GetProcessIdentifier() { - var line = await Process.GetOutputLineStartsWithAsync("PID =", DefaultMessageTimeOut); - var pid = line.Split('=').Last(); - return int.Parse(pid); + // Process ID is insufficient because PID's may be reused. Process identifier also includes other info to distinguish + // between different process instances. + var line = await Process.GetOutputLineStartsWithAsync("Process identifier =", DefaultMessageTimeOut); + return line.Split('=').Last(); } public async Task PrepareAsync() diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/Program.cs b/test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/Program.cs index c9338cbc98..a96a0bf341 100644 --- a/test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/Program.cs +++ b/test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/Program.cs @@ -14,7 +14,8 @@ namespace ConsoleApplication public static void Main(string[] args) { Console.WriteLine("Started"); - Console.WriteLine($"PID = " + Process.GetCurrentProcess().Id); + // Process ID is insufficient because PID's may be reused. + Console.WriteLine($"Process identifier = {Process.GetCurrentProcess().Id}, {Process.GetCurrentProcess().StartTime:hh:mm:ss.FF}"); Thread.Sleep(Timeout.Infinite); } } diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/Program.cs b/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/Program.cs index 768257e074..07c6d0a527 100644 --- a/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/Program.cs +++ b/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/Program.cs @@ -14,7 +14,8 @@ namespace ConsoleApplication public static void Main(string[] args) { Console.WriteLine("Started"); - Console.WriteLine("PID = " + Process.GetCurrentProcess().Id); + // Process ID is insufficient because PID's may be reused. + Console.WriteLine($"Process identifier = {Process.GetCurrentProcess().Id}, {Process.GetCurrentProcess().StartTime:hh:mm:ss.FF}"); Console.WriteLine("Defined types = " + typeof(Program).GetTypeInfo().Assembly.DefinedTypes.Count()); Thread.Sleep(Timeout.Infinite); } diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/Program.cs b/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/Program.cs index f38dc8231b..ab2edae7a7 100644 --- a/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/Program.cs +++ b/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/Program.cs @@ -11,7 +11,8 @@ namespace KitchenSink static void Main(string[] args) { Console.WriteLine("Started"); - Console.WriteLine("PID = " + Process.GetCurrentProcess().Id); + // Process ID is insufficient because PID's may be reused. + Console.WriteLine($"Process identifier = {Process.GetCurrentProcess().Id}, {Process.GetCurrentProcess().StartTime:hh:mm:ss.FF}"); Console.WriteLine("DOTNET_WATCH = " + Environment.GetEnvironmentVariable("DOTNET_WATCH")); Console.WriteLine("DOTNET_WATCH_ITERATION = " + Environment.GetEnvironmentVariable("DOTNET_WATCH_ITERATION")); } diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/Program.cs b/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/Program.cs index b503e70ce6..f3da51ab08 100644 --- a/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/Program.cs +++ b/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/Program.cs @@ -12,7 +12,8 @@ namespace ConsoleApplication public static void Main(string[] args) { Console.WriteLine("Started"); - Console.WriteLine($"PID = " + Process.GetCurrentProcess().Id); + // Process ID is insufficient because PID's may be reused. + Console.WriteLine($"Process identifier = {Process.GetCurrentProcess().Id}, {Process.GetCurrentProcess().StartTime:hh:mm:ss.FF}"); if (args.Length > 0 && args[0] == "--no-exit") { Thread.Sleep(Timeout.Infinite); From 03c287406e2259b1fd647796634ee07e2ff5794d Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 8 Nov 2018 08:15:16 -0800 Subject: [PATCH 0992/1029] Updating submodule(s) EntityFrameworkCore => 68a631e43b262c1ad3039cd36728b49bed128cdd [auto-updated: submodules] --- modules/EntityFrameworkCore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/EntityFrameworkCore b/modules/EntityFrameworkCore index d5745f8b89..68a631e43b 160000 --- a/modules/EntityFrameworkCore +++ b/modules/EntityFrameworkCore @@ -1 +1 @@ -Subproject commit d5745f8b895de2c9f7636ecded35d387e2ff4d7b +Subproject commit 68a631e43b262c1ad3039cd36728b49bed128cdd From 79923e6a9f8ac4ceec0d69a3b3931b11eee77638 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 8 Nov 2018 17:21:41 +0000 Subject: [PATCH 0993/1029] Updating BuildTools from 2.1.3-rtm-15839 to 2.1.3-rtm-15840 [auto-updated: buildtools] --- korebuild-lock.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/korebuild-lock.txt b/korebuild-lock.txt index bf511bf4d6..f2b171d1e9 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.3-rtm-15839 -commithash:ee0ad5bd4ede948c6954704b621acc0c83445e5d +version:2.1.3-rtm-15840 +commithash:a47f557c0d6fecd333599e7691fa64239642ea33 From 0b77cfa4632a555201c4c529f3c3d76146609720 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 8 Nov 2018 17:35:13 +0000 Subject: [PATCH 0994/1029] Updating BuildTools from 2.1.3-rtm-15840 to 2.1.3-rtm-15841 [auto-updated: buildtools] --- korebuild-lock.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/korebuild-lock.txt b/korebuild-lock.txt index f2b171d1e9..774bb6d85d 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.3-rtm-15840 -commithash:a47f557c0d6fecd333599e7691fa64239642ea33 +version:2.1.3-rtm-15841 +commithash:b3eda40cef3d95be448f972e328801706267dfba From bf9fd0d10667e605d1df45f89e198be7f3bd1138 Mon Sep 17 00:00:00 2001 From: Alexander Shabunevich Date: Fri, 9 Nov 2018 01:29:34 +0300 Subject: [PATCH 0995/1029] Prevent null refs when copying a property with a null value * Fix aspnet/AspNetCore#3559 Json Patch: System.NullReferenceException while trying to use copy operation from property with null value. * Fix aspnet/AspNetCore#3559: Missing tests added. --- .../Adapters/ObjectAdapter.cs | 2 +- .../Internal/ConversionResultProvider.cs | 2 +- .../JsonPatchDocumentOfT.cs | 2 +- .../ExpandoObjectIntegrationTest.cs | 19 ++++++++++++++ .../NestedObjectIntegrationTest.cs | 25 ++++++++++++++++++- .../SimpleObjectIntegrationTest.cs | 20 +++++++++++++++ 6 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs index d625176376..75cc513312 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs @@ -229,7 +229,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters if (TryGetValue(operation.from, objectToApplyTo, operation, out var propertyValue)) { // Create deep copy - var copyResult = ConversionResultProvider.CopyTo(propertyValue, propertyValue.GetType()); + var copyResult = ConversionResultProvider.CopyTo(propertyValue, propertyValue?.GetType()); if (copyResult.CanBeConverted) { Add(operation.path, diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ConversionResultProvider.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ConversionResultProvider.cs index 71af0d27fc..3d0b6cc979 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Internal/ConversionResultProvider.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ConversionResultProvider.cs @@ -39,7 +39,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal var targetType = typeToConvertTo; if (value == null) { - return new ConversionResult(IsNullableType(typeToConvertTo), null); + return new ConversionResult(canBeConverted: true, convertedInstance: null); } else if (typeToConvertTo.IsAssignableFrom(value.GetType())) { diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs index 3db0aac458..e0b4fca240 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs +++ b/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs @@ -503,7 +503,7 @@ namespace Microsoft.AspNetCore.JsonPatch } /// - /// Copy the value at specified location to the target location. Willr esult in, for example: + /// Copy the value at specified location to the target location. Will result in, for example: /// { "op": "copy", "from": "/a/b/c", "path": "/a/b/e" } /// /// source location diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/ExpandoObjectIntegrationTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/ExpandoObjectIntegrationTest.cs index b1b58556f0..29fa5fc731 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/ExpandoObjectIntegrationTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/ExpandoObjectIntegrationTest.cs @@ -159,6 +159,25 @@ namespace Microsoft.AspNetCore.JsonPatch.IntegrationTests Assert.Equal("A", targetObject.AnotherStringProperty); } + [Fact] + public void CopyNullStringProperty_ToAnotherStringProperty() + { + // Arrange + dynamic targetObject = new ExpandoObject(); + + targetObject.StringProperty = null; + targetObject.AnotherStringProperty = "B"; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Copy("StringProperty", "AnotherStringProperty"); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Null(targetObject.AnotherStringProperty); + } + [Fact] public void MoveIntegerValue_ToAnotherIntegerProperty() { diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/NestedObjectIntegrationTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/NestedObjectIntegrationTest.cs index 92c0e7fb2d..2a7d6f7cd2 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/NestedObjectIntegrationTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/NestedObjectIntegrationTest.cs @@ -175,7 +175,30 @@ namespace Microsoft.AspNetCore.JsonPatch.IntegrationTests // Assert Assert.Equal("A", targetObject.SimpleObject.AnotherStringProperty); - } + } + + [Fact] + public void CopyNullStringProperty_ToAnotherStringProperty() + { + // Arrange + var targetObject = new SimpleObjectWithNestedObject() + { + SimpleObject = new SimpleObject() + { + StringProperty = null, + AnotherStringProperty = "B" + } + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Copy(o => o.SimpleObject.StringProperty, o => o.SimpleObject.AnotherStringProperty); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Null(targetObject.SimpleObject.AnotherStringProperty); + } [Fact] public void Copy_DeepClonesObject() diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/SimpleObjectIntegrationTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/SimpleObjectIntegrationTest.cs index 4672d9c97b..731e181697 100644 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/SimpleObjectIntegrationTest.cs +++ b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/SimpleObjectIntegrationTest.cs @@ -46,6 +46,26 @@ namespace Microsoft.AspNetCore.JsonPatch.IntegrationTests Assert.Equal("A", targetObject.AnotherStringProperty); } + [Fact] + public void CopyNullStringProperty_ToAnotherStringProperty() + { + // Arrange + var targetObject = new SimpleObject() + { + StringProperty = null, + AnotherStringProperty = "B" + }; + + var patchDocument = new JsonPatchDocument(); + patchDocument.Copy("StringProperty", "AnotherStringProperty"); + + // Act + patchDocument.ApplyTo(targetObject); + + // Assert + Assert.Null(targetObject.AnotherStringProperty); + } + [Fact] public void MoveIntegerProperty_ToAnotherIntegerProperty() { From f260f0947498e47efe7b588adb0d4ad1690bc6e1 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 8 Nov 2018 15:08:35 -0800 Subject: [PATCH 0996/1029] Updating BuildTools from 2.1.3-rtm-15841 to 2.1.3-rtm-15842 [auto-updated: buildtools] --- korebuild-lock.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 774bb6d85d..08f95645f0 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.3-rtm-15841 -commithash:b3eda40cef3d95be448f972e328801706267dfba +version:2.1.3-rtm-15842 +commithash:b631cb7a2b982cbbfc4d2e02be66c6612f9e3afd From 0c6e4bebab2b2755b7dd6eda732d2f2443a9cea6 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 8 Nov 2018 17:07:18 -0800 Subject: [PATCH 0997/1029] Prepare to build the 2.1.7 patch (#3970) * Prepare 2.1.7 patch * Add documentation for how we prepare servicing updates --- build/submodules.props | 6 +- docs/preparing-patch-updates.md | 37 + modules/MetaPackages | 2 +- modules/Scaffolding | 2 +- modules/Templating | 2 +- src/IISIntegration/version.props | 2 +- .../ArchiveBaseline.2.1.6.txt | 675 ++++++++++++++++++ .../ArchiveBaseline.2.1.6.txt | 667 +++++++++++++++++ version.props | 2 +- 9 files changed, 1387 insertions(+), 8 deletions(-) create mode 100644 docs/preparing-patch-updates.md create mode 100644 src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.1.6.txt create mode 100644 src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.1.6.txt diff --git a/build/submodules.props b/build/submodules.props index 086b29a461..4064fe8af9 100644 --- a/build/submodules.props +++ b/build/submodules.props @@ -36,8 +36,7 @@ - - + @@ -55,6 +54,7 @@ + @@ -69,7 +69,7 @@ - + diff --git a/docs/preparing-patch-updates.md b/docs/preparing-patch-updates.md new file mode 100644 index 0000000000..87821935de --- /dev/null +++ b/docs/preparing-patch-updates.md @@ -0,0 +1,37 @@ +Preparing new servicing updates +=============================== + +In order to prepare this repo to build a new servicing update, the following changes need to be made. + +* Increment the patch version in the [version.props](/version.props) file in the repository root. + + ```diff + - 7 + + 8 + ``` + +* Update the package archive baselines. This is used to make sure each build + of the package archives we give to Azure only contains new files and does + not require overwriting existing files. See [src/PackageArchive/ZipManifestGenerator/](/src/PackageArchive/ZipManifestGenerator/README.md) for instructions on how to run this tool. + +* Update the list of repositories which will contain changes in [build/submodules.props](/build/submodules.props). + + * `` items represent repos which were released in a previous patch, and will not contain servicing updates in the next patch. + * `` items represent repos which will produce new packages in this patch. + * It is usually best to move everything to `` and then iteratively add them back to `` as new repos receive approval to patch. + * Don't change the `PatchPolicy` attribute. The build system uses this to ensure patching rules are obeyed. + +* For each repository still listed as a ``, update the version.props file in that submodule. For example, https://github.com/aspnet/Templating/pull/824 + + * The version prefix in repos should match the version of ASP.NET Core. + * Exception: SignalR, which is "1.1", not "2.1". + * This leaves holes in versioning, which is okay. This may mean you increment the patch value by more than one. Example: + * EF Core ships patches in 2.1.4 as "2.1.4" + * EF Core does not ship patches in 2.1.5 or 2.1.6 + * EF Core ships in 2.1.7, therefore, EFCore's version.props file should jump from 2.1.4 to 2.1.7. + + ```diff + + - 2.1.4 + + 2.1.7 + ``` diff --git a/modules/MetaPackages b/modules/MetaPackages index 96be626c87..975011071b 160000 --- a/modules/MetaPackages +++ b/modules/MetaPackages @@ -1 +1 @@ -Subproject commit 96be626c87c3ca325b18aa6653602f5e7087497f +Subproject commit 975011071b02f6937261c604fcde48d7e43030ce diff --git a/modules/Scaffolding b/modules/Scaffolding index 840531e6a0..2f81b98c13 160000 --- a/modules/Scaffolding +++ b/modules/Scaffolding @@ -1 +1 @@ -Subproject commit 840531e6a03fab451c1efb83098ea4d724a5d03d +Subproject commit 2f81b98c133c24ec699f370bf07b557dd484c646 diff --git a/modules/Templating b/modules/Templating index 6bafc157e7..3f26b56fef 160000 --- a/modules/Templating +++ b/modules/Templating @@ -1 +1 @@ -Subproject commit 6bafc157e78371f4ad4c80e4671a9c9a00d03694 +Subproject commit 3f26b56fefaa559d1ca9ba9181a249c0af26b9c3 diff --git a/src/IISIntegration/version.props b/src/IISIntegration/version.props index e897351a24..eb76a7c8ee 100644 --- a/src/IISIntegration/version.props +++ b/src/IISIntegration/version.props @@ -2,7 +2,7 @@ 2 1 - 2 + 7 $(DotNetMajorVersion).$(DotNetMinorVersion).$(DotNetPatchVersion) 12 $(DotNetMinorVersion) diff --git a/src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.1.6.txt b/src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.1.6.txt new file mode 100644 index 0000000000..62153a6836 --- /dev/null +++ b/src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.1.6.txt @@ -0,0 +1,675 @@ +libuv\1.10.0\.nupkg.metadata +libuv\1.10.0\.signature.p7s +messagepack\1.7.3.4\.nupkg.metadata +messagepack\1.7.3.4\.signature.p7s +microsoft.applicationinsights.aspnetcore\2.1.1\.nupkg.metadata +microsoft.applicationinsights.aspnetcore\2.1.1\.signature.p7s +microsoft.applicationinsights.dependencycollector\2.4.1\.nupkg.metadata +microsoft.applicationinsights.dependencycollector\2.4.1\.signature.p7s +microsoft.applicationinsights\2.4.0\.nupkg.metadata +microsoft.applicationinsights\2.4.0\.signature.p7s +microsoft.aspnet.webapi.client\5.2.6\.nupkg.metadata +microsoft.aspnetcore.all\2.1.1\.nupkg.metadata +microsoft.aspnetcore.antiforgery\2.1.1\.nupkg.metadata +microsoft.aspnetcore.app\2.1.1\.nupkg.metadata +microsoft.aspnetcore.applicationinsights.hostingstartup\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.azuread.ui\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.azureadb2c.ui\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.cookies\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.core\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.facebook\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.google\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.jwtbearer\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.microsoftaccount\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.oauth\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.openidconnect\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.twitter\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.wsfederation\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authorization.policy\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authorization\2.1.1\.nupkg.metadata +microsoft.aspnetcore.azureappservices.hostingstartup\2.1.1\.nupkg.metadata +microsoft.aspnetcore.azureappservicesintegration\2.1.1\.nupkg.metadata +microsoft.aspnetcore.connections.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.cookiepolicy\2.1.1\.nupkg.metadata +microsoft.aspnetcore.cors\2.1.1\.nupkg.metadata +microsoft.aspnetcore.cryptography.internal\2.1.1\.nupkg.metadata +microsoft.aspnetcore.cryptography.keyderivation\2.1.1\.nupkg.metadata +microsoft.aspnetcore.dataprotection.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.dataprotection.azurekeyvault\2.1.1\.nupkg.metadata +microsoft.aspnetcore.dataprotection.azurestorage\2.1.1\.nupkg.metadata +microsoft.aspnetcore.dataprotection.extensions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.dataprotection\2.1.1\.nupkg.metadata +microsoft.aspnetcore.diagnostics.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.1.1\.nupkg.metadata +microsoft.aspnetcore.diagnostics\2.1.1\.nupkg.metadata +microsoft.aspnetcore.hostfiltering\2.1.1\.nupkg.metadata +microsoft.aspnetcore.hosting.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.hosting.server.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.hosting\2.1.1\.nupkg.metadata +microsoft.aspnetcore.html.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.http.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.http.connections.common\1.0.1\.nupkg.metadata +microsoft.aspnetcore.http.connections\1.0.1\.nupkg.metadata +microsoft.aspnetcore.http.extensions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.http.features\2.1.1\.nupkg.metadata +microsoft.aspnetcore.http\2.1.1\.nupkg.metadata +microsoft.aspnetcore.httpoverrides\2.1.1\.nupkg.metadata +microsoft.aspnetcore.httpspolicy\2.1.1\.nupkg.metadata +microsoft.aspnetcore.identity.entityframeworkcore\2.1.1\.nupkg.metadata +microsoft.aspnetcore.identity.ui\2.1.1\.nupkg.metadata +microsoft.aspnetcore.identity\2.1.1\.nupkg.metadata +microsoft.aspnetcore.jsonpatch\2.1.1\.nupkg.metadata +microsoft.aspnetcore.localization.routing\2.1.1\.nupkg.metadata +microsoft.aspnetcore.localization\2.1.1\.nupkg.metadata +microsoft.aspnetcore.middlewareanalysis\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.analyzers\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.apiexplorer\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.core\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.cors\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.dataannotations\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.formatters.json\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.formatters.xml\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.localization\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.razor.extensions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.razor.viewcompilation\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.razor\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.razorpages\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.taghelpers\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.viewfeatures\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc\2.1.1\.nupkg.metadata +microsoft.aspnetcore.nodeservices\2.1.1\.nupkg.metadata +microsoft.aspnetcore.owin\2.1.1\.nupkg.metadata +microsoft.aspnetcore.razor.design\2.1.2\.nupkg.metadata +microsoft.aspnetcore.razor.language\2.1.1\.nupkg.metadata +microsoft.aspnetcore.razor.runtime\2.1.1\.nupkg.metadata +microsoft.aspnetcore.razor\2.1.1\.nupkg.metadata +microsoft.aspnetcore.responsecaching.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.responsecaching\2.1.1\.nupkg.metadata +microsoft.aspnetcore.responsecompression\2.1.1\.nupkg.metadata +microsoft.aspnetcore.rewrite\2.1.1\.nupkg.metadata +microsoft.aspnetcore.routing.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.routing\2.1.1\.nupkg.metadata +microsoft.aspnetcore.server.httpsys\2.1.1\.nupkg.metadata +microsoft.aspnetcore.server.iisintegration\2.1.1\.nupkg.metadata +microsoft.aspnetcore.server.kestrel.core\2.1.1\.nupkg.metadata +microsoft.aspnetcore.server.kestrel.https\2.1.1\.nupkg.metadata +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.server.kestrel.transport.libuv\2.1.1\.nupkg.metadata +microsoft.aspnetcore.server.kestrel.transport.sockets\2.1.1\.nupkg.metadata +microsoft.aspnetcore.server.kestrel\2.1.1\.nupkg.metadata +microsoft.aspnetcore.session\2.1.1\.nupkg.metadata +microsoft.aspnetcore.signalr.common\1.0.1\.nupkg.metadata +microsoft.aspnetcore.signalr.core\1.0.1\.nupkg.metadata +microsoft.aspnetcore.signalr.protocols.json\1.0.1\.nupkg.metadata +microsoft.aspnetcore.signalr.redis\1.0.1\.nupkg.metadata +microsoft.aspnetcore.signalr\1.0.1\.nupkg.metadata +microsoft.aspnetcore.spaservices.extensions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.spaservices\2.1.1\.nupkg.metadata +microsoft.aspnetcore.staticfiles\2.1.1\.nupkg.metadata +microsoft.aspnetcore.websockets\2.1.1\.nupkg.metadata +microsoft.aspnetcore.webutilities\2.1.1\.nupkg.metadata +microsoft.aspnetcore\2.1.1\.nupkg.metadata +microsoft.azure.keyvault.webkey\2.0.7\.nupkg.metadata +microsoft.azure.keyvault.webkey\2.0.7\.signature.p7s +microsoft.azure.keyvault\2.3.2\.nupkg.metadata +microsoft.azure.keyvault\2.3.2\.signature.p7s +microsoft.azure.services.appauthentication\1.0.1\.nupkg.metadata +microsoft.azure.services.appauthentication\1.0.1\.signature.p7s +microsoft.codeanalysis.analyzers\1.1.0\.nupkg.metadata +microsoft.codeanalysis.common\2.8.0\.nupkg.metadata +microsoft.codeanalysis.csharp.workspaces\2.8.0\.nupkg.metadata +microsoft.codeanalysis.csharp\2.8.0\.nupkg.metadata +microsoft.codeanalysis.razor\2.1.1\.nupkg.metadata +microsoft.codeanalysis.workspaces.common\2.8.0\.nupkg.metadata +microsoft.csharp\4.0.1\.nupkg.metadata +microsoft.csharp\4.3.0\.nupkg.metadata +microsoft.csharp\4.5.0\.nupkg.metadata +microsoft.data.edm\5.8.2\.nupkg.metadata +microsoft.data.odata\5.8.2\.nupkg.metadata +microsoft.data.sqlite.core\2.1.0\.nupkg.metadata +microsoft.data.sqlite\2.1.0\.nupkg.metadata +microsoft.dotnet.platformabstractions\2.1.0\.nupkg.metadata +microsoft.entityframeworkcore.abstractions\2.1.1\.nupkg.metadata +microsoft.entityframeworkcore.analyzers\2.1.1\.nupkg.metadata +microsoft.entityframeworkcore.design\2.1.1\.nupkg.metadata +microsoft.entityframeworkcore.inmemory\2.1.1\.nupkg.metadata +microsoft.entityframeworkcore.relational\2.1.1\.nupkg.metadata +microsoft.entityframeworkcore.sqlite.core\2.1.1\.nupkg.metadata +microsoft.entityframeworkcore.sqlite\2.1.1\.nupkg.metadata +microsoft.entityframeworkcore.sqlserver\2.1.1\.nupkg.metadata +microsoft.entityframeworkcore.tools\2.1.1\.nupkg.metadata +microsoft.entityframeworkcore\2.1.1\.nupkg.metadata +microsoft.extensions.caching.abstractions\2.1.1\.nupkg.metadata +microsoft.extensions.caching.memory\2.1.1\.nupkg.metadata +microsoft.extensions.caching.redis\2.1.1\.nupkg.metadata +microsoft.extensions.caching.sqlserver\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.abstractions\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.azurekeyvault\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.binder\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.commandline\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.environmentvariables\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.fileextensions\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.ini\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.json\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.keyperfile\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.usersecrets\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.xml\2.1.1\.nupkg.metadata +microsoft.extensions.configuration\2.1.1\.nupkg.metadata +microsoft.extensions.dependencyinjection.abstractions\2.1.1\.nupkg.metadata +microsoft.extensions.dependencyinjection\2.1.1\.nupkg.metadata +microsoft.extensions.dependencymodel\2.1.0\.nupkg.metadata +microsoft.extensions.diagnosticadapter\2.1.0\.nupkg.metadata +microsoft.extensions.fileproviders.abstractions\2.1.1\.nupkg.metadata +microsoft.extensions.fileproviders.composite\2.1.1\.nupkg.metadata +microsoft.extensions.fileproviders.embedded\2.1.1\.nupkg.metadata +microsoft.extensions.fileproviders.physical\2.1.1\.nupkg.metadata +microsoft.extensions.filesystemglobbing\2.1.1\.nupkg.metadata +microsoft.extensions.hosting.abstractions\2.1.1\.nupkg.metadata +microsoft.extensions.hosting\2.1.1\.nupkg.metadata +microsoft.extensions.http\2.1.1\.nupkg.metadata +microsoft.extensions.identity.core\2.1.1\.nupkg.metadata +microsoft.extensions.identity.stores\2.1.1\.nupkg.metadata +microsoft.extensions.localization.abstractions\2.1.1\.nupkg.metadata +microsoft.extensions.localization\2.1.1\.nupkg.metadata +microsoft.extensions.logging.abstractions\2.1.1\.nupkg.metadata +microsoft.extensions.logging.azureappservices\2.1.1\.nupkg.metadata +microsoft.extensions.logging.configuration\2.1.1\.nupkg.metadata +microsoft.extensions.logging.console\2.1.1\.nupkg.metadata +microsoft.extensions.logging.debug\2.1.1\.nupkg.metadata +microsoft.extensions.logging.eventsource\2.1.1\.nupkg.metadata +microsoft.extensions.logging.tracesource\2.1.1\.nupkg.metadata +microsoft.extensions.logging\2.1.1\.nupkg.metadata +microsoft.extensions.objectpool\2.1.1\.nupkg.metadata +microsoft.extensions.options.configurationextensions\2.1.1\.nupkg.metadata +microsoft.extensions.options\2.1.1\.nupkg.metadata +microsoft.extensions.platformabstractions\1.1.0\.nupkg.metadata +microsoft.extensions.primitives\2.1.1\.nupkg.metadata +microsoft.extensions.webencoders\2.1.1\.nupkg.metadata +microsoft.identitymodel.clients.activedirectory\3.14.2\.nupkg.metadata +microsoft.identitymodel.clients.activedirectory\3.14.2\.signature.p7s +microsoft.identitymodel.logging\5.2.0\.nupkg.metadata +microsoft.identitymodel.logging\5.2.0\.signature.p7s +microsoft.identitymodel.protocols.openidconnect\5.2.0\.nupkg.metadata +microsoft.identitymodel.protocols.openidconnect\5.2.0\.signature.p7s +microsoft.identitymodel.protocols.wsfederation\5.2.0\.nupkg.metadata +microsoft.identitymodel.protocols.wsfederation\5.2.0\.signature.p7s +microsoft.identitymodel.protocols\5.2.0\.nupkg.metadata +microsoft.identitymodel.protocols\5.2.0\.signature.p7s +microsoft.identitymodel.tokens.saml\5.2.0\.nupkg.metadata +microsoft.identitymodel.tokens.saml\5.2.0\.signature.p7s +microsoft.identitymodel.tokens\5.2.0\.nupkg.metadata +microsoft.identitymodel.tokens\5.2.0\.signature.p7s +microsoft.identitymodel.xml\5.2.0\.nupkg.metadata +microsoft.identitymodel.xml\5.2.0\.signature.p7s +microsoft.net.http.headers\2.1.1\.nupkg.metadata +microsoft.netcore.app\2.1.0\.nupkg.metadata +microsoft.netcore.dotnetapphost\2.1.0\.nupkg.metadata +microsoft.netcore.dotnethostpolicy\2.1.0\.nupkg.metadata +microsoft.netcore.dotnethostresolver\2.1.0\.nupkg.metadata +microsoft.netcore.platforms\1.0.1\.nupkg.metadata +microsoft.netcore.platforms\1.0.1\.signature.p7s +microsoft.netcore.platforms\1.0.2\.nupkg.metadata +microsoft.netcore.platforms\1.0.2\.signature.p7s +microsoft.netcore.platforms\1.1.0\.nupkg.metadata +microsoft.netcore.platforms\1.1.0\.signature.p7s +microsoft.netcore.platforms\2.0.0\.nupkg.metadata +microsoft.netcore.platforms\2.0.0\.signature.p7s +microsoft.netcore.platforms\2.1.0\.nupkg.metadata +microsoft.netcore.targets\1.0.1\.nupkg.metadata +microsoft.netcore.targets\1.1.0\.nupkg.metadata +microsoft.netcore.targets\2.1.0\.nupkg.metadata +microsoft.rest.clientruntime.azure\3.3.7\.nupkg.metadata +microsoft.rest.clientruntime.azure\3.3.7\.signature.p7s +microsoft.rest.clientruntime\2.3.8\.nupkg.metadata +microsoft.rest.clientruntime\2.3.8\.signature.p7s +microsoft.visualstudio.web.browserlink\2.1.1\.nupkg.metadata +microsoft.visualstudio.web.codegeneration.contracts\2.1.6\.nupkg.metadata +microsoft.visualstudio.web.codegeneration.contracts\2.1.6\.signature.p7s +microsoft.visualstudio.web.codegeneration.contracts\2.1.6\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Contracts.dll +microsoft.visualstudio.web.codegeneration.contracts\2.1.6\microsoft.visualstudio.web.codegeneration.contracts.2.1.6.nupkg +microsoft.visualstudio.web.codegeneration.contracts\2.1.6\microsoft.visualstudio.web.codegeneration.contracts.2.1.6.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.contracts\2.1.6\microsoft.visualstudio.web.codegeneration.contracts.nuspec +microsoft.visualstudio.web.codegeneration.core\2.1.6\.nupkg.metadata +microsoft.visualstudio.web.codegeneration.core\2.1.6\.signature.p7s +microsoft.visualstudio.web.codegeneration.core\2.1.6\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Core.dll +microsoft.visualstudio.web.codegeneration.core\2.1.6\microsoft.visualstudio.web.codegeneration.core.2.1.6.nupkg +microsoft.visualstudio.web.codegeneration.core\2.1.6\microsoft.visualstudio.web.codegeneration.core.2.1.6.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.core\2.1.6\microsoft.visualstudio.web.codegeneration.core.nuspec +microsoft.visualstudio.web.codegeneration.design\2.1.6\.nupkg.metadata +microsoft.visualstudio.web.codegeneration.design\2.1.6\.signature.p7s +microsoft.visualstudio.web.codegeneration.design\2.1.6\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.6\lib\netstandard2.0\dotnet-aspnet-codegenerator-design.dll +microsoft.visualstudio.web.codegeneration.design\2.1.6\microsoft.visualstudio.web.codegeneration.design.2.1.6.nupkg +microsoft.visualstudio.web.codegeneration.design\2.1.6\microsoft.visualstudio.web.codegeneration.design.2.1.6.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.design\2.1.6\microsoft.visualstudio.web.codegeneration.design.nuspec +microsoft.visualstudio.web.codegeneration.design\2.1.6\runtimes\win7-x64\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.6\runtimes\win7-x86\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.6\runtimes\win-arm\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.6\runtimes\win-arm64\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.6\.nupkg.metadata +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.6\.signature.p7s +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.6\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore.dll +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.6\microsoft.visualstudio.web.codegeneration.entityframeworkcore.2.1.6.nupkg +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.6\microsoft.visualstudio.web.codegeneration.entityframeworkcore.2.1.6.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.6\microsoft.visualstudio.web.codegeneration.entityframeworkcore.nuspec +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.6\Templates\DbContext\NewLocalDbContext.cshtml +microsoft.visualstudio.web.codegeneration.templating\2.1.6\.nupkg.metadata +microsoft.visualstudio.web.codegeneration.templating\2.1.6\.signature.p7s +microsoft.visualstudio.web.codegeneration.templating\2.1.6\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Templating.dll +microsoft.visualstudio.web.codegeneration.templating\2.1.6\microsoft.visualstudio.web.codegeneration.templating.2.1.6.nupkg +microsoft.visualstudio.web.codegeneration.templating\2.1.6\microsoft.visualstudio.web.codegeneration.templating.2.1.6.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.templating\2.1.6\microsoft.visualstudio.web.codegeneration.templating.nuspec +microsoft.visualstudio.web.codegeneration.utils\2.1.6\.nupkg.metadata +microsoft.visualstudio.web.codegeneration.utils\2.1.6\.signature.p7s +microsoft.visualstudio.web.codegeneration.utils\2.1.6\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Utils.dll +microsoft.visualstudio.web.codegeneration.utils\2.1.6\microsoft.visualstudio.web.codegeneration.utils.2.1.6.nupkg +microsoft.visualstudio.web.codegeneration.utils\2.1.6\microsoft.visualstudio.web.codegeneration.utils.2.1.6.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.utils\2.1.6\microsoft.visualstudio.web.codegeneration.utils.nuspec +microsoft.visualstudio.web.codegeneration\2.1.6\.nupkg.metadata +microsoft.visualstudio.web.codegeneration\2.1.6\.signature.p7s +microsoft.visualstudio.web.codegeneration\2.1.6\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.dll +microsoft.visualstudio.web.codegeneration\2.1.6\microsoft.visualstudio.web.codegeneration.2.1.6.nupkg +microsoft.visualstudio.web.codegeneration\2.1.6\microsoft.visualstudio.web.codegeneration.2.1.6.nupkg.sha512 +microsoft.visualstudio.web.codegeneration\2.1.6\microsoft.visualstudio.web.codegeneration.nuspec +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\.nupkg.metadata +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\.signature.p7s +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Generators\ParameterDefinitions\area.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Generators\ParameterDefinitions\controller.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Generators\ParameterDefinitions\identity.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Generators\ParameterDefinitions\razorpage.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Generators\ParameterDefinitions\view.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\lib\netstandard2.0\identitygeneratorfilesconfig.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGenerators.Mvc.dll +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\microsoft.visualstudio.web.codegenerators.mvc.2.1.6.nupkg +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\microsoft.visualstudio.web.codegenerators.mvc.2.1.6.nupkg.sha512 +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\microsoft.visualstudio.web.codegenerators.mvc.nuspec +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ControllerGenerator\ApiControllerWithActions.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ControllerGenerator\ApiControllerWithContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ControllerGenerator\ApiEmptyController.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ControllerGenerator\ControllerWithActions.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ControllerGenerator\EmptyController.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ControllerGenerator\MvcControllerWithContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\_LoginPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Data\ApplicationDbContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Data\ApplicationUser.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\IdentityHostingStartup.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\_Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\_ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\_ViewStart.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.AccessDenied.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.AccessDenied.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ConfirmEmail.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ConfirmEmail.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ExternalLogin.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ExternalLogin.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ForgotPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ForgotPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ForgotPasswordConfirmation.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ForgotPasswordConfirmation.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.Lockout.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.Lockout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.Login.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.Login.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.LoginWith2fa.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.LoginWith2fa.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.LoginWithRecoveryCode.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.LoginWithRecoveryCode.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.Logout.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.Logout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.Register.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.Register.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ResetPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ResetPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ResetPasswordConfirmation.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ResetPasswordConfirmation.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage._Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage._ManageNav.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage._StatusMessage.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.ChangePassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.ChangePassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.DeletePersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.DeletePersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.Disable2fa.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.Disable2fa.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.DownloadPersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.DownloadPersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.EnableAuthenticator.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.EnableAuthenticator.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.ExternalLogins.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.ExternalLogins.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.GenerateRecoveryCodes.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.GenerateRecoveryCodes.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.Index.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.Index.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.ManageNavPages.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.PersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.PersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.ResetAuthenticator.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.ResetAuthenticator.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.SetPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.SetPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.ShowRecoveryCodes.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.ShowRecoveryCodes.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.TwoFactorAuthentication.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.TwoFactorAuthentication.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Error.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Error.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\ScaffoldingReadme.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\SupportPages._CookieConsentPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\SupportPages._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\SupportPages._ViewStart.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\css\site.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\css\site.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\favicon.ico +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\images\banner1.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\images\banner2.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\images\banner3.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\js\site.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\js\site.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.min.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.min.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.eot +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.ttf +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.woff +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.woff2 +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\js\bootstrap.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\js\bootstrap.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\js\npm.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\LICENSE +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery\dist\jquery.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery\dist\jquery.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery\dist\jquery.min.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery\LICENSE.txt +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery-validation\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery-validation\dist\additional-methods.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery-validation\dist\additional-methods.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery-validation\dist\jquery.validate.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery-validation\dist\jquery.validate.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery-validation\LICENSE.md +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\LICENSE.txt +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\MvcLayout\_Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\MvcLayout\Error.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\Create.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\CreatePageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\Delete.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\DeletePageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\Details.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\DetailsPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\Edit.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\EditPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\Empty.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\EmptyPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\List.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\ListPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Startup\ReadMe.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Startup\Startup.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ViewGenerator\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ViewGenerator\Create.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ViewGenerator\Delete.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ViewGenerator\Details.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ViewGenerator\Edit.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ViewGenerator\Empty.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ViewGenerator\List.cshtml +microsoft.win32.primitives\4.0.1\.nupkg.metadata +microsoft.win32.primitives\4.3.0\.nupkg.metadata +microsoft.win32.registry\4.3.0\.nupkg.metadata +microsoft.win32.registry\4.5.0\.nupkg.metadata +netstandard.library\1.6.0\.nupkg.metadata +netstandard.library\1.6.1\.nupkg.metadata +netstandard.library\2.0.3\.nupkg.metadata +newtonsoft.json.bson\1.0.1\.nupkg.metadata +newtonsoft.json.bson\1.0.1\.signature.p7s +newtonsoft.json\10.0.1\.nupkg.metadata +newtonsoft.json\10.0.1\.signature.p7s +newtonsoft.json\11.0.2\.nupkg.metadata +newtonsoft.json\11.0.2\.signature.p7s +newtonsoft.json\9.0.1\.nupkg.metadata +nuget.frameworks\4.7.0\.nupkg.metadata +remotion.linq\2.2.0\.nupkg.metadata +remotion.linq\2.2.0\.signature.p7s +runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.native.system.data.sqlclient.sni\4.4.0\.nupkg.metadata +runtime.native.system.io.compression\4.1.0\.nupkg.metadata +runtime.native.system.io.compression\4.3.0\.nupkg.metadata +runtime.native.system.net.http\4.0.1\.nupkg.metadata +runtime.native.system.net.http\4.3.0\.nupkg.metadata +runtime.native.system.net.security\4.3.0\.nupkg.metadata +runtime.native.system.security.cryptography.apple\4.3.0\.nupkg.metadata +runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.native.system.security.cryptography\4.0.0\.nupkg.metadata +runtime.native.system\4.0.0\.nupkg.metadata +runtime.native.system\4.3.0\.nupkg.metadata +runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple\4.3.0\.nupkg.metadata +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.win-arm64.runtime.native.system.data.sqlclient.sni\4.4.0\.nupkg.metadata +runtime.win-x64.runtime.native.system.data.sqlclient.sni\4.4.0\.nupkg.metadata +runtime.win-x86.runtime.native.system.data.sqlclient.sni\4.4.0\.nupkg.metadata +sqlitepclraw.bundle_green\1.1.11\.nupkg.metadata +sqlitepclraw.bundle_green\1.1.11\.signature.p7s +sqlitepclraw.core\1.1.11\.nupkg.metadata +sqlitepclraw.core\1.1.11\.signature.p7s +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\.nupkg.metadata +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\.signature.p7s +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\.nupkg.metadata +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\.signature.p7s +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\.nupkg.metadata +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\.signature.p7s +sqlitepclraw.provider.e_sqlite3.netstandard11\1.1.11\.nupkg.metadata +sqlitepclraw.provider.e_sqlite3.netstandard11\1.1.11\.signature.p7s +stackexchange.redis.strongname\1.2.4\.nupkg.metadata +stackexchange.redis.strongname\1.2.4\.signature.p7s +system.appcontext\4.1.0\.nupkg.metadata +system.appcontext\4.3.0\.nupkg.metadata +system.buffers\4.0.0\.nupkg.metadata +system.buffers\4.3.0\.nupkg.metadata +system.buffers\4.5.0\.nupkg.metadata +system.collections.concurrent\4.0.12\.nupkg.metadata +system.collections.concurrent\4.3.0\.nupkg.metadata +system.collections.immutable\1.3.0\.nupkg.metadata +system.collections.immutable\1.3.1\.nupkg.metadata +system.collections.immutable\1.5.0\.nupkg.metadata +system.collections.nongeneric\4.3.0\.nupkg.metadata +system.collections.specialized\4.3.0\.nupkg.metadata +system.collections\4.0.11\.nupkg.metadata +system.collections\4.3.0\.nupkg.metadata +system.componentmodel.annotations\4.5.0\.nupkg.metadata +system.componentmodel.primitives\4.3.0\.nupkg.metadata +system.componentmodel.typeconverter\4.3.0\.nupkg.metadata +system.componentmodel\4.3.0\.nupkg.metadata +system.composition.attributedmodel\1.0.31\.nupkg.metadata +system.composition.convention\1.0.31\.nupkg.metadata +system.composition.hosting\1.0.31\.nupkg.metadata +system.composition.runtime\1.0.31\.nupkg.metadata +system.composition.typedparts\1.0.31\.nupkg.metadata +system.composition\1.0.31\.nupkg.metadata +system.console\4.0.0\.nupkg.metadata +system.console\4.3.0\.nupkg.metadata +system.data.sqlclient\4.5.1\.nupkg.metadata +system.diagnostics.contracts\4.3.0\.nupkg.metadata +system.diagnostics.debug\4.0.11\.nupkg.metadata +system.diagnostics.debug\4.3.0\.nupkg.metadata +system.diagnostics.diagnosticsource\4.0.0\.nupkg.metadata +system.diagnostics.diagnosticsource\4.3.0\.nupkg.metadata +system.diagnostics.diagnosticsource\4.4.0\.nupkg.metadata +system.diagnostics.diagnosticsource\4.4.0\.signature.p7s +system.diagnostics.diagnosticsource\4.5.0\.nupkg.metadata +system.diagnostics.fileversioninfo\4.3.0\.nupkg.metadata +system.diagnostics.process\4.3.0\.nupkg.metadata +system.diagnostics.stacktrace\4.3.0\.nupkg.metadata +system.diagnostics.tools\4.0.1\.nupkg.metadata +system.diagnostics.tools\4.3.0\.nupkg.metadata +system.diagnostics.tracing\4.1.0\.nupkg.metadata +system.diagnostics.tracing\4.3.0\.nupkg.metadata +system.dynamic.runtime\4.0.11\.nupkg.metadata +system.dynamic.runtime\4.3.0\.nupkg.metadata +system.globalization.calendars\4.0.1\.nupkg.metadata +system.globalization.calendars\4.3.0\.nupkg.metadata +system.globalization.extensions\4.0.1\.nupkg.metadata +system.globalization.extensions\4.3.0\.nupkg.metadata +system.globalization\4.0.11\.nupkg.metadata +system.globalization\4.3.0\.nupkg.metadata +system.identitymodel.tokens.jwt\5.2.0\.nupkg.metadata +system.identitymodel.tokens.jwt\5.2.0\.signature.p7s +system.interactive.async\3.1.1\.nupkg.metadata +system.interactive.async\3.1.1\.signature.p7s +system.io.compression.zipfile\4.0.1\.nupkg.metadata +system.io.compression.zipfile\4.3.0\.nupkg.metadata +system.io.compression\4.1.0\.nupkg.metadata +system.io.compression\4.3.0\.nupkg.metadata +system.io.filesystem.primitives\4.0.1\.nupkg.metadata +system.io.filesystem.primitives\4.3.0\.nupkg.metadata +system.io.filesystem\4.0.1\.nupkg.metadata +system.io.filesystem\4.3.0\.nupkg.metadata +system.io.pipelines\4.5.0\.nupkg.metadata +system.io\4.1.0\.nupkg.metadata +system.io\4.3.0\.nupkg.metadata +system.linq.expressions\4.1.0\.nupkg.metadata +system.linq.expressions\4.3.0\.nupkg.metadata +system.linq.parallel\4.3.0\.nupkg.metadata +system.linq.queryable\4.0.1\.nupkg.metadata +system.linq\4.1.0\.nupkg.metadata +system.linq\4.3.0\.nupkg.metadata +system.memory\4.5.1\.nupkg.metadata +system.net.http\4.1.0\.nupkg.metadata +system.net.http\4.1.0\.signature.p7s +system.net.http\4.3.0\.nupkg.metadata +system.net.http\4.3.0\.signature.p7s +system.net.nameresolution\4.3.0\.nupkg.metadata +system.net.primitives\4.0.11\.nupkg.metadata +system.net.primitives\4.3.0\.nupkg.metadata +system.net.security\4.3.0\.nupkg.metadata +system.net.sockets\4.1.0\.nupkg.metadata +system.net.sockets\4.3.0\.nupkg.metadata +system.net.websockets.websocketprotocol\4.5.1\.nupkg.metadata +system.numerics.vectors\4.5.0\.nupkg.metadata +system.objectmodel\4.0.12\.nupkg.metadata +system.objectmodel\4.3.0\.nupkg.metadata +system.private.datacontractserialization\4.1.1\.nupkg.metadata +system.private.datacontractserialization\4.3.0\.nupkg.metadata +system.reflection.emit.ilgeneration\4.0.1\.nupkg.metadata +system.reflection.emit.ilgeneration\4.3.0\.nupkg.metadata +system.reflection.emit.lightweight\4.0.1\.nupkg.metadata +system.reflection.emit.lightweight\4.3.0\.nupkg.metadata +system.reflection.emit\4.0.1\.nupkg.metadata +system.reflection.emit\4.3.0\.nupkg.metadata +system.reflection.extensions\4.0.1\.nupkg.metadata +system.reflection.extensions\4.3.0\.nupkg.metadata +system.reflection.metadata\1.4.1\.nupkg.metadata +system.reflection.metadata\1.4.2\.nupkg.metadata +system.reflection.metadata\1.6.0\.nupkg.metadata +system.reflection.primitives\4.0.1\.nupkg.metadata +system.reflection.primitives\4.3.0\.nupkg.metadata +system.reflection.typeextensions\4.1.0\.nupkg.metadata +system.reflection.typeextensions\4.3.0\.nupkg.metadata +system.reflection\4.1.0\.nupkg.metadata +system.reflection\4.3.0\.nupkg.metadata +system.resources.resourcemanager\4.0.1\.nupkg.metadata +system.resources.resourcemanager\4.3.0\.nupkg.metadata +system.runtime.compilerservices.unsafe\4.5.0\.nupkg.metadata +system.runtime.compilerservices.unsafe\4.5.1\.nupkg.metadata +system.runtime.extensions\4.1.0\.nupkg.metadata +system.runtime.extensions\4.3.0\.nupkg.metadata +system.runtime.handles\4.0.1\.nupkg.metadata +system.runtime.handles\4.3.0\.nupkg.metadata +system.runtime.interopservices.runtimeinformation\4.0.0\.nupkg.metadata +system.runtime.interopservices.runtimeinformation\4.3.0\.nupkg.metadata +system.runtime.interopservices\4.1.0\.nupkg.metadata +system.runtime.interopservices\4.3.0\.nupkg.metadata +system.runtime.numerics\4.0.1\.nupkg.metadata +system.runtime.numerics\4.3.0\.nupkg.metadata +system.runtime.serialization.formatters\4.3.0\.nupkg.metadata +system.runtime.serialization.json\4.0.2\.nupkg.metadata +system.runtime.serialization.primitives\4.1.1\.nupkg.metadata +system.runtime.serialization.primitives\4.3.0\.nupkg.metadata +system.runtime.serialization.xml\4.3.0\.nupkg.metadata +system.runtime\4.1.0\.nupkg.metadata +system.runtime\4.3.0\.nupkg.metadata +system.security.accesscontrol\4.5.0\.nupkg.metadata +system.security.claims\4.3.0\.nupkg.metadata +system.security.cryptography.algorithms\4.2.0\.nupkg.metadata +system.security.cryptography.algorithms\4.3.0\.nupkg.metadata +system.security.cryptography.cng\4.2.0\.nupkg.metadata +system.security.cryptography.cng\4.3.0\.nupkg.metadata +system.security.cryptography.cng\4.5.0\.nupkg.metadata +system.security.cryptography.csp\4.0.0\.nupkg.metadata +system.security.cryptography.csp\4.3.0\.nupkg.metadata +system.security.cryptography.encoding\4.0.0\.nupkg.metadata +system.security.cryptography.encoding\4.3.0\.nupkg.metadata +system.security.cryptography.openssl\4.0.0\.nupkg.metadata +system.security.cryptography.openssl\4.3.0\.nupkg.metadata +system.security.cryptography.pkcs\4.5.0\.nupkg.metadata +system.security.cryptography.primitives\4.0.0\.nupkg.metadata +system.security.cryptography.primitives\4.3.0\.nupkg.metadata +system.security.cryptography.x509certificates\4.1.0\.nupkg.metadata +system.security.cryptography.x509certificates\4.3.0\.nupkg.metadata +system.security.cryptography.xml\4.5.0\.nupkg.metadata +system.security.permissions\4.5.0\.nupkg.metadata +system.security.principal.windows\4.3.0\.nupkg.metadata +system.security.principal.windows\4.5.0\.nupkg.metadata +system.security.principal\4.3.0\.nupkg.metadata +system.spatial\5.8.2\.nupkg.metadata +system.text.encoding.codepages\4.3.0\.nupkg.metadata +system.text.encoding.codepages\4.5.0\.nupkg.metadata +system.text.encoding.extensions\4.0.11\.nupkg.metadata +system.text.encoding.extensions\4.3.0\.nupkg.metadata +system.text.encoding\4.0.11\.nupkg.metadata +system.text.encoding\4.3.0\.nupkg.metadata +system.text.encodings.web\4.3.1\.nupkg.metadata +system.text.encodings.web\4.3.1\.signature.p7s +system.text.encodings.web\4.5.0\.nupkg.metadata +system.text.regularexpressions\4.1.0\.nupkg.metadata +system.text.regularexpressions\4.3.0\.nupkg.metadata +system.threading.channels\4.5.0\.nupkg.metadata +system.threading.tasks.extensions\4.0.0\.nupkg.metadata +system.threading.tasks.extensions\4.3.0\.nupkg.metadata +system.threading.tasks.extensions\4.5.1\.nupkg.metadata +system.threading.tasks.parallel\4.3.0\.nupkg.metadata +system.threading.tasks\4.0.11\.nupkg.metadata +system.threading.tasks\4.3.0\.nupkg.metadata +system.threading.thread\4.3.0\.nupkg.metadata +system.threading.threadpool\4.3.0\.nupkg.metadata +system.threading.timer\4.0.1\.nupkg.metadata +system.threading.timer\4.3.0\.nupkg.metadata +system.threading\4.0.11\.nupkg.metadata +system.threading\4.3.0\.nupkg.metadata +system.valuetuple\4.3.0\.nupkg.metadata +system.valuetuple\4.5.0\.nupkg.metadata +system.xml.readerwriter\4.0.11\.nupkg.metadata +system.xml.readerwriter\4.3.0\.nupkg.metadata +system.xml.xdocument\4.0.11\.nupkg.metadata +system.xml.xdocument\4.3.0\.nupkg.metadata +system.xml.xmldocument\4.0.1\.nupkg.metadata +system.xml.xmldocument\4.3.0\.nupkg.metadata +system.xml.xmlserializer\4.0.11\.nupkg.metadata +system.xml.xmlserializer\4.3.0\.nupkg.metadata +system.xml.xpath.xdocument\4.3.0\.nupkg.metadata +system.xml.xpath\4.3.0\.nupkg.metadata +windowsazure.storage\8.1.4\.nupkg.metadata +windowsazure.storage\8.1.4\.signature.p7s diff --git a/src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.1.6.txt b/src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.1.6.txt new file mode 100644 index 0000000000..ba2033ed81 --- /dev/null +++ b/src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.1.6.txt @@ -0,0 +1,667 @@ +libuv\1.10.0\.nupkg.metadata +libuv\1.10.0\.signature.p7s +messagepack\1.7.3.4\.nupkg.metadata +messagepack\1.7.3.4\.signature.p7s +microsoft.applicationinsights.aspnetcore\2.1.1\.nupkg.metadata +microsoft.applicationinsights.aspnetcore\2.1.1\.signature.p7s +microsoft.applicationinsights.dependencycollector\2.4.1\.nupkg.metadata +microsoft.applicationinsights.dependencycollector\2.4.1\.signature.p7s +microsoft.applicationinsights\2.4.0\.nupkg.metadata +microsoft.applicationinsights\2.4.0\.signature.p7s +microsoft.aspnet.webapi.client\5.2.6\.nupkg.metadata +microsoft.aspnetcore.all\2.1.1\.nupkg.metadata +microsoft.aspnetcore.antiforgery\2.1.1\.nupkg.metadata +microsoft.aspnetcore.app\2.1.1\.nupkg.metadata +microsoft.aspnetcore.applicationinsights.hostingstartup\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.azuread.ui\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.azureadb2c.ui\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.cookies\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.core\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.facebook\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.google\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.jwtbearer\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.microsoftaccount\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.oauth\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.openidconnect\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.twitter\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication.wsfederation\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authentication\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authorization.policy\2.1.1\.nupkg.metadata +microsoft.aspnetcore.authorization\2.1.1\.nupkg.metadata +microsoft.aspnetcore.azureappservices.hostingstartup\2.1.1\.nupkg.metadata +microsoft.aspnetcore.azureappservicesintegration\2.1.1\.nupkg.metadata +microsoft.aspnetcore.connections.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.cookiepolicy\2.1.1\.nupkg.metadata +microsoft.aspnetcore.cors\2.1.1\.nupkg.metadata +microsoft.aspnetcore.cryptography.internal\2.1.1\.nupkg.metadata +microsoft.aspnetcore.cryptography.keyderivation\2.1.1\.nupkg.metadata +microsoft.aspnetcore.dataprotection.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.dataprotection.azurekeyvault\2.1.1\.nupkg.metadata +microsoft.aspnetcore.dataprotection.azurestorage\2.1.1\.nupkg.metadata +microsoft.aspnetcore.dataprotection.extensions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.dataprotection\2.1.1\.nupkg.metadata +microsoft.aspnetcore.diagnostics.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.1.1\.nupkg.metadata +microsoft.aspnetcore.diagnostics\2.1.1\.nupkg.metadata +microsoft.aspnetcore.hostfiltering\2.1.1\.nupkg.metadata +microsoft.aspnetcore.hosting.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.hosting.server.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.hosting\2.1.1\.nupkg.metadata +microsoft.aspnetcore.html.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.http.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.http.connections.common\1.0.1\.nupkg.metadata +microsoft.aspnetcore.http.connections\1.0.1\.nupkg.metadata +microsoft.aspnetcore.http.extensions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.http.features\2.1.1\.nupkg.metadata +microsoft.aspnetcore.http\2.1.1\.nupkg.metadata +microsoft.aspnetcore.httpoverrides\2.1.1\.nupkg.metadata +microsoft.aspnetcore.httpspolicy\2.1.1\.nupkg.metadata +microsoft.aspnetcore.identity.entityframeworkcore\2.1.1\.nupkg.metadata +microsoft.aspnetcore.identity.ui\2.1.1\.nupkg.metadata +microsoft.aspnetcore.identity\2.1.1\.nupkg.metadata +microsoft.aspnetcore.jsonpatch\2.1.1\.nupkg.metadata +microsoft.aspnetcore.localization.routing\2.1.1\.nupkg.metadata +microsoft.aspnetcore.localization\2.1.1\.nupkg.metadata +microsoft.aspnetcore.middlewareanalysis\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.analyzers\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.apiexplorer\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.core\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.cors\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.dataannotations\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.formatters.json\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.formatters.xml\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.localization\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.razor.extensions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.razor.viewcompilation\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.razor\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.razorpages\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.taghelpers\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc.viewfeatures\2.1.1\.nupkg.metadata +microsoft.aspnetcore.mvc\2.1.1\.nupkg.metadata +microsoft.aspnetcore.nodeservices\2.1.1\.nupkg.metadata +microsoft.aspnetcore.owin\2.1.1\.nupkg.metadata +microsoft.aspnetcore.razor.design\2.1.2\.nupkg.metadata +microsoft.aspnetcore.razor.language\2.1.1\.nupkg.metadata +microsoft.aspnetcore.razor.runtime\2.1.1\.nupkg.metadata +microsoft.aspnetcore.razor\2.1.1\.nupkg.metadata +microsoft.aspnetcore.responsecaching.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.responsecaching\2.1.1\.nupkg.metadata +microsoft.aspnetcore.responsecompression\2.1.1\.nupkg.metadata +microsoft.aspnetcore.rewrite\2.1.1\.nupkg.metadata +microsoft.aspnetcore.routing.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.routing\2.1.1\.nupkg.metadata +microsoft.aspnetcore.server.httpsys\2.1.1\.nupkg.metadata +microsoft.aspnetcore.server.iisintegration\2.1.1\.nupkg.metadata +microsoft.aspnetcore.server.kestrel.core\2.1.1\.nupkg.metadata +microsoft.aspnetcore.server.kestrel.https\2.1.1\.nupkg.metadata +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.server.kestrel.transport.libuv\2.1.1\.nupkg.metadata +microsoft.aspnetcore.server.kestrel.transport.sockets\2.1.1\.nupkg.metadata +microsoft.aspnetcore.server.kestrel\2.1.1\.nupkg.metadata +microsoft.aspnetcore.session\2.1.1\.nupkg.metadata +microsoft.aspnetcore.signalr.common\1.0.1\.nupkg.metadata +microsoft.aspnetcore.signalr.core\1.0.1\.nupkg.metadata +microsoft.aspnetcore.signalr.protocols.json\1.0.1\.nupkg.metadata +microsoft.aspnetcore.signalr.redis\1.0.1\.nupkg.metadata +microsoft.aspnetcore.signalr\1.0.1\.nupkg.metadata +microsoft.aspnetcore.spaservices.extensions\2.1.1\.nupkg.metadata +microsoft.aspnetcore.spaservices\2.1.1\.nupkg.metadata +microsoft.aspnetcore.staticfiles\2.1.1\.nupkg.metadata +microsoft.aspnetcore.websockets\2.1.1\.nupkg.metadata +microsoft.aspnetcore.webutilities\2.1.1\.nupkg.metadata +microsoft.aspnetcore\2.1.1\.nupkg.metadata +microsoft.azure.keyvault.webkey\2.0.7\.nupkg.metadata +microsoft.azure.keyvault.webkey\2.0.7\.signature.p7s +microsoft.azure.keyvault\2.3.2\.nupkg.metadata +microsoft.azure.keyvault\2.3.2\.signature.p7s +microsoft.azure.services.appauthentication\1.0.1\.nupkg.metadata +microsoft.azure.services.appauthentication\1.0.1\.signature.p7s +microsoft.codeanalysis.analyzers\1.1.0\.nupkg.metadata +microsoft.codeanalysis.common\2.8.0\.nupkg.metadata +microsoft.codeanalysis.csharp.workspaces\2.8.0\.nupkg.metadata +microsoft.codeanalysis.csharp\2.8.0\.nupkg.metadata +microsoft.codeanalysis.razor\2.1.1\.nupkg.metadata +microsoft.codeanalysis.workspaces.common\2.8.0\.nupkg.metadata +microsoft.csharp\4.0.1\.nupkg.metadata +microsoft.csharp\4.3.0\.nupkg.metadata +microsoft.csharp\4.5.0\.nupkg.metadata +microsoft.data.edm\5.8.2\.nupkg.metadata +microsoft.data.odata\5.8.2\.nupkg.metadata +microsoft.data.sqlite.core\2.1.0\.nupkg.metadata +microsoft.data.sqlite\2.1.0\.nupkg.metadata +microsoft.dotnet.platformabstractions\2.1.0\.nupkg.metadata +microsoft.entityframeworkcore.abstractions\2.1.1\.nupkg.metadata +microsoft.entityframeworkcore.analyzers\2.1.1\.nupkg.metadata +microsoft.entityframeworkcore.design\2.1.1\.nupkg.metadata +microsoft.entityframeworkcore.inmemory\2.1.1\.nupkg.metadata +microsoft.entityframeworkcore.relational\2.1.1\.nupkg.metadata +microsoft.entityframeworkcore.sqlite.core\2.1.1\.nupkg.metadata +microsoft.entityframeworkcore.sqlite\2.1.1\.nupkg.metadata +microsoft.entityframeworkcore.sqlserver\2.1.1\.nupkg.metadata +microsoft.entityframeworkcore.tools\2.1.1\.nupkg.metadata +microsoft.entityframeworkcore\2.1.1\.nupkg.metadata +microsoft.extensions.caching.abstractions\2.1.1\.nupkg.metadata +microsoft.extensions.caching.memory\2.1.1\.nupkg.metadata +microsoft.extensions.caching.redis\2.1.1\.nupkg.metadata +microsoft.extensions.caching.sqlserver\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.abstractions\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.azurekeyvault\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.binder\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.commandline\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.environmentvariables\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.fileextensions\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.ini\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.json\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.keyperfile\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.usersecrets\2.1.1\.nupkg.metadata +microsoft.extensions.configuration.xml\2.1.1\.nupkg.metadata +microsoft.extensions.configuration\2.1.1\.nupkg.metadata +microsoft.extensions.dependencyinjection.abstractions\2.1.1\.nupkg.metadata +microsoft.extensions.dependencyinjection\2.1.1\.nupkg.metadata +microsoft.extensions.dependencymodel\2.1.0\.nupkg.metadata +microsoft.extensions.diagnosticadapter\2.1.0\.nupkg.metadata +microsoft.extensions.fileproviders.abstractions\2.1.1\.nupkg.metadata +microsoft.extensions.fileproviders.composite\2.1.1\.nupkg.metadata +microsoft.extensions.fileproviders.embedded\2.1.1\.nupkg.metadata +microsoft.extensions.fileproviders.physical\2.1.1\.nupkg.metadata +microsoft.extensions.filesystemglobbing\2.1.1\.nupkg.metadata +microsoft.extensions.hosting.abstractions\2.1.1\.nupkg.metadata +microsoft.extensions.hosting\2.1.1\.nupkg.metadata +microsoft.extensions.http\2.1.1\.nupkg.metadata +microsoft.extensions.identity.core\2.1.1\.nupkg.metadata +microsoft.extensions.identity.stores\2.1.1\.nupkg.metadata +microsoft.extensions.localization.abstractions\2.1.1\.nupkg.metadata +microsoft.extensions.localization\2.1.1\.nupkg.metadata +microsoft.extensions.logging.abstractions\2.1.1\.nupkg.metadata +microsoft.extensions.logging.azureappservices\2.1.1\.nupkg.metadata +microsoft.extensions.logging.configuration\2.1.1\.nupkg.metadata +microsoft.extensions.logging.console\2.1.1\.nupkg.metadata +microsoft.extensions.logging.debug\2.1.1\.nupkg.metadata +microsoft.extensions.logging.eventsource\2.1.1\.nupkg.metadata +microsoft.extensions.logging.tracesource\2.1.1\.nupkg.metadata +microsoft.extensions.logging\2.1.1\.nupkg.metadata +microsoft.extensions.objectpool\2.1.1\.nupkg.metadata +microsoft.extensions.options.configurationextensions\2.1.1\.nupkg.metadata +microsoft.extensions.options\2.1.1\.nupkg.metadata +microsoft.extensions.platformabstractions\1.1.0\.nupkg.metadata +microsoft.extensions.primitives\2.1.1\.nupkg.metadata +microsoft.extensions.webencoders\2.1.1\.nupkg.metadata +microsoft.identitymodel.clients.activedirectory\3.14.2\.nupkg.metadata +microsoft.identitymodel.clients.activedirectory\3.14.2\.signature.p7s +microsoft.identitymodel.logging\5.2.0\.nupkg.metadata +microsoft.identitymodel.logging\5.2.0\.signature.p7s +microsoft.identitymodel.protocols.openidconnect\5.2.0\.nupkg.metadata +microsoft.identitymodel.protocols.openidconnect\5.2.0\.signature.p7s +microsoft.identitymodel.protocols.wsfederation\5.2.0\.nupkg.metadata +microsoft.identitymodel.protocols.wsfederation\5.2.0\.signature.p7s +microsoft.identitymodel.protocols\5.2.0\.nupkg.metadata +microsoft.identitymodel.protocols\5.2.0\.signature.p7s +microsoft.identitymodel.tokens.saml\5.2.0\.nupkg.metadata +microsoft.identitymodel.tokens.saml\5.2.0\.signature.p7s +microsoft.identitymodel.tokens\5.2.0\.nupkg.metadata +microsoft.identitymodel.tokens\5.2.0\.signature.p7s +microsoft.identitymodel.xml\5.2.0\.nupkg.metadata +microsoft.identitymodel.xml\5.2.0\.signature.p7s +microsoft.net.http.headers\2.1.1\.nupkg.metadata +microsoft.netcore.app\2.1.0\.nupkg.metadata +microsoft.netcore.dotnetapphost\2.1.0\.nupkg.metadata +microsoft.netcore.dotnethostpolicy\2.1.0\.nupkg.metadata +microsoft.netcore.dotnethostresolver\2.1.0\.nupkg.metadata +microsoft.netcore.platforms\1.0.1\.nupkg.metadata +microsoft.netcore.platforms\1.0.1\.signature.p7s +microsoft.netcore.platforms\1.0.2\.nupkg.metadata +microsoft.netcore.platforms\1.0.2\.signature.p7s +microsoft.netcore.platforms\1.1.0\.nupkg.metadata +microsoft.netcore.platforms\1.1.0\.signature.p7s +microsoft.netcore.platforms\2.0.0\.nupkg.metadata +microsoft.netcore.platforms\2.0.0\.signature.p7s +microsoft.netcore.platforms\2.1.0\.nupkg.metadata +microsoft.netcore.targets\1.0.1\.nupkg.metadata +microsoft.netcore.targets\1.1.0\.nupkg.metadata +microsoft.netcore.targets\2.1.0\.nupkg.metadata +microsoft.rest.clientruntime.azure\3.3.7\.nupkg.metadata +microsoft.rest.clientruntime.azure\3.3.7\.signature.p7s +microsoft.rest.clientruntime\2.3.8\.nupkg.metadata +microsoft.rest.clientruntime\2.3.8\.signature.p7s +microsoft.visualstudio.web.browserlink\2.1.1\.nupkg.metadata +microsoft.visualstudio.web.codegeneration.contracts\2.1.6\.nupkg.metadata +microsoft.visualstudio.web.codegeneration.contracts\2.1.6\.signature.p7s +microsoft.visualstudio.web.codegeneration.contracts\2.1.6\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Contracts.dll +microsoft.visualstudio.web.codegeneration.contracts\2.1.6\microsoft.visualstudio.web.codegeneration.contracts.2.1.6.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.contracts\2.1.6\microsoft.visualstudio.web.codegeneration.contracts.nuspec +microsoft.visualstudio.web.codegeneration.core\2.1.6\.nupkg.metadata +microsoft.visualstudio.web.codegeneration.core\2.1.6\.signature.p7s +microsoft.visualstudio.web.codegeneration.core\2.1.6\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Core.dll +microsoft.visualstudio.web.codegeneration.core\2.1.6\microsoft.visualstudio.web.codegeneration.core.2.1.6.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.core\2.1.6\microsoft.visualstudio.web.codegeneration.core.nuspec +microsoft.visualstudio.web.codegeneration.design\2.1.6\.nupkg.metadata +microsoft.visualstudio.web.codegeneration.design\2.1.6\.signature.p7s +microsoft.visualstudio.web.codegeneration.design\2.1.6\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.6\lib\netstandard2.0\dotnet-aspnet-codegenerator-design.dll +microsoft.visualstudio.web.codegeneration.design\2.1.6\microsoft.visualstudio.web.codegeneration.design.2.1.6.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.design\2.1.6\microsoft.visualstudio.web.codegeneration.design.nuspec +microsoft.visualstudio.web.codegeneration.design\2.1.6\runtimes\win7-x64\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.6\runtimes\win7-x86\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.6\runtimes\win-arm\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.design\2.1.6\runtimes\win-arm64\lib\net461\dotnet-aspnet-codegenerator-design.exe +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.6\.nupkg.metadata +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.6\.signature.p7s +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.6\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore.dll +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.6\microsoft.visualstudio.web.codegeneration.entityframeworkcore.2.1.6.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.6\microsoft.visualstudio.web.codegeneration.entityframeworkcore.nuspec +microsoft.visualstudio.web.codegeneration.entityframeworkcore\2.1.6\Templates\DbContext\NewLocalDbContext.cshtml +microsoft.visualstudio.web.codegeneration.templating\2.1.6\.nupkg.metadata +microsoft.visualstudio.web.codegeneration.templating\2.1.6\.signature.p7s +microsoft.visualstudio.web.codegeneration.templating\2.1.6\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Templating.dll +microsoft.visualstudio.web.codegeneration.templating\2.1.6\microsoft.visualstudio.web.codegeneration.templating.2.1.6.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.templating\2.1.6\microsoft.visualstudio.web.codegeneration.templating.nuspec +microsoft.visualstudio.web.codegeneration.utils\2.1.6\.nupkg.metadata +microsoft.visualstudio.web.codegeneration.utils\2.1.6\.signature.p7s +microsoft.visualstudio.web.codegeneration.utils\2.1.6\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.Utils.dll +microsoft.visualstudio.web.codegeneration.utils\2.1.6\microsoft.visualstudio.web.codegeneration.utils.2.1.6.nupkg.sha512 +microsoft.visualstudio.web.codegeneration.utils\2.1.6\microsoft.visualstudio.web.codegeneration.utils.nuspec +microsoft.visualstudio.web.codegeneration\2.1.6\.nupkg.metadata +microsoft.visualstudio.web.codegeneration\2.1.6\.signature.p7s +microsoft.visualstudio.web.codegeneration\2.1.6\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGeneration.dll +microsoft.visualstudio.web.codegeneration\2.1.6\microsoft.visualstudio.web.codegeneration.2.1.6.nupkg.sha512 +microsoft.visualstudio.web.codegeneration\2.1.6\microsoft.visualstudio.web.codegeneration.nuspec +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\.nupkg.metadata +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\.signature.p7s +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Generators\ParameterDefinitions\area.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Generators\ParameterDefinitions\controller.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Generators\ParameterDefinitions\identity.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Generators\ParameterDefinitions\razorpage.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Generators\ParameterDefinitions\view.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\lib\netstandard2.0\identitygeneratorfilesconfig.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\lib\netstandard2.0\Microsoft.VisualStudio.Web.CodeGenerators.Mvc.dll +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\microsoft.visualstudio.web.codegenerators.mvc.2.1.6.nupkg.sha512 +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\microsoft.visualstudio.web.codegenerators.mvc.nuspec +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ControllerGenerator\ApiControllerWithActions.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ControllerGenerator\ApiControllerWithContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ControllerGenerator\ApiEmptyController.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ControllerGenerator\ControllerWithActions.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ControllerGenerator\EmptyController.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ControllerGenerator\MvcControllerWithContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\_LoginPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Data\ApplicationDbContext.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Data\ApplicationUser.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\IdentityHostingStartup.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\_Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\_ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\_ViewStart.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.AccessDenied.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.AccessDenied.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ConfirmEmail.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ConfirmEmail.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ExternalLogin.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ExternalLogin.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ForgotPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ForgotPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ForgotPasswordConfirmation.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ForgotPasswordConfirmation.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.Lockout.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.Lockout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.Login.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.Login.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.LoginWith2fa.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.LoginWith2fa.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.LoginWithRecoveryCode.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.LoginWithRecoveryCode.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.Logout.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.Logout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.Register.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.Register.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ResetPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ResetPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ResetPasswordConfirmation.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Account.ResetPasswordConfirmation.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage._Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage._ManageNav.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage._StatusMessage.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.ChangePassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.ChangePassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.DeletePersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.DeletePersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.Disable2fa.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.Disable2fa.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.DownloadPersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.DownloadPersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.EnableAuthenticator.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.EnableAuthenticator.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.ExternalLogins.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.ExternalLogins.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.GenerateRecoveryCodes.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.GenerateRecoveryCodes.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.Index.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.Index.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.ManageNavPages.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.PersonalData.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.PersonalData.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.ResetAuthenticator.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.ResetAuthenticator.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.SetPassword.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.SetPassword.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.ShowRecoveryCodes.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.ShowRecoveryCodes.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.TwoFactorAuthentication.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Account\Manage\Account.Manage.TwoFactorAuthentication.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Error.cs.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\Pages\Error.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\ScaffoldingReadme.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\SupportPages._CookieConsentPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\SupportPages._ViewImports.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\SupportPages._ViewStart.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\css\site.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\css\site.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\favicon.ico +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\images\banner1.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\images\banner2.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\images\banner3.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\js\site.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\js\site.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap.min.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.min.css +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\css\bootstrap-theme.min.css.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.eot +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.svg +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.ttf +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.woff +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\fonts\glyphicons-halflings-regular.woff2 +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\js\bootstrap.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\js\bootstrap.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\dist\js\npm.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\bootstrap\LICENSE +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery\dist\jquery.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery\dist\jquery.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery\dist\jquery.min.map +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery\LICENSE.txt +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery-validation\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery-validation\dist\additional-methods.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery-validation\dist\additional-methods.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery-validation\dist\jquery.validate.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery-validation\dist\jquery.validate.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery-validation\LICENSE.md +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\.bower.json +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.min.js +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Identity\wwwroot\lib\jquery-validation-unobtrusive\LICENSE.txt +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\MvcLayout\_Layout.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\MvcLayout\Error.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\Create.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\CreatePageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\Delete.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\DeletePageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\Details.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\DetailsPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\Edit.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\EditPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\Empty.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\EmptyPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\List.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\RazorPageGenerator\ListPageModel.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Startup\ReadMe.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\Startup\Startup.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ViewGenerator\_ValidationScriptsPartial.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ViewGenerator\Create.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ViewGenerator\Delete.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ViewGenerator\Details.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ViewGenerator\Edit.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ViewGenerator\Empty.cshtml +microsoft.visualstudio.web.codegenerators.mvc\2.1.6\Templates\ViewGenerator\List.cshtml +microsoft.win32.primitives\4.0.1\.nupkg.metadata +microsoft.win32.primitives\4.3.0\.nupkg.metadata +microsoft.win32.registry\4.3.0\.nupkg.metadata +microsoft.win32.registry\4.5.0\.nupkg.metadata +netstandard.library\1.6.0\.nupkg.metadata +netstandard.library\1.6.1\.nupkg.metadata +netstandard.library\2.0.3\.nupkg.metadata +newtonsoft.json.bson\1.0.1\.nupkg.metadata +newtonsoft.json.bson\1.0.1\.signature.p7s +newtonsoft.json\10.0.1\.nupkg.metadata +newtonsoft.json\10.0.1\.signature.p7s +newtonsoft.json\11.0.2\.nupkg.metadata +newtonsoft.json\11.0.2\.signature.p7s +newtonsoft.json\9.0.1\.nupkg.metadata +nuget.frameworks\4.7.0\.nupkg.metadata +remotion.linq\2.2.0\.nupkg.metadata +remotion.linq\2.2.0\.signature.p7s +runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.native.system.data.sqlclient.sni\4.4.0\.nupkg.metadata +runtime.native.system.io.compression\4.1.0\.nupkg.metadata +runtime.native.system.io.compression\4.3.0\.nupkg.metadata +runtime.native.system.net.http\4.0.1\.nupkg.metadata +runtime.native.system.net.http\4.3.0\.nupkg.metadata +runtime.native.system.net.security\4.3.0\.nupkg.metadata +runtime.native.system.security.cryptography.apple\4.3.0\.nupkg.metadata +runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.native.system.security.cryptography\4.0.0\.nupkg.metadata +runtime.native.system\4.0.0\.nupkg.metadata +runtime.native.system\4.3.0\.nupkg.metadata +runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple\4.3.0\.nupkg.metadata +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.win-arm64.runtime.native.system.data.sqlclient.sni\4.4.0\.nupkg.metadata +runtime.win-x64.runtime.native.system.data.sqlclient.sni\4.4.0\.nupkg.metadata +runtime.win-x86.runtime.native.system.data.sqlclient.sni\4.4.0\.nupkg.metadata +sqlitepclraw.bundle_green\1.1.11\.nupkg.metadata +sqlitepclraw.bundle_green\1.1.11\.signature.p7s +sqlitepclraw.core\1.1.11\.nupkg.metadata +sqlitepclraw.core\1.1.11\.signature.p7s +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\.nupkg.metadata +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\.signature.p7s +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\.nupkg.metadata +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\.signature.p7s +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\.nupkg.metadata +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\.signature.p7s +sqlitepclraw.provider.e_sqlite3.netstandard11\1.1.11\.nupkg.metadata +sqlitepclraw.provider.e_sqlite3.netstandard11\1.1.11\.signature.p7s +stackexchange.redis.strongname\1.2.4\.nupkg.metadata +stackexchange.redis.strongname\1.2.4\.signature.p7s +system.appcontext\4.1.0\.nupkg.metadata +system.appcontext\4.3.0\.nupkg.metadata +system.buffers\4.0.0\.nupkg.metadata +system.buffers\4.3.0\.nupkg.metadata +system.buffers\4.5.0\.nupkg.metadata +system.collections.concurrent\4.0.12\.nupkg.metadata +system.collections.concurrent\4.3.0\.nupkg.metadata +system.collections.immutable\1.3.0\.nupkg.metadata +system.collections.immutable\1.3.1\.nupkg.metadata +system.collections.immutable\1.5.0\.nupkg.metadata +system.collections.nongeneric\4.3.0\.nupkg.metadata +system.collections.specialized\4.3.0\.nupkg.metadata +system.collections\4.0.11\.nupkg.metadata +system.collections\4.3.0\.nupkg.metadata +system.componentmodel.annotations\4.5.0\.nupkg.metadata +system.componentmodel.primitives\4.3.0\.nupkg.metadata +system.componentmodel.typeconverter\4.3.0\.nupkg.metadata +system.componentmodel\4.3.0\.nupkg.metadata +system.composition.attributedmodel\1.0.31\.nupkg.metadata +system.composition.convention\1.0.31\.nupkg.metadata +system.composition.hosting\1.0.31\.nupkg.metadata +system.composition.runtime\1.0.31\.nupkg.metadata +system.composition.typedparts\1.0.31\.nupkg.metadata +system.composition\1.0.31\.nupkg.metadata +system.console\4.0.0\.nupkg.metadata +system.console\4.3.0\.nupkg.metadata +system.data.sqlclient\4.5.1\.nupkg.metadata +system.diagnostics.contracts\4.3.0\.nupkg.metadata +system.diagnostics.debug\4.0.11\.nupkg.metadata +system.diagnostics.debug\4.3.0\.nupkg.metadata +system.diagnostics.diagnosticsource\4.0.0\.nupkg.metadata +system.diagnostics.diagnosticsource\4.3.0\.nupkg.metadata +system.diagnostics.diagnosticsource\4.4.0\.nupkg.metadata +system.diagnostics.diagnosticsource\4.4.0\.signature.p7s +system.diagnostics.diagnosticsource\4.5.0\.nupkg.metadata +system.diagnostics.fileversioninfo\4.3.0\.nupkg.metadata +system.diagnostics.process\4.3.0\.nupkg.metadata +system.diagnostics.stacktrace\4.3.0\.nupkg.metadata +system.diagnostics.tools\4.0.1\.nupkg.metadata +system.diagnostics.tools\4.3.0\.nupkg.metadata +system.diagnostics.tracing\4.1.0\.nupkg.metadata +system.diagnostics.tracing\4.3.0\.nupkg.metadata +system.dynamic.runtime\4.0.11\.nupkg.metadata +system.dynamic.runtime\4.3.0\.nupkg.metadata +system.globalization.calendars\4.0.1\.nupkg.metadata +system.globalization.calendars\4.3.0\.nupkg.metadata +system.globalization.extensions\4.0.1\.nupkg.metadata +system.globalization.extensions\4.3.0\.nupkg.metadata +system.globalization\4.0.11\.nupkg.metadata +system.globalization\4.3.0\.nupkg.metadata +system.identitymodel.tokens.jwt\5.2.0\.nupkg.metadata +system.identitymodel.tokens.jwt\5.2.0\.signature.p7s +system.interactive.async\3.1.1\.nupkg.metadata +system.interactive.async\3.1.1\.signature.p7s +system.io.compression.zipfile\4.0.1\.nupkg.metadata +system.io.compression.zipfile\4.3.0\.nupkg.metadata +system.io.compression\4.1.0\.nupkg.metadata +system.io.compression\4.3.0\.nupkg.metadata +system.io.filesystem.primitives\4.0.1\.nupkg.metadata +system.io.filesystem.primitives\4.3.0\.nupkg.metadata +system.io.filesystem\4.0.1\.nupkg.metadata +system.io.filesystem\4.3.0\.nupkg.metadata +system.io.pipelines\4.5.0\.nupkg.metadata +system.io\4.1.0\.nupkg.metadata +system.io\4.3.0\.nupkg.metadata +system.linq.expressions\4.1.0\.nupkg.metadata +system.linq.expressions\4.3.0\.nupkg.metadata +system.linq.parallel\4.3.0\.nupkg.metadata +system.linq.queryable\4.0.1\.nupkg.metadata +system.linq\4.1.0\.nupkg.metadata +system.linq\4.3.0\.nupkg.metadata +system.memory\4.5.1\.nupkg.metadata +system.net.http\4.1.0\.nupkg.metadata +system.net.http\4.1.0\.signature.p7s +system.net.http\4.3.0\.nupkg.metadata +system.net.http\4.3.0\.signature.p7s +system.net.nameresolution\4.3.0\.nupkg.metadata +system.net.primitives\4.0.11\.nupkg.metadata +system.net.primitives\4.3.0\.nupkg.metadata +system.net.security\4.3.0\.nupkg.metadata +system.net.sockets\4.1.0\.nupkg.metadata +system.net.sockets\4.3.0\.nupkg.metadata +system.net.websockets.websocketprotocol\4.5.1\.nupkg.metadata +system.numerics.vectors\4.5.0\.nupkg.metadata +system.objectmodel\4.0.12\.nupkg.metadata +system.objectmodel\4.3.0\.nupkg.metadata +system.private.datacontractserialization\4.1.1\.nupkg.metadata +system.private.datacontractserialization\4.3.0\.nupkg.metadata +system.reflection.emit.ilgeneration\4.0.1\.nupkg.metadata +system.reflection.emit.ilgeneration\4.3.0\.nupkg.metadata +system.reflection.emit.lightweight\4.0.1\.nupkg.metadata +system.reflection.emit.lightweight\4.3.0\.nupkg.metadata +system.reflection.emit\4.0.1\.nupkg.metadata +system.reflection.emit\4.3.0\.nupkg.metadata +system.reflection.extensions\4.0.1\.nupkg.metadata +system.reflection.extensions\4.3.0\.nupkg.metadata +system.reflection.metadata\1.4.1\.nupkg.metadata +system.reflection.metadata\1.4.2\.nupkg.metadata +system.reflection.metadata\1.6.0\.nupkg.metadata +system.reflection.primitives\4.0.1\.nupkg.metadata +system.reflection.primitives\4.3.0\.nupkg.metadata +system.reflection.typeextensions\4.1.0\.nupkg.metadata +system.reflection.typeextensions\4.3.0\.nupkg.metadata +system.reflection\4.1.0\.nupkg.metadata +system.reflection\4.3.0\.nupkg.metadata +system.resources.resourcemanager\4.0.1\.nupkg.metadata +system.resources.resourcemanager\4.3.0\.nupkg.metadata +system.runtime.compilerservices.unsafe\4.5.0\.nupkg.metadata +system.runtime.compilerservices.unsafe\4.5.1\.nupkg.metadata +system.runtime.extensions\4.1.0\.nupkg.metadata +system.runtime.extensions\4.3.0\.nupkg.metadata +system.runtime.handles\4.0.1\.nupkg.metadata +system.runtime.handles\4.3.0\.nupkg.metadata +system.runtime.interopservices.runtimeinformation\4.0.0\.nupkg.metadata +system.runtime.interopservices.runtimeinformation\4.3.0\.nupkg.metadata +system.runtime.interopservices\4.1.0\.nupkg.metadata +system.runtime.interopservices\4.3.0\.nupkg.metadata +system.runtime.numerics\4.0.1\.nupkg.metadata +system.runtime.numerics\4.3.0\.nupkg.metadata +system.runtime.serialization.formatters\4.3.0\.nupkg.metadata +system.runtime.serialization.json\4.0.2\.nupkg.metadata +system.runtime.serialization.primitives\4.1.1\.nupkg.metadata +system.runtime.serialization.primitives\4.3.0\.nupkg.metadata +system.runtime.serialization.xml\4.3.0\.nupkg.metadata +system.runtime\4.1.0\.nupkg.metadata +system.runtime\4.3.0\.nupkg.metadata +system.security.accesscontrol\4.5.0\.nupkg.metadata +system.security.claims\4.3.0\.nupkg.metadata +system.security.cryptography.algorithms\4.2.0\.nupkg.metadata +system.security.cryptography.algorithms\4.3.0\.nupkg.metadata +system.security.cryptography.cng\4.2.0\.nupkg.metadata +system.security.cryptography.cng\4.3.0\.nupkg.metadata +system.security.cryptography.cng\4.5.0\.nupkg.metadata +system.security.cryptography.csp\4.0.0\.nupkg.metadata +system.security.cryptography.csp\4.3.0\.nupkg.metadata +system.security.cryptography.encoding\4.0.0\.nupkg.metadata +system.security.cryptography.encoding\4.3.0\.nupkg.metadata +system.security.cryptography.openssl\4.0.0\.nupkg.metadata +system.security.cryptography.openssl\4.3.0\.nupkg.metadata +system.security.cryptography.pkcs\4.5.0\.nupkg.metadata +system.security.cryptography.primitives\4.0.0\.nupkg.metadata +system.security.cryptography.primitives\4.3.0\.nupkg.metadata +system.security.cryptography.x509certificates\4.1.0\.nupkg.metadata +system.security.cryptography.x509certificates\4.3.0\.nupkg.metadata +system.security.cryptography.xml\4.5.0\.nupkg.metadata +system.security.permissions\4.5.0\.nupkg.metadata +system.security.principal.windows\4.3.0\.nupkg.metadata +system.security.principal.windows\4.5.0\.nupkg.metadata +system.security.principal\4.3.0\.nupkg.metadata +system.spatial\5.8.2\.nupkg.metadata +system.text.encoding.codepages\4.3.0\.nupkg.metadata +system.text.encoding.codepages\4.5.0\.nupkg.metadata +system.text.encoding.extensions\4.0.11\.nupkg.metadata +system.text.encoding.extensions\4.3.0\.nupkg.metadata +system.text.encoding\4.0.11\.nupkg.metadata +system.text.encoding\4.3.0\.nupkg.metadata +system.text.encodings.web\4.3.1\.nupkg.metadata +system.text.encodings.web\4.3.1\.signature.p7s +system.text.encodings.web\4.5.0\.nupkg.metadata +system.text.regularexpressions\4.1.0\.nupkg.metadata +system.text.regularexpressions\4.3.0\.nupkg.metadata +system.threading.channels\4.5.0\.nupkg.metadata +system.threading.tasks.extensions\4.0.0\.nupkg.metadata +system.threading.tasks.extensions\4.3.0\.nupkg.metadata +system.threading.tasks.extensions\4.5.1\.nupkg.metadata +system.threading.tasks.parallel\4.3.0\.nupkg.metadata +system.threading.tasks\4.0.11\.nupkg.metadata +system.threading.tasks\4.3.0\.nupkg.metadata +system.threading.thread\4.3.0\.nupkg.metadata +system.threading.threadpool\4.3.0\.nupkg.metadata +system.threading.timer\4.0.1\.nupkg.metadata +system.threading.timer\4.3.0\.nupkg.metadata +system.threading\4.0.11\.nupkg.metadata +system.threading\4.3.0\.nupkg.metadata +system.valuetuple\4.3.0\.nupkg.metadata +system.valuetuple\4.5.0\.nupkg.metadata +system.xml.readerwriter\4.0.11\.nupkg.metadata +system.xml.readerwriter\4.3.0\.nupkg.metadata +system.xml.xdocument\4.0.11\.nupkg.metadata +system.xml.xdocument\4.3.0\.nupkg.metadata +system.xml.xmldocument\4.0.1\.nupkg.metadata +system.xml.xmldocument\4.3.0\.nupkg.metadata +system.xml.xmlserializer\4.0.11\.nupkg.metadata +system.xml.xmlserializer\4.3.0\.nupkg.metadata +system.xml.xpath.xdocument\4.3.0\.nupkg.metadata +system.xml.xpath\4.3.0\.nupkg.metadata +windowsazure.storage\8.1.4\.nupkg.metadata +windowsazure.storage\8.1.4\.signature.p7s diff --git a/version.props b/version.props index c0217598a3..3e4178aafa 100644 --- a/version.props +++ b/version.props @@ -2,7 +2,7 @@ 2 1 - 6 + 7 servicing Servicing t000 From 34999a804e6ad9f99bb96ef7969dcf8180bd78bb Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 9 Nov 2018 08:48:42 -0800 Subject: [PATCH 0998/1029] Remove submodules for repos that merged to aspnet/Extensions (#3671) Builds of the packages in aspnet/Extensions repo go through ProdCon instead of building as a submodule of this repo. --- .gitmodules | 36 -- build/GenerateCode.targets | 17 - build/artifacts.props | 59 --- build/buildorder.props | 15 +- build/dependencies.props | 68 ++- build/external-dependencies.props | 76 ++++ build/repo.targets | 1 - build/submodules.props | 9 - build/tasks/AnalyzeBuildGraph.cs | 24 +- build/tasks/CodeGen/DirectedGraphXml.cs | 42 -- build/tasks/CodeGen/GenerateSubmoduleGraph.cs | 226 ---------- build/tasks/CodeGen/RepositoryProject.cs | 46 -- build/tasks/RepoTasks.tasks | 1 - modules/Caching | 1 - modules/Common | 1 - modules/Configuration | 1 - modules/DependencyInjection | 1 - modules/EventNotification | 1 - modules/FileSystem | 1 - modules/Logging | 1 - modules/Options | 1 - modules/SubmoduleGraph.dgml | 421 ------------------ modules/Testing | 1 - scripts/UpdateDependencies.ps1 | 8 +- 24 files changed, 165 insertions(+), 893 deletions(-) delete mode 100644 build/GenerateCode.targets delete mode 100644 build/tasks/CodeGen/DirectedGraphXml.cs delete mode 100644 build/tasks/CodeGen/GenerateSubmoduleGraph.cs delete mode 100644 build/tasks/CodeGen/RepositoryProject.cs delete mode 160000 modules/Caching delete mode 160000 modules/Common delete mode 160000 modules/Configuration delete mode 160000 modules/DependencyInjection delete mode 160000 modules/EventNotification delete mode 160000 modules/FileSystem delete mode 160000 modules/Logging delete mode 160000 modules/Options delete mode 100644 modules/SubmoduleGraph.dgml delete mode 160000 modules/Testing diff --git a/.gitmodules b/.gitmodules index e8c4effa7e..76458daf89 100644 --- a/.gitmodules +++ b/.gitmodules @@ -22,26 +22,10 @@ path = modules/BrowserLink url = https://github.com/aspnet/BrowserLink.git branch = release/2.1 -[submodule "modules/Caching"] - path = modules/Caching - url = https://github.com/aspnet/Caching.git - branch = release/2.1 -[submodule "modules/Common"] - path = modules/Common - url = https://github.com/aspnet/Common.git - branch = release/2.1 -[submodule "modules/Configuration"] - path = modules/Configuration - url = https://github.com/aspnet/Configuration.git - branch = release/2.1 [submodule "modules/CORS"] path = modules/CORS url = https://github.com/aspnet/CORS.git branch = release/2.1 -[submodule "modules/DependencyInjection"] - path = modules/DependencyInjection - url = https://github.com/aspnet/DependencyInjection.git - branch = release/2.1 [submodule "modules/Diagnostics"] path = modules/Diagnostics url = https://github.com/aspnet/Diagnostics.git @@ -54,14 +38,6 @@ path = modules/EntityFrameworkCore url = https://github.com/aspnet/EntityFrameworkCore.git branch = release/2.1 -[submodule "modules/EventNotification"] - path = modules/EventNotification - url = https://github.com/aspnet/EventNotification.git - branch = release/2.1 -[submodule "modules/FileSystem"] - path = modules/FileSystem - url = https://github.com/aspnet/FileSystem.git - branch = release/2.1 [submodule "modules/Hosting"] path = modules/Hosting url = https://github.com/aspnet/Hosting.git @@ -102,10 +78,6 @@ path = modules/Localization url = https://github.com/aspnet/Localization.git branch = release/2.1 -[submodule "modules/Logging"] - path = modules/Logging - url = https://github.com/aspnet/Logging.git - branch = release/2.1 [submodule "modules/MetaPackages"] path = modules/MetaPackages url = https://github.com/aspnet/MetaPackages.git @@ -122,10 +94,6 @@ path = modules/MvcPrecompilation url = https://github.com/aspnet/MvcPrecompilation.git branch = release/2.1 -[submodule "modules/Options"] - path = modules/Options - url = https://github.com/aspnet/Options.git - branch = release/2.1 [submodule "modules/Razor"] path = modules/Razor url = https://github.com/aspnet/Razor.git @@ -166,7 +134,3 @@ path = modules/Templating url = https://github.com/aspnet/Templating.git branch = release/2.1 -[submodule "modules/Testing"] - path = modules/Testing - url = https://github.com/aspnet/Testing.git - branch = release/2.1 diff --git a/build/GenerateCode.targets b/build/GenerateCode.targets deleted file mode 100644 index 069e358ae6..0000000000 --- a/build/GenerateCode.targets +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - diff --git a/build/artifacts.props b/build/artifacts.props index 39b35505e6..a4ec6e8774 100644 --- a/build/artifacts.props +++ b/build/artifacts.props @@ -51,9 +51,7 @@ - - @@ -156,7 +154,6 @@ - @@ -183,40 +180,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -225,32 +192,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/buildorder.props b/build/buildorder.props index fdc4e89b0f..1cb0f6cec8 100644 --- a/build/buildorder.props +++ b/build/buildorder.props @@ -7,18 +7,9 @@ - - - - - - - - - - - - + + + diff --git a/build/dependencies.props b/build/dependencies.props index 7de10ef40d..d906e02d29 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -2,9 +2,9 @@ - 2.1.6-servicing-27017-02 - 2.1.6-servicing-27017-02 - + 2.1.6 + 2.1.6 + @@ -19,6 +19,68 @@ + + 2.1.6 + 2.1.6 + 2.1.0 + 2.1.1 + 2.1.2 + 2.1.2 + 2.1.2 + 2.1.2 + 2.1.6 + 2.1.6 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.6 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.6 + 2.1.1 + 0.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.6 + 2.1.6 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.6 + 2.1.6 + 2.1.6 + 2.1.6 + 2.1.6 + 2.1.6 + 2.1.6 + 2.1.6 + 2.1.6 + 2.1.6 + + 0.9.9 0.10.13 4.2.1 diff --git a/build/external-dependencies.props b/build/external-dependencies.props index 8f8858d98c..d9edeee7cf 100644 --- a/build/external-dependencies.props +++ b/build/external-dependencies.props @@ -10,9 +10,85 @@ false + + + + + + + false + + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/repo.targets b/build/repo.targets index 076c50232e..cde696935c 100644 --- a/build/repo.targets +++ b/build/repo.targets @@ -5,7 +5,6 @@ - diff --git a/build/submodules.props b/build/submodules.props index 4064fe8af9..8b30d5efcb 100644 --- a/build/submodules.props +++ b/build/submodules.props @@ -53,17 +53,11 @@ - - - - - - @@ -74,10 +68,8 @@ - - @@ -85,7 +77,6 @@ - diff --git a/build/tasks/AnalyzeBuildGraph.cs b/build/tasks/AnalyzeBuildGraph.cs index a7193d7735..c70d1d8a56 100644 --- a/build/tasks/AnalyzeBuildGraph.cs +++ b/build/tasks/AnalyzeBuildGraph.cs @@ -111,16 +111,26 @@ namespace RepoTasks var dependencyMap = new Dictionary>(StringComparer.OrdinalIgnoreCase); foreach (var dep in Dependencies) { - if (!dependencyMap.TryGetValue(dep.ItemSpec, out var versions)) + if (dep.GetMetadata("IsExtensionsPackage") == "true") { - dependencyMap[dep.ItemSpec] = versions = new List(); + buildPackageMap.Add(dep.ItemSpec, new ArtifactInfo.Package + { + PackageInfo = new PackageInfo(dep.ItemSpec, new NuGetVersion(dep.GetMetadata("Version")), null, null), + }); } - - versions.Add(new ExternalDependency + else { - PackageId = dep.ItemSpec, - Version = dep.GetMetadata("Version"), - }); + if (!dependencyMap.TryGetValue(dep.ItemSpec, out var versions)) + { + dependencyMap[dep.ItemSpec] = versions = new List(); + } + + versions.Add(new ExternalDependency + { + PackageId = dep.ItemSpec, + Version = dep.GetMetadata("Version"), + }); + } } var inconsistentVersions = new List(); diff --git a/build/tasks/CodeGen/DirectedGraphXml.cs b/build/tasks/CodeGen/DirectedGraphXml.cs deleted file mode 100644 index e90d66ca6b..0000000000 --- a/build/tasks/CodeGen/DirectedGraphXml.cs +++ /dev/null @@ -1,42 +0,0 @@ - -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Xml.Linq; - -namespace RepoTasks.CodeGen -{ - class DirectedGraphXml - { - private readonly XNamespace _ns = "http://schemas.microsoft.com/vs/2009/dgml"; - private readonly XDocument _doc; - private readonly XElement _nodes; - private readonly XElement _links; - - public DirectedGraphXml() - { - _doc = new XDocument(new XElement(_ns + "DirectedGraph")); - _nodes = new XElement(_ns + "Nodes"); - _links = new XElement(_ns + "Links"); - _doc.Root.Add(_nodes); - _doc.Root.Add(_links); - } - - public void AddNode(string id) - { - _nodes.Add(new XElement(_ns + "Node", new XAttribute("Id", id), new XAttribute("Label", id))); - } - - public void AddLink(string source, string target) - { - _links.Add(new XElement(_ns + "Link", - new XAttribute("Source", source), - new XAttribute("Target", target))); - } - - public void Save(string path) - { - _doc.Save(path); - } - } -} diff --git a/build/tasks/CodeGen/GenerateSubmoduleGraph.cs b/build/tasks/CodeGen/GenerateSubmoduleGraph.cs deleted file mode 100644 index 7940b5cba2..0000000000 --- a/build/tasks/CodeGen/GenerateSubmoduleGraph.cs +++ /dev/null @@ -1,226 +0,0 @@ - -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.IO; -using System.Text; -using System.Threading; -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; -using NuGet.Frameworks; -using NuGet.Versioning; -using RepoTools.BuildGraph; -using RepoTasks.ProjectModel; -using RepoTasks.Utilities; -using RepoTasks.CodeGen; -using NuGet.Packaging.Core; - -namespace RepoTasks -{ - public class GenerateSubmoduleGraph : Task, ICancelableTask - { - private readonly CancellationTokenSource _cts = new CancellationTokenSource(); - - /// - /// Repositories that we are building new versions of. - /// - [Required] - public ITaskItem[] Solutions { get; set; } - - [Required] - public ITaskItem[] Artifacts { get; set; } - - [Required] - public ITaskItem[] Repositories { get; set; } - - [Required] - public string RepositoryRoot { get; set; } - - [Required] - public string Properties { get; set; } - - public void Cancel() - { - _cts.Cancel(); - } - - public override bool Execute() - { - var packageArtifacts = Artifacts.Select(ArtifactInfo.Parse) - .OfType() - .Where(p => !p.IsSymbolsArtifact) - .ToDictionary(p => p.PackageInfo.Id, p => p, StringComparer.OrdinalIgnoreCase); - - var factory = new SolutionInfoFactory(Log, BuildEngine5); - var props = MSBuildListSplitter.GetNamedProperties(Properties); - - Log.LogMessage(MessageImportance.High, $"Beginning cross-repo analysis on {Solutions.Length} solutions. Hang tight..."); - - if (!props.TryGetValue("Configuration", out var defaultConfig)) - { - defaultConfig = "Debug"; - } - - var solutions = factory.Create(Solutions, props, defaultConfig, _cts.Token).OrderBy(f => f.Directory).ToList(); - Log.LogMessage($"Found {solutions.Count} and {solutions.Sum(p => p.Projects.Count)} projects"); - - if (_cts.IsCancellationRequested) - { - return false; - } - - return GenerateGraph(packageArtifacts, solutions); - } - - private bool GenerateGraph(IDictionary packageArtifacts, IReadOnlyList solutions) - { - var repoGraph = new AdjacencyMatrix(solutions.Count); - var packageToProjectMap = new Dictionary(); - - for (var i = 0; i < solutions.Count; i++) - { - var sln = repoGraph[i] = solutions[i]; - - foreach (var proj in sln.Projects) - { - if (!proj.IsPackable || proj.FullPath.Contains("samples")) - { - continue; - } - - var id = new PackageIdentity(proj.PackageId, new NuGetVersion(proj.PackageVersion)); - - if (packageToProjectMap.TryGetValue(id, out var otherProj)) - { - Log.LogError($"Both {proj.FullPath} and {otherProj.FullPath} produce {id}"); - continue; - } - - packageToProjectMap.Add(id, proj); - } - - var sharedSrc = Path.Combine(sln.Directory, "shared"); - if (Directory.Exists(sharedSrc)) - { - foreach (var dir in Directory.GetDirectories(sharedSrc, "*.Sources")) - { - var id = Path.GetFileName(dir); - var artifactInfo = packageArtifacts[id]; - var sharedSrcProj = new ProjectInfo(dir, - Array.Empty(), - Array.Empty(), - true, - artifactInfo.PackageInfo.Id, - artifactInfo.PackageInfo.Version.ToNormalizedString()); - sharedSrcProj.SolutionInfo = sln; - var identity = new PackageIdentity(artifactInfo.PackageInfo.Id, artifactInfo.PackageInfo.Version); - packageToProjectMap.Add(identity, sharedSrcProj); - } - } - } - - if (Log.HasLoggedErrors) - { - return false; - } - - for (var i = 0; i < solutions.Count; i++) - { - var sln = repoGraph[i]; - - var deps = from proj in sln.Projects - from tfm in proj.Frameworks - from dep in tfm.Dependencies.Values - select dep; - - foreach (var dep in deps) - { - if (packageToProjectMap.TryGetValue(new PackageIdentity(dep.Id, new NuGetVersion(dep.Version)), out var target)) - { - var j = repoGraph.FindIndex(target.SolutionInfo); - repoGraph.SetLink(i, j); - } - } - - var toolDeps = from proj in sln.Projects - from tool in proj.Tools - select tool; - - foreach (var toolDep in toolDeps) - { - if (packageToProjectMap.TryGetValue(new PackageIdentity(toolDep.Id, new NuGetVersion(toolDep.Version)), out var target)) - { - var j = repoGraph.FindIndex(target.SolutionInfo); - repoGraph.SetLink(i, j); - } - } - } - - CreateDgml(repoGraph); - return !Log.HasLoggedErrors; - } - - - private void CreateDgml(AdjacencyMatrix repoGraph) - { - var dgml = new DirectedGraphXml(); - - for (var i = 0; i < repoGraph.Count; i++) - { - var node = repoGraph[i]; - var nodeName = Path.GetFileName(node.Directory); - dgml.AddNode(nodeName); - - for (var j = 0; j < repoGraph.Count; j++) - { - if (j == i) continue; - if (repoGraph.HasLink(i, j)) - { - var target = repoGraph[j]; - var targetName = Path.GetFileName(target.Directory); - dgml.AddLink(nodeName, targetName); - } - } - } - - dgml.Save(Path.Combine(RepositoryRoot, "modules", "SubmoduleGraph.dgml")); - } - - private class AdjacencyMatrix - { - private readonly bool[,] _matrix; - private readonly SolutionInfo[] _items; - - public AdjacencyMatrix(int size) - { - _matrix = new bool[size, size]; - _items = new SolutionInfo[size]; - Count = size; - } - - public SolutionInfo this[int idx] - { - get => _items[idx]; - set => _items[idx] = value; - } - - public int FindIndex(SolutionInfo item) - { - return Array.FindIndex(_items, t => t.Equals(item)); - } - - public int Count { get; } - - public bool HasLink(int source, int target) => _matrix[source, target]; - - public void SetLink(int source, int target) - { - _matrix[source, target] = true; - } - } - } -} diff --git a/build/tasks/CodeGen/RepositoryProject.cs b/build/tasks/CodeGen/RepositoryProject.cs deleted file mode 100644 index 1cb3b76391..0000000000 --- a/build/tasks/CodeGen/RepositoryProject.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Text; -using Microsoft.Build.Construction; -using Microsoft.Build.Evaluation; - -namespace RepoTasks.CodeGen -{ - class RepositoryProject - { - private readonly ProjectRootElement _doc; - - public RepositoryProject(string repositoryRoot) - { - _doc = ProjectRootElement.Create(NewProjectFileOptions.None); - var import = _doc.CreateImportElement(@"$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"); - var propGroup = _doc.AddPropertyGroup(); - if (repositoryRoot[repositoryRoot.Length - 1] != '\\') - { - repositoryRoot += '\\'; - } - propGroup.AddProperty("RepositoryRoot", repositoryRoot); - _doc.AddItemGroup(); - _doc.PrependChild(import); - _doc.AddImport(@"$(MSBuildToolsPath)\Microsoft.Common.targets"); - } - - public void AddProjectReference(string path) - { - _doc.AddItem("ProjectReference", path); - } - - public void AddProperty(string name, string value) - { - _doc.AddProperty(name, value); - } - - public void Save(string filePath) - { - _doc.Save(filePath, Encoding.UTF8); - } - } -} diff --git a/build/tasks/RepoTasks.tasks b/build/tasks/RepoTasks.tasks index 1339fcba27..2c2f8d48af 100644 --- a/build/tasks/RepoTasks.tasks +++ b/build/tasks/RepoTasks.tasks @@ -10,7 +10,6 @@ - diff --git a/modules/Caching b/modules/Caching deleted file mode 160000 index ced279b071..0000000000 --- a/modules/Caching +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ced279b071920f055a309cd81acc333780ef2bf4 diff --git a/modules/Common b/modules/Common deleted file mode 160000 index 975fcf3026..0000000000 --- a/modules/Common +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 975fcf302632a83059086cd8faabb92379f09d02 diff --git a/modules/Configuration b/modules/Configuration deleted file mode 160000 index ef29dc86b9..0000000000 --- a/modules/Configuration +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ef29dc86b970893147fd2a27d527f5a907af9fdd diff --git a/modules/DependencyInjection b/modules/DependencyInjection deleted file mode 160000 index 7a283947c2..0000000000 --- a/modules/DependencyInjection +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7a283947c231b6585c8ac95e653950b660f3da96 diff --git a/modules/EventNotification b/modules/EventNotification deleted file mode 160000 index 69d9ba1300..0000000000 --- a/modules/EventNotification +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 69d9ba130050107409fc5c3d9d834ca55fc7a95d diff --git a/modules/FileSystem b/modules/FileSystem deleted file mode 160000 index baebb8b0c6..0000000000 --- a/modules/FileSystem +++ /dev/null @@ -1 +0,0 @@ -Subproject commit baebb8b0c672ab37bac72d7196da1b919d362cc5 diff --git a/modules/Logging b/modules/Logging deleted file mode 160000 index 8270c54522..0000000000 --- a/modules/Logging +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8270c545224e8734d7297e54edef5c584ee82f01 diff --git a/modules/Options b/modules/Options deleted file mode 160000 index 2ea21ace21..0000000000 --- a/modules/Options +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2ea21ace21105df2839766a5f13e8e2636b7fc41 diff --git a/modules/SubmoduleGraph.dgml b/modules/SubmoduleGraph.dgml deleted file mode 100644 index cdcd0a92cd..0000000000 --- a/modules/SubmoduleGraph.dgml +++ /dev/null @@ -1,421 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/modules/Testing b/modules/Testing deleted file mode 160000 index 8639233365..0000000000 --- a/modules/Testing +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8639233365b85997c7e0b97b50f23aaddd36f671 diff --git a/scripts/UpdateDependencies.ps1 b/scripts/UpdateDependencies.ps1 index f8bfdac4fb..4ecb207047 100755 --- a/scripts/UpdateDependencies.ps1 +++ b/scripts/UpdateDependencies.ps1 @@ -54,10 +54,8 @@ foreach ($package in $remoteDeps.SelectNodes('//Package')) { } } - -$currentBranch = Invoke-Block { & git rev-parse --abbrev-ref HEAD } - if (-not $NoCommit) { + $currentBranch = Invoke-Block { & git rev-parse --abbrev-ref HEAD } $destinationBranch = "dotnetbot/UpdateDeps" Invoke-Block { & git checkout -tb $destinationBranch "origin/$GithubUpstreamBranch" } } @@ -74,5 +72,7 @@ try { } } finally { - Invoke-Block { & git checkout $currentBranch } + if (-not $NoCommit) { + Invoke-Block { & git checkout $currentBranch } + } } From a3baf40c7466a0d83dcb57f9f7a8934bdd4b4769 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 9 Nov 2018 09:12:52 -0800 Subject: [PATCH 0999/1029] Set dependency version on Microsoft.Extensions.DiagnosticAdapter to 2.1.0 and prune unused logging analyzers dependency There was never a 2.1.1 --- build/dependencies.props | 3 +-- build/external-dependencies.props | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index d906e02d29..dda2ffa595 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -46,7 +46,7 @@ 2.1.1 2.1.1 2.1.1 - 2.1.1 + 2.1.0 2.1.1 2.1.1 2.1.1 @@ -54,7 +54,6 @@ 2.1.1 2.1.6 2.1.1 - 0.1.1 2.1.1 2.1.1 2.1.1 diff --git a/build/external-dependencies.props b/build/external-dependencies.props index d9edeee7cf..ce501765b3 100644 --- a/build/external-dependencies.props +++ b/build/external-dependencies.props @@ -59,7 +59,6 @@ - From 8356baf7a612bd21cc92f8fc7098e292274de102 Mon Sep 17 00:00:00 2001 From: Justin Kotalik Date: Fri, 9 Nov 2018 11:10:33 -0800 Subject: [PATCH 1000/1029] Port ANCM installer changes to 2.1 (#3874) --- Directory.Build.props | 2 + Directory.Build.targets | 1 + THIRD-PARTY-NOTICES | 49 + eng/targets/Cpp.Common.props | 11 + eng/targets/Cpp.Common.targets | 6 + .../ANCMIISExpressV1/AncmIISExpressV1.wixproj | 72 + .../ANCMIISExpressV1/ancm_iis_express.wxs | 674 +++ .../ANCMPackageResolver.csproj | 25 + .../ANCMV1/AncmV1.wixproj | 74 + .../ANCMV1/aspnetcoremodule.wxs | 276 ++ .../CustomAction/Directory.Build.props | 15 + .../CustomAction/aspnetcoreCA.cpp | 184 + .../CustomAction/aspnetcoreCA.def | 23 + .../CustomAction/aspnetcoreCA.rc | 10 + .../CustomAction/aspnetcoreCA.vcxproj | 98 + .../CustomAction/avoid_restart.cpp | 244 + .../Directory.Build.props | 43 + .../IIS-Setup/IIS-Common/Common.sln | 41 + .../IIS-Setup/IIS-Common/Include/acache.h | 116 + .../IIS-Setup/IIS-Common/Include/ahutil.h | 264 + .../IIS-Setup/IIS-Common/Include/base64.hxx | 42 + .../IIS-Setup/IIS-Common/Include/buffer.h | 271 ++ .../IIS-Setup/IIS-Common/Include/datetime.h | 14 + .../IIS-Setup/IIS-Common/Include/dbgutil.h | 102 + .../IIS-Setup/IIS-Common/Include/debugutil.h | 124 + .../IIS-Setup/IIS-Common/Include/hashfn.h | 325 ++ .../IIS-Setup/IIS-Common/Include/hashtable.h | 666 +++ .../IIS-Setup/IIS-Common/Include/http_xp.h | 2797 +++++++++++ .../IIS-Common/Include/httpserv_xp.h | 3404 +++++++++++++ .../IIS-Common/Include/hybrid_array.h | 243 + .../IIS-Setup/IIS-Common/Include/listentry.h | 163 + .../IIS-Setup/IIS-Common/Include/macros.h | 63 + .../IIS-Setup/IIS-Common/Include/multisz.hxx | 225 + .../IIS-Setup/IIS-Common/Include/multisza.hxx | 225 + .../IIS-Setup/IIS-Common/Include/normalize.h | 40 + .../IIS-Setup/IIS-Common/Include/ntassert.h | 32 + .../IIS-Setup/IIS-Common/Include/percpu.h | 305 ++ .../IIS-Setup/IIS-Common/Include/prime.h | 85 + .../IIS-Setup/IIS-Common/Include/reftrace.h | 88 + .../IIS-Setup/IIS-Common/Include/rwlock.h | 193 + .../IIS-Setup/IIS-Common/Include/statichash.h | 730 +++ .../IIS-Setup/IIS-Common/Include/stdtypes.h | 24 + .../IIS-Setup/IIS-Common/Include/stringa.h | 515 ++ .../IIS-Setup/IIS-Common/Include/stringu.h | 433 ++ .../IIS-Setup/IIS-Common/Include/sttimer.h | 243 + .../IIS-Setup/IIS-Common/Include/tracelog.h | 105 + .../IIS-Setup/IIS-Common/Include/treehash.h | 850 ++++ .../IIS-Setup/IIS-Common/LICENSE | 21 + .../Managed/MySQL/MySqlConnector.cs | 28 + .../Managed/NativeMethods/AdvApi32.cs | 386 ++ .../Managed/NativeMethods/Common.cs | 111 + .../Managed/NativeMethods/Fusion.cs | 179 + .../Managed/NativeMethods/Kernel32.cs | 99 + .../IIS-Common/Managed/NativeMethods/Mlang.cs | 768 +++ .../Managed/NativeMethods/User32.cs | 88 + .../Managed/NativeMethods/UxTheme.cs | 46 + .../Managed/PseudoLoc/PseudoLoc.targets | 8 + .../Managed/PseudoLoc/PseudoLocalizer.cs | 456 ++ .../v7Sp1/Microsoft.Web.administration.dll | Bin 0 -> 126976 bytes .../v7Sp1/Microsoft.Web.management.dll | Bin 0 -> 999424 bytes .../Managed/Util/AuthenticationModule.cs | 111 + .../Managed/Util/ExceptionHelper.cs | 122 + .../Managed/Util/GACManagedAccess.cs | 192 + .../IIS-Common/Managed/Util/WebUtility.cs | 65 + .../IIS-Setup/IIS-Common/README.md | 18 + .../IIS-Common/UnitTests/common_tests.rc | 7 + .../IIS-Common/UnitTests/dbgutil_tests.cpp | 72 + .../IIS-Common/UnitTests/hash_tests.cpp | 52 + .../UnitTests/hybrid_array_tests.cpp | 95 + .../IIS-Setup/IIS-Common/UnitTests/my_hash.h | 63 + .../IIS-Common/UnitTests/precomp.hxx | 7 + .../IIS-Common/UnitTests/string_tests.cpp | 680 +++ .../IIS-Common/lib/CommonLib.vcxproj | 79 + .../IIS-Setup/IIS-Common/lib/acache.cxx | 443 ++ .../IIS-Setup/IIS-Common/lib/ahutil.cpp | 1734 +++++++ .../IIS-Setup/IIS-Common/lib/base64.cxx | 482 ++ .../IIS-Setup/IIS-Common/lib/datetime.cxx | 247 + .../IIS-Setup/IIS-Common/lib/multisz.cxx | 480 ++ .../IIS-Setup/IIS-Common/lib/multisza.cxx | 414 ++ .../IIS-Setup/IIS-Common/lib/normalize.cxx | 890 ++++ .../IIS-Setup/IIS-Common/lib/packages.config | 4 + .../IIS-Setup/IIS-Common/lib/precomp.h | 18 + .../IIS-Setup/IIS-Common/lib/stringa.cpp | 1767 +++++++ .../IIS-Setup/IIS-Common/lib/stringu.cpp | 1289 +++++ .../IIS-Setup/IIS-Common/lib/ulparse.cxx | 1416 ++++++ .../IIS-Setup/IIS-Common/lib/util.cxx | 74 + .../IIS-Setup/IIS-Common/open-inc/stbuff.h | 1013 ++++ .../IIS-Setup/IIS-Common/open-inc/stlist.h | 87 + .../IIS-Setup/IIS-Common/open-inc/stlock.h | 149 + .../IIS-Setup/IIS-Common/open-inc/sttable.h | 599 +++ .../IIS-Setup/IIS-Common/open-inc/sttimer.h | 232 + .../IIS-Common/reftrace/include/dbgutil2.h | 49 + .../IIS-Common/reftrace/include/irtldbg.h | 154 + .../IIS-Common/reftrace/include/irtlmisc.h | 131 + .../IIS-Common/reftrace/include/memorylog.hxx | 67 + .../IIS-Common/reftrace/include/precomp.hxx | 9 + .../IIS-Common/reftrace/include/pudebug.h | 748 +++ .../IIS-Common/reftrace/reftrace.vcxproj | 78 + .../reftrace/reftrace.vcxproj.filters | 54 + .../IIS-Common/reftrace/src/irtldbg.cpp | 150 + .../IIS-Common/reftrace/src/isplat.cxx | 63 + .../IIS-Common/reftrace/src/memorylog.cxx | 123 + .../IIS-Common/reftrace/src/pudebug.cxx | 1164 +++++ .../IIS-Common/reftrace/src/reftrace.c | 232 + .../IIS-Common/reftrace/src/tracelog.c | 239 + .../IIS-Common/reftrace/src/win32obj.cxx | 348 ++ .../IIS-Setup/IIS-Common/version/bldver.h | 64 + .../IIS-Setup/IIS-Common/version/bldver.rc | 73 + .../IIS-Setup/IIS-Setup.sln | 41 + .../AspNetCoreModule-Setup/IIS-Setup/LICENSE | 21 + .../IIS-Setup/README.md | 18 + .../IIS-Setup/appsearch/appsearch.wxi | 98 + .../IIS-Setup/iisca/lib/ConfigShared.cpp | 59 + .../IIS-Setup/iisca/lib/ConfigShared.h | 8 + .../IIS-Setup/iisca/lib/CustomAction.def | 15 + .../IIS-Setup/iisca/lib/cgi_restrictions.cpp | 271 ++ .../IIS-Setup/iisca/lib/cgi_restrictions.h | 30 + .../IIS-Setup/iisca/lib/config_custom.cpp | 72 + .../IIS-Setup/iisca/lib/config_custom.h | 16 + .../IIS-Setup/iisca/lib/consoleprops.cpp | 594 +++ .../IIS-Setup/iisca/lib/consoleprops.h | 16 + .../IIS-Setup/iisca/lib/defaults.cpp | 716 +++ .../IIS-Setup/iisca/lib/defaults.h | 52 + .../IIS-Setup/iisca/lib/elevatedsc.cpp | 346 ++ .../IIS-Setup/iisca/lib/elevatedsc.h | 16 + .../IIS-Setup/iisca/lib/handlers.cpp | 472 ++ .../IIS-Setup/iisca/lib/handlers.h | 54 + .../IIS-Setup/iisca/lib/hotfix.cpp | 766 +++ .../IIS-Setup/iisca/lib/httpapi.cpp | 518 ++ .../IIS-Setup/iisca/lib/httpapi.h | 55 + .../IIS-Setup/iisca/lib/iisca.cpp | 4302 +++++++++++++++++ .../IIS-Setup/iisca/lib/iisca.h | 255 + .../IIS-Setup/iisca/lib/iisca.vcxproj | 131 + .../IIS-Setup/iisca/lib/iiscaexp.cpp | 791 +++ .../IIS-Setup/iisca/lib/iiscaexp.h | 39 + .../IIS-Setup/iisca/lib/modules.cpp | 655 +++ .../IIS-Setup/iisca/lib/mof.cpp | 82 + .../IIS-Setup/iisca/lib/msiutil.cpp | 581 +++ .../IIS-Setup/iisca/lib/msiutil.h | 192 + .../IIS-Setup/iisca/lib/packages.config | 4 + .../IIS-Setup/iisca/lib/precomp.h | 51 + .../IIS-Setup/iisca/lib/schema.cpp | 741 +++ .../IIS-Setup/iisca/lib/secutils.cpp | 1125 +++++ .../IIS-Setup/iisca/lib/secutils.h | 98 + .../IIS-Setup/iisca/lib/setup_log.cpp | 423 ++ .../IIS-Setup/iisca/lib/setup_log.h | 53 + .../IIS-Setup/iisca/lib/tracing.cpp | 343 ++ .../IIS-Setup/iisca/lib/tracing.h | 36 + .../IIS-Setup/iisca/lib/uimodule.cpp | 637 +++ .../IIS-Setup/iisca/lib/wuerror.h | 2456 ++++++++++ .../IIS-Setup/iisca/wix/iisca.wxs | 209 + .../IIS-Setup/iisca/wix/setupstrings.wxl | 255 + .../IIS-Setup/iisca/wix3/ElevatedShortcut.wxi | 25 + .../iisca/wix3/FixPatchingBehavior.wxi | 36 + .../IIS-Setup/iisca/wix3/HttpListener.wxi | 44 + .../iisca/wix3/ShortcutConsoleProperties.wxi | 41 + .../IIS-Setup/iisca/wix3/WindowsHotfix.wxi | 41 + .../IIS-Setup/iisca/wix3/iisca.wxs | 99 + .../IIS-Setup/include.wxi | 32 + .../IIS-Setup/loc/CHS/misc/setupstrings.wxl | 351 ++ .../IIS-Setup/loc/CHT/misc/setupstrings.wxl | 351 ++ .../IIS-Setup/loc/CSY/misc/setupstrings.wxl | 351 ++ .../IIS-Setup/loc/DEU/misc/setupstrings.wxl | 351 ++ .../IIS-Setup/loc/ESN/misc/setupstrings.wxl | 351 ++ .../IIS-Setup/loc/FRA/misc/setupstrings.wxl | 352 ++ .../IIS-Setup/loc/ITA/misc/setupstrings.wxl | 351 ++ .../IIS-Setup/loc/JPN/misc/setupstrings.wxl | 351 ++ .../IIS-Setup/loc/KOR/misc/setupstrings.wxl | 351 ++ .../IIS-Setup/loc/PLK/misc/setupstrings.wxl | 351 ++ .../IIS-Setup/loc/PTB/misc/setupstrings.wxl | 351 ++ .../IIS-Setup/loc/RUS/misc/setupstrings.wxl | 351 ++ .../IIS-Setup/loc/TRK/misc/setupstrings.wxl | 351 ++ .../IIS-Setup/wcautil/dutil.h | 181 + .../IIS-Setup/wcautil/memutil.h | 42 + .../IIS-Setup/wcautil/precomp.h | 15 + .../IIS-Setup/wcautil/qtexec.cpp | 276 ++ .../IIS-Setup/wcautil/strutil.h | 165 + .../IIS-Setup/wcautil/wcalog.cpp | 150 + .../IIS-Setup/wcautil/wcascript.cpp | 447 ++ .../IIS-Setup/wcautil/wcautil.cpp | 201 + .../IIS-Setup/wcautil/wcautil.h | 344 ++ .../IIS-Setup/wcautil/wcawrap.cpp | 1419 ++++++ .../bitmaps/AspNetCoreModule.ico | Bin 0 -> 894 bytes .../bitmaps/bannrbmp.bmp | Bin 0 -> 5950 bytes .../AspNetCoreModule-Setup/bitmaps/dlgbmp.bmp | Bin 0 -> 20396 bytes .../build/copy-outputs.targets | 18 + .../build/exports.props | 13 + .../build/settings.props | 7 + .../build/settings/common.props | 53 + .../build/settings/debug.props | 29 + .../build/settings/release.props | 51 + .../build/submodule.props | 11 + .../build/versions.props | 38 + .../license/license.rtf | 97 + .../AspNetCoreModule-Setup/setupstrings.wxl | 52 + .../Windows/WindowsHostingBundle/ANCM.wxs | 4 +- src/Installers/Windows/WindowsInstallers.proj | 14 + src/Installers/Windows/Wix.props | 1 - src/Installers/Windows/Wix.targets | 3 +- .../Windows/clone_and_build_ancm.ps1 | 105 - 200 files changed, 59594 insertions(+), 109 deletions(-) create mode 100644 eng/targets/Cpp.Common.props create mode 100644 eng/targets/Cpp.Common.targets create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV1/AncmIISExpressV1.wixproj create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV1/ancm_iis_express.wxs create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/ANCMPackageResolver/ANCMPackageResolver.csproj create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/ANCMV1/AncmV1.wixproj create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/ANCMV1/aspnetcoremodule.wxs create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/Directory.Build.props create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.def create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.rc create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.vcxproj create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/avoid_restart.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/Directory.Build.props create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Common.sln create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/acache.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/ahutil.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/base64.hxx create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/buffer.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/datetime.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/dbgutil.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/debugutil.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hashfn.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hashtable.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/http_xp.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/httpserv_xp.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hybrid_array.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/listentry.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/macros.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/multisz.hxx create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/multisza.hxx create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/normalize.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/ntassert.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/percpu.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/prime.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/reftrace.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/rwlock.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/statichash.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stdtypes.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stringa.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stringu.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/sttimer.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/tracelog.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/treehash.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/LICENSE create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/MySQL/MySqlConnector.cs create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/AdvApi32.cs create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Common.cs create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Fusion.cs create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Kernel32.cs create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Mlang.cs create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/User32.cs create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/UxTheme.cs create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/PseudoLoc/PseudoLoc.targets create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/PseudoLoc/PseudoLocalizer.cs create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/References/v7Sp1/Microsoft.Web.administration.dll create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/References/v7Sp1/Microsoft.Web.management.dll create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/AuthenticationModule.cs create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/ExceptionHelper.cs create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/GACManagedAccess.cs create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/WebUtility.cs create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/README.md create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/common_tests.rc create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/dbgutil_tests.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/hash_tests.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/hybrid_array_tests.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/my_hash.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/precomp.hxx create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/string_tests.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/CommonLib.vcxproj create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/acache.cxx create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/ahutil.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/base64.cxx create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/datetime.cxx create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/multisz.cxx create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/multisza.cxx create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/normalize.cxx create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/packages.config create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/precomp.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/stringa.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/stringu.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/ulparse.cxx create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/util.cxx create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stbuff.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stlist.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stlock.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/sttable.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/sttimer.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/dbgutil2.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/irtldbg.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/irtlmisc.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/memorylog.hxx create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/precomp.hxx create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/pudebug.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj.filters create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/irtldbg.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/isplat.cxx create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/memorylog.cxx create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/pudebug.cxx create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/reftrace.c create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/tracelog.c create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/win32obj.cxx create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/version/bldver.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/version/bldver.rc create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Setup.sln create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/LICENSE create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/README.md create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/appsearch/appsearch.wxi create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/ConfigShared.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/ConfigShared.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/CustomAction.def create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/cgi_restrictions.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/cgi_restrictions.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/config_custom.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/config_custom.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/consoleprops.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/consoleprops.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/defaults.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/defaults.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/elevatedsc.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/elevatedsc.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/handlers.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/handlers.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/hotfix.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/httpapi.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/httpapi.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.vcxproj create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iiscaexp.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iiscaexp.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/modules.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/mof.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/msiutil.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/msiutil.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/packages.config create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/precomp.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/schema.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/secutils.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/secutils.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/setup_log.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/setup_log.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/tracing.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/tracing.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/uimodule.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/wuerror.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix/iisca.wxs create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix/setupstrings.wxl create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/ElevatedShortcut.wxi create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/FixPatchingBehavior.wxi create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/HttpListener.wxi create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/ShortcutConsoleProperties.wxi create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/WindowsHotfix.wxi create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/iisca.wxs create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/include.wxi create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CHS/misc/setupstrings.wxl create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CHT/misc/setupstrings.wxl create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CSY/misc/setupstrings.wxl create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/DEU/misc/setupstrings.wxl create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/ESN/misc/setupstrings.wxl create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/FRA/misc/setupstrings.wxl create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/ITA/misc/setupstrings.wxl create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/JPN/misc/setupstrings.wxl create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/KOR/misc/setupstrings.wxl create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/PLK/misc/setupstrings.wxl create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/PTB/misc/setupstrings.wxl create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/RUS/misc/setupstrings.wxl create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/TRK/misc/setupstrings.wxl create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/dutil.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/memutil.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/precomp.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/qtexec.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/strutil.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcalog.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcascript.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcautil.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcautil.h create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcawrap.cpp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/bitmaps/AspNetCoreModule.ico create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/bitmaps/bannrbmp.bmp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/bitmaps/dlgbmp.bmp create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/build/copy-outputs.targets create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/build/exports.props create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/build/settings.props create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/build/settings/common.props create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/build/settings/debug.props create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/build/settings/release.props create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/build/submodule.props create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/build/versions.props create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/license/license.rtf create mode 100644 src/Installers/Windows/AspNetCoreModule-Setup/setupstrings.wxl delete mode 100644 src/Installers/Windows/clone_and_build_ancm.ps1 diff --git a/Directory.Build.props b/Directory.Build.props index bdb885cd9f..b281c92a76 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -35,4 +35,6 @@ + + diff --git a/Directory.Build.targets b/Directory.Build.targets index 30ce3e3322..b834d88ec0 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -14,4 +14,5 @@ + diff --git a/THIRD-PARTY-NOTICES b/THIRD-PARTY-NOTICES index a6470f40de..d1bf499032 100644 --- a/THIRD-PARTY-NOTICES +++ b/THIRD-PARTY-NOTICES @@ -35,3 +35,52 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +License notice for IIS-Common +------------------------------------ + +MIT License + +Copyright (c) Microsoft Corporation. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE + +License notice for IIS-Setup +------------------------------------ + +MIT License + +Copyright (c) Microsoft Corporation. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE diff --git a/eng/targets/Cpp.Common.props b/eng/targets/Cpp.Common.props new file mode 100644 index 0000000000..f295dbafad --- /dev/null +++ b/eng/targets/Cpp.Common.props @@ -0,0 +1,11 @@ + + + + + true + + + + + + diff --git a/eng/targets/Cpp.Common.targets b/eng/targets/Cpp.Common.targets new file mode 100644 index 0000000000..f2cad0d8c0 --- /dev/null +++ b/eng/targets/Cpp.Common.targets @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV1/AncmIISExpressV1.wixproj b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV1/AncmIISExpressV1.wixproj new file mode 100644 index 0000000000..8aac844ad9 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV1/AncmIISExpressV1.wixproj @@ -0,0 +1,72 @@ + + + + + + AspNetCoreModuleIISExpress + 2A6A4709-30D2-4716-A597-55DF0FB74D37 + Package + ICE03 + true + + + + ancm_iis_express_x86_en + + + ancm_iis_express_x64_en + + + True + + + + + iisca.wxs + + + + + + + + + + This project is trying to import a missing file: {0}. + + + + + + + + + + $(WixExtDir)\WixUtilExtension.dll + WixUtilExtension + + + $(WixExtDir)\WixDependencyExtension.dll + WixDependencyExtension + + + $(WixExtDir)\WixUIExtension.dll + WixUIExtension + + + + + + setupstrings.wxl + + + + + include.wxi + + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV1/ancm_iis_express.wxs b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV1/ancm_iis_express.wxs new file mode 100644 index 0000000000..00a8af36cf --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV1/ancm_iis_express.wxs @@ -0,0 +1,674 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Microsoft Corporation + + + + + + + + + + + (NOT NEWERVERSIONFOUND) OR Installed + + + Privileged + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + !(loc.Error30001) + !(loc.Error30002) + + !(loc.WebServicesRunning) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMPackageResolver/ANCMPackageResolver.csproj b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMPackageResolver/ANCMPackageResolver.csproj new file mode 100644 index 0000000000..591599ecca --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMPackageResolver/ANCMPackageResolver.csproj @@ -0,0 +1,25 @@ + + + netstandard1.0 + true + true + $(RepositoryRoot).deps\ANCM + + + + + + + + + $(RepositoryRoot).deps\ANCM; + + + $(RestoreSources); + https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json; + https://api.nuget.org/v3/index.json; + https://dotnet.myget.org/F/dotnet-core/api/v3/index.json; + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV1/AncmV1.wixproj b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV1/AncmV1.wixproj new file mode 100644 index 0000000000..c1f389495c --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV1/AncmV1.wixproj @@ -0,0 +1,74 @@ + + + + + + AspNetCoreModule + D36FDC38-FE53-48CC-BC82-A17C28F1CEE1 + true + Package + true + + + + aspnetcoremodule_x86_en + + + aspnetcoremodule_x64_en + + + + True + + + + + iisca.wxs + + + + + + + + + + + This project is trying to import a missing file: {0}. + + + + + + + + + + $(WixExtDir)\WixUtilExtension.dll + WixUtilExtension + + + $(WixExtDir)\WixDependencyExtension.dll + WixDependencyExtension + + + $(WixExtDir)\WixUIExtension.dll + WixUIExtension + + + + + + setupstrings.wxl + + + + + include.wxi + + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV1/aspnetcoremodule.wxs b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV1/aspnetcoremodule.wxs new file mode 100644 index 0000000000..cdb387e44f --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV1/aspnetcoremodule.wxs @@ -0,0 +1,276 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Microsoft Corporation + + + + + + + + + + + + + + + + + + (NOT NEWERVERSIONFOUND) OR Installed + + + + Privileged + + + + + + + + + + + + + + + + 1 + + + + = 601)]]> + + + + + ((IISCOREWEBENGINEINSTALLED = "#1") AND (IISW3SVCINSTALLED = "#1")) OR (Installed) + + + + + NOT ( (VersionNT = 600) AND (ServicePackLevel = 1) AND (WINDOWSUPDATE_START_TYPE = "#4") ) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + !(loc.Error30001) + !(loc.Error30002) + + !(loc.WebServicesRunning) + + + + + + AspNetCoreModule + AspNetCoreModuleDll + + + + + + system.webServer/aspNetCore + AspNetCoreSchemaFile + Allow + + + + + + WWW Server + {3a2a4e84-4c21-4981-ae10-3fda0d9b0f83} + ANCM + 65536 + AspNetCoreModule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/Directory.Build.props b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/Directory.Build.props new file mode 100644 index 0000000000..2f47372910 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/Directory.Build.props @@ -0,0 +1,15 @@ + + + + + + + $(_TwoDigitYear)$(_ThreeDigitDayOfYear) + $(PRODUCT_MAJOR) + $(PRODUCT_MINOR) + $(BUILD_MAJOR) + $(BUILD_MINOR) + BLDVERMAJOR=$(BLDVERMAJOR);BLDVERMINOR=$(BLDVERMINOR);BLDNUMMAJOR=$(BLDNUMMAJOR);BLDNUMMINOR=$(BLDNUMMINOR);$(DefineConstants) + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.cpp new file mode 100644 index 0000000000..48d826f720 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.cpp @@ -0,0 +1,184 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +#include + +DECLARE_DEBUG_PRINT_OBJECT( "proxyCA.dll" ); + +HINSTANCE g_hinst; + +BOOL WINAPI +DllMain( + HINSTANCE hModule, + DWORD dwReason, + LPVOID lpReserved + ) +{ + UNREFERENCED_PARAMETER( lpReserved ); + switch( dwReason ) + { + case DLL_PROCESS_ATTACH: + CREATE_DEBUG_PRINT_OBJECT; + DisableThreadLibraryCalls( hModule ); + g_hinst = hModule; + break; + + case DLL_PROCESS_DETACH: + break; + } + + return TRUE; +} + + +struct COMPRESSION_MIME_TYPE +{ + PCWSTR pszMimeType; + BOOL fEnabled; +}; + +COMPRESSION_MIME_TYPE gMimeTypes[] = + { { L"text/event-stream", FALSE} }; + +UINT +WINAPI +RegisterANCMCompressionCA( + IN MSIHANDLE + ) +{ + HRESULT hr = S_OK; + DWORD i; + VARIANT varName; + IAppHostWritableAdminManager * pAdminMgr = NULL; + IAppHostElement * pHttpCompressionSection = NULL; + IAppHostElement * pDynamicCompressionElement = NULL; + IAppHostElementCollection * pMimeTypeCollection = NULL; + IAppHostElement * pMimeTypeElement = NULL; + + VariantInit(&varName); + + hr = CoCreateInstance(__uuidof(AppHostWritableAdminManager), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IAppHostWritableAdminManager), + (VOID **)&pAdminMgr); + if (FAILED(hr)) + { + goto exit; + } + + hr = pAdminMgr->GetAdminSection(L"system.webServer/httpCompression", + L"MACHINE/WEBROOT/APPHOST", + &pHttpCompressionSection); + if (FAILED(hr)) + { + goto exit; + } + + hr = pHttpCompressionSection->GetElementByName(L"dynamicTypes", + &pDynamicCompressionElement); + if (FAILED(hr)) + { + goto exit; + } + + hr = pDynamicCompressionElement->get_Collection(&pMimeTypeCollection); + if (FAILED(hr)) + { + goto exit; + } + + hr = pMimeTypeCollection->get_Count(&i); + if (FAILED(hr) || i == 0) + { + // failure or DynamicCmpression is not enabled + goto exit; + } + + for (i=0; i<_countof(gMimeTypes); i++) + { + hr = pMimeTypeCollection->CreateNewElement(L"add", + &pMimeTypeElement); + if (FAILED(hr)) + { + goto exit; + } + + hr = VariantAssign(&varName, + gMimeTypes[i].pszMimeType); + if (FAILED(hr)) + { + goto exit; + } + + hr = SetElementProperty(pMimeTypeElement, + L"mimeType", + &varName); + if (FAILED(hr)) + { + goto exit; + } + VariantClear(&varName); + + varName.vt = VT_BOOL; + varName.boolVal = gMimeTypes[i].fEnabled ? VARIANT_TRUE : VARIANT_FALSE; + + hr = SetElementProperty(pMimeTypeElement, + L"enabled", + &varName); + if (FAILED(hr)) + { + goto exit; + } + VariantClear(&varName); + + hr = pMimeTypeCollection->AddElement(pMimeTypeElement); + if (FAILED(hr) && + hr != HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) + { + goto exit; + } + + pMimeTypeElement->Release(); + pMimeTypeElement = NULL; + } + + hr = pAdminMgr->CommitChanges(); + + exit: + + VariantClear(&varName); + + if (pMimeTypeElement != NULL) + { + pMimeTypeElement->Release(); + pMimeTypeElement = NULL; + } + + if (pMimeTypeCollection != NULL) + { + pMimeTypeCollection->Release(); + pMimeTypeCollection = NULL; + } + + if (pDynamicCompressionElement != NULL) + { + pDynamicCompressionElement->Release(); + pDynamicCompressionElement = NULL; + } + + if (pHttpCompressionSection != NULL) + { + pHttpCompressionSection->Release(); + pHttpCompressionSection = NULL; + } + + if (pAdminMgr != NULL) + { + pAdminMgr->Release(); + pAdminMgr = NULL; + } + + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_SUCCESS; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.def b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.def new file mode 100644 index 0000000000..3518cde35f --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.def @@ -0,0 +1,23 @@ +LIBRARY aspnetcoreCA + +EXPORTS + + ; IIS Common Config custom actions + + IISScheduleInstallCA + IISScheduleUninstallCA + IISExecuteCA + IISBeginTransactionCA + IISRollbackTransactionCA + IISCommitTransactionCA + + CheckForSharedConfigurationCA + + ScheduleInstallWindowsHotfixCA + ExecuteInstallWindowsHotfixCA + ExecuteCleanUpWindowsHotfixCA + ScheduleRebootIfRequiredCA + + RegisterANCMCompressionCA + + CheckForServicesRunningCA diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.rc b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.rc new file mode 100644 index 0000000000..8f05349435 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.rc @@ -0,0 +1,10 @@ +#define VER_FILETYPE VFT_DLL +#define RC_VERSION_INTERNAL_NAME "aspnetcoreCA\0" +#define RC_VERSION_ORIGINAL_FILE_NAME "aspnetcoreCA.dll\0" +#define RC_VERSION_FILE_DESCRIPTION "IIS AspNet Core Support Module Custom Action DLL\0" +#define PRODUCT_MAJOR 7 +#define PRODUCT_MINOR 1 +#define BUILD_MAJOR 1972 +#define BUILD_MINOR 0 + +#include diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.vcxproj b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.vcxproj new file mode 100644 index 0000000000..d4b2493fb9 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.vcxproj @@ -0,0 +1,98 @@ + + + + + $(MSBuildThisFileDirectory)..\ + + + + <_IIS-SetupExportsPath>$(ANCM-Setup)IIS-Setup\build\exports.props + + + + + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {7C27E72F-54D0-4820-8CFA-5E4BE640974B} + aspnetcoreca + aspnetcoreCA + + + + DynamicLibrary + v141 + Unicode + + + true + + + + $(IIS-Common)version;$(IIS-Common)Include;$(IIS-Setup)iisca\lib;$(WIX)sdk\$(WixPlatformToolset)\inc;$(AdditionalIncludeDirectories) + + + + true + $(AdditionalIncludeDirectories) + + + httpapi.lib;shlwapi.lib;ahadmin.lib;xmllite.lib;msi.lib;Version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + aspnetcoreCA.def + $(OutDir)$(TargetName).lib + /NODEFAULTLIB:MSVCRT %(AdditionalOptions) + + + + + + + + + + + + $(IIS-Common)version + + + + + {7324770c-0871-4d73-be3d-5e2f3e9e1b1e} + + + {b54a8f61-60de-4ad9-87ca-d102f230678e} + + + + + + + + This project is trying to import a missing file: {0}. + + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/avoid_restart.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/avoid_restart.cpp new file mode 100644 index 0000000000..b0e4753c44 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/avoid_restart.cpp @@ -0,0 +1,244 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +#include +#include + +HRESULT +GetServiceCurrentState( + __in LPCWSTR pszServiceName, + __out SERVICE_STATUS * pServiceStatus +) +{ + HRESULT hr = S_OK; + SC_HANDLE hServiceControlManager = NULL; + SC_HANDLE hService = NULL; + + hServiceControlManager = OpenSCManager( NULL, // Local machine + NULL, + STANDARD_RIGHTS_READ ); + if ( hServiceControlManager == NULL ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto Finished; + } + + hService = OpenService( hServiceControlManager, + pszServiceName, + SERVICE_QUERY_STATUS ); + if ( hService == NULL ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto Finished; + } + + if ( !QueryServiceStatus( hService, + pServiceStatus ) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto Finished; + } + +Finished: + + if ( hService != NULL ) + { + CloseServiceHandle( hService ); + hService = NULL; + } + + if ( hServiceControlManager != NULL ) + { + CloseServiceHandle( hService ); + hService = NULL; + } + + return hr; +} + +BOOL +IsServiceRunning( + const SERVICE_STATUS & ServiceStatus +) +{ + switch( ServiceStatus.dwCurrentState ) + { + case SERVICE_RUNNING: + case SERVICE_START_PENDING: + case SERVICE_CONTINUE_PENDING: + return TRUE; + default: + return FALSE; + } +} + +HRESULT +IsQfeInstalled( + __in LPCWSTR pszQfeName, + __out BOOL * pfIsInstalled +) +{ + HRESULT hr = S_OK; + CComPtr< IWbemLocator > pLocator; + CComPtr< IWbemServices > pService; + CComPtr< IEnumWbemClassObject > pEnumerator; + ULONG Count = 0; + CComPtr< IWbemClassObject > pProcessor; + CComBSTR bstrNamespace; + CComBSTR bstrQueryLanguage; + CComBSTR bstrQuery; + + if ( FAILED( hr = bstrNamespace.Append( L"root\\CIMV2", 10 ) ) || + FAILED( hr = bstrQueryLanguage.Append( L"WQL", 3 ) ) || + FAILED( hr = bstrQuery.Append( L"SELECT HotFixID FROM Win32_QuickFixEngineering WHERE HotFixID='" ) ) || + FAILED( hr = bstrQuery.Append( pszQfeName ) ) || + FAILED( hr = bstrQuery.Append( L"'", 1 ) ) ) + { + goto Finished; + } + + hr = CoCreateInstance( __uuidof(WbemAdministrativeLocator), + NULL, // pUnkOuter + CLSCTX_INPROC_SERVER, + __uuidof(IWbemLocator), + reinterpret_cast< void** >( &pLocator ) ); + if ( FAILED( hr ) ) + { + goto Finished; + } + + hr = pLocator->ConnectServer( bstrNamespace, + NULL, // strUser + NULL, // strPassword + NULL, // strLocale + WBEM_FLAG_CONNECT_USE_MAX_WAIT, + NULL, // strAuthority + NULL, // pCtx + &pService ); + if ( FAILED( hr ) ) + { + goto Finished; + } + + // + // Set the proxy so that impersonation of the client occurs. + // + hr = CoSetProxyBlanket( pService, + RPC_C_AUTHN_DEFAULT, + RPC_C_AUTHZ_NONE, + NULL, + RPC_C_AUTHN_LEVEL_CONNECT, + RPC_C_IMP_LEVEL_IMPERSONATE, + NULL, + EOAC_NONE); + if ( FAILED( hr ) ) + { + goto Finished; + } + + hr = pService->ExecQuery( bstrQueryLanguage, + bstrQuery, + WBEM_FLAG_FORWARD_ONLY, + NULL, + &pEnumerator ); + if ( FAILED( hr ) ) + { + goto Finished; + } + + hr = pEnumerator->Next( WBEM_INFINITE, + 1L, + &pProcessor, + &Count ); + if ( FAILED( hr ) ) + { + goto Finished; + } + + *pfIsInstalled = Count > 0; + +Finished: + + return hr; +} + +UINT +WINAPI +CheckForServicesRunningCA( + MSIHANDLE hInstall +) +{ + HRESULT hr = S_OK; + BOOL fIsServiceRunning = FALSE; + SERVICE_STATUS ServiceStatus; + LPCWSTR rgServiceNames[] = { L"WAS", L"WMSVC" }; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + // + // Check if any pService is running. + // + for( DWORD Index = 0; Index < _countof( rgServiceNames ); Index ++ ) + { + hr = GetServiceCurrentState( rgServiceNames[Index], + &ServiceStatus ); + if ( hr == HRESULT_FROM_WIN32( ERROR_SERVICE_DOES_NOT_EXIST ) ) + { + hr = S_OK; + } + else if ( FAILED( hr ) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"Failed to query the state of the service '%s' hr=0x%x", + rgServiceNames[Index], + hr ); + DBGERROR_HR(hr); + goto Finished; + } + else + { + fIsServiceRunning = IsServiceRunning( ServiceStatus ); + if ( fIsServiceRunning ) + { + break; + } + } + } + + if ( fIsServiceRunning ) + { + BOOL fQfeInstalled = FALSE; + + hr = IsQfeInstalled( L"KB954438", + &fQfeInstalled ); + if ( FAILED( hr ) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"Failed to query the hotfix 'KB949172' information hr=0x%x", + hr ); + DBGERROR_HR(hr); + goto Finished; + } + + if ( fQfeInstalled ) + { + // + // hotfix is already installed. + // + goto Finished; + } + + IISLogClose(); + return LogMsiCustomActionError( hInstall, 30003 ); + } + +Finished: + + IISLogClose(); + + // TODO Wire up when Rollback CA's are wired up + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_SUCCESS; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/Directory.Build.props b/src/Installers/Windows/AspNetCoreModule-Setup/Directory.Build.props new file mode 100644 index 0000000000..e790ba07a1 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/Directory.Build.props @@ -0,0 +1,43 @@ + + + + + + + <_TwoDigitYear>$([MSBuild]::Subtract($([System.DateTime]::UtcNow.Year), 2000)) + <_ThreeDigitDayOfYear>$([System.DateTime]::UtcNow.DayOfYear.ToString().PadLeft(3, '0')) + + + $(_TwoDigitYear)$(_ThreeDigitDayOfYear) + $(PRODUCT_MAJOR) + $(PRODUCT_MINOR) + $(BUILD_MAJOR) + $(BUILD_MINOR) + + + 1$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).$(BUILD_MAJOR).0 + + + 2.0.0 + + + $(RepositoryRoot)src\Installers\Windows\AspNetCoreModule-Setup\ + $(AspNetCoreSetupRoot)IIS-Setup\ + $(IIS-Setup)IIS-Common\ + $(AspNetCoreSetupRoot)build\ + + + CustomAction=$(AspNetCoreSetupRoot)CustomAction\bin\$(Configuration)\$(Platform)\aspnetcoreca.dll + $(RepositoryRoot).deps\ANCM\Microsoft.AspNetCore.AspNetCoreModule\$(MicrosoftAspNetCoreAspNetCoreModulePackageVersion)\ + $(RepositoryRoot).deps\ANCM\Microsoft.AspNetCore.AspNetCoreModuleV2\$(MicrosoftAspNetCoreAspNetCoreModuleV2PackageVersion)\ + $(PreBuiltANCMSchema)contentFiles\any\any\ + $(PreBuiltANCMV2Schema)contentFiles\any\any\ + + BLDVERMAJOR=$(BLDVERMAJOR);BLDVERMINOR=$(BLDVERMINOR);BLDNUMMAJOR=$(BLDNUMMAJOR);BLDNUMMINOR=$(BLDNUMMINOR);$(DefineConstants) + ANCMMsiVersion=$(ANCMMsiVersion);ANCMOutOfProcessNugetPackageHandlerVersion=$(ANCMOutOfProcessNugetPackageHandlerVersion);$(DefineConstants) + PreBuiltANCMRoot=$(PreBuiltANCMRoot);PreBuiltANCMV2Root=$(PreBuiltANCMV2Root);$(DefineConstants) + $(CustomActionVariable);PreBuiltANCMSchema=$(PreBuiltANCMSchema);PreBuiltANCMV2Schema=$(PreBuiltANCMV2Schema);$(DefineConstants) + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Common.sln b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Common.sln new file mode 100644 index 0000000000..5b48ec6769 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Common.sln @@ -0,0 +1,41 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27120.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CommonLib", "lib\CommonLib.vcxproj", "{B54A8F61-60DE-4AD9-87CA-D102F230678E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "reftrace", "reftrace\reftrace.vcxproj", "{A2599642-CBE5-4230-8511-3DC2D81874BE}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x64.ActiveCfg = Debug|x64 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x64.Build.0 = Debug|x64 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x86.ActiveCfg = Debug|Win32 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x86.Build.0 = Debug|Win32 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x64.ActiveCfg = Release|x64 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x64.Build.0 = Release|x64 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x86.ActiveCfg = Release|Win32 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x86.Build.0 = Release|Win32 + {A2599642-CBE5-4230-8511-3DC2D81874BE}.Debug|x64.ActiveCfg = Debug|x64 + {A2599642-CBE5-4230-8511-3DC2D81874BE}.Debug|x64.Build.0 = Debug|x64 + {A2599642-CBE5-4230-8511-3DC2D81874BE}.Debug|x86.ActiveCfg = Debug|Win32 + {A2599642-CBE5-4230-8511-3DC2D81874BE}.Debug|x86.Build.0 = Debug|Win32 + {A2599642-CBE5-4230-8511-3DC2D81874BE}.Release|x64.ActiveCfg = Release|x64 + {A2599642-CBE5-4230-8511-3DC2D81874BE}.Release|x64.Build.0 = Release|x64 + {A2599642-CBE5-4230-8511-3DC2D81874BE}.Release|x86.ActiveCfg = Release|Win32 + {A2599642-CBE5-4230-8511-3DC2D81874BE}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {81F5A61A-A12A-4F53-B0F9-C0E541CA6567} + EndGlobalSection +EndGlobal diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/acache.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/acache.h new file mode 100644 index 0000000000..83e39fd7ff --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/acache.h @@ -0,0 +1,116 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "percpu.h" + + +class ALLOC_CACHE_HANDLER +{ +public: + + ALLOC_CACHE_HANDLER( + VOID + ); + + ~ALLOC_CACHE_HANDLER( + VOID + ); + + HRESULT + Initialize( + DWORD cbSize, + LONG nThreshold + ); + + LPVOID + Alloc( + VOID + ); + + VOID + Free( + __in LPVOID pMemory + ); + + +private: + + VOID + CleanupLookaside( + VOID + ); + + DWORD + QueryDepthForAllSLists( + VOID + ); + + LONG m_nThreshold; + DWORD m_cbSize; + + PER_CPU * m_pFreeLists; + + // + // Total heap allocations done over the lifetime. + // Note that this is not interlocked, it is just a hint for debugging. + // + volatile LONG m_nTotal; + + LONG m_nFillPattern; + +public: + + static + HRESULT + StaticInitialize( + VOID + ); + + static + VOID + StaticTerminate( + VOID + ); + + static + BOOL + IsPageheapEnabled(); + +private: + + static LONG sm_nFillPattern; + static HANDLE sm_hHeap; +}; + + +// You can use ALLOC_CACHE_HANDLER as a per-class allocator +// in your C++ classes. Add the following to your class definition: +// +// protected: +// static ALLOC_CACHE_HANDLER* sm_palloc; +// public: +// static void* operator new(size_t s) +// { +// IRTLASSERT(s == sizeof(C)); +// IRTLASSERT(sm_palloc != NULL); +// return sm_palloc->Alloc(); +// } +// static void operator delete(void* pv) +// { +// IRTLASSERT(pv != NULL); +// if (sm_palloc != NULL) +// sm_palloc->Free(pv); +// } +// +// Obviously, you must initialize sm_palloc before you can allocate +// any objects of this class. +// +// Note that if you derive a class from this base class, the derived class +// must also provide its own operator new and operator delete. If not, the +// base class's allocator will be called, but the size of the derived +// object will almost certainly be larger than that of the base object. +// Furthermore, the allocator will not be used for arrays of objects +// (override operator new[] and operator delete[]), but this is a +// harder problem since the allocator works with one fixed size. diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/ahutil.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/ahutil.h new file mode 100644 index 0000000000..a39c09bb73 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/ahutil.h @@ -0,0 +1,264 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +HRESULT +SetElementProperty( + IN IAppHostElement * pElement, + IN CONST WCHAR * szPropName, + IN CONST VARIANT * varPropValue + ); + +HRESULT +SetElementStringProperty( + IN IAppHostElement * pElement, + IN CONST WCHAR * szPropName, + IN CONST WCHAR * szPropValue + ); + +HRESULT +GetElementStringProperty( + IN IAppHostElement * pElement, + IN CONST WCHAR * szPropName, + OUT BSTR * pbstrPropValue + ); + +HRESULT +GetElementStringProperty( + IN IAppHostElement * pElement, + IN CONST WCHAR * szPropName, + OUT STRU * pstrPropValue + ); + +HRESULT +GetElementBoolProperty( + IN IAppHostElement * pElement, + IN LPCWSTR pszPropertyName, + OUT BOOL * pBool + ); + +HRESULT +GetElementBoolProperty( + IN IAppHostElement * pElement, + IN LPCWSTR pszPropertyName, + OUT bool * pBool + ); + +HRESULT +GetElementChildByName( + IN IAppHostElement * pElement, + IN LPCWSTR pszElementName, + OUT IAppHostElement ** ppChildElement + ); + +HRESULT +GetElementDWORDProperty( + IN IAppHostElement * pElement, + IN LPCWSTR pszPropertyName, + OUT DWORD * pdwValue + ); + +HRESULT +GetElementINTProperty( + IN IAppHostElement * pElement, + IN LPCWSTR pszPropertyName, + OUT INT * pintValue + ); + +HRESULT +GetElementLONGLONGProperty( + IN IAppHostElement * pElement, + IN LPCWSTR pszPropertyName, + OUT LONGLONG * pllValue +); + + +HRESULT +GetElementRawTimeSpanProperty( + IN IAppHostElement * pElement, + IN LPCWSTR pszPropertyName, + OUT ULONGLONG * pulonglong + ); + +#define FIND_ELEMENT_CASE_SENSITIVE 0x00000000 +#define FIND_ELEMENT_CASE_INSENSITIVE 0x00000001 + +HRESULT +DeleteElementFromCollection( + IAppHostElementCollection *pCollection, + CONST WCHAR * szKeyName, + CONST WCHAR * szKeyValue, + ULONG BehaviorFlags, + BOOL * pfDeleted + ); + +HRESULT +DeleteAllElementsFromCollection( + IAppHostElementCollection *pCollection, + CONST WCHAR * szKeyName, + CONST WCHAR * szKeyValue, + ULONG BehaviorFlags, + UINT * pNumDeleted + ); + +HRESULT +FindElementInCollection( + IAppHostElementCollection *pCollection, + CONST WCHAR * szKeyName, + CONST WCHAR * szKeyValue, + ULONG BehaviorFlags, + OUT ULONG * pIndex + ); + +HRESULT +VariantAssign( + IN OUT VARIANT * pv, + IN CONST WCHAR * sz + ); + +HRESULT +GetLocationFromFile( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szLocationPath, + OUT IAppHostConfigLocation ** ppLocation, + OUT BOOL * pFound + ); + +HRESULT +GetSectionFromLocation( + IN IAppHostConfigLocation * pLocation, + IN CONST WCHAR * szSectionName, + OUT IAppHostElement ** ppSectionElement, + OUT BOOL * pFound + ); + +HRESULT +GetAdminElement( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szElementName, + OUT IAppHostElement ** pElement + ); + +HRESULT +ClearAdminElement( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szElementName + ); + +HRESULT +ClearElementFromAllSites( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szElementName + ); + +HRESULT +ClearElementFromAllLocations( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szElementName + ); + +HRESULT +ClearLocationElements( + IN IAppHostConfigLocation * pLocation, + IN CONST WCHAR * szElementName + ); + +HRESULT +CompareElementName( + IN IAppHostElement * pElement, + IN CONST WCHAR * szNameToMatch, + OUT BOOL * pMatched + ); + +HRESULT +ClearChildElementsByName( + IN IAppHostChildElementCollection * pCollection, + IN CONST WCHAR * szElementName, + OUT BOOL * pFound + ); + +HRESULT +GetSitesCollection( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + OUT IAppHostElementCollection ** pSitesCollection + ); + +HRESULT +GetLocationCollection( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + OUT IAppHostConfigLocationCollection ** pLocationCollection + ); + +struct ENUM_INDEX +{ + VARIANT Index; + ULONG Count; +}; + +HRESULT +FindFirstElement( + IN IAppHostElementCollection * pCollection, + OUT ENUM_INDEX * pIndex, + OUT IAppHostElement ** pElement + ); + +HRESULT +FindNextElement( + IN IAppHostElementCollection * pCollection, + IN OUT ENUM_INDEX * pIndex, + OUT IAppHostElement ** pElement + ); + +HRESULT +FindFirstChildElement( + IN IAppHostChildElementCollection * pCollection, + OUT ENUM_INDEX * pIndex, + OUT IAppHostElement ** pElement + ); + +HRESULT +FindNextChildElement( + IN IAppHostChildElementCollection * pCollection, + IN OUT ENUM_INDEX * pIndex, + OUT IAppHostElement ** pElement + ); + +HRESULT +FindFirstLocation( + IN IAppHostConfigLocationCollection * pCollection, + OUT ENUM_INDEX * pIndex, + OUT IAppHostConfigLocation ** pLocation + ); + +HRESULT +FindNextLocation( + IN IAppHostConfigLocationCollection * pCollection, + IN OUT ENUM_INDEX * pIndex, + OUT IAppHostConfigLocation ** pLocation + ); + +HRESULT +FindFirstLocationElement( + IN IAppHostConfigLocation * pLocation, + OUT ENUM_INDEX * pIndex, + OUT IAppHostElement ** pElement + ); + +HRESULT +FindNextLocationElement( + IN IAppHostConfigLocation * pLocation, + IN OUT ENUM_INDEX * pIndex, + OUT IAppHostElement ** pElement + ); + +HRESULT GetSharedConfigEnabled( + BOOL * pfIsSharedConfig +); \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/base64.hxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/base64.hxx new file mode 100644 index 0000000000..871c7e8e0f --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/base64.hxx @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _BASE64_HXX_ +#define _BASE64_HXX_ + +DWORD +Base64Encode( + __in_bcount( cbDecodedBufferSize ) VOID * pDecodedBuffer, + IN DWORD cbDecodedBufferSize, + __out_ecount_opt( cchEncodedStringSize ) PWSTR pszEncodedString, + IN DWORD cchEncodedStringSize, + __out_opt DWORD * pcchEncoded + ); + +DWORD +Base64Decode( + __in PCWSTR pszEncodedString, + __out_opt VOID * pDecodeBuffer, + __in DWORD cbDecodeBufferSize, + __out_opt DWORD * pcbDecoded + ); + +DWORD +Base64Encode( + __in_bcount( cbDecodedBufferSize ) VOID * pDecodedBuffer, + IN DWORD cbDecodedBufferSize, + __out_ecount_opt( cchEncodedStringSize ) PSTR pszEncodedString, + IN DWORD cchEncodedStringSize, + __out_opt DWORD * pcchEncoded + ); + +DWORD +Base64Decode( + __in PCSTR pszEncodedString, + __out_opt VOID * pDecodeBuffer, + __in DWORD cbDecodeBufferSize, + __out_opt DWORD * pcbDecoded + ); + +#endif // _BASE64_HXX_ + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/buffer.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/buffer.h new file mode 100644 index 0000000000..63e567be4d --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/buffer.h @@ -0,0 +1,271 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include + + +// +// BUFFER_T class shouldn't be used directly. Use BUFFER specialization class instead. +// The only BUFFER_T partners are STRU and STRA classes. +// BUFFER_T cannot hold other but primitive types since it doesn't call +// constructor and destructor. +// +// Note: Size is in bytes. +// +template +class BUFFER_T +{ +public: + + BUFFER_T() + : m_cbBuffer( sizeof(m_rgBuffer) ), + m_fHeapAllocated( false ), + m_pBuffer(m_rgBuffer) + /*++ + Description: + + Default constructor where the inline buffer is used. + + Arguments: + + None. + + Returns: + + None. + + --*/ + { + } + + BUFFER_T( + __inout_bcount(cbInit) T* pbInit, + __in DWORD cbInit + ) : m_pBuffer( pbInit ), + m_cbBuffer( cbInit ), + m_fHeapAllocated( false ) + /*++ + Description: + + Instantiate BUFFER, initially using pbInit as buffer + This is useful for stack-buffers and inline-buffer class members + (see STACK_BUFFER and INLINE_BUFFER_INIT below) + + BUFFER does not free pbInit. + + Arguments: + + pbInit - Initial buffer to use. + cbInit - Size of pbInit in bytes (not in elements). + + Returns: + + None. + + --*/ + { + _ASSERTE( NULL != pbInit ); + _ASSERTE( cbInit > 0 ); + } + + ~BUFFER_T() + { + if( IsHeapAllocated() ) + { + _ASSERTE( NULL != m_pBuffer ); + HeapFree( GetProcessHeap(), 0, m_pBuffer ); + m_pBuffer = NULL; + m_cbBuffer = 0; + m_fHeapAllocated = false; + } + } + + T* + QueryPtr( + VOID + ) const + { + // + // Return pointer to data buffer. + // + return m_pBuffer; + } + + DWORD + QuerySize( + VOID + ) const + { + // + // Return number of bytes. + // + return m_cbBuffer; + } + + __success(return == true) + bool + Resize( + const SIZE_T cbNewSize, + const bool fZeroMemoryBeyondOldSize = false + ) + /*++ + Description: + + Resizes the buffer. + + Arguments: + + cbNewSize - Size in bytes to grow to. + fZeroMemoryBeyondOldSize + - Whether to zero the region of memory of the + new buffer beyond the original size. + + Returns: + + TRUE on success, FALSE on failure. + + --*/ + { + PVOID pNewMem; + + if ( cbNewSize <= m_cbBuffer ) + { + return true; + } + + if ( cbNewSize > MAXDWORD ) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return false; + } + + DWORD dwHeapAllocFlags = fZeroMemoryBeyondOldSize ? HEAP_ZERO_MEMORY : 0; + + if( IsHeapAllocated() ) + { + pNewMem = HeapReAlloc( GetProcessHeap(), dwHeapAllocFlags, m_pBuffer, cbNewSize ); + } + else + { + pNewMem = HeapAlloc( GetProcessHeap(), dwHeapAllocFlags, cbNewSize ); + } + + if( pNewMem == NULL ) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return false; + } + + if( !IsHeapAllocated() ) + { + // + // First time this block is allocated. Copy over old contents. + // + memcpy_s( pNewMem, static_cast(cbNewSize), m_pBuffer, m_cbBuffer ); + m_fHeapAllocated = true; + } + + m_pBuffer = reinterpret_cast(pNewMem); + m_cbBuffer = static_cast(cbNewSize); + + _ASSERTE( m_pBuffer != NULL ); + + return true; + } + +private: + + bool + IsHeapAllocated( + VOID + ) const + { + return m_fHeapAllocated; + } + + // + // The default inline buffer. + // This member should be at the beginning for alignment purposes. + // + T m_rgBuffer[LENGTH]; + + // + // Is m_pBuffer dynamically allocated? + // + bool m_fHeapAllocated; + + // + // Size of the buffer as requested by client in bytes. + // + DWORD m_cbBuffer; + + // + // Pointer to buffer. + // + __field_bcount_full(m_cbBuffer) + T* m_pBuffer; +}; + +// +// Resizes the buffer by 2 if the ideal size is bigger +// than the buffer length. That give us lg(n) allocations. +// +// Use template inferring like: +// +// BUFFER buff; +// hr = ResizeBufferByTwo(buff, 100); +// +template +HRESULT +ResizeBufferByTwo( + BUFFER_T& Buffer, + SIZE_T cbIdealSize, + bool fZeroMemoryBeyondOldSize = false +) +{ + if (cbIdealSize > Buffer.QuerySize()) + { + if (!Buffer.Resize(max(cbIdealSize, static_cast(Buffer.QuerySize() * 2)), + fZeroMemoryBeyondOldSize)) + { + return E_OUTOFMEMORY; + } + } + return S_OK; +} + + +// +// +// Lots of code uses BUFFER class to store a bunch of different +// structures, so m_rgBuffer needs to be 8 byte aligned when it is used +// as an opaque buffer. +// +#define INLINED_BUFFER_LEN 32 +typedef BUFFER_T BUFFER; + +// +// Assumption of macros below for pointer alignment purposes +// +C_ASSERT( sizeof(VOID*) <= sizeof(ULONGLONG) ); + +// +// Declare a BUFFER that will use stack memory of +// bytes. If the buffer overflows then a heap buffer will be allocated. +// +#define STACK_BUFFER( _name, _size ) \ + ULONGLONG __aqw##_name[ ( ( (_size) + sizeof(ULONGLONG) - 1 ) / sizeof(ULONGLONG) ) ]; \ + BUFFER _name( (BYTE*)__aqw##_name, sizeof(__aqw##_name) ) + +// +// Macros for declaring and initializing a BUFFER that will use inline memory +// of bytes as a member of an object. +// +#define INLINE_BUFFER( _name, _size ) \ + ULONGLONG __aqw##_name[ ( ( (_size) + sizeof(ULONGLONG) - 1 ) / sizeof(ULONGLONG) ) ]; \ + BUFFER _name; + +#define INLINE_BUFFER_INIT( _name ) \ + _name( (BYTE*)__aqw##_name, sizeof( __aqw##_name ) ) diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/datetime.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/datetime.h new file mode 100644 index 0000000000..82ac441abd --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/datetime.h @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _DATETIME_H_ +#define _DATETIME_H_ + +BOOL +StringTimeToFileTime( + PCSTR pszTime, + ULONGLONG * pulTime +); + +#endif + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/dbgutil.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/dbgutil.h new file mode 100644 index 0000000000..9a33cca394 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/dbgutil.h @@ -0,0 +1,102 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _DBGUTIL_H_ +#define _DBGUTIL_H_ + +#include + +// +// TODO +// Using _CrtDbg implementation. If hooking is desired +// wrappers should be provided here so that we can reimplement +// if neecessary. +// +// IF_DEBUG/DEBUG FLAGS +// +// registry configuration +// + +// +// Debug error levels for DEBUG_FLAGS_VAR. +// + +#define DEBUG_FLAG_INFO 0x00000001 +#define DEBUG_FLAG_WARN 0x00000002 +#define DEBUG_FLAG_ERROR 0x00000004 + +// +// Predefined error level values. These are backwards from the +// windows definitions. +// + +#define DEBUG_FLAGS_INFO (DEBUG_FLAG_ERROR | DEBUG_FLAG_WARN | DEBUG_FLAG_INFO) +#define DEBUG_FLAGS_WARN (DEBUG_FLAG_ERROR | DEBUG_FLAG_WARN) +#define DEBUG_FLAGS_ERROR (DEBUG_FLAG_ERROR) +#define DEBUG_FLAGS_ANY (DEBUG_FLAG_INFO | DEBUG_FLAG_WARN | DEBUG_FLAG_ERROR) + +// +// Global variables to control tracing. Generally per module +// + +#ifndef DEBUG_FLAGS_VAR +#define DEBUG_FLAGS_VAR g_dwDebugFlags +#endif + +#ifndef DEBUG_LABEL_VAR +#define DEBUG_LABEL_VAR g_szDebugLabel +#endif + +extern PCSTR DEBUG_LABEL_VAR; +extern DWORD DEBUG_FLAGS_VAR; + +// +// Module should make this declaration globally. +// + +#define DECLARE_DEBUG_PRINT_OBJECT( _pszLabel_ ) \ + PCSTR DEBUG_LABEL_VAR = _pszLabel_; \ + DWORD DEBUG_FLAGS_VAR = DEBUG_FLAGS_ANY; \ + +#define DECLARE_DEBUG_PRINT_OBJECT2( _pszLabel_, _dwLevel_ ) \ + PCSTR DEBUG_LABEL_VAR = _pszLabel_; \ + DWORD DEBUG_FLAGS_VAR = _dwLevel_; \ + +// +// This doesn't do anything now. Should be safe to call in dll main. +// + +#define CREATE_DEBUG_PRINT_OBJECT + +// +// Trace macros +// + +#define DBG_CONTEXT _CRT_WARN, __FILE__, __LINE__, DEBUG_LABEL_VAR + +#ifdef DEBUG +#define DBGINFO(args) \ + {if( DEBUG_FLAGS_VAR & DEBUG_FLAG_INFO ) { _CrtDbgReport args; }} +#define DBGWARN(args) \ + {if( DEBUG_FLAGS_VAR & DEBUG_FLAG_WARN ) { _CrtDbgReport args; }} +#define DBGERROR(args) \ + {if( DEBUG_FLAGS_VAR & DEBUG_FLAG_ERROR ) { _CrtDbgReport args; }} +#else +#define DBGINFO +#define DBGWARN +#define DBGERROR +#endif + +#define DBGPRINTF DBGINFO + +// +// Simple error traces +// + +#define DBGERROR_HR( _hr_ ) \ + DBGERROR(( DBG_CONTEXT, "hr=0x%x\n", _hr_ )) + +#define DBGERROR_STATUS( _status_ ) \ + DBGERROR(( DBG_CONTEXT, "status=%d\n", _status_ )) + +#endif diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/debugutil.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/debugutil.h new file mode 100644 index 0000000000..39033973ce --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/debugutil.h @@ -0,0 +1,124 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#define DEBUG_FLAG_INFO 0x00000001 +#define DEBUG_FLAG_WARN 0x00000002 +#define DEBUG_FLAG_ERROR 0x00000004 + +// +// Predefined error level values. These are backwards from the +// windows definitions. +// + +#define DEBUG_FLAGS_INFO (DEBUG_FLAG_ERROR | DEBUG_FLAG_WARN | DEBUG_FLAG_INFO) +#define DEBUG_FLAGS_WARN (DEBUG_FLAG_ERROR | DEBUG_FLAG_WARN) +#define DEBUG_FLAGS_ERROR (DEBUG_FLAG_ERROR) +#define DEBUG_FLAGS_ANY (DEBUG_FLAG_INFO | DEBUG_FLAG_WARN | DEBUG_FLAG_ERROR) + +#define DEBUG_FLAGS_REGISTRY_LOCATION_A "DebugFlags" + +extern DWORD g_dwDebugFlags; + +static +BOOL +IfDebug( + DWORD dwFlag + ) +{ + return ( dwFlag & g_dwDebugFlags ); +} + +static +VOID +DebugPrint( + DWORD dwFlag, + LPCSTR szString + ) +{ + STBUFF strOutput; + HRESULT hr; + + if ( IfDebug( dwFlag ) ) + { + hr = strOutput.Printf( "[dipmodule.dll] %s\r\n", + szString ); + + if ( FAILED( hr ) ) + { + goto Finished; + } + + OutputDebugStringA( strOutput.QueryStr() ); + } + +Finished: + + return; +} + +static +VOID +DebugPrintf( +DWORD dwFlag, +LPCSTR szFormat, +... +) +{ + STBUFF strCooked; + STBUFF strOutput; + va_list args; + HRESULT hr; + + if ( IfDebug( dwFlag ) ) + { + va_start( args, szFormat ); + + hr = strCooked.Vsprintf( (LPSTR)szFormat, args ); + + va_end( args ); + + if ( FAILED( hr ) ) + { + goto Finished; + } + + DebugPrint( dwFlag, strCooked.QueryStr() ); + } + +Finished: + + return; +} + +static void ReadDebugFlagFromRegistryKey(const char* pszRegKey, IN DWORD dwDefault) +{ + HKEY hkey = NULL; + g_dwDebugFlags = dwDefault; + DWORD dwType; + DWORD dwBuffer; + DWORD cbBuffer = sizeof(dwBuffer); + + DWORD dwError = RegOpenKeyExA(HKEY_LOCAL_MACHINE, + pszRegKey, + 0, + KEY_READ, + &hkey); + if ( dwError == NO_ERROR && hkey != NULL) + { + dwError = RegQueryValueExA( hkey, + DEBUG_FLAGS_REGISTRY_LOCATION_A, + NULL, + &dwType, + (LPBYTE)&dwBuffer, + &cbBuffer ); + if( ( dwError == NO_ERROR ) && ( dwType == REG_DWORD ) ) + { + g_dwDebugFlags = dwBuffer; + } + RegCloseKey( hkey); + hkey = NULL; + } +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hashfn.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hashfn.h new file mode 100644 index 0000000000..a86b0a1358 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hashfn.h @@ -0,0 +1,325 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef __HASHFN_H__ +#define __HASHFN_H__ + + +// Produce a scrambled, randomish number in the range 0 to RANDOM_PRIME-1. +// Applying this to the results of the other hash functions is likely to +// produce a much better distribution, especially for the identity hash +// functions such as Hash(char c), where records will tend to cluster at +// the low end of the hashtable otherwise. LKRhash applies this internally +// to all hash signatures for exactly this reason. + +inline DWORD +HashScramble(DWORD dwHash) +{ + // Here are 10 primes slightly greater than 10^9 + // 1000000007, 1000000009, 1000000021, 1000000033, 1000000087, + // 1000000093, 1000000097, 1000000103, 1000000123, 1000000181. + + // default value for "scrambling constant" + const DWORD RANDOM_CONSTANT = 314159269UL; + // large prime number, also used for scrambling + const DWORD RANDOM_PRIME = 1000000007UL; + + return (RANDOM_CONSTANT * dwHash) % RANDOM_PRIME ; +} + + +// Faster scrambling function suggested by Eric Jacobsen + +inline DWORD +HashRandomizeBits(DWORD dw) +{ + return (((dw * 1103515245 + 12345) >> 16) + | ((dw * 69069 + 1) & 0xffff0000)); +} + + +// Small prime number used as a multiplier in the supplied hash functions +const DWORD HASH_MULTIPLIER = 101; + +#undef HASH_SHIFT_MULTIPLY + +#ifdef HASH_SHIFT_MULTIPLY +# define HASH_MULTIPLY(dw) (((dw) << 7) - (dw)) +#else +# define HASH_MULTIPLY(dw) ((dw) * HASH_MULTIPLIER) +#endif + +// Fast, simple hash function that tends to give a good distribution. +// Apply HashScramble to the result if you're using this for something +// other than LKRhash. + +inline DWORD +HashString( + const char* psz, + DWORD dwHash = 0) +{ + // force compiler to use unsigned arithmetic + const unsigned char* upsz = (const unsigned char*) psz; + + for ( ; *upsz; ++upsz) + dwHash = HASH_MULTIPLY(dwHash) + *upsz; + + return dwHash; +} + +inline DWORD +HashString( + __in_ecount(cch) const char* psz, + __in DWORD cch, + __in DWORD dwHash +) +{ + // force compiler to use unsigned arithmetic + const unsigned char* upsz = (const unsigned char*) psz; + + for (DWORD Index = 0; + Index < cch; + ++Index, ++upsz) + { + dwHash = HASH_MULTIPLY(dwHash) + *upsz; + } + + return dwHash; +} + + +// Unicode version of above + +inline DWORD +HashString( + const wchar_t* pwsz, + DWORD dwHash = 0) +{ + for ( ; *pwsz; ++pwsz) + dwHash = HASH_MULTIPLY(dwHash) + *pwsz; + + return dwHash; +} + +// Based on length of the string instead of null-terminating character + +inline DWORD +HashString( + __in_ecount(cch) const wchar_t* pwsz, + __in DWORD cch, + __in DWORD dwHash +) +{ + for (DWORD Index = 0; + Index < cch; + ++Index, ++pwsz) + { + dwHash = HASH_MULTIPLY(dwHash) + *pwsz; + } + + return dwHash; +} + + +// Quick-'n'-dirty case-insensitive string hash function. +// Make sure that you follow up with _stricmp or _mbsicmp. You should +// also cache the length of strings and check those first. Caching +// an uppercase version of a string can help too. +// Again, apply HashScramble to the result if using with something other +// than LKRhash. +// Note: this is not really adequate for MBCS strings. + +inline DWORD +HashStringNoCase( + const char* psz, + DWORD dwHash = 0) +{ + const unsigned char* upsz = (const unsigned char*) psz; + + for ( ; *upsz; ++upsz) + dwHash = HASH_MULTIPLY(dwHash) + + (*upsz & 0xDF); // strip off lowercase bit + + return dwHash; +} + +inline DWORD +HashStringNoCase( + __in_ecount(cch) + const char* psz, + SIZE_T cch, + DWORD dwHash) +{ + const unsigned char* upsz = (const unsigned char*) psz; + + for (SIZE_T Index = 0; + Index < cch; + ++Index, ++upsz) + { + dwHash = HASH_MULTIPLY(dwHash) + + (*upsz & 0xDF); // strip off lowercase bit + } + return dwHash; +} + + +// Unicode version of above + +inline DWORD +HashStringNoCase( + const wchar_t* pwsz, + DWORD dwHash = 0) +{ + for ( ; *pwsz; ++pwsz) + dwHash = HASH_MULTIPLY(dwHash) + (*pwsz & 0xFFDF); + + return dwHash; +} + +// Unicode version of above with length + +inline DWORD +HashStringNoCase( + __in_ecount(cch) + const wchar_t* pwsz, + SIZE_T cch, + DWORD dwHash) +{ + for (SIZE_T Index = 0; + Index < cch; + ++Index, ++pwsz) + { + dwHash = HASH_MULTIPLY(dwHash) + (*pwsz & 0xFFDF); + } + return dwHash; +} + + +// HashBlob returns the hash of a blob of arbitrary binary data. +// +// Warning: HashBlob is generally not the right way to hash a class object. +// Consider: +// class CFoo { +// public: +// char m_ch; +// double m_d; +// char* m_psz; +// }; +// +// inline DWORD Hash(const CFoo& rFoo) +// { return HashBlob(&rFoo, sizeof(CFoo)); } +// +// This is the wrong way to hash a CFoo for two reasons: (a) there will be +// a 7-byte gap between m_ch and m_d imposed by the alignment restrictions +// of doubles, which will be filled with random data (usually non-zero for +// stack variables), and (b) it hashes the address (rather than the +// contents) of the string m_psz. Similarly, +// +// bool operator==(const CFoo& rFoo1, const CFoo& rFoo2) +// { return memcmp(&rFoo1, &rFoo2, sizeof(CFoo)) == 0; } +// +// does the wrong thing. Much better to do this: +// +// DWORD Hash(const CFoo& rFoo) +// { +// return HashString(rFoo.m_psz, +// HASH_MULTIPLIER * Hash(rFoo.m_ch) +// + Hash(rFoo.m_d)); +// } +// +// Again, apply HashScramble if using with something other than LKRhash. + +inline DWORD +HashBlob( + const void* pv, + size_t cb, + DWORD dwHash = 0) +{ + const BYTE * pb = static_cast(pv); + + while (cb-- > 0) + dwHash = HASH_MULTIPLY(dwHash) + *pb++; + + return dwHash; +} + + + +// +// Overloaded hash functions for all the major builtin types. +// Again, apply HashScramble to result if using with something other than +// LKRhash. +// + +inline DWORD Hash(const char* psz) +{ return HashString(psz); } + +inline DWORD Hash(const unsigned char* pusz) +{ return HashString(reinterpret_cast(pusz)); } + +inline DWORD Hash(const signed char* pssz) +{ return HashString(reinterpret_cast(pssz)); } + +inline DWORD Hash(const wchar_t* pwsz) +{ return HashString(pwsz); } + +inline DWORD +Hash( + const GUID* pguid, + DWORD dwHash = 0) +{ + + return * reinterpret_cast(const_cast(pguid)) + dwHash; +} + +// Identity hash functions: scalar values map to themselves +inline DWORD Hash(char c) +{ return c; } + +inline DWORD Hash(unsigned char uc) +{ return uc; } + +inline DWORD Hash(signed char sc) +{ return sc; } + +inline DWORD Hash(short sh) +{ return sh; } + +inline DWORD Hash(unsigned short ush) +{ return ush; } + +inline DWORD Hash(int i) +{ return i; } + +inline DWORD Hash(unsigned int u) +{ return u; } + +inline DWORD Hash(long l) +{ return l; } + +inline DWORD Hash(unsigned long ul) +{ return ul; } + +inline DWORD Hash(float f) +{ + // be careful of rounding errors when computing keys + union { + float f; + DWORD dw; + } u; + u.f = f; + return u.dw; +} + +inline DWORD Hash(double dbl) +{ + // be careful of rounding errors when computing keys + union { + double dbl; + DWORD dw[2]; + } u; + u.dbl = dbl; + return u.dw[0] * HASH_MULTIPLIER + u.dw[1]; +} + +#endif // __HASHFN_H__ diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hashtable.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hashtable.h new file mode 100644 index 0000000000..9a299ca1af --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hashtable.h @@ -0,0 +1,666 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include +#include "rwlock.h" +#include "prime.h" + +template +class HASH_NODE +{ + template + friend class HASH_TABLE; + + HASH_NODE( + _Record * pRecord, + DWORD dwHash + ) : _pNext (NULL), + _pRecord (pRecord), + _dwHash (dwHash) + {} + + ~HASH_NODE() + { + _ASSERTE(_pRecord == NULL); + } + + private: + // Next node in the hash table look-aside + HASH_NODE<_Record> *_pNext; + + // actual record + _Record * _pRecord; + + // hash value + DWORD _dwHash; +}; + +template +class HASH_TABLE +{ +protected: + typedef BOOL + (PFN_DELETE_IF)( + _Record * pRecord, + PVOID pvContext + ); + + typedef VOID + (PFN_APPLY)( + _Record * pRecord, + PVOID pvContext + ); + +public: + HASH_TABLE( + VOID + ) + : _ppBuckets( NULL ), + _nBuckets( 0 ), + _nItems( 0 ) + { + } + + virtual + ~HASH_TABLE(); + + virtual + VOID + ReferenceRecord( + _Record * pRecord + ) = 0; + + virtual + VOID + DereferenceRecord( + _Record * pRecord + ) = 0; + + virtual + _Key + ExtractKey( + _Record * pRecord + ) = 0; + + virtual + DWORD + CalcKeyHash( + _Key key + ) = 0; + + virtual + BOOL + EqualKeys( + _Key key1, + _Key key2 + ) = 0; + + DWORD + Count( + VOID + ) const; + + bool + IsInitialized( + VOID + ) const; + + virtual + VOID + Clear(); + + HRESULT + Initialize( + DWORD nBucketSize + ); + + virtual + VOID + FindKey( + _Key key, + _Record ** ppRecord + ); + + virtual + HRESULT + InsertRecord( + _Record * pRecord + ); + + virtual + VOID + DeleteKey( + _Key key + ); + + virtual + VOID + DeleteIf( + PFN_DELETE_IF pfnDeleteIf, + PVOID pvContext + ); + + VOID + Apply( + PFN_APPLY pfnApply, + PVOID pvContext + ); + +private: + + __success(*ppNode != NULL && return != FALSE) + BOOL + FindNodeInternal( + _Key key, + DWORD dwHash, + __deref_out + HASH_NODE<_Record> ** ppNode, + __deref_opt_out + HASH_NODE<_Record> *** pppPreviousNodeNextPointer = NULL + ); + + VOID + DeleteNode( + HASH_NODE<_Record> * pNode + ) + { + if (pNode->_pRecord != NULL) + { + DereferenceRecord(pNode->_pRecord); + pNode->_pRecord = NULL; + } + + delete pNode; + } + + VOID + RehashTableIfNeeded( + VOID + ); + + HASH_NODE<_Record> ** _ppBuckets; + DWORD _nBuckets; + DWORD _nItems; + // + // Allow to use lock object in const methods. + // + mutable + CWSDRWLock _tableLock; +}; + +template +HRESULT +HASH_TABLE<_Record,_Key>::Initialize( + DWORD nBuckets +) +{ + HRESULT hr = S_OK; + + if ( nBuckets == 0 ) + { + hr = E_INVALIDARG; + goto Failed; + } + + if (nBuckets >= MAXDWORD/sizeof(HASH_NODE<_Record> *)) + { + hr = E_INVALIDARG; + goto Failed; + } + + _ASSERTE(_ppBuckets == NULL ); + if ( _ppBuckets != NULL ) + { + hr = E_INVALIDARG; + goto Failed; + } + + hr = _tableLock.Init(); + if ( FAILED( hr ) ) + { + goto Failed; + } + + _ppBuckets = (HASH_NODE<_Record> **)HeapAlloc( + GetProcessHeap(), + HEAP_ZERO_MEMORY, + nBuckets*sizeof(HASH_NODE<_Record> *)); + if (_ppBuckets == NULL) + { + hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); + goto Failed; + } + _nBuckets = nBuckets; + + return S_OK; + +Failed: + + if (_ppBuckets) + { + HeapFree(GetProcessHeap(), + 0, + _ppBuckets); + _ppBuckets = NULL; + } + + return hr; +} + + +template +HASH_TABLE<_Record,_Key>::~HASH_TABLE() +{ + if (_ppBuckets == NULL) + { + return; + } + + _ASSERTE(_nItems == 0); + + HeapFree(GetProcessHeap(), + 0, + _ppBuckets); + _ppBuckets = NULL; + _nBuckets = 0; +} + +template< class _Record, class _Key> +DWORD +HASH_TABLE<_Record,_Key>::Count() const +{ + return _nItems; +} + +template< class _Record, class _Key> +bool +HASH_TABLE<_Record,_Key>::IsInitialized( + VOID +) const +{ + return _ppBuckets != NULL; +} + + +template +VOID +HASH_TABLE<_Record,_Key>::Clear() +{ + HASH_NODE<_Record> *pCurrent; + HASH_NODE<_Record> *pNext; + + // This is here in the off cases where someone instantiates a hashtable + // and then does an automatic "clear" before its destruction WITHOUT + // ever initializing it. + if ( ! _tableLock.QueryInited() ) + { + return; + } + + _tableLock.ExclusiveAcquire(); + + for (DWORD i=0; i<_nBuckets; i++) + { + pCurrent = _ppBuckets[i]; + _ppBuckets[i] = NULL; + while (pCurrent != NULL) + { + pNext = pCurrent->_pNext; + DeleteNode(pCurrent); + pCurrent = pNext; + } + } + + _nItems = 0; + _tableLock.ExclusiveRelease(); +} + +template +__success(*ppNode != NULL && return != FALSE) +BOOL +HASH_TABLE<_Record,_Key>::FindNodeInternal( + _Key key, + DWORD dwHash, + __deref_out + HASH_NODE<_Record> ** ppNode, + __deref_opt_out + HASH_NODE<_Record> *** pppPreviousNodeNextPointer +) +/*++ + Return value indicates whether the item is found + key, dwHash - key and hash for the node to find + ppNode - on successful return, the node found, on failed return, the first + node with hash value greater than the node to be found + pppPreviousNodeNextPointer - the pointer to previous node's _pNext + + This routine may be called under either read or write lock +--*/ +{ + HASH_NODE<_Record> **ppPreviousNodeNextPointer; + HASH_NODE<_Record> *pNode; + BOOL fFound = FALSE; + + ppPreviousNodeNextPointer = _ppBuckets + (dwHash % _nBuckets); + pNode = *ppPreviousNodeNextPointer; + while (pNode != NULL) + { + if (pNode->_dwHash == dwHash) + { + if (EqualKeys(key, + ExtractKey(pNode->_pRecord))) + { + fFound = TRUE; + break; + } + } + else if (pNode->_dwHash > dwHash) + { + break; + } + + ppPreviousNodeNextPointer = &(pNode->_pNext); + pNode = *ppPreviousNodeNextPointer; + } + + __analysis_assume( (pNode == NULL && fFound == FALSE) || + (pNode != NULL && fFound == TRUE ) ); + *ppNode = pNode; + if (pppPreviousNodeNextPointer != NULL) + { + *pppPreviousNodeNextPointer = ppPreviousNodeNextPointer; + } + return fFound; +} + +template +VOID +HASH_TABLE<_Record,_Key>::FindKey( + _Key key, + _Record ** ppRecord +) +{ + HASH_NODE<_Record> *pNode; + + *ppRecord = NULL; + + DWORD dwHash = CalcKeyHash(key); + + _tableLock.SharedAcquire(); + + if (FindNodeInternal(key, dwHash, &pNode) && + pNode->_pRecord != NULL) + { + ReferenceRecord(pNode->_pRecord); + *ppRecord = pNode->_pRecord; + } + + _tableLock.SharedRelease(); +} + +template +HRESULT +HASH_TABLE<_Record,_Key>::InsertRecord( + _Record * pRecord +) +/*++ + This method inserts a node for this record and also empty nodes for paths + in the heirarchy leading upto this path + + The insert is done under only a read-lock - this is possible by keeping + the hashes in a bucket in increasing order and using interlocked operations + to actually insert the item in the hash-bucket lookaside list and the parent + children list + + Returns HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) if the record already exists. + Never leak this error to the end user because "*file* already exists" may be confusing. +--*/ +{ + BOOL fLocked = FALSE; + _Key key = ExtractKey(pRecord); + DWORD dwHash = CalcKeyHash(key); + HRESULT hr = S_OK; + HASH_NODE<_Record> * pNewNode; + HASH_NODE<_Record> * pNextNode; + HASH_NODE<_Record> ** ppPreviousNodeNextPointer; + + // + // Ownership of pRecord is not transferred to pNewNode yet, so remember + // to either set it to null before deleting pNewNode or add an extra + // reference later - this is to make sure we do not do an extra ref/deref + // which users may view as getting flushed out of the hash-table + // + pNewNode = new HASH_NODE<_Record>(pRecord, dwHash); + if (pNewNode == NULL) + { + hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); + goto Finished; + } + + _tableLock.SharedAcquire(); + fLocked = TRUE; + + do + { + // + // Find the right place to add this node + // + if (FindNodeInternal(key, dwHash, &pNextNode, &ppPreviousNodeNextPointer)) + { + // + // If node already there, return error + // + pNewNode->_pRecord = NULL; + DeleteNode(pNewNode); + + // + // We should never leak this error to the end user + // because "file already exists" may be confusing. + // + hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS); + goto Finished; + } + + // + // If another node got inserted in between, we will have to retry + // + pNewNode->_pNext = pNextNode; + } while (InterlockedCompareExchangePointer((PVOID *)ppPreviousNodeNextPointer, + pNewNode, + pNextNode) != pNextNode); + // pass ownership of pRecord now + if (pRecord != NULL) + { + ReferenceRecord(pRecord); + pRecord = NULL; + } + InterlockedIncrement((LONG *)&_nItems); + +Finished: + + if (fLocked) + { + _tableLock.SharedRelease(); + } + + if (SUCCEEDED(hr)) + { + RehashTableIfNeeded(); + } + + return hr; +} + +template +VOID +HASH_TABLE<_Record,_Key>::DeleteKey( + _Key key +) +{ + HASH_NODE<_Record> *pNode; + HASH_NODE<_Record> **ppPreviousNodeNextPointer; + + DWORD dwHash = CalcKeyHash(key); + + _tableLock.ExclusiveAcquire(); + + if (FindNodeInternal(key, dwHash, &pNode, &ppPreviousNodeNextPointer)) + { + *ppPreviousNodeNextPointer = pNode->_pNext; + DeleteNode(pNode); + _nItems--; + } + + _tableLock.ExclusiveRelease(); +} + +template +VOID +HASH_TABLE<_Record,_Key>::DeleteIf( + PFN_DELETE_IF pfnDeleteIf, + PVOID pvContext +) +{ + HASH_NODE<_Record> *pNode; + HASH_NODE<_Record> **ppPreviousNodeNextPointer; + + _tableLock.ExclusiveAcquire(); + + for (DWORD i=0; i<_nBuckets; i++) + { + ppPreviousNodeNextPointer = _ppBuckets + i; + pNode = *ppPreviousNodeNextPointer; + while (pNode != NULL) + { + // + // Non empty nodes deleted based on DeleteIf, empty nodes deleted + // if they have no children + // + if (pfnDeleteIf(pNode->_pRecord, pvContext)) + { + *ppPreviousNodeNextPointer = pNode->_pNext; + DeleteNode(pNode); + _nItems--; + } + else + { + ppPreviousNodeNextPointer = &pNode->_pNext; + } + + pNode = *ppPreviousNodeNextPointer; + } + } + + _tableLock.ExclusiveRelease(); +} + +template +VOID +HASH_TABLE<_Record,_Key>::Apply( + PFN_APPLY pfnApply, + PVOID pvContext +) +{ + HASH_NODE<_Record> *pNode; + + _tableLock.SharedAcquire(); + + for (DWORD i=0; i<_nBuckets; i++) + { + pNode = _ppBuckets[i]; + while (pNode != NULL) + { + if (pNode->_pRecord != NULL) + { + pfnApply(pNode->_pRecord, pvContext); + } + + pNode = pNode->_pNext; + } + } + + _tableLock.SharedRelease(); +} + +template +VOID +HASH_TABLE<_Record,_Key>::RehashTableIfNeeded( + VOID +) +{ + HASH_NODE<_Record> **ppBuckets; + DWORD nBuckets; + HASH_NODE<_Record> *pNode; + HASH_NODE<_Record> *pNextNode; + HASH_NODE<_Record> **ppNextPointer; + HASH_NODE<_Record> *pNewNextNode; + DWORD nNewBuckets; + + // + // If number of items has become too many, we will double the hash table + // size (we never reduce it however) + // + if (_nItems <= PRIME::GetPrime(2*_nBuckets)) + { + return; + } + + _tableLock.ExclusiveAcquire(); + + nNewBuckets = PRIME::GetPrime(2*_nBuckets); + + if (_nItems <= nNewBuckets) + { + goto Finished; + } + + nBuckets = nNewBuckets; + if (nBuckets >= 0xffffffff/sizeof(HASH_NODE<_Record> *)) + { + goto Finished; + } + ppBuckets = (HASH_NODE<_Record> **)HeapAlloc( + GetProcessHeap(), + HEAP_ZERO_MEMORY, + nBuckets*sizeof(HASH_NODE<_Record> *)); + if (ppBuckets == NULL) + { + goto Finished; + } + + // + // Take out nodes from the old hash table and insert in the new one, make + // sure to keep the hashes in increasing order + // + for (DWORD i=0; i<_nBuckets; i++) + { + pNode = _ppBuckets[i]; + while (pNode != NULL) + { + pNextNode = pNode->_pNext; + + ppNextPointer = ppBuckets + (pNode->_dwHash % nBuckets); + pNewNextNode = *ppNextPointer; + while (pNewNextNode != NULL && + pNewNextNode->_dwHash <= pNode->_dwHash) + { + ppNextPointer = &pNewNextNode->_pNext; + pNewNextNode = pNewNextNode->_pNext; + } + pNode->_pNext = pNewNextNode; + *ppNextPointer = pNode; + + pNode = pNextNode; + } + } + + HeapFree(GetProcessHeap(), 0, _ppBuckets); + _ppBuckets = ppBuckets; + _nBuckets = nBuckets; + ppBuckets = NULL; + +Finished: + + _tableLock.ExclusiveRelease(); +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/http_xp.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/http_xp.h new file mode 100644 index 0000000000..400d8ec855 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/http_xp.h @@ -0,0 +1,2797 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef __HTTP_H__ +#define __HTTP_H__ + +#pragma once + +#if _WIN32_WINNT >= 0x0501 + +// +// HTTPAPI is available on +// +// a) WinXP SP2 and higher +// b) Windows 2003 and higher +// c) Vista and higher. +// + + + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + + +// +// Flags for HttpInitialize() and HttpTerminate(). +// + +// +// HTTP_INITIALIZE_SERVER - Initializes the HTTP API layer and driver for +// applications using server APIs. +// +// HTTP_INITIALIZE_CONFIG - Initializes the HTTP API layer and driver for +// applications using HTTP configuration APIs. +// +// +// Notes - +// +// 1. These flags can be used in combination. +// +// 2. HttpTerminate() must be called for each call to HttpInitialize() made +// with each flag set when invoking HttpInitialize. For example, one +// could make two calls to HttpInitialize() setting HTTP_INITIALIZE_SERVER +// the first time and HTTP_INITIALIZE_CONFIG the second time. One call +// to HttpTerminate() with both flags set suffices to clean up both +// calls to HttpInitialize(). +// + +#define HTTP_INITIALIZE_SERVER 0x00000001 +#define HTTP_INITIALIZE_CONFIG 0x00000002 + +#if _WIN32_WINNT <= 0x0501 +#define BUILD_IIS_FOR_XP 1 +#endif + +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + +// +// Following section defines the properties supported by the +// server side HTTP API. +// + +typedef enum _HTTP_SERVER_PROPERTY +{ + // + // Used for enabling server side authentication. + // + + HttpServerAuthenticationProperty, + + // + // Used for enabling logging. + // + + HttpServerLoggingProperty, + + // + // Used for setting QoS properties. + // + + HttpServerQosProperty, + + // + // Used for configuring timeouts. + // + + HttpServerTimeoutsProperty, + + // + // Used for limiting request queue lengths. + // + + HttpServerQueueLengthProperty, + + // + // Used for manipulating the state. + // + + HttpServerStateProperty, + + // + // Used for modifying the verbosity level of 503 type responses + // generated by server side API. + // + + HttpServer503VerbosityProperty, + + // + // Used for manipulating Url Group to Request Queue association. + // + + HttpServerBindingProperty, + + // + // Extended authentication property. + // + + HttpServerExtendedAuthenticationProperty, + + // + // Listening endpoint property. + // + + HttpServerListenEndpointProperty + + // + // Authentication channel binding property + // + +#endif +#if _WIN32_WINNT >= _WIN32_WINNT_WIN7 || BUILD_IIS_FOR_XP + + ,HttpServerChannelBindProperty + + // + // IP Protection level policy for a Url Group. + // + + ,HttpServerProtectionLevelProperty +#endif +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + + +} HTTP_SERVER_PROPERTY, *PHTTP_SERVER_PROPERTY; + + +#define HTTP_MAX_SERVER_QUEUE_LENGTH 0x7FFFFFFF +#define HTTP_MIN_SERVER_QUEUE_LENGTH 1 + +// +// Generic property flags. Each structure defining a property info typically +// contain an element of this type. +// + +typedef struct _HTTP_PROPERTY_FLAGS +{ + ULONG Present:1; + +} HTTP_PROPERTY_FLAGS, *PHTTP_PROPERTY_FLAGS; + +// +// Enabled state. +// + +typedef enum _HTTP_ENABLED_STATE +{ + HttpEnabledStateActive, + HttpEnabledStateInactive, + +} HTTP_ENABLED_STATE, *PHTTP_ENABLED_STATE; + + +typedef struct _HTTP_STATE_INFO +{ + HTTP_PROPERTY_FLAGS Flags; + HTTP_ENABLED_STATE State; + +} HTTP_STATE_INFO, *PHTTP_STATE_INFO; + +// +// Defines the verbosity level for a request queue which will be used +// when sending "503 - Service Unavailable" type error responses. Note that +// this setting only affects the error responses generated internally +// by HTTPAPI. +// + +typedef enum _HTTP_503_RESPONSE_VERBOSITY +{ + // + // Instead of sending a 503 response, the connection will be reset. + // This is the default behavior. + // + Http503ResponseVerbosityBasic, + + // + // Will send a 503 w/ a generic reason phrase. + // + Http503ResponseVerbosityLimited, + + // + // Will send a 503 w/ a detailed reason phrase. + // + Http503ResponseVerbosityFull + +} HTTP_503_RESPONSE_VERBOSITY, *PHTTP_503_RESPONSE_VERBOSITY; + +// +// Network QoS related. +// + +typedef enum _HTTP_QOS_SETTING_TYPE +{ + HttpQosSettingTypeBandwidth, + HttpQosSettingTypeConnectionLimit, + HttpQosSettingTypeFlowRate + +} HTTP_QOS_SETTING_TYPE, *PHTTP_QOS_SETTING_TYPE; + +typedef struct _HTTP_QOS_SETTING_INFO +{ + HTTP_QOS_SETTING_TYPE QosType; + PVOID QosSetting; +} HTTP_QOS_SETTING_INFO, *PHTTP_QOS_SETTING_INFO; + +typedef struct _HTTP_CONNECTION_LIMIT_INFO +{ + HTTP_PROPERTY_FLAGS Flags; + ULONG MaxConnections; + +} HTTP_CONNECTION_LIMIT_INFO, *PHTTP_CONNECTION_LIMIT_INFO; + +typedef struct _HTTP_BANDWIDTH_LIMIT_INFO +{ + HTTP_PROPERTY_FLAGS Flags; + ULONG MaxBandwidth; + +} HTTP_BANDWIDTH_LIMIT_INFO, *PHTTP_BANDWIDTH_LIMIT_INFO; + +typedef struct _HTTP_FLOWRATE_INFO +{ + HTTP_PROPERTY_FLAGS Flags; + ULONG MaxBandwidth; + ULONG MaxPeakBandwidth; + ULONG BurstSize; + +} HTTP_FLOWRATE_INFO, *PHTTP_FLOWRATE_INFO; + +// +// Bandwidth throttling limit can not be set lower than the following +// number. The value is in bytes/sec. +// + +#define HTTP_MIN_ALLOWED_BANDWIDTH_THROTTLING_RATE ((ULONG)1024) + +// +// Distinguished value for bandwidth, connection limits and logging rollover +// size indicating "no limit". +// + +#define HTTP_LIMIT_INFINITE ((ULONG)-1) + +// +// Timeout information. +// + +// +// For manipulating global timeout settings. +// These timers run when connection does not belong to any application. +// Value zero is not allowed for driver wide timeout settings. +// + +typedef enum _HTTP_SERVICE_CONFIG_TIMEOUT_KEY +{ + IdleConnectionTimeout = 0, + HeaderWaitTimeout + +} HTTP_SERVICE_CONFIG_TIMEOUT_KEY, *PHTTP_SERVICE_CONFIG_TIMEOUT_KEY; + +typedef USHORT HTTP_SERVICE_CONFIG_TIMEOUT_PARAM, + *PHTTP_SERVICE_CONFIG_TIMEOUT_PARAM; + +// +// To set a timeout value use the set structure. To query/delete use the key +// directly. When you query a timeout value the output buffer must be exactly +// the sizeof param. +// + +typedef struct _HTTP_SERVICE_CONFIG_TIMEOUT_SET +{ + HTTP_SERVICE_CONFIG_TIMEOUT_KEY KeyDesc; + HTTP_SERVICE_CONFIG_TIMEOUT_PARAM ParamDesc; + +} HTTP_SERVICE_CONFIG_TIMEOUT_SET, *PHTTP_SERVICE_CONFIG_TIMEOUT_SET; + +// +// For manipulating application specific timeout settings. +// These timers run when there's a request being processed on a connection +// and HTTPAPI has already associated the request with an application. +// Setting a timeout value to zero will cause HTTPAPI to revert to default. +// + +typedef struct _HTTP_TIMEOUT_LIMIT_INFO +{ + HTTP_PROPERTY_FLAGS Flags; + + // + // Timeouts configured in seconds. + // + + USHORT EntityBody; + USHORT DrainEntityBody; + USHORT RequestQueue; + + // + // Following two timeouts are only enforced after first request on + // connection is routed to the application. These will not manipulate + // the driver wide timeouts. + // + + USHORT IdleConnection; + USHORT HeaderWait; + + // + // Timeouts configured in bytes/second. + // This timer can be turned off by setting it to MAXULONG. + // + + ULONG MinSendRate; + +} HTTP_TIMEOUT_LIMIT_INFO, *PHTTP_TIMEOUT_LIMIT_INFO; + +// +// Controls whether IP-based URLs should listen on the specific IP or wildcard. +// + +typedef struct _HTTP_LISTEN_ENDPOINT_INFO +{ + HTTP_PROPERTY_FLAGS Flags; + + BOOLEAN EnableSharing; + +} HTTP_LISTEN_ENDPOINT_INFO, *PHTTP_LISTEN_ENDPOINT_INFO; + + +typedef struct _HTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS +{ + USHORT DomainNameLength; + PWSTR DomainName; + USHORT RealmLength; + PWSTR Realm; +} HTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS, + *PHTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS; + +typedef struct _HTTP_SERVER_AUTHENTICATION_BASIC_PARAMS +{ + USHORT RealmLength; + PWSTR Realm; +} HTTP_SERVER_AUTHENTICATION_BASIC_PARAMS, + *PHTTP_SERVER_AUTHENTICATION_BASIC_PARAMS; + +// +// Definitions used for setting server side authentication property. +// + +#define HTTP_AUTH_ENABLE_BASIC (0x00000001) +#define HTTP_AUTH_ENABLE_DIGEST (0x00000002) +#define HTTP_AUTH_ENABLE_NTLM (0x00000004) +#define HTTP_AUTH_ENABLE_NEGOTIATE (0x00000008) +#define HTTP_AUTH_ENABLE_KERBEROS (0x00000010) + +#define HTTP_AUTH_ENABLE_ALL \ + (HTTP_AUTH_ENABLE_BASIC |\ + HTTP_AUTH_ENABLE_DIGEST |\ + HTTP_AUTH_ENABLE_NTLM |\ + HTTP_AUTH_ENABLE_NEGOTIATE |\ + HTTP_AUTH_ENABLE_KERBEROS) + + +C_ASSERT(HTTP_AUTH_ENABLE_NEGOTIATE > HTTP_AUTH_ENABLE_NTLM); +C_ASSERT(HTTP_AUTH_ENABLE_NTLM > HTTP_AUTH_ENABLE_DIGEST); +C_ASSERT(HTTP_AUTH_ENABLE_DIGEST > HTTP_AUTH_ENABLE_BASIC); + +#define HTTP_AUTH_EX_FLAG_ENABLE_KERBEROS_CREDENTIAL_CACHING (0x01) +#define HTTP_AUTH_EX_FLAG_CAPTURE_CREDENTIAL (0x02) + +typedef struct _HTTP_SERVER_AUTHENTICATION_INFO +{ + HTTP_PROPERTY_FLAGS Flags; + + ULONG AuthSchemes; + + BOOLEAN ReceiveMutualAuth; + BOOLEAN ReceiveContextHandle; + BOOLEAN DisableNTLMCredentialCaching; + + UCHAR ExFlags; + + HTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS DigestParams; + HTTP_SERVER_AUTHENTICATION_BASIC_PARAMS BasicParams; + +} HTTP_SERVER_AUTHENTICATION_INFO, *PHTTP_SERVER_AUTHENTICATION_INFO; + +#if _WIN32_WINNT >= _WIN32_WINNT_WIN7 || BUILD_IIS_FOR_XP + +// +// Definitions for setting authentication channel binding properties +// + +typedef enum _HTTP_SERVICE_BINDING_TYPE +{ + HttpServiceBindingTypeNone = 0, + HttpServiceBindingTypeW, + HttpServiceBindingTypeA + +} HTTP_SERVICE_BINDING_TYPE; + +typedef struct _HTTP_SERVICE_BINDING_BASE +{ + HTTP_SERVICE_BINDING_TYPE Type; + +} HTTP_SERVICE_BINDING_BASE, *PHTTP_SERVICE_BINDING_BASE; + +typedef struct _HTTP_SERVICE_BINDING_A +{ + HTTP_SERVICE_BINDING_BASE Base; + PCHAR Buffer; + ULONG BufferSize; + +} HTTP_SERVICE_BINDING_A, *PHTTP_SERVICE_BINDING_A; + +typedef struct _HTTP_SERVICE_BINDING_W +{ + HTTP_SERVICE_BINDING_BASE Base; + PWCHAR Buffer; + ULONG BufferSize; + +} HTTP_SERVICE_BINDING_W, *PHTTP_SERVICE_BINDING_W; + +typedef enum _HTTP_AUTHENTICATION_HARDENING_LEVELS +{ + HttpAuthenticationHardeningLegacy = 0, + HttpAuthenticationHardeningMedium, + HttpAuthenticationHardeningStrict + +} HTTP_AUTHENTICATION_HARDENING_LEVELS; + +// +// Channel binding token verification flags. +// + +#define HTTP_CHANNEL_BIND_PROXY 0x1 +#define HTTP_CHANNEL_BIND_PROXY_COHOSTING 0x20 + +// +// Service bind verification flags +// + +#define HTTP_CHANNEL_BIND_NO_SERVICE_NAME_CHECK 0x2 +#define HTTP_CHANNEL_BIND_DOTLESS_SERVICE 0x4 + +// +// Flags triggering channel bind parameters retrieval +// + +#define HTTP_CHANNEL_BIND_SECURE_CHANNEL_TOKEN 0x8 +#define HTTP_CHANNEL_BIND_CLIENT_SERVICE 0x10 + +// +// All valid flags (mask for internal checks) +// + +typedef struct _HTTP_CHANNEL_BIND_INFO +{ + HTTP_AUTHENTICATION_HARDENING_LEVELS Hardening; + ULONG Flags; + PHTTP_SERVICE_BINDING_BASE * ServiceNames; + ULONG NumberOfServiceNames; + +} HTTP_CHANNEL_BIND_INFO, *PHTTP_CHANNEL_BIND_INFO; + +typedef struct _HTTP_REQUEST_CHANNEL_BIND_STATUS +{ + PHTTP_SERVICE_BINDING_BASE ServiceName; + PUCHAR ChannelToken; + ULONG ChannelTokenSize; + ULONG Flags; + +} HTTP_REQUEST_CHANNEL_BIND_STATUS, *PHTTP_REQUEST_CHANNEL_BIND_STATUS; + +#endif + +// +// Definitions used for setting logging property. +// + +// +// The known log fields recognized/supported by HTTPAPI. Following fields +// are used for W3C logging. Subset of them are also used for error +// logging. +// + +#define HTTP_LOG_FIELD_DATE 0x00000001 +#define HTTP_LOG_FIELD_TIME 0x00000002 +#define HTTP_LOG_FIELD_CLIENT_IP 0x00000004 +#define HTTP_LOG_FIELD_USER_NAME 0x00000008 +#define HTTP_LOG_FIELD_SITE_NAME 0x00000010 +#define HTTP_LOG_FIELD_COMPUTER_NAME 0x00000020 +#define HTTP_LOG_FIELD_SERVER_IP 0x00000040 +#define HTTP_LOG_FIELD_METHOD 0x00000080 +#define HTTP_LOG_FIELD_URI_STEM 0x00000100 +#define HTTP_LOG_FIELD_URI_QUERY 0x00000200 +#define HTTP_LOG_FIELD_STATUS 0x00000400 +#define HTTP_LOG_FIELD_WIN32_STATUS 0x00000800 +#define HTTP_LOG_FIELD_BYTES_SENT 0x00001000 +#define HTTP_LOG_FIELD_BYTES_RECV 0x00002000 +#define HTTP_LOG_FIELD_TIME_TAKEN 0x00004000 +#define HTTP_LOG_FIELD_SERVER_PORT 0x00008000 +#define HTTP_LOG_FIELD_USER_AGENT 0x00010000 +#define HTTP_LOG_FIELD_COOKIE 0x00020000 +#define HTTP_LOG_FIELD_REFERER 0x00040000 +#define HTTP_LOG_FIELD_VERSION 0x00080000 +#define HTTP_LOG_FIELD_HOST 0x00100000 +#define HTTP_LOG_FIELD_SUB_STATUS 0x00200000 + +// +// Fields that are used only for error logging. +// + +#define HTTP_LOG_FIELD_CLIENT_PORT 0x00400000 +#define HTTP_LOG_FIELD_URI 0x00800000 +#define HTTP_LOG_FIELD_SITE_ID 0x01000000 +#define HTTP_LOG_FIELD_REASON 0x02000000 +#define HTTP_LOG_FIELD_QUEUE_NAME 0x04000000 + +// +// Defines the logging type. +// + +typedef enum _HTTP_LOGGING_TYPE +{ + HttpLoggingTypeW3C, + HttpLoggingTypeIIS, + HttpLoggingTypeNCSA, + HttpLoggingTypeRaw + ,HttpLoggingTypeMaximum + +} HTTP_LOGGING_TYPE, *PHTTP_LOGGING_TYPE; + +// +// Defines the rollover type for log files. +// + +typedef enum _HTTP_LOGGING_ROLLOVER_TYPE +{ + HttpLoggingRolloverSize, + HttpLoggingRolloverDaily, + HttpLoggingRolloverWeekly, + HttpLoggingRolloverMonthly, + HttpLoggingRolloverHourly + +} HTTP_LOGGING_ROLLOVER_TYPE, *PHTTP_LOGGING_ROLLOVER_TYPE; + +// +// Log file rollover size can not be set lower than the following +// limit. The value is in bytes. +// + +#define HTTP_MIN_ALLOWED_LOG_FILE_ROLLOVER_SIZE ((ULONG)(1 * 1024 * 1024)) + +// +// Logging option flags. When used in the logging configuration alters +// some default logging behaviour. +// +// HTTP_LOGGING_FLAG_LOCAL_TIME_ROLLOVER - This flag is used to change +// the log file rollover to happen by local time based. By default +// log file rollovers happen by GMT time. +// +// HTTP_LOGGING_FLAG_USE_UTF8_CONVERSION - When set the unicode fields +// will be converted to UTF8 multibytes when writting to the log +// files. When this flag is not present, the local code page +// conversion happens. +// +// HTTP_LOGGING_FLAG_LOG_ERRORS_ONLY - +// HTTP_LOGGING_FLAG_LOG_SUCCESS_ONLY - These two flags are used to +// to do selective logging. If neither of them are present both +// types of requests will be logged. Only one these flags can be +// set at a time. They are mutually exclusive. +// + +#define HTTP_LOGGING_FLAG_LOCAL_TIME_ROLLOVER (0x00000001) +#define HTTP_LOGGING_FLAG_USE_UTF8_CONVERSION (0x00000002) +#define HTTP_LOGGING_FLAG_LOG_ERRORS_ONLY (0x00000004) +#define HTTP_LOGGING_FLAG_LOG_SUCCESS_ONLY (0x00000008) + +// +// Configuration structure used for setting the logging property. +// + +typedef struct _HTTP_LOGGING_INFO +{ + // + // Specifies whether this property exists or not. + // + + HTTP_PROPERTY_FLAGS Flags; + + // + // Optional logging flags. + // + + ULONG LoggingFlags; + + // + // Optional informatonal software directive string for W3C type logging. Not + // used for other types of logging. If nothing is provided here HTTPAPI will + // log a default string. Any arbitrary string could be used here to identify + // the application. Length cannot be greater than MAX_PATH. Lenght is in + // bytes. + // + + PCWSTR SoftwareName; + USHORT SoftwareNameLength; + + // + // Log file directory must be a fully qualified path. + // Length must be in number of bytes. + // + + USHORT DirectoryNameLength; + PCWSTR DirectoryName; + + // + // Specifies the format for the log files. + // + + HTTP_LOGGING_TYPE Format; + + // + // Bitmask value indicates which fields to be logged + // if the log format is set to W3C. This must be the 'bitwise or' + // of the HTTP_LOG_FIELD_... values. + // + + ULONG Fields; + + // + // Following fields are reserved they must be NULL and zero.. + // + + PVOID pExtFields; + USHORT NumOfExtFields; + + // + // Reserved must be zero. + // + + USHORT MaxRecordSize; + + // + // Defines the rollover type for the log files. + // + + HTTP_LOGGING_ROLLOVER_TYPE RolloverType; + + // + // Indicates the maximum size (in bytes) after which + // the log files should be rolled over. A value of -1 + // (HTTP_LIMIT_INFINITE) indicates an unlimited size. + // This value is discarded if rollover type is not set to + // HttpLoggingRolloverSize. + // + + ULONG RolloverSize; + + // + // Specifies the security descriptor to be applied to + // the log files and the sub-directories. If null we will + // inherit the system default. This security descriptor must + // be self-relative. + // + + PSECURITY_DESCRIPTOR pSecurityDescriptor; + +} HTTP_LOGGING_INFO, *PHTTP_LOGGING_INFO; + +// +// Binding information. +// + +typedef struct _HTTP_BINDING_INFO +{ + HTTP_PROPERTY_FLAGS Flags; + HANDLE RequestQueueHandle; + +} HTTP_BINDING_INFO, *PHTTP_BINDING_INFO; + +#endif +#if _WIN32_WINNT >= _WIN32_WINNT_WIN7 || BUILD_IIS_FOR_XP + +// +// Defines the protection level types for UrlGroups. +// + +typedef enum _HTTP_PROTECTION_LEVEL_TYPE +{ + // + // This option will allow edge (NAT) traversed traffic, i.e. Teredo + // for the UrlGroup, unless there is an admin rule that overwrites the + // application's intend. + // + + HttpProtectionLevelUnrestricted, + + // + // This setting will ensure that edge (NAT) traversed traffic + // will not be allowed. + // + + HttpProtectionLevelEdgeRestricted, + + // + // Below type is not supported by HTTP API. + // + + HttpProtectionLevelRestricted + + +} HTTP_PROTECTION_LEVEL_TYPE, *PHTTP_PROTECTION_LEVEL_TYPE; + +// +// Controls whether the associated UrlGroup Namespace should receive +// edge traversed traffic. By default this parameter is unspecified. +// + +typedef struct _HTTP_PROTECTION_LEVEL_INFO +{ + HTTP_PROPERTY_FLAGS Flags; + HTTP_PROTECTION_LEVEL_TYPE Level; + +} HTTP_PROTECTION_LEVEL_INFO, *PHTTP_PROTECTION_LEVEL_INFO; + +#endif +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + + +// +// Definitions for request queue manipulation. +// +// These flags are used with HttpCreateRequestQueue() API. +// +// HTTP_CREATE_REQUEST_QUEUE_FLAG_OPEN_EXISTING - To open an existing request +// queue. The request queue name must be supplied. +// +// HTTP_CREATE_REQUEST_QUEUE_FLAG_CONTROLLER - Creates the request queue and +// marks that the caller process is not willing to do send/receive (HTTP I/O)on +// the handle directly. +// + +#define HTTP_CREATE_REQUEST_QUEUE_FLAG_OPEN_EXISTING (0x00000001) +#define HTTP_CREATE_REQUEST_QUEUE_FLAG_CONTROLLER (0x00000002) + +#endif // _WIN32_WINNT >= 0x0600 + +// +// Flags for HttpReceiveHttpRequest(). +// +// HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY - Specifies that the caller would like +// any available entity body to be copied along with the protocol headers. +// +// HTTP_RECEIVE_REQUEST_FLAG_FLUSH_BODY - Specifies that the caller would like +// all of the entity bodies to be copied along with the protocol headers. +// + +#define HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY 0x00000001 +#define HTTP_RECEIVE_REQUEST_FLAG_FLUSH_BODY 0x00000002 + + +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + +// +// Flags for HttpReceiveRequestEntityBody(). +// +// HTTP_RECEIVE_REQUEST_ENTITY_BODY_FLAG_FILL_BUFFER - Specifies that the +// caller would like the buffer to get filled up with entity bodies unless +// there are no more entity bodies to be copied. +// + +#define HTTP_RECEIVE_REQUEST_ENTITY_BODY_FLAG_FILL_BUFFER 0x00000001 + +#endif // _WIN32_WINNT >= 0x0600 + + +// +// Flags for HttpSendHttpResponse() and HttpSendResponseEntityBody(). +// +// HTTP_SEND_RESPONSE_FLAG_DISCONNECT - Specifies that the network connection +// should be disconnected immediately after sending the response, overriding +// the HTTP protocol's persistent connection features, such as +// "Connection: keep-alive". +// +// HTTP_SEND_RESPONSE_FLAG_MORE_DATA - Specifies that additional entity body +// data will be sent by the caller. +// +// HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA - Specifies that a caller wants the +// response to complete as soon as possible at the cost of buffering partial +// or the entire response. +// +// HTTP_SEND_RESPONSE_FLAG_ENABLE_NAGLING - Specifies that a caller wants to +// enable the TCP nagling algorithm for this particular send. +// +// HTTP_SEND_RESPONSE_FLAG_PROCESS_RANGES - Specifies that for a range request +// a full response content is passed and a caller wants HTTP API to process +// ranges properly. +// + +#define HTTP_SEND_RESPONSE_FLAG_DISCONNECT 0x00000001 +#define HTTP_SEND_RESPONSE_FLAG_MORE_DATA 0x00000002 +#define HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA 0x00000004 +#define HTTP_SEND_RESPONSE_FLAG_ENABLE_NAGLING 0x00000008 +#define HTTP_SEND_RESPONSE_FLAG_PROCESS_RANGES 0x00000020 + + +// +// Flags for HttpFlushResponseCache(). +// +// HTTP_FLUSH_RESPONSE_FLAG_RECURSIVE - Flushes the specified URL and all +// hierarchally-related sub-URLs from the response or fragment cache. +// + +#define HTTP_FLUSH_RESPONSE_FLAG_RECURSIVE 0x00000001 + + +// +// Opaque identifiers for various HTTPAPI objects. +// + +typedef ULONGLONG HTTP_OPAQUE_ID, *PHTTP_OPAQUE_ID; + +typedef HTTP_OPAQUE_ID HTTP_REQUEST_ID, *PHTTP_REQUEST_ID; +typedef HTTP_OPAQUE_ID HTTP_CONNECTION_ID, *PHTTP_CONNECTION_ID; +typedef HTTP_OPAQUE_ID HTTP_RAW_CONNECTION_ID, *PHTTP_RAW_CONNECTION_ID; + +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + +typedef HTTP_OPAQUE_ID HTTP_URL_GROUP_ID, *PHTTP_URL_GROUP_ID; +typedef HTTP_OPAQUE_ID HTTP_SERVER_SESSION_ID, *PHTTP_SERVER_SESSION_ID; + +#endif // _WIN32_WINNT >= 0x0600 + +// +// Macros for opaque identifier manipulations. +// + +#define HTTP_NULL_ID (0ui64) +#define HTTP_IS_NULL_ID(pid) (HTTP_NULL_ID == *(pid)) +#define HTTP_SET_NULL_ID(pid) (*(pid) = HTTP_NULL_ID) + +// +// This structure defines a file byte range. +// +// If the Length field is HTTP_BYTE_RANGE_TO_EOF then the remainder of the +// file (everything after StartingOffset) is sent. +// + +#define HTTP_BYTE_RANGE_TO_EOF ((ULONGLONG)-1) + +typedef struct _HTTP_BYTE_RANGE +{ + ULARGE_INTEGER StartingOffset; + ULARGE_INTEGER Length; + +} HTTP_BYTE_RANGE, *PHTTP_BYTE_RANGE; + +// +// The type for HTTP protocol version numbers. +// + +typedef struct _HTTP_VERSION +{ + USHORT MajorVersion; + USHORT MinorVersion; + +} HTTP_VERSION, *PHTTP_VERSION; + +// +// Some useful macros for HTTP protocol version manipulation. +// + +#define HTTP_VERSION_UNKNOWN { 0, 0 } +#define HTTP_VERSION_0_9 { 0, 9 } +#define HTTP_VERSION_1_0 { 1, 0 } +#define HTTP_VERSION_1_1 { 1, 1 } + +#define HTTP_SET_VERSION(version, major, minor) \ +do { \ + (version).MajorVersion = (major); \ + (version).MinorVersion = (minor); \ +} while (0, 0) + +#define HTTP_EQUAL_VERSION(version, major, minor) \ + ((version).MajorVersion == (major) && \ + (version).MinorVersion == (minor)) + +#define HTTP_GREATER_VERSION(version, major, minor) \ + ((version).MajorVersion > (major) || \ + ((version).MajorVersion == (major) && \ + (version).MinorVersion > (minor))) + +#define HTTP_LESS_VERSION(version, major, minor) \ + ((version).MajorVersion < (major) || \ + ((version).MajorVersion == (major) && \ + (version).MinorVersion < (minor))) + +#define HTTP_NOT_EQUAL_VERSION(version, major, minor) \ + (!HTTP_EQUAL_VERSION(version, major, minor)) + +#define HTTP_GREATER_EQUAL_VERSION(version, major, minor) \ + (!HTTP_LESS_VERSION(version, major, minor)) + +#define HTTP_LESS_EQUAL_VERSION(version, major, minor) \ + (!HTTP_GREATER_VERSION(version, major, minor)) + +// +// The enum type for HTTP verbs. +// + +typedef enum _HTTP_VERB +{ + HttpVerbUnparsed, + HttpVerbUnknown, + HttpVerbInvalid, + HttpVerbOPTIONS, + HttpVerbGET, + HttpVerbHEAD, + HttpVerbPOST, + HttpVerbPUT, + HttpVerbDELETE, + HttpVerbTRACE, + HttpVerbCONNECT, + HttpVerbTRACK, // used by Microsoft Cluster Server for a non-logged trace + HttpVerbMOVE, + HttpVerbCOPY, + HttpVerbPROPFIND, + HttpVerbPROPPATCH, + HttpVerbMKCOL, + HttpVerbLOCK, + HttpVerbUNLOCK, + HttpVerbSEARCH, + + HttpVerbMaximum + +} HTTP_VERB, *PHTTP_VERB; + +// +// Symbols for all HTTP/1.1 headers and other tokens. Notice request + +// response values overlap. Make sure you know which type of header array +// you are indexing. +// +// These values are used as offsets into arrays and as token values in +// HTTP_KNOWN_HEADER arrays in HTTP_REQUEST_HEADERS and HTTP_RESPONSE_HEADERS. +// +// See RFC 2616, HTTP/1.1, for further explanation of most of these headers. +// + +typedef enum _HTTP_HEADER_ID +{ + HttpHeaderCacheControl = 0, // general-header [section 4.5] + HttpHeaderConnection = 1, // general-header [section 4.5] + HttpHeaderDate = 2, // general-header [section 4.5] + HttpHeaderKeepAlive = 3, // general-header [not in rfc] + HttpHeaderPragma = 4, // general-header [section 4.5] + HttpHeaderTrailer = 5, // general-header [section 4.5] + HttpHeaderTransferEncoding = 6, // general-header [section 4.5] + HttpHeaderUpgrade = 7, // general-header [section 4.5] + HttpHeaderVia = 8, // general-header [section 4.5] + HttpHeaderWarning = 9, // general-header [section 4.5] + + HttpHeaderAllow = 10, // entity-header [section 7.1] + HttpHeaderContentLength = 11, // entity-header [section 7.1] + HttpHeaderContentType = 12, // entity-header [section 7.1] + HttpHeaderContentEncoding = 13, // entity-header [section 7.1] + HttpHeaderContentLanguage = 14, // entity-header [section 7.1] + HttpHeaderContentLocation = 15, // entity-header [section 7.1] + HttpHeaderContentMd5 = 16, // entity-header [section 7.1] + HttpHeaderContentRange = 17, // entity-header [section 7.1] + HttpHeaderExpires = 18, // entity-header [section 7.1] + HttpHeaderLastModified = 19, // entity-header [section 7.1] + + + // Request Headers + + HttpHeaderAccept = 20, // request-header [section 5.3] + HttpHeaderAcceptCharset = 21, // request-header [section 5.3] + HttpHeaderAcceptEncoding = 22, // request-header [section 5.3] + HttpHeaderAcceptLanguage = 23, // request-header [section 5.3] + HttpHeaderAuthorization = 24, // request-header [section 5.3] + HttpHeaderCookie = 25, // request-header [not in rfc] + HttpHeaderExpect = 26, // request-header [section 5.3] + HttpHeaderFrom = 27, // request-header [section 5.3] + HttpHeaderHost = 28, // request-header [section 5.3] + HttpHeaderIfMatch = 29, // request-header [section 5.3] + + HttpHeaderIfModifiedSince = 30, // request-header [section 5.3] + HttpHeaderIfNoneMatch = 31, // request-header [section 5.3] + HttpHeaderIfRange = 32, // request-header [section 5.3] + HttpHeaderIfUnmodifiedSince = 33, // request-header [section 5.3] + HttpHeaderMaxForwards = 34, // request-header [section 5.3] + HttpHeaderProxyAuthorization = 35, // request-header [section 5.3] + HttpHeaderReferer = 36, // request-header [section 5.3] + HttpHeaderRange = 37, // request-header [section 5.3] + HttpHeaderTe = 38, // request-header [section 5.3] + HttpHeaderTranslate = 39, // request-header [webDAV, not in rfc 2518] + + HttpHeaderUserAgent = 40, // request-header [section 5.3] + + HttpHeaderRequestMaximum = 41, + + + // Response Headers + + HttpHeaderAcceptRanges = 20, // response-header [section 6.2] + HttpHeaderAge = 21, // response-header [section 6.2] + HttpHeaderEtag = 22, // response-header [section 6.2] + HttpHeaderLocation = 23, // response-header [section 6.2] + HttpHeaderProxyAuthenticate = 24, // response-header [section 6.2] + HttpHeaderRetryAfter = 25, // response-header [section 6.2] + HttpHeaderServer = 26, // response-header [section 6.2] + HttpHeaderSetCookie = 27, // response-header [not in rfc] + HttpHeaderVary = 28, // response-header [section 6.2] + HttpHeaderWwwAuthenticate = 29, // response-header [section 6.2] + + HttpHeaderResponseMaximum = 30, + + + HttpHeaderMaximum = 41 + +} HTTP_HEADER_ID, *PHTTP_HEADER_ID; + + +// +// Structure defining format of a known HTTP header. +// Name is from HTTP_HEADER_ID. +// + +typedef struct _HTTP_KNOWN_HEADER +{ + USHORT RawValueLength; // in bytes not including the NUL + PCSTR pRawValue; + +} HTTP_KNOWN_HEADER, *PHTTP_KNOWN_HEADER; + +// +// Structure defining format of an unknown header. +// + +typedef struct _HTTP_UNKNOWN_HEADER +{ + USHORT NameLength; // in bytes not including the NUL + USHORT RawValueLength; // in bytes not including the NUL + PCSTR pName; // The header name (minus the ':' character) + PCSTR pRawValue; // The header value + +} HTTP_UNKNOWN_HEADER, *PHTTP_UNKNOWN_HEADER; + +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + +// +// Log fields data structure is used for logging a request. This structure must +// be provided along with an HttpSendHttpResponse or HttpSendResponseEntityBody +// call that concludes the send. +// + +// Base structure is for future versioning. + +typedef enum _HTTP_LOG_DATA_TYPE +{ + HttpLogDataTypeFields = 0 + +} HTTP_LOG_DATA_TYPE, *PHTTP_LOG_DATA_TYPE; + +// should we DECLSPEC_ALIGN(4 or 8) == DECLSPEC_POINTERALIGN? +typedef struct _HTTP_LOG_DATA +{ + HTTP_LOG_DATA_TYPE Type; + +} HTTP_LOG_DATA, *PHTTP_LOG_DATA; + +// Current log fields data structure for of type HttpLogDataTypeFields. + +typedef struct _HTTP_LOG_FIELDS_DATA +{ + HTTP_LOG_DATA Base; + + USHORT UserNameLength; + USHORT UriStemLength; + USHORT ClientIpLength; + USHORT ServerNameLength; + USHORT ServiceNameLength; + USHORT ServerIpLength; + USHORT MethodLength; + USHORT UriQueryLength; + USHORT HostLength; + USHORT UserAgentLength; + USHORT CookieLength; + USHORT ReferrerLength; + + PWCHAR UserName; + PWCHAR UriStem; + PCHAR ClientIp; + PCHAR ServerName; + PCHAR ServiceName; + PCHAR ServerIp; + PCHAR Method; + PCHAR UriQuery; + PCHAR Host; + PCHAR UserAgent; + PCHAR Cookie; + PCHAR Referrer; + + USHORT ServerPort; + USHORT ProtocolStatus; + + ULONG Win32Status; + + HTTP_VERB MethodNum; + + USHORT SubStatus; + +} HTTP_LOG_FIELDS_DATA, *PHTTP_LOG_FIELDS_DATA; + +#endif // _WIN32_WINNT >= 0x0600 + +// +// This enum defines a data source for a particular chunk of data. +// + +typedef enum _HTTP_DATA_CHUNK_TYPE +{ + HttpDataChunkFromMemory, + HttpDataChunkFromFileHandle, + HttpDataChunkFromFragmentCache, + HttpDataChunkFromFragmentCacheEx, + + HttpDataChunkMaximum + +} HTTP_DATA_CHUNK_TYPE, *PHTTP_DATA_CHUNK_TYPE; + + +// +// This structure describes an individual data chunk. +// + +typedef struct _HTTP_DATA_CHUNK +{ + // + // The type of this data chunk. + // + + HTTP_DATA_CHUNK_TYPE DataChunkType; + + // + // The data chunk structures, one per supported data chunk type. + // + + union + { + // + // From-memory data chunk. + // + + struct + { + PVOID pBuffer; + ULONG BufferLength; + + } FromMemory; + + // + // From-file handle data chunk. + // + + struct + { + HTTP_BYTE_RANGE ByteRange; + HANDLE FileHandle; + + } FromFileHandle; + + // + // From-fragment cache data chunk. + // + + struct + { + USHORT FragmentNameLength; // in bytes not including the NUL + PCWSTR pFragmentName; + + } FromFragmentCache; + + // + // From-fragment cache data chunk that specifies a byte range. + // + + struct + { + HTTP_BYTE_RANGE ByteRange; + PCWSTR pFragmentName; // NULL-terminated string + + } FromFragmentCacheEx; + + }; + +} HTTP_DATA_CHUNK, *PHTTP_DATA_CHUNK; + +// +// HTTP API doesn't support 16 bit applications. +// Neither WIN32 nor _WIN64 was defined. +// + +C_ASSERT(TYPE_ALIGNMENT(HTTP_DATA_CHUNK) == sizeof(ULONGLONG)); + +// +// Structure defining format of request headers. +// + +typedef struct _HTTP_REQUEST_HEADERS +{ + // + // The array of unknown HTTP headers and the number of + // entries in the array. + // + + USHORT UnknownHeaderCount; + PHTTP_UNKNOWN_HEADER pUnknownHeaders; + + // + // Trailers - we don't use these currently, reserved for a future release + // + USHORT TrailerCount; // Reserved, must be 0 + PHTTP_UNKNOWN_HEADER pTrailers; // Reserved, must be NULL + + + // + // Known headers. + // + + HTTP_KNOWN_HEADER KnownHeaders[HttpHeaderRequestMaximum]; + +} HTTP_REQUEST_HEADERS, *PHTTP_REQUEST_HEADERS; + +// +// Structure defining format of response headers. +// + +typedef struct _HTTP_RESPONSE_HEADERS +{ + // + // The array of unknown HTTP headers and the number of + // entries in the array. + // + + USHORT UnknownHeaderCount; + PHTTP_UNKNOWN_HEADER pUnknownHeaders; + + // + // Trailers - we don't use these currently, reserved for a future release + // + USHORT TrailerCount; // Reserved, must be 0 + PHTTP_UNKNOWN_HEADER pTrailers; // Reserved, must be NULL + + // + // Known headers. + // + + HTTP_KNOWN_HEADER KnownHeaders[HttpHeaderResponseMaximum]; + +} HTTP_RESPONSE_HEADERS, *PHTTP_RESPONSE_HEADERS; + +// +// Structure defining format of transport address. Use pLocalAddress->sa_family +// to determine whether this is an IPv4 address (AF_INET) or IPv6 (AF_INET6). +// +// pRemoteAddress->sa_family will be the same as pLocalAddress->sa_family. +// +// SOCKADDRs are always in network order, not host order. +// + +typedef struct _HTTP_TRANSPORT_ADDRESS +{ + PSOCKADDR pRemoteAddress; + PSOCKADDR pLocalAddress; + +} HTTP_TRANSPORT_ADDRESS, *PHTTP_TRANSPORT_ADDRESS; + +// +// Structure defining format of cooked URL. +// + +typedef struct _HTTP_COOKED_URL +{ + // + // Pointers overlap and point into pFullUrl. NULL if not present. + // + + USHORT FullUrlLength; // in bytes not including the NUL + USHORT HostLength; // in bytes (no NUL) + USHORT AbsPathLength; // in bytes (no NUL) + USHORT QueryStringLength; // in bytes (no NUL) + + PCWSTR pFullUrl; // points to "http://hostname:port/abs/.../path?query" + PCWSTR pHost; // points to the first char in the hostname + PCWSTR pAbsPath; // Points to the 3rd '/' char + PCWSTR pQueryString; // Points to the 1st '?' char or NULL + +} HTTP_COOKED_URL, *PHTTP_COOKED_URL; + +// +// An opaque context for URL manipulation. +// + +typedef ULONGLONG HTTP_URL_CONTEXT; + + +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + +// +// Optional flags for URL manipulation functions. +// +// HTTP_URL_FLAG_REMOVE_ALL : When this flag is used +// when removing a Url from a url group, regardless of +// the passed URL, all of the Urls from the url group +// will be removed. +// + +#define HTTP_URL_FLAG_REMOVE_ALL 0x00000001 + + +// +// Request Authentication related. +// + +typedef enum _HTTP_AUTH_STATUS +{ + HttpAuthStatusSuccess, + HttpAuthStatusNotAuthenticated, + HttpAuthStatusFailure + +} HTTP_AUTH_STATUS, *PHTTP_AUTH_STATUS; + + +typedef enum _HTTP_REQUEST_AUTH_TYPE +{ + HttpRequestAuthTypeNone = 0, + HttpRequestAuthTypeBasic, + HttpRequestAuthTypeDigest, + HttpRequestAuthTypeNTLM, + HttpRequestAuthTypeNegotiate, + HttpRequestAuthTypeKerberos + + +} HTTP_REQUEST_AUTH_TYPE, *PHTTP_REQUEST_AUTH_TYPE; + +#endif // _WIN32_WINNT >= 0x0600 + +// +// SSL Client certificate information. +// + +typedef struct _HTTP_SSL_CLIENT_CERT_INFO +{ + ULONG CertFlags; + ULONG CertEncodedSize; + PUCHAR pCertEncoded; + HANDLE Token; + BOOLEAN CertDeniedByMapper; + +} HTTP_SSL_CLIENT_CERT_INFO, *PHTTP_SSL_CLIENT_CERT_INFO; + +#if _WIN32_WINNT >= _WIN32_WINNT_WIN7 || BUILD_IIS_FOR_XP + +// +// Flag to retrieve secure channel binding with HttpReceiveClientCertificate +// + +#define HTTP_RECEIVE_SECURE_CHANNEL_TOKEN 0x1 + +#endif + +// +// Data computed during SSL handshake. +// + +typedef struct _HTTP_SSL_INFO +{ + USHORT ServerCertKeySize; + USHORT ConnectionKeySize; + ULONG ServerCertIssuerSize; + ULONG ServerCertSubjectSize; + + PCSTR pServerCertIssuer; + PCSTR pServerCertSubject; + + PHTTP_SSL_CLIENT_CERT_INFO pClientCertInfo; + ULONG SslClientCertNegotiated; + +} HTTP_SSL_INFO, *PHTTP_SSL_INFO; + + +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + +// +// Generic request information type. +// + +typedef enum _HTTP_REQUEST_INFO_TYPE +{ + HttpRequestInfoTypeAuth + +#if _WIN32_WINNT >= _WIN32_WINNT_WIN7 + ,HttpRequestInfoTypeChannelBind +#endif + + +} HTTP_REQUEST_INFO_TYPE, *PHTTP_REQUEST_INFO_TYPE; + +typedef struct _HTTP_REQUEST_INFO +{ + HTTP_REQUEST_INFO_TYPE InfoType; + ULONG InfoLength; + PVOID pInfo; + +} HTTP_REQUEST_INFO, *PHTTP_REQUEST_INFO; + +#ifndef __SECSTATUS_DEFINED__ +typedef LONG SECURITY_STATUS; +#define __SECSTATUS_DEFINED__ +#endif // __SECSTATUS_DEFINED__ + +// +// Authentication request info structure +// + +#define HTTP_REQUEST_AUTH_FLAG_TOKEN_FOR_CACHED_CRED (0x00000001) + +typedef struct _HTTP_REQUEST_AUTH_INFO +{ + HTTP_AUTH_STATUS AuthStatus; + SECURITY_STATUS SecStatus; + + ULONG Flags; + + HTTP_REQUEST_AUTH_TYPE AuthType; + + HANDLE AccessToken; + ULONG ContextAttributes; + + // + // Optional serialized context. + // + + ULONG PackedContextLength; + ULONG PackedContextType; + PVOID PackedContext; + + // + // Optional mutual authentication data and its length in bytes. + // + + ULONG MutualAuthDataLength; + PCHAR pMutualAuthData; + + // + // For SSPI based schemes the package name is returned. Length does + // not include the terminating null and it is in bytes. + // + + USHORT PackageNameLength; + PWSTR pPackageName; + +} HTTP_REQUEST_AUTH_INFO, *PHTTP_REQUEST_AUTH_INFO; + +#endif // _WIN32_WINNT >= 0x0600 + +// +// The structure of an HTTP request for downlevel OS +// + +typedef struct _HTTP_REQUEST_V1 +{ + // + // Request flags (see HTTP_REQUEST_FLAG_* definitions below). + // + + ULONG Flags; + + // + // An opaque request identifier. These values are used by the driver + // to correlate outgoing responses with incoming requests. + // + + HTTP_CONNECTION_ID ConnectionId; + HTTP_REQUEST_ID RequestId; + + // + // The context associated with the URL prefix. + // + + HTTP_URL_CONTEXT UrlContext; + + // + // The HTTP version number. + // + + HTTP_VERSION Version; + + // + // The request verb. + // + + HTTP_VERB Verb; + + // + // The length of the verb string if the Verb field is HttpVerbUnknown. + // + + USHORT UnknownVerbLength; // in bytes not including the NUL + + // + // The length of the raw (uncooked) URL + // + + USHORT RawUrlLength; // in bytes not including the NUL + + // + // Pointer to the verb string if the Verb field is HttpVerbUnknown. + // + + PCSTR pUnknownVerb; + + // + // Pointer to the raw (uncooked) URL + // + + PCSTR pRawUrl; + + // + // The canonicalized Unicode URL + // + + HTTP_COOKED_URL CookedUrl; + + // + // Local and remote transport addresses for the connection. + // + + HTTP_TRANSPORT_ADDRESS Address; + + // + // The request headers. + // + + HTTP_REQUEST_HEADERS Headers; + + // + // The total number of bytes received from network for this request. + // + + ULONGLONG BytesReceived; + + // + // pEntityChunks is an array of EntityChunkCount HTTP_DATA_CHUNKs. The + // entity body is copied only if HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY + // was passed to HttpReceiveHttpRequest(). + // + + USHORT EntityChunkCount; + PHTTP_DATA_CHUNK pEntityChunks; + + // + // SSL connection information. + // + + HTTP_RAW_CONNECTION_ID RawConnectionId; + PHTTP_SSL_INFO pSslInfo; + +} HTTP_REQUEST_V1, *PHTTP_REQUEST_V1; + +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + +// Vista + +// +// Version 2.0 members are defined here +// N.B. One must define V2 elements in two places :( +// This is due to the fact that C++ doesn't allow anonymous +// structure declarations and one must use structure +// inheritance instead. +// + +#ifdef __cplusplus + +typedef struct _HTTP_REQUEST_V2 : _HTTP_REQUEST_V1 +{ + // + // Version 1.0 members are inherited + // Version 2.0 members are declared below + // + + // + // Additional Request Informations. + // + + USHORT RequestInfoCount; + PHTTP_REQUEST_INFO pRequestInfo; +} HTTP_REQUEST_V2, *PHTTP_REQUEST_V2; + +#else // __cplusplus + +typedef struct _HTTP_REQUEST_V2 +{ + struct _HTTP_REQUEST_V1; // Anonymous structure + + // + // Version 2.0 members are declared below + // + + // + // Additional Request Informations. + // + + USHORT RequestInfoCount; + PHTTP_REQUEST_INFO pRequestInfo; +} HTTP_REQUEST_V2, *PHTTP_REQUEST_V2; + +#endif // __cplusplus + +typedef HTTP_REQUEST_V2 HTTP_REQUEST; + +#else // _WIN32_WINNT >= 0x0600 + +typedef HTTP_REQUEST_V1 HTTP_REQUEST; + +#endif // _WIN32_WINNT >= 0x0600 + +typedef HTTP_REQUEST * PHTTP_REQUEST; + + +// +// Values for HTTP_REQUEST::Flags. Zero or more of these may be ORed together. +// +// HTTP_REQUEST_FLAG_MORE_ENTITY_BODY_EXISTS - there is more entity body +// to be read for this request. Otherwise, there is no entity body or +// all of the entity body was copied into pEntityChunks. +// HTTP_REQUEST_FLAG_IP_ROUTED - This flag indicates that the request has been +// routed based on host plus ip or ip binding.This is a hint for the application +// to include the local ip while flushing kernel cache entries build for this +// request if any. +// + +#define HTTP_REQUEST_FLAG_MORE_ENTITY_BODY_EXISTS 0x00000001 +#define HTTP_REQUEST_FLAG_IP_ROUTED 0x00000002 + + +// +// This structure describes an HTTP response. +// + +typedef struct _HTTP_RESPONSE_V1 +{ + // + // Response flags (see HTTP_RESPONSE_FLAG_* definitions below). + // + + ULONG Flags; + + // + // The raw HTTP protocol version number. + // + + HTTP_VERSION Version; + + // + // The HTTP status code (e.g., 200). + // + + USHORT StatusCode; + + // + // The HTTP reason (e.g., "OK"). This MUST not contain + // non-ASCII characters (i.e., all chars must be in range 0x20-0x7E). + // + + USHORT ReasonLength; // in bytes not including the '\0' + PCSTR pReason; + + // + // The response headers. + // + + HTTP_RESPONSE_HEADERS Headers; + + // + // pEntityChunks points to an array of EntityChunkCount HTTP_DATA_CHUNKs. + // + + USHORT EntityChunkCount; + PHTTP_DATA_CHUNK pEntityChunks; + +} HTTP_RESPONSE_V1, *PHTTP_RESPONSE_V1; + +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + +// +// Values for HTTP_RESPONSE::Flags. +// +// HTTP_RESPONSE_FLAG_MULTIPLE_ENCODINGS_AVAILABLE - Set this flag if encodings +// other than identity form are available for this resource.This flag is ignored +// if application has not asked for response to be cached. It's used as a hint +// to the Http Server API for content negotiation used when serving from the +// the kernel response cache. +// + +#define HTTP_RESPONSE_FLAG_MULTIPLE_ENCODINGS_AVAILABLE 0x00000001 + + +// Vista + +typedef enum _HTTP_RESPONSE_INFO_TYPE +{ + HttpResponseInfoTypeMultipleKnownHeaders, + HttpResponseInfoTypeAuthenticationProperty, + HttpResponseInfoTypeQoSProperty + +#if _WIN32_WINNT >= _WIN32_WINNT_WIN7 || BUILD_IIS_FOR_XP + ,HttpResponseInfoTypeChannelBind +#endif + +} HTTP_RESPONSE_INFO_TYPE, PHTTP_RESPONSE_INFO_TYPE; + +typedef struct _HTTP_RESPONSE_INFO +{ + HTTP_RESPONSE_INFO_TYPE Type; + ULONG Length; + PVOID pInfo; +} HTTP_RESPONSE_INFO, *PHTTP_RESPONSE_INFO; + +#define HTTP_RESPONSE_INFO_FLAGS_PRESERVE_ORDER 0x00000001 + +// +// This structure allows the provision of providing multiple known headers. +// + +typedef struct _HTTP_MULTIPLE_KNOWN_HEADERS +{ + // + // Known header id. + // + + HTTP_HEADER_ID HeaderId; + + ULONG Flags; + + // + // Number of headers of the same category. + // + + USHORT KnownHeaderCount; + + // + // Array of known header structures. + // + + PHTTP_KNOWN_HEADER KnownHeaders; + +} HTTP_MULTIPLE_KNOWN_HEADERS, *PHTTP_MULTIPLE_KNOWN_HEADERS; + +// +// Version 2.0 members are defined here +// N.B. One must define V2 elements in two places :( +// This is due to the fact that C++ doesn't allow anonymous +// structure declarations and one must use structure +// inheritance instead. +// + +#ifdef __cplusplus + +typedef struct _HTTP_RESPONSE_V2 : _HTTP_RESPONSE_V1 +{ + // + // Version 1.0 members are inherited + // Version 2.0 members are declared below + // + + USHORT ResponseInfoCount; + PHTTP_RESPONSE_INFO pResponseInfo; + +} HTTP_RESPONSE_V2, *PHTTP_RESPONSE_V2; + +#else // __cplusplus + +typedef struct _HTTP_RESPONSE_V2 +{ + struct _HTTP_RESPONSE_V1; + + // + // Version 2.0 members are declared below + // + + USHORT ResponseInfoCount; + PHTTP_RESPONSE_INFO pResponseInfo; +} HTTP_RESPONSE_V2, *PHTTP_RESPONSE_V2; + +#endif // __cplusplus + +typedef HTTP_RESPONSE_V2 HTTP_RESPONSE; + +#else // _WIN32_WINNT >= 0x0600 + +typedef HTTP_RESPONSE_V1 HTTP_RESPONSE; + +#endif // _WIN32_WINNT >= 0x0600 + +typedef HTTP_RESPONSE *PHTTP_RESPONSE; + +// +// Api Version. This is used to ensure compatibility between applications and +// httpapi.dll and http.sys. +// +// This must not be confused with the HTTP Protocol version. +// + +typedef struct _HTTPAPI_VERSION +{ + USHORT HttpApiMajorVersion; + USHORT HttpApiMinorVersion; + +} HTTPAPI_VERSION, *PHTTPAPI_VERSION; + + +#if _WIN32_WINNT >= 0x0600 || BUILD_IIS_FOR_XP + +// Vista + +#define HTTPAPI_VERSION_2 { 2, 0 } + +#endif // _WIN32_WINNT >= 0x0600 + +#define HTTPAPI_VERSION_1 { 1, 0 } + +#define HTTPAPI_EQUAL_VERSION(version, major, minor) \ + ((version).HttpApiMajorVersion == (major) && \ + (version).HttpApiMinorVersion == (minor)) + +#define HTTPAPI_GREATER_VERSION(version, major, minor) \ + ((version).HttpApiMajorVersion > (major) || \ + ((version).HttpApiMajorVersion == (major) && \ + (version).HttpApiMinorVersion > (minor))) + +#define HTTPAPI_LESS_VERSION(version, major, minor) \ + ((version).HttpApiMajorVersion < (major) || \ + ((version).HttpApiMajorVersion == (major) && \ + (version).HttpApiMinorVersion < (minor))) + +#define HTTPAPI_VERSION_GREATER_OR_EQUAL( version, major, minor) \ + (!HTTPAPI_LESS_VERSION(version, major, minor)) + + +// +// Cache control. +// + +// +// This enum defines the available cache policies. +// + +typedef enum _HTTP_CACHE_POLICY_TYPE +{ + HttpCachePolicyNocache, + HttpCachePolicyUserInvalidates, + HttpCachePolicyTimeToLive, + + HttpCachePolicyMaximum + +} HTTP_CACHE_POLICY_TYPE, *PHTTP_CACHE_POLICY_TYPE; + + +// +// Only cache unauthorized GETs + HEADs. +// + +typedef struct _HTTP_CACHE_POLICY +{ + HTTP_CACHE_POLICY_TYPE Policy; + ULONG SecondsToLive; + +} HTTP_CACHE_POLICY, *PHTTP_CACHE_POLICY; + +// +// Enum that is used with HttpSetServiceConfiguration(), +// HttpQueryServiceConfiguration(), and HttpDeleteServiceConfiguration() APIs. +// + +typedef enum _HTTP_SERVICE_CONFIG_ID +{ + HttpServiceConfigIPListenList, // Set, Query & Delete. + HttpServiceConfigSSLCertInfo, // Set, Query & Delete. + HttpServiceConfigUrlAclInfo, // Set, Query & Delete. + HttpServiceConfigTimeout, // Set, Query & Delete. + HttpServiceConfigCache, // Set, Query & Delete. + HttpServiceConfigMax + +} HTTP_SERVICE_CONFIG_ID, *PHTTP_SERVICE_CONFIG_ID; + +// +// Generic Query enum that can be used with HttpQueryServiceConfiguration() +// + +typedef enum _HTTP_SERVICE_CONFIG_QUERY_TYPE +{ + HttpServiceConfigQueryExact, + HttpServiceConfigQueryNext, + HttpServiceConfigQueryMax + +} HTTP_SERVICE_CONFIG_QUERY_TYPE, *PHTTP_SERVICE_CONFIG_QUERY_TYPE; + +// +// This data structure is used to define a key of the SSL certificate hash +// store. +// + +typedef struct _HTTP_SERVICE_CONFIG_SSL_KEY +{ + PSOCKADDR pIpPort; +} HTTP_SERVICE_CONFIG_SSL_KEY, *PHTTP_SERVICE_CONFIG_SSL_KEY; + +// +// This defines a record for the SSL config store. +// + +typedef struct _HTTP_SERVICE_CONFIG_SSL_PARAM +{ + ULONG SslHashLength; // Length of the SSL hash (in bytes) + PVOID pSslHash; // Pointer to the SSL hash + GUID AppId; // A unique identifier that can be used to + // identify the app that has set this parameter + + PWSTR pSslCertStoreName; // Store name to read the server certificate + // from; defaults to "MY". Certificate must be + // stored in the LOCAL_MACHINE context. + + // + // The following settings are used only for client certificates + // + + // + // DefaultCertCheckMode is a bit flag with the following semantics + // 0x1 - Client certificate will not be verified for revocation + // 0x2 - Only cached certificate revocation will be used. + // 0x4 - Enable use of the DefaultRevocationFreshnessTime setting + // 0x10000 - No usage check. + + DWORD DefaultCertCheckMode; + + // + // DefaultRevocationFreshnessTime (seconds) - How often to check for + // an updated Certificate revocation list (CRL). If this value is 0 + // then the new CRL is updated only if the previous one expires + // + + DWORD DefaultRevocationFreshnessTime; + + // + // DefaultRevocationUrlRetrievalTimeout (milliseconds) - Timeout on + // attempt to retrieve certificate revocation list from the remote URL. + // + + DWORD DefaultRevocationUrlRetrievalTimeout; + + // + // pDefaultSslCtlIdentifier - Restrict the certificate issuers that you + // want to trust. Can be a subset of the certificate issuers that are + // trusted by the machine. + // + + PWSTR pDefaultSslCtlIdentifier; + + // + // Store name under LOCAL_MACHINE where Ctl identified by + // pDefaultSslCtlIdentifier is stored. + // + + PWSTR pDefaultSslCtlStoreName; + + // + // Default Flags - see HTTP_SERVICE_CONFIG_SSL_FLAG* below. + // + + DWORD DefaultFlags; + +} HTTP_SERVICE_CONFIG_SSL_PARAM, *PHTTP_SERVICE_CONFIG_SSL_PARAM; + +#define HTTP_SERVICE_CONFIG_SSL_FLAG_USE_DS_MAPPER 0x00000001 +#define HTTP_SERVICE_CONFIG_SSL_FLAG_NEGOTIATE_CLIENT_CERT 0x00000002 +#if _WIN32_WINNT < 0x0600 +#define HTTP_SERVICE_CONFIG_SSL_FLAG_NO_RAW_FILTER 0x00000004 +#endif // _WIN32_WINNT < 0x0600 + +// +// This data structure is used by HttpSetServiceConfiguration() for the +// config ID HttpServiceConfigSSLCertInfo. It's used to add a new record +// to the SSL store. +// + +typedef struct _HTTP_SERVICE_CONFIG_SSL_SET +{ + HTTP_SERVICE_CONFIG_SSL_KEY KeyDesc; + HTTP_SERVICE_CONFIG_SSL_PARAM ParamDesc; +} HTTP_SERVICE_CONFIG_SSL_SET, *PHTTP_SERVICE_CONFIG_SSL_SET; + +// +// This data structure is used by HttpQueryServiceConfiguration() for the +// config ID HttpServiceConfigSSLCertInfo. It's used to query a particular +// record from the SSL store. +// +// If QueryType is HttpServiceConfigQueryExact, then one particular record of +// the type HTTP_SERVICE_CONFIG_SSL_SET is returned. If the QueryType is +// HttpServiceConfigQueryNext, then the next instance of +// HTTP_SERVICE_CONFIG_SSL_SET is returned. In such cases, the dwToken field +// represents the cursor. For the first item, dwToken has to be 0. +// For subsequent items, dwToken has to be incremented by 1, +// until ERROR_NO_MORE_ITEMS is returned. +// + +typedef struct _HTTP_SERVICE_CONFIG_SSL_QUERY +{ + HTTP_SERVICE_CONFIG_QUERY_TYPE QueryDesc; + HTTP_SERVICE_CONFIG_SSL_KEY KeyDesc; + DWORD dwToken; +} HTTP_SERVICE_CONFIG_SSL_QUERY, *PHTTP_SERVICE_CONFIG_SSL_QUERY; + +// +// Set/Delete IP Listen-Only List record +// +// Used as a parameter to both HttpSetServiceConfiguration() and +// HttpDeleteServiceConfiguration() functions. +// + +typedef struct _HTTP_SERVICE_CONFIG_IP_LISTEN_PARAM +{ + USHORT AddrLength; + PSOCKADDR pAddress; +} HTTP_SERVICE_CONFIG_IP_LISTEN_PARAM, *PHTTP_SERVICE_CONFIG_IP_LISTEN_PARAM; + +// +// Query IP Listen-Only List record. +// +// Parameter to HttpQueryServiceConfiguration() for the config ID +// HttpServiceConfigIPListenList. On successful return, AddrList +// contains an array of AddrCount elements. Caller must provide a +// large enough buffer to hold all elements in one call. +// +// Caller may determine the type of each returned element by examining +// AddrList[i].ss_family. If it's AF_INET, use ((PSOCKADDR_IN) &AddrList[i]); +// otherwise, for AF_INET6, use ((PSOCKADDR_IN6) &AddrList[i]) +// to select the appropriate address type. +// + +typedef struct _HTTP_SERVICE_CONFIG_IP_LISTEN_QUERY +{ + ULONG AddrCount; + SOCKADDR_STORAGE AddrList[ANYSIZE_ARRAY]; +} HTTP_SERVICE_CONFIG_IP_LISTEN_QUERY, *PHTTP_SERVICE_CONFIG_IP_LISTEN_QUERY; + +// +// URL ACL +// +// +typedef struct _HTTP_SERVICE_CONFIG_URLACL_KEY +{ + PWSTR pUrlPrefix; + +} HTTP_SERVICE_CONFIG_URLACL_KEY, *PHTTP_SERVICE_CONFIG_URLACL_KEY; + +// +// This defines a record for the SSL config store. +// + +typedef struct _HTTP_SERVICE_CONFIG_URLACL_PARAM +{ + PWSTR pStringSecurityDescriptor; +} HTTP_SERVICE_CONFIG_URLACL_PARAM, *PHTTP_SERVICE_CONFIG_URLACL_PARAM; + + +// +// This data structure is used by HttpSetServiceConfiguration for the config ID +// HttpServiceConfigUrlAclInfo. It is used to add a new record to the URL ACL +// store. +// + +typedef struct _HTTP_SERVICE_CONFIG_URLACL_SET +{ + HTTP_SERVICE_CONFIG_URLACL_KEY KeyDesc; + HTTP_SERVICE_CONFIG_URLACL_PARAM ParamDesc; +} HTTP_SERVICE_CONFIG_URLACL_SET, *PHTTP_SERVICE_CONFIG_URLACL_SET; + + +// +// This data structure is used by HttpQueryServiceConfiguration() for the +// config ID HttpServiceConfigUrlAclInfo. It's used to query a particular +// record from the URL ACL store. +// +// If QueryType is HttpServiceConfigQueryExact, then one particular record of +// the type HTTP_SERVICE_CONFIG_URLACL_SET is returned. If the QueryType is +// HttpServiceConfigQueryNext, then the next instance of +// HTTP_SERVICE_CONFIG_URLACL_SET is returned. In such cases, the dwToken field +// represents the cursor. For the first item, dwToken has to be 0. +// For subsequent items, dwToken has to be incremented by 1, +// until ERROR_NO_MORE_ITEMS is returned. +// + +typedef struct _HTTP_SERVICE_CONFIG_URLACL_QUERY +{ + HTTP_SERVICE_CONFIG_QUERY_TYPE QueryDesc; + HTTP_SERVICE_CONFIG_URLACL_KEY KeyDesc; + DWORD dwToken; +} HTTP_SERVICE_CONFIG_URLACL_QUERY, *PHTTP_SERVICE_CONFIG_URLACL_QUERY; + +// +// Cache Paramemers +// + +// +// For manipulating global cache parameters. +// The parameters that can be changed or queued are per-uri cache size +// and cached range chunk size. +// + +typedef enum _HTTP_SERVICE_CONFIG_CACHE_KEY +{ + MaxCacheResponseSize = 0, + CacheRangeChunkSize +} HTTP_SERVICE_CONFIG_CACHE_KEY, *PHTTP_SERVICE_CONFIG_CACHE_KEY; + +typedef ULONG HTTP_SERVICE_CONFIG_CACHE_PARAM, + *PHTTP_SERVICE_CONFIG_CACHE_PARAM; + +// +// To set a cache parameter value use the set structure. To query use the key +// directly. When you query a parameter value the output buffer must be exactly +// the sizeof param. +// + +typedef struct { + HTTP_SERVICE_CONFIG_CACHE_KEY KeyDesc; + HTTP_SERVICE_CONFIG_CACHE_PARAM ParamDesc; +} HTTP_SERVICE_CONFIG_CACHE_SET, *PHTTP_SERVICE_CONFIG_CACHE_SET; + + +// +// Define our API linkage. +// + +#if !defined(HTTPAPI_LINKAGE) +#define HTTPAPI_LINKAGE DECLSPEC_IMPORT +#endif // !HTTPAPI_LINKAGE + +// +// Initialize/Terminate APIs. +// + + +// NOTE: MUST be called once before all other APIs + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpInitialize( + IN HTTPAPI_VERSION Version, + IN ULONG Flags, + __reserved IN OUT PVOID pReserved + ); + +// NOTE: MUST be called after final API call returns. + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpTerminate( + IN ULONG Flags, + __reserved IN OUT PVOID pReserved + ); + +// +// HTTP Request Queue manipulation APIs. +// +// This API is maintained for backward competibility for the first +// version of the HTTPAPI and should not be used. Instead the new +// HttpCreateRequestQueue() API must be used. +// +// Use CloseHandle() to release the handles returned by +// HttpCreateHttpHandle() API. +// + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpCreateHttpHandle( + OUT PHANDLE pReqQueueHandle, + __reserved IN ULONG Reserved + ); + +#if _WIN32_WINNT >= 0x0600 + +// +// Extended Request Queue manipulation APIs. +// +// Use HttpCloseRequestQueue() API to close the handles +// created by the HttpCreateRequestQueue API. +// + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpCreateRequestQueue( + IN HTTPAPI_VERSION Version, + IN PCWSTR pName OPTIONAL, + IN PSECURITY_ATTRIBUTES pSecurityAttributes OPTIONAL, + IN ULONG Flags OPTIONAL, + OUT PHANDLE pReqQueueHandle + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpCloseRequestQueue( + IN HANDLE ReqQueueHandle + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpSetRequestQueueProperty( + IN HANDLE Handle, + IN HTTP_SERVER_PROPERTY Property, + __in_bcount(PropertyInformationLength) IN PVOID pPropertyInformation, + IN ULONG PropertyInformationLength, + __reserved IN ULONG Reserved, + __reserved IN PVOID pReserved + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpQueryRequestQueueProperty( + IN HANDLE Handle, + IN HTTP_SERVER_PROPERTY Property, + __out_bcount_part(PropertyInformationLength, *pReturnLength) + OUT PVOID pPropertyInformation, + IN ULONG PropertyInformationLength, + __reserved IN ULONG Reserved, + __out_opt OUT PULONG pReturnLength OPTIONAL, + __reserved IN PVOID pReserved + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpShutdownRequestQueue( + IN HANDLE ReqQueueHandle + ); + +#endif // _WIN32_WINNT >= 0x0600 + +// +// SSL APIs. +// + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpReceiveClientCertificate( + IN HANDLE ReqQueueHandle, + IN HTTP_CONNECTION_ID ConnectionId, + IN ULONG Flags, + __out_bcount_part(SslClientCertInfoSize, *pBytesReceived) + OUT PHTTP_SSL_CLIENT_CERT_INFO pSslClientCertInfo, + IN ULONG SslClientCertInfoSize, + __out_opt OUT PULONG pBytesReceived OPTIONAL, + IN LPOVERLAPPED pOverlapped OPTIONAL + ); + +#if _WIN32_WINNT >= 0x0600 + +// +// Server Session APIs. +// + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpCreateServerSession( + IN HTTPAPI_VERSION Version, + OUT PHTTP_SERVER_SESSION_ID pServerSessionId, + __reserved IN ULONG Reserved + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpCloseServerSession( + IN HTTP_SERVER_SESSION_ID ServerSessionId + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpQueryServerSessionProperty( + IN HTTP_SERVER_SESSION_ID ServerSessionId, + IN HTTP_SERVER_PROPERTY Property, + __out_bcount_part(PropertyInformationLength, *pReturnLength) + OUT PVOID pPropertyInformation, + IN ULONG PropertyInformationLength, + __out_opt OUT PULONG pReturnLength OPTIONAL + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpSetServerSessionProperty( + IN HTTP_SERVER_SESSION_ID ServerSessionId, + IN HTTP_SERVER_PROPERTY Property, + __in_bcount(PropertyInformationLength) IN PVOID pPropertyInformation, + IN ULONG PropertyInformationLength + ); + +#endif // _WIN32_WINNT >= 0x0600 + +// +// Url Configuration APIs. Can only be used for V1 request queues. +// + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpAddUrl( + IN HANDLE ReqQueueHandle, + IN PCWSTR pFullyQualifiedUrl, + __reserved IN PVOID pReserved + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpRemoveUrl( + IN HANDLE ReqQueueHandle, + IN PCWSTR pFullyQualifiedUrl + ); + +#if _WIN32_WINNT >= 0x0600 + +// +// Url Group APIs. +// + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpCreateUrlGroup( + IN HTTP_SERVER_SESSION_ID ServerSessionId, + OUT PHTTP_URL_GROUP_ID pUrlGroupId, + __reserved IN ULONG Reserved + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpCloseUrlGroup( + IN HTTP_URL_GROUP_ID UrlGroupId + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpAddUrlToUrlGroup( + IN HTTP_URL_GROUP_ID UrlGroupId, + IN PCWSTR pFullyQualifiedUrl, + IN HTTP_URL_CONTEXT UrlContext OPTIONAL, + __reserved IN ULONG Reserved + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpRemoveUrlFromUrlGroup( + IN HTTP_URL_GROUP_ID UrlGroupId, + IN PCWSTR pFullyQualifiedUrl, + IN ULONG Flags + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpSetUrlGroupProperty( + IN HTTP_URL_GROUP_ID UrlGroupId, + IN HTTP_SERVER_PROPERTY Property, + __in_bcount(PropertyInformationLength) IN PVOID pPropertyInformation, + IN ULONG PropertyInformationLength + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpQueryUrlGroupProperty( + IN HTTP_URL_GROUP_ID UrlGroupId, + IN HTTP_SERVER_PROPERTY Property, + __out_bcount_part(PropertyInformationLength, *pReturnLength) + OUT PVOID pPropertyInformation, + IN ULONG PropertyInformationLength, + __out_opt OUT PULONG pReturnLength OPTIONAL + ); + +#endif // _WIN32_WINNT >= 0x0600 + +// +// HTTP Server I/O APIs. +// + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpReceiveHttpRequest( + IN HANDLE ReqQueueHandle, + IN HTTP_REQUEST_ID RequestId, + IN ULONG Flags, + __out_bcount_part(RequestBufferLength, *pBytesReceived) + OUT PHTTP_REQUEST pRequestBuffer, + IN ULONG RequestBufferLength, + __out_opt OUT PULONG pBytesReceived OPTIONAL, + IN LPOVERLAPPED pOverlapped OPTIONAL + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpReceiveRequestEntityBody( + IN HANDLE ReqQueueHandle, + IN HTTP_REQUEST_ID RequestId, + IN ULONG Flags, + __out_bcount_part(BufferLength, *pBytesReceived) OUT PVOID pBuffer, + IN ULONG BufferLength, + __out_opt OUT PULONG pBytesReceived OPTIONAL, + IN LPOVERLAPPED pOverlapped OPTIONAL + ); + +#if _WIN32_WINNT >= 0x0600 + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpSendHttpResponse( + IN HANDLE ReqQueueHandle, + IN HTTP_REQUEST_ID RequestId, + IN ULONG Flags, + IN PHTTP_RESPONSE pHttpResponse, + IN PHTTP_CACHE_POLICY pCachePolicy OPTIONAL, + OUT PULONG pBytesSent OPTIONAL, + OUT PVOID pReserved1 OPTIONAL, // must be NULL + IN ULONG Reserved2 OPTIONAL, // must be 0 + IN LPOVERLAPPED pOverlapped OPTIONAL, + IN PHTTP_LOG_DATA pLogData OPTIONAL + ); + +#else // _WIN32_WINNT >= 0x0600 + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpSendHttpResponse( + IN HANDLE ReqQueueHandle, + IN HTTP_REQUEST_ID RequestId, + IN ULONG Flags, + IN PHTTP_RESPONSE pHttpResponse, + IN PVOID pReserved1 OPTIONAL, // must be NULL + OUT PULONG pBytesSent OPTIONAL, + OUT PVOID pReserved2 OPTIONAL, // must be NULL + IN ULONG Reserved3 OPTIONAL, // must be 0 + IN LPOVERLAPPED pOverlapped OPTIONAL, + IN PVOID pReserved4 OPTIONAL // must be NULL + ); + +#endif // _WIN32_WINNT >= 0x0600 + +#if _WIN32_WINNT >= 0x0600 + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpSendResponseEntityBody( + IN HANDLE ReqQueueHandle, + IN HTTP_REQUEST_ID RequestId, + IN ULONG Flags, + IN USHORT EntityChunkCount OPTIONAL, + __in_ecount_opt(EntityChunkCount) + IN PHTTP_DATA_CHUNK pEntityChunks OPTIONAL, + OUT PULONG pBytesSent OPTIONAL, + OUT PVOID pReserved1 OPTIONAL, // must be NULL + IN ULONG Reserved2 OPTIONAL, // must be 0 + IN LPOVERLAPPED pOverlapped OPTIONAL, + IN PHTTP_LOG_DATA pLogData OPTIONAL + ); + +#else // _WIN32_WINNT >= 0x0600 + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpSendResponseEntityBody( + IN HANDLE ReqQueueHandle, + IN HTTP_REQUEST_ID RequestId, + IN ULONG Flags, + IN USHORT EntityChunkCount OPTIONAL, + __in_ecount_opt(EntityChunkCount) + IN PHTTP_DATA_CHUNK pEntityChunks OPTIONAL, + OUT PULONG pBytesSent OPTIONAL, + OUT PVOID pReserved1 OPTIONAL, // must be NULL + IN ULONG Reserved2 OPTIONAL, // must be 0 + IN LPOVERLAPPED pOverlapped OPTIONAL, + IN PVOID pReserved3 OPTIONAL // must be NULL + ); + +#endif // _WIN32_WINNT >= 0x0600 + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpWaitForDisconnect( + IN HANDLE ReqQueueHandle, + IN HTTP_CONNECTION_ID ConnectionId, + IN LPOVERLAPPED pOverlapped OPTIONAL + ); + +#if _WIN32_WINNT >= 0x0600 + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpWaitForDisconnectEx( + IN HANDLE ReqQueueHandle, + IN HTTP_CONNECTION_ID ConnectionId, + __reserved IN ULONG Reserved OPTIONAL, + IN LPOVERLAPPED pOverlapped OPTIONAL + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpCancelHttpRequest( + IN HANDLE ReqQueueHandle, + IN HTTP_REQUEST_ID RequestId, + IN LPOVERLAPPED pOverlapped OPTIONAL + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpWaitForDemandStart( + IN HANDLE ReqQueueHandle, + IN LPOVERLAPPED pOverlapped OPTIONAL + ); + + +#endif // _WIN32_WINNT >= 0x0600 + +// +// Cache manipulation APIs. +// + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpFlushResponseCache( + IN HANDLE ReqQueueHandle, + IN PCWSTR pUrlPrefix, + IN ULONG Flags, + IN LPOVERLAPPED pOverlapped OPTIONAL + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpAddFragmentToCache( + IN HANDLE ReqQueueHandle, + IN PCWSTR pUrlPrefix, + IN PHTTP_DATA_CHUNK pDataChunk, + IN PHTTP_CACHE_POLICY pCachePolicy, + IN LPOVERLAPPED pOverlapped OPTIONAL + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpReadFragmentFromCache( + IN HANDLE ReqQueueHandle, + IN PCWSTR pUrlPrefix, + IN PHTTP_BYTE_RANGE pByteRange OPTIONAL, + __out_bcount_part(BufferLength, *pBytesRead) OUT PVOID pBuffer, + IN ULONG BufferLength, + OUT PULONG pBytesRead OPTIONAL, + IN LPOVERLAPPED pOverlapped OPTIONAL + ); + +// +// Server configuration APIs +// + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpSetServiceConfiguration( + __reserved IN HANDLE ServiceHandle, + IN HTTP_SERVICE_CONFIG_ID ConfigId, + __in_bcount(ConfigInformationLength) IN PVOID pConfigInformation, + IN ULONG ConfigInformationLength, + __reserved IN LPOVERLAPPED pOverlapped + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpDeleteServiceConfiguration( + __reserved IN HANDLE ServiceHandle, + IN HTTP_SERVICE_CONFIG_ID ConfigId, + __in_bcount(ConfigInformationLength) IN PVOID pConfigInformation, + IN ULONG ConfigInformationLength, + __reserved IN LPOVERLAPPED pOverlapped + ); + +HTTPAPI_LINKAGE +ULONG +WINAPI +HttpQueryServiceConfiguration( + __reserved IN HANDLE ServiceHandle, + IN HTTP_SERVICE_CONFIG_ID ConfigId, + __in_bcount_opt(InputConfigInformationLength) + IN PVOID pInputConfigInformation OPTIONAL, + IN ULONG InputConfigInformationLength OPTIONAL, + __out_bcount_part_opt(OutputConfigInformationLength, *pReturnLength) + OUT PVOID pOutputConfigInformation OPTIONAL, + IN ULONG OutputConfigInformationLength OPTIONAL, + __out_opt OUT PULONG pReturnLength OPTIONAL, + __reserved IN LPOVERLAPPED pOverlapped + ); + + +#if BUILD_IIS_FOR_XP + +// part of the httpp.h necessary to build for XP + +// +// Counter Group. +// + +// +// Counter property description. +// + +typedef struct _HTTP_PROP_DESC +{ + ULONG Size; + ULONG Offset; + BOOLEAN WPZeros; + +} HTTP_PROP_DESC, *PHTTP_PROP_DESC; + + +// +// This enum defines the available counter groups. +// + +typedef enum _HTTP_COUNTER_GROUP +{ + HttpCounterGroupSite, + HttpCounterGroupGlobal, + + HttpCounterGroupMaximum + +} HTTP_COUNTER_GROUP, *PHTTP_COUNTER_GROUP; + +// +// Structures for IOCTL_HTTP_GET_COUNTERS. +// + +typedef struct _HTTP_COUNTER_INFO +{ + HTTP_SERVER_SESSION_ID ServerSessionId; + HTTP_COUNTER_GROUP CounterGroup; + +} HTTP_COUNTER_INFO, *PHTTP_COUNTER_INFO; + +// +// This enum defines the type of global couters. +// + +typedef enum _HTTP_GLOBAL_COUNTER_ID +{ + HttpGlobalCounterCurrentUrisCached, + HttpGlobalCounterTotalUrisCached, + HttpGlobalCounterUriCacheHits, + HttpGlobalCounterUriCacheMisses, + HttpGlobalCounterUriCacheFlushes, + HttpGlobalCounterTotalFlushedUris, + + HttpGlobalCounterMaximum + +} HTTP_GLOBAL_COUNTER_ID, *PHTTP_GLOBAL_COUNTER_ID; + + +// +// Global couters. +// + +typedef struct _HTTP_GLOBAL_COUNTERS +{ + ULONG CurrentUrisCached; + ULONG TotalUrisCached; + ULONG UriCacheHits; + ULONG UriCacheMisses; + ULONG UriCacheFlushes; + ULONG TotalFlushedUris; + +} HTTP_GLOBAL_COUNTERS, *PHTTP_GLOBAL_COUNTERS; + + +// +// This enum defines the type of site counters. +// NB: HTTP_SITE_COUNTER_ID and HTTP_SITE_COUNTERS +// must be in the same order +// + +typedef enum _HTTP_SITE_COUNTER_ID +{ + HttpSiteCounterBytesSent, + HttpSiteCounterBytesReceived, + HttpSiteCounterBytesTransfered, + HttpSiteCounterCurrentConns, + HttpSiteCounterMaxConnections, + HttpSiteCounterConnAttempts, + HttpSiteCounterGetReqs, + HttpSiteCounterHeadReqs, + HttpSiteCounterAllReqs, + HttpSiteCounterMeasuredIoBandwidthUsage, + HttpSiteCounterCurrentBlockedBandwidthBytes, + HttpSiteCounterTotalBlockedBandwidthBytes, + + HttpSiteCounterMaximum + +} HTTP_SITE_COUNTER_ID, *PHTTP_SITE_COUNTER_ID; + + +// +// Site counters. +// + +typedef struct _HTTP_SITE_COUNTERS +{ + ULONG SiteId; + ULONGLONG BytesSent; + ULONGLONG BytesReceived; + ULONGLONG BytesTransfered; + ULONG CurrentConns; + ULONG MaxConnections; + ULONG ConnAttempts; + ULONG GetReqs; + ULONG HeadReqs; + ULONG AllReqs; + ULONG MeasuredIoBandwidthUsage; + ULONG CurrentBlockedBandwidthBytes; + ULONG TotalBlockedBandwidthBytes; + +} HTTP_SITE_COUNTERS, *PHTTP_SITE_COUNTERS; + +#endif + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // _WIN32_WINNT >= 0x0501 + +#endif // __HTTP_H__ + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/httpserv_xp.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/httpserv_xp.h new file mode 100644 index 0000000000..6e9437d7ed --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/httpserv_xp.h @@ -0,0 +1,3404 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _HTTPSERV_H_ +#define _HTTPSERV_H_ + +#if (!defined(_WIN64) && !defined(WIN32)) +#error httpserv.h is only supported on WIN32 or WIN64 platforms +#endif + +#include + +#if _WIN32_WINNT >= 0x0600 +#include "http.h" +#else +#include "http_xp.h" +#endif + +// +// Request deterministic notifications +// + +// request is beginning +#define RQ_BEGIN_REQUEST 0x00000001 +// request is being authenticated +#define RQ_AUTHENTICATE_REQUEST 0x00000002 +// request is being authorized +#define RQ_AUTHORIZE_REQUEST 0x00000004 +// satisfy request from cache +#define RQ_RESOLVE_REQUEST_CACHE 0x00000008 +// map handler for request +#define RQ_MAP_REQUEST_HANDLER 0x00000010 +// acquire request state +#define RQ_ACQUIRE_REQUEST_STATE 0x00000020 +// pre-execute handler +#define RQ_PRE_EXECUTE_REQUEST_HANDLER 0x00000040 +// execute handler +#define RQ_EXECUTE_REQUEST_HANDLER 0x00000080 +// release request state +#define RQ_RELEASE_REQUEST_STATE 0x00000100 +// update cache +#define RQ_UPDATE_REQUEST_CACHE 0x00000200 +// log request +#define RQ_LOG_REQUEST 0x00000400 +// end request +#define RQ_END_REQUEST 0x00000800 + +// +// Request non-deterministic notifications +// + +// custom notification +#define RQ_CUSTOM_NOTIFICATION 0x10000000 +// send response +#define RQ_SEND_RESPONSE 0x20000000 +// read entity +#define RQ_READ_ENTITY 0x40000000 +// map a url to a physical path +#define RQ_MAP_PATH 0x80000000 + +// +// Global notifications +// + +// stop accepting new requests +#define GL_STOP_LISTENING 0x00000002 +// cache cleanup before termination +#define GL_CACHE_CLEANUP 0x00000004 +// cache operation +#define GL_CACHE_OPERATION 0x00000010 +// health check +#define GL_HEALTH_CHECK 0x00000020 +// configuration changed +#define GL_CONFIGURATION_CHANGE 0x00000040 +// file changed +#define GL_FILE_CHANGE 0x00000080 +// before request pipeline has started +#define GL_PRE_BEGIN_REQUEST 0x00000100 +// application start +#define GL_APPLICATION_START 0x00000200 +// resolve modules for an application +#define GL_APPLICATION_RESOLVE_MODULES 0x00000400 +// application end +#define GL_APPLICATION_STOP 0x00000800 +// RSCA query +#define GL_RSCA_QUERY 0x00001000 +// trace event was raised +#define GL_TRACE_EVENT 0x00002000 +// custom notification +#define GL_CUSTOM_NOTIFICATION 0x00004000 +// thread cleanup notification +#define GL_THREAD_CLEANUP 0x00008000 +// application preload notification +#define GL_APPLICATION_PRELOAD 0x00010000 + +// +// Request notification return status +// + +typedef enum REQUEST_NOTIFICATION_STATUS +{ + RQ_NOTIFICATION_CONTINUE, // continue processing + // for notification + RQ_NOTIFICATION_PENDING, // suspend processing + // for notification + RQ_NOTIFICATION_FINISH_REQUEST // finish request + // processing +}; + +// +// Out of band return codes +// + +typedef enum GLOBAL_NOTIFICATION_STATUS +{ + GL_NOTIFICATION_CONTINUE, // continue processing + // for notification + GL_NOTIFICATION_HANDLED // finish processing for + // notification +}; + +// +// Priority class aliases +// + +#define PRIORITY_ALIAS_FIRST L"FIRST" +#define PRIORITY_ALIAS_HIGH L"HIGH" +#define PRIORITY_ALIAS_MEDIUM L"MEDIUM" +#define PRIORITY_ALIAS_LOW L"LOW" +#define PRIORITY_ALIAS_LAST L"LAST" + +// +// Cache operations +// + +typedef enum CACHE_OPERATION +{ + CACHE_OPERATION_RETRIEVE, + CACHE_OPERATION_ADD, + CACHE_OPERATION_DELETE, + CACHE_OPERATION_FLUSH_PREFIX, + CACHE_OPERATION_ENUM +}; + +// +// Module identifier +// + +typedef VOID* HTTP_MODULE_ID; + +// +// Flags for IHttpContext->CloneContext() +// + +#define CLONE_FLAG_BASICS 0x01 +#define CLONE_FLAG_HEADERS 0x02 +#define CLONE_FLAG_ENTITY 0x04 +#define CLONE_FLAG_NO_PRECONDITION 0x08 +#define CLONE_FLAG_NO_DAV 0x10 + +// +// Flags for IHttpContext->ExecuteRequest() +// + +#define EXECUTE_FLAG_NO_HEADERS 0x01 +#define EXECUTE_FLAG_IGNORE_CURRENT_INTERCEPTOR 0x02 +#define EXECUTE_FLAG_IGNORE_APPPOOL 0x04 +#define EXECUTE_FLAG_DISABLE_CUSTOM_ERROR 0x08 +#define EXECUTE_FLAG_SAME_URL 0x10 +// do not flush the child response but copy it back to the parent +#define EXECUTE_FLAG_BUFFER_RESPONSE 0x20 +// child response is still eligible for http.sys caching +#define EXECUTE_FLAG_HTTP_CACHE_ELIGIBLE 0x40 + + +// +// forward declarations +// +struct HTTP_TRACE_CONFIGURATION; +struct HTTP_TRACE_EVENT; + +class IWpfSettings; +class IHttpTraceContext; + +// +// Module-specific context descriptor +// +class __declspec(uuid("f1927f76-790e-4ccb-a72e-396bdfdae05d")) +IHttpStoredContext +{ + public: + virtual + VOID + CleanupStoredContext( + VOID + ) = 0; +}; + +// +// Context container +// +class __declspec(uuid("d7fad7c9-aa27-4ab9-bd60-e55ccba3f5dc")) +IHttpModuleContextContainer +{ + public: + virtual + IHttpStoredContext * + GetModuleContext( + IN HTTP_MODULE_ID moduleId + ) = 0; + + virtual + HRESULT + SetModuleContext( + IN IHttpStoredContext * ppStoredContext, + IN HTTP_MODULE_ID moduleId + ) = 0; +}; + +// +// Dispensed context container +// +class __declspec(uuid("2ae49359-95dd-4e48-ae20-c0cb9d0bc03a")) +IDispensedHttpModuleContextContainer : public IHttpModuleContextContainer +{ +public: + virtual + VOID + ReleaseContainer( + VOID + ) = 0; +}; + +// +// Performance counter descriptor +// +class __declspec(uuid("bdfc4c4a-12a4-4744-87d8-765eb320c59f")) +IHttpPerfCounterInfo +{ + public: + virtual + VOID + IncrementCounter( + DWORD dwCounterIndex, + DWORD dwValue = 1 + ) = 0; + + virtual + VOID + DecrementCounter( + DWORD dwCounterIndex, + DWORD dwValue = 1 + ) = 0; +}; + +// +// Application descriptor +// +class __declspec(uuid("3f75d9e6-1075-422c-ad89-93a85f2d7bdc")) +IHttpApplication +{ + public: + virtual + PCWSTR + GetApplicationPhysicalPath( + VOID + ) const = 0; + + virtual + PCWSTR + GetApplicationId( + VOID + ) const = 0; + + virtual + PCWSTR + GetAppConfigPath( + VOID + ) const = 0; + + virtual + IHttpModuleContextContainer * + GetModuleContextContainer( + VOID + ) = 0; +}; + +// +// URI cache entry descriptor +// +class __declspec(uuid("7e0e6167-0094-49a1-8287-ecf6dc6e73a6")) +IHttpUrlInfo +{ + public: + virtual + IHttpModuleContextContainer * + GetModuleContextContainer( + VOID + ) = 0; + + virtual + BOOL + IsFrequentlyHit( + VOID + ) const = 0; +}; + +// +// Script map descriptor +// +class __declspec(uuid("d7fe3d77-68bc-4d4a-851f-eec9fb68017c")) +IScriptMapInfo +{ + public: + virtual + PCWSTR + GetPath( + VOID + ) const = 0; + + virtual + PCSTR + GetAllowedVerbs( + VOID + ) const = 0; + + virtual + PCWSTR + GetModules( + OUT DWORD * pcchModules = NULL + ) const = 0; + + virtual + PCWSTR + GetScriptProcessor( + OUT DWORD * pcchScriptProcessor = NULL + ) const = 0; + + virtual + PCWSTR + GetManagedType( + OUT DWORD * pcchManagedType = NULL + ) const = 0; + + virtual + BOOL + GetAllowPathInfoForScriptMappings( + VOID + ) const = 0; + + virtual + DWORD + GetRequiredAccess( + VOID + ) const = 0; + + virtual + DWORD + GetResourceType( + VOID + ) const = 0; + + virtual + BOOL + GetIsStarScriptMap( + VOID + ) const = 0; + + virtual + DWORD + GetResponseBufferLimit( + VOID + ) const = 0; + + virtual + PCWSTR + GetName( + VOID + ) const = 0; +}; + +class __declspec(uuid("fd86e6de-fb0e-47dd-820a-e0da12be46e9")) +IHttpTokenEntry; + +// +// Metadata descriptor +// +class __declspec(uuid("48b10633-825d-495e-93b0-225380053e8e")) +IMetadataInfo +{ + public: + virtual + PCWSTR + GetMetaPath( + VOID + ) const = 0; + + virtual + PCWSTR + GetVrPath( + VOID + ) const = 0; + + virtual + IHttpTokenEntry * + GetVrToken( + VOID + ) = 0; + + virtual + IHttpModuleContextContainer * + GetModuleContextContainer( + VOID + ) = 0; +}; + +// +// Provides an interface to an HTTP request object. The methods on this +// class can be used to inspect and modify request data. +// +class __declspec(uuid("e8698f7e-576e-4cac-a309-67435355faef")) +IHttpRequest +{ + public: + virtual + HTTP_REQUEST * + GetRawHttpRequest( + VOID + ) = 0; + + virtual + const HTTP_REQUEST * + GetRawHttpRequest( + VOID + ) const = 0; + + virtual + PCSTR + GetHeader( + IN PCSTR pszHeaderName, + OUT USHORT * pcchHeaderValue = NULL + ) const = 0; + + virtual + PCSTR + GetHeader( + IN HTTP_HEADER_ID ulHeaderIndex, + OUT USHORT * pcchHeaderValue = NULL + ) const = 0; + + virtual + HRESULT + SetHeader( + IN PCSTR pszHeaderName, + IN PCSTR pszHeaderValue, + IN USHORT cchHeaderValue, + IN BOOL fReplace + ) = 0; + + virtual + HRESULT + SetHeader( + IN HTTP_HEADER_ID ulHeaderIndex, + IN PCSTR pszHeaderValue, + IN USHORT cchHeaderValue, + IN BOOL fReplace + ) = 0; + + virtual + HRESULT + DeleteHeader( + IN PCSTR pszHeaderName + ) = 0; + + virtual + HRESULT + DeleteHeader( + IN HTTP_HEADER_ID ulHeaderIndex + ) = 0; + + virtual + PCSTR + GetHttpMethod( + VOID + ) const = 0; + + virtual + HRESULT + SetHttpMethod( + IN PCSTR pszHttpMethod + ) = 0; + + virtual + HRESULT + SetUrl( + IN PCWSTR pszUrl, + IN DWORD cchUrl, + IN BOOL fResetQueryString + ) = 0; + + virtual + HRESULT + SetUrl( + IN PCSTR pszUrl, + IN DWORD cchUrl, + IN BOOL fResetQueryString + ) = 0; + + virtual + BOOL + GetUrlChanged( + VOID + ) const = 0; + + virtual + PCWSTR + GetForwardedUrl( + VOID + ) const = 0; + + virtual + PSOCKADDR + GetLocalAddress( + VOID + ) const = 0; + + virtual + PSOCKADDR + GetRemoteAddress( + VOID + ) const = 0; + + virtual + HRESULT + ReadEntityBody( + OUT VOID * pvBuffer, + IN DWORD cbBuffer, + IN BOOL fAsync, + OUT DWORD * pcbBytesReceived, + OUT BOOL * pfCompletionPending = NULL + ) = 0; + + virtual + HRESULT + InsertEntityBody( + IN VOID * pvBuffer, + IN DWORD cbBuffer + ) = 0; + + virtual + DWORD + GetRemainingEntityBytes( + VOID + ) = 0; + + virtual + VOID + GetHttpVersion( + OUT USHORT * pMajorVersion, + OUT USHORT * pMinorVersion + ) const = 0; + + virtual + HRESULT + GetClientCertificate( + OUT HTTP_SSL_CLIENT_CERT_INFO ** ppClientCertInfo, + OUT BOOL * pfClientCertNegotiated + ) = 0; + + virtual + HRESULT + NegotiateClientCertificate( + IN BOOL fAsync, + OUT BOOL * pfCompletionPending = NULL + ) = 0; + + virtual + DWORD + GetSiteId( + VOID + ) const = 0; + + virtual + HRESULT + GetHeaderChanges( + IN DWORD dwOldChangeNumber, + OUT DWORD * pdwNewChangeNumber, + IN OUT PCSTR knownHeaderSnapshot[HttpHeaderRequestMaximum], + IN OUT DWORD * pdwUnknownHeaderSnapshot, + IN OUT PCSTR **ppUnknownHeaderNameSnapshot, + IN OUT PCSTR **ppUnknownHeaderValueSnapshot, + __out_ecount(HttpHeaderRequestMaximum+1) + DWORD diffedKnownHeaderIndices[HttpHeaderRequestMaximum+1], + OUT DWORD * pdwDiffedUnknownHeaders, + OUT DWORD **ppDiffedUnknownHeaderIndices + ) = 0; +}; + +class __declspec(uuid("d9244ae1-51f8-4aa1-a66d-19277c33e610")) +IHttpRequest2 : public IHttpRequest +{ + public: + virtual + HRESULT + GetChannelBindingToken( + __deref_out_bcount_part(*pTokenSize, *pTokenSize) + PBYTE * ppToken, + DWORD * pTokenSize + ) = 0; +}; + +class __declspec(uuid("cb1c40ca-70f2-41a0-add2-881f5ef57388")) +IHttpCachePolicy +{ + public: + virtual + HTTP_CACHE_POLICY * + GetKernelCachePolicy( + VOID + ) = 0; + + virtual + VOID + SetKernelCacheInvalidatorSet( + VOID + ) = 0; + + virtual + HTTP_CACHE_POLICY * + GetUserCachePolicy( + VOID + ) = 0; + + virtual + HRESULT + AppendVaryByHeader( + PCSTR pszHeader + ) = 0; + + virtual + PCSTR + GetVaryByHeaders( + VOID + ) const = 0; + + virtual + HRESULT + AppendVaryByQueryString( + PCSTR pszParam + ) = 0; + + virtual + PCSTR + GetVaryByQueryStrings( + VOID + ) const = 0; + + virtual + HRESULT + SetVaryByValue( + PCSTR pszValue + ) = 0; + + virtual + PCSTR + GetVaryByValue( + VOID + ) const = 0; + + virtual + BOOL + IsUserCacheEnabled( + VOID + ) const = 0; + + virtual + VOID + DisableUserCache( + VOID + ) = 0; + + virtual + BOOL + IsCached( + VOID + ) const = 0; + + virtual + VOID + SetIsCached( + VOID + ) = 0; + + virtual + BOOL + GetKernelCacheInvalidatorSet( + VOID + ) const = 0; +}; + +class __declspec(uuid("9f4ba807-050e-4495-ae55-8870f7e9194a")) +IHttpCachePolicy2 : public IHttpCachePolicy +{ + public: + virtual + BOOL + IsForceUpdateSet( + VOID + ) const = 0; + + virtual + VOID + SetForceUpdate( + VOID + ) = 0; +}; + +// +// Response descriptor +// +class __declspec(uuid("7e1c6b38-628f-4e6c-95dc-41237eb7f95e")) +IHttpResponse +{ + public: + virtual + HTTP_RESPONSE * + GetRawHttpResponse( + VOID + ) = 0; + + virtual + const HTTP_RESPONSE * + GetRawHttpResponse( + VOID + ) const = 0; + + virtual + IHttpCachePolicy * + GetCachePolicy( + VOID + ) = 0; + + virtual + HRESULT + SetStatus( + IN USHORT statusCode, + IN PCSTR pszReason, + IN USHORT uSubStatus = 0, + IN HRESULT hrErrorToReport = S_OK, + IN IAppHostConfigException *pException = NULL, + IN BOOL fTrySkipCustomErrors = FALSE + ) = 0; + + virtual + HRESULT + SetHeader( + IN PCSTR pszHeaderName, + IN PCSTR pszHeaderValue, + IN USHORT cchHeaderValue, + IN BOOL fReplace + ) = 0; + + virtual + HRESULT + SetHeader( + IN HTTP_HEADER_ID ulHeaderIndex, + IN PCSTR pszHeaderValue, + IN USHORT cchHeaderValue, + IN BOOL fReplace + ) = 0; + + virtual + HRESULT + DeleteHeader( + IN PCSTR pszHeaderName + ) = 0; + + virtual + HRESULT + DeleteHeader( + IN HTTP_HEADER_ID ulHeaderIndex + ) = 0; + + virtual + PCSTR + GetHeader( + IN PCSTR pszHeaderName, + OUT USHORT * pcchHeaderValue = NULL + ) const = 0; + + virtual + PCSTR + GetHeader( + IN HTTP_HEADER_ID ulHeaderIndex, + OUT USHORT * pcchHeaderValue = NULL + ) const = 0; + + virtual + VOID + Clear( + VOID + ) = 0; + + virtual + VOID + ClearHeaders( + VOID + ) = 0; + + virtual + VOID + SetNeedDisconnect( + VOID + ) = 0; + + virtual + VOID + ResetConnection( + VOID + ) = 0; + + virtual + VOID + DisableKernelCache( + ULONG reason = 9 + ) = 0; + + virtual + BOOL + GetKernelCacheEnabled( + VOID + ) const = 0; + + virtual + VOID + SuppressHeaders( + VOID + ) = 0; + + virtual + BOOL + GetHeadersSuppressed( + VOID + ) const = 0; + + virtual + HRESULT + Flush( + IN BOOL fAsync, + IN BOOL fMoreData, + OUT DWORD * pcbSent, + OUT BOOL * pfCompletionExpected = NULL + ) = 0; + + virtual + HRESULT + Redirect( + IN PCSTR pszUrl, + IN BOOL fResetStatusCode = TRUE, + IN BOOL fIncludeParameters = FALSE + ) = 0; + + virtual + HRESULT + WriteEntityChunkByReference( + IN HTTP_DATA_CHUNK * pDataChunk, + IN LONG lInsertPosition = -1 + ) = 0; + + virtual + HRESULT + WriteEntityChunks( + IN HTTP_DATA_CHUNK * pDataChunks, + IN DWORD nChunks, + IN BOOL fAsync, + IN BOOL fMoreData, + OUT DWORD * pcbSent, + OUT BOOL * pfCompletionExpected = NULL + ) = 0; + + virtual + VOID + DisableBuffering( + VOID + ) = 0; + + virtual + VOID + GetStatus( + OUT USHORT * pStatusCode, + OUT USHORT * pSubStatus = NULL, + OUT PCSTR * ppszReason = NULL, + OUT USHORT * pcchReason = NULL, + OUT HRESULT * phrErrorToReport = NULL, + OUT PCWSTR * ppszModule = NULL, + OUT DWORD * pdwNotification = NULL, + OUT IAppHostConfigException ** ppException = NULL, + OUT BOOL * pfTrySkipCustomErrors = NULL + ) = 0; + + virtual + HRESULT + SetErrorDescription( + IN PCWSTR pszDescription, + IN DWORD cchDescription, + IN BOOL fHtmlEncode = TRUE + ) = 0; + + virtual + PCWSTR + GetErrorDescription( + OUT DWORD * pcchDescription = NULL + ) = 0; + + virtual + HRESULT + GetHeaderChanges( + IN DWORD dwOldChangeNumber, + OUT DWORD * pdwNewChangeNumber, + IN OUT PCSTR knownHeaderSnapshot[HttpHeaderResponseMaximum], + IN OUT DWORD * pdwUnknownHeaderSnapshot, + IN OUT PCSTR **ppUnknownHeaderNameSnapshot, + IN OUT PCSTR **ppUnknownHeaderValueSnapshot, + __out_ecount(HttpHeaderResponseMaximum+1) + DWORD diffedKnownHeaderIndices[HttpHeaderResponseMaximum+1], + OUT DWORD * pdwDiffedUnknownHeaders, + OUT DWORD **ppDiffedUnknownHeaderIndices + ) = 0; + + virtual + VOID + CloseConnection( + VOID + ) = 0; +}; + +// +// User descriptor +// +class __declspec(uuid("8059e6f8-10ce-4d61-b47e-5a1d8d9a8b67")) +IHttpUser +{ + public: + virtual + PCWSTR + GetRemoteUserName( + VOID + ) = 0; + + virtual + PCWSTR + GetUserName( + VOID + ) = 0; + + virtual + PCWSTR + GetAuthenticationType( + VOID + ) = 0; + + virtual + PCWSTR + GetPassword( + VOID + ) = 0; + + virtual + HANDLE + GetImpersonationToken( + VOID + ) = 0; + + virtual + HANDLE + GetPrimaryToken( + VOID + ) = 0; + + virtual + VOID + ReferenceUser( + VOID + ) = 0; + + virtual + VOID + DereferenceUser( + VOID + ) = 0; + + virtual + BOOL + SupportsIsInRole( + VOID + ) = 0; + + virtual + HRESULT + IsInRole( + IN PCWSTR pszRoleName, + OUT BOOL * pfInRole + ) = 0; + + virtual + PVOID + GetUserVariable( + IN PCSTR pszVariableName + ) = 0; +}; + +#define HTTP_USER_VARIABLE_SID "SID" +#define HTTP_USER_VARIABLE_CTXT_HANDLE "CtxtHandle" +#define HTTP_USER_VARIABLE_CRED_HANDLE "CredHandle" + +class __declspec(uuid("841d9a71-75f4-4626-8b97-66046ca7e45b")) +IHttpConnectionStoredContext : public IHttpStoredContext +{ + public: + virtual + VOID + NotifyDisconnect( + VOID + ) = 0; +}; + +class __declspec(uuid("f3dd2fb3-4d11-4295-b8ab-4cb667add1fe")) +IHttpConnectionModuleContextContainer : public IHttpModuleContextContainer +{ + public: + virtual + IHttpConnectionStoredContext * + GetConnectionModuleContext( + IN HTTP_MODULE_ID moduleId + ) = 0; + + virtual + HRESULT + SetConnectionModuleContext( + IN IHttpConnectionStoredContext * ppStoredContext, + IN HTTP_MODULE_ID moduleId + ) = 0; +}; + +// +// Connection descriptor +// +class __declspec(uuid("d9a5de00-3346-4599-9826-fe88565e1226")) +IHttpConnection +{ + public: + virtual + BOOL + IsConnected( + VOID + ) const = 0; + + virtual + VOID * + AllocateMemory( + DWORD cbAllocation + ) = 0; + + virtual + IHttpConnectionModuleContextContainer * + GetModuleContextContainer( + VOID + ) = 0; +}; + +// +// Forward declarations +// +class __declspec(uuid("71e95595-8c74-44d9-88a9-f5112d5f5900")) +IHttpFileInfo; + +class __declspec(uuid("eb16a6ec-ba5d-436f-bf24-3ede13906450")) +IHttpSite; + +class __declspec(uuid("671e6d34-9380-4df4-b453-91129df02b24")) +ICustomNotificationProvider; + +class __declspec(uuid("6f3f657d-2fb8-43c6-a096-5064b41f0580")) +IHttpEventProvider; + +class CHttpModule; + +// +// IHttpContext extended interface versions (deprecated) +// +enum HTTP_CONTEXT_INTERFACE_VERSION +{ +}; + +// +// Context object representing the processing of an HTTP request +// +class __declspec(uuid("424c1b8c-a1ba-44d7-ac98-9f8f457701a5")) +IHttpContext +{ + public: + virtual + IHttpSite * + GetSite( + VOID + ) = 0; + + virtual + IHttpApplication * + GetApplication( + VOID + ) = 0; + + virtual + IHttpConnection * + GetConnection( + VOID + ) = 0; + + virtual + IHttpRequest * + GetRequest( + VOID + ) = 0; + + virtual + IHttpResponse * + GetResponse( + VOID + ) = 0; + + virtual + BOOL + GetResponseHeadersSent( + VOID + ) const = 0; + + virtual + IHttpUser * + GetUser( + VOID + ) const = 0; + + virtual + IHttpModuleContextContainer * + GetModuleContextContainer( + VOID + ) = 0; + + virtual + VOID + IndicateCompletion( + IN REQUEST_NOTIFICATION_STATUS notificationStatus + ) = 0; + + virtual + HRESULT + PostCompletion( + IN DWORD cbBytes + ) = 0; + + virtual + VOID + DisableNotifications( + IN DWORD dwNotifications, + IN DWORD dwPostNotifications + ) = 0; + + virtual + BOOL + GetNextNotification( + IN REQUEST_NOTIFICATION_STATUS status, + OUT DWORD * pdwNotification, + OUT BOOL * pfIsPostNotification, + OUT CHttpModule ** ppModuleInfo, + OUT IHttpEventProvider ** ppRequestOutput + ) = 0; + + virtual + BOOL + GetIsLastNotification( + IN REQUEST_NOTIFICATION_STATUS status + ) = 0; + + virtual + HRESULT + ExecuteRequest( + IN BOOL fAsync, + IN IHttpContext * pHttpContext, + IN DWORD dwExecuteFlags, + IN IHttpUser * pHttpUser, + OUT BOOL * pfCompletionExpected = NULL + ) = 0; + + virtual + DWORD + GetExecuteFlags( + VOID + ) const = 0; + + virtual + HRESULT + GetServerVariable( + PCSTR pszVariableName, + __deref_out_ecount(*pcchValueLength) PCWSTR * ppszValue, + __out DWORD * pcchValueLength + ) = 0; + + virtual + HRESULT + GetServerVariable( + PCSTR pszVariableName, + __deref_out_ecount(*pcchValueLength) PCSTR * ppszValue, + __out DWORD * pcchValueLength + ) = 0; + + virtual + HRESULT + SetServerVariable( + PCSTR pszVariableName, + PCWSTR pszVariableValue + ) = 0; + + virtual + VOID * + AllocateRequestMemory( + IN DWORD cbAllocation + ) = 0; + + virtual + IHttpUrlInfo * + GetUrlInfo( + VOID + ) = 0; + + virtual + IMetadataInfo * + GetMetadata( + VOID + ) = 0; + + virtual + PCWSTR + GetPhysicalPath( + OUT DWORD * pcchPhysicalPath = NULL + ) = 0; + + virtual + PCWSTR + GetScriptName( + OUT DWORD * pcchScriptName = NULL + ) const = 0; + + virtual + PCWSTR + GetScriptTranslated( + OUT DWORD * pcchScriptTranslated = NULL + ) = 0; + + virtual + IScriptMapInfo * + GetScriptMap( + VOID + ) const = 0; + + virtual + VOID + SetRequestHandled( + VOID + ) = 0; + + virtual + IHttpFileInfo * + GetFileInfo( + VOID + ) const = 0; + + virtual + HRESULT + MapPath( + PCWSTR pszUrl, + __out_bcount_opt(*pcbPhysicalPath) PWSTR pszPhysicalPath, + IN OUT DWORD * pcbPhysicalPath + ) = 0; + + virtual + HRESULT + NotifyCustomNotification( + ICustomNotificationProvider * pCustomOutput, + OUT BOOL * pfCompletionExpected + ) = 0; + + virtual + IHttpContext * + GetParentContext( + VOID + ) const = 0; + + virtual + IHttpContext * + GetRootContext( + VOID + ) const = 0; + + virtual + HRESULT + CloneContext( + IN DWORD dwCloneFlags, + OUT IHttpContext ** ppHttpContext + ) = 0; + + virtual + HRESULT + ReleaseClonedContext( + VOID + ) = 0; + + virtual + HRESULT + GetCurrentExecutionStats( + OUT DWORD * pdwNotification, + OUT DWORD * pdwNotificationStartTickCount = NULL, + OUT PCWSTR * ppszModule = NULL, + OUT DWORD * pdwModuleStartTickCount = NULL, + OUT DWORD * pdwAsyncNotification = NULL, + OUT DWORD * pdwAsyncNotificationStartTickCount = NULL + ) const = 0; + + virtual + IHttpTraceContext * + GetTraceContext( + VOID + ) const = 0; + + virtual + HRESULT + GetServerVarChanges( + IN DWORD dwOldChangeNumber, + OUT DWORD * pdwNewChangeNumber, + IN OUT DWORD * pdwVariableSnapshot, + IN OUT PCSTR ** ppVariableNameSnapshot, + IN OUT PCWSTR ** ppVariableValueSnapshot, + OUT DWORD * pdwDiffedVariables, + OUT DWORD ** ppDiffedVariableIndices + ) = 0; + + virtual + HRESULT + CancelIo( + VOID + ) = 0; + + virtual + HRESULT + MapHandler( + IN DWORD dwSiteId, + IN PCWSTR pszSiteName, + IN PCWSTR pszUrl, + IN PCSTR pszVerb, + OUT IScriptMapInfo ** ppScriptMap, + IN BOOL fIgnoreWildcardMappings = FALSE + ) = 0; + + __declspec(deprecated("This method is deprecated. Use the HttpGetExtendedInterface helper function instead.")) + virtual + HRESULT + GetExtendedInterface( + IN HTTP_CONTEXT_INTERFACE_VERSION version, + OUT PVOID * ppInterface + ) = 0; +}; + +class __declspec(uuid("9f9098d5-915c-4294-a52e-66532a232bc9")) +IHttpTraceContext +{ +public: + virtual + HRESULT + GetTraceConfiguration( + IN OUT HTTP_TRACE_CONFIGURATION * pHttpTraceConfiguration + ) = 0; + + virtual + HRESULT + SetTraceConfiguration( + IN HTTP_MODULE_ID moduleId, + IN HTTP_TRACE_CONFIGURATION * pHttpTraceConfiguration, + IN DWORD cHttpTraceConfiguration = 1 + ) = 0; + + virtual + HRESULT + RaiseTraceEvent( + IN HTTP_TRACE_EVENT * pTraceEvent + ) = 0; + + virtual + LPCGUID + GetTraceActivityId( + ) = 0; + + virtual + HRESULT + QuickTrace( + IN PCWSTR pszData1, + IN PCWSTR pszData2 = NULL, + IN HRESULT hrLastError = S_OK, + // + // 4 == TRACE_LEVEL_INFORMATION + // + IN UCHAR Level = 4 + ) = 0; +}; + +class __declspec(uuid("37776aff-852e-4eec-93a5-b85a285a95b8")) +IHttpCacheSpecificData; + +// +// Cache helpers +// +class __declspec(uuid("cdef2aad-20b3-4512-b1b1-094b3844aeb2")) +IHttpCacheKey +{ + public: + virtual + DWORD + GetHash( + VOID + ) const = 0; + + virtual + PCWSTR + GetCacheName( + VOID + ) const = 0; + + virtual + bool + GetIsEqual( + IHttpCacheKey * pCacheCompareKey + ) const = 0; + + virtual + bool + GetIsPrefix( + IHttpCacheKey * pCacheCompareKey + ) const = 0; + + virtual + VOID + Enum( + IHttpCacheSpecificData * + ) = 0; +}; + +class __declspec(uuid("37776aff-852e-4eec-93a5-b85a285a95b8")) +IHttpCacheSpecificData +{ + public: + virtual + IHttpCacheKey * + GetCacheKey( + VOID + ) const = 0; + + virtual + VOID + ReferenceCacheData( + VOID + ) = 0; + + virtual + VOID + DereferenceCacheData( + VOID + ) = 0; + + virtual + VOID + ResetTTL( + VOID + ) = 0; + + virtual + VOID + DecrementTTL( + OUT BOOL *pfTTLExpired + ) = 0; + + virtual + VOID + SetFlushed( + VOID + ) = 0; + + virtual + BOOL + GetFlushed( + VOID + ) const = 0; +}; + +// +// Site descriptor +// +class __declspec(uuid("eb16a6ec-ba5d-436f-bf24-3ede13906450")) +IHttpSite +{ + public: + virtual + DWORD + GetSiteId( + VOID + ) const = 0; + + virtual + PCWSTR + GetSiteName( + VOID + ) const = 0; + + virtual + IHttpModuleContextContainer * + GetModuleContextContainer( + VOID + ) = 0; + + virtual + IHttpPerfCounterInfo * + GetPerfCounterInfo( + VOID + ) = 0; +}; + +// +// File change monitor +// +// +class __declspec(uuid("985422da-b0cf-473b-ba9e-8148ceb3e240")) +IHttpFileMonitor +{ + public: + virtual + IHttpModuleContextContainer * + GetModuleContextContainer( + VOID + ) = 0; + + virtual + VOID + DereferenceFileMonitor( + VOID + ) = 0; +}; + +// +// File descriptor +// +// +class __declspec(uuid("71e95595-8c74-44d9-88a9-f5112d5f5900")) +IHttpFileInfo : public IHttpCacheSpecificData +{ + public: + virtual + DWORD + GetAttributes( + VOID + ) const = 0; + + virtual + VOID + GetSize( + OUT ULARGE_INTEGER * pliSize + ) const = 0; + + virtual + const BYTE * + GetFileBuffer( + VOID + ) const = 0; + + virtual + HANDLE + GetFileHandle( + VOID + ) const = 0; + + virtual + PCWSTR + GetFilePath( + VOID + ) const = 0; + + virtual + PCSTR + GetETag( + OUT USHORT * pcchETag = NULL + ) const = 0; + + virtual + VOID + GetLastModifiedTime( + OUT FILETIME * pFileTime + ) const = 0; + + virtual + PCSTR + GetLastModifiedString( + VOID + ) const = 0; + + virtual + BOOL + GetHttpCacheAllowed( + OUT DWORD * pSecondsToLive + ) const = 0; + + virtual + HRESULT + AccessCheck( + IN HANDLE hUserToken, + IN PSID pUserSid + ) = 0; + + virtual + HANDLE + GetVrToken( + VOID + ) const = 0; + + virtual + PCWSTR + GetVrPath( + VOID + ) const = 0; + + virtual + IHttpModuleContextContainer * + GetModuleContextContainer( + VOID + ) = 0; + + virtual + BOOL + CheckIfFileHasChanged( + IN HANDLE hUserToken + ) = 0; +}; + + +// +// Token-cache entry +// +class __declspec(uuid("fd86e6de-fb0e-47dd-820a-e0da12be46e9")) +IHttpTokenEntry : public IHttpCacheSpecificData +{ + public: + virtual + HANDLE + GetImpersonationToken( + VOID + ) = 0; + + virtual + HANDLE + GetPrimaryToken( + VOID + ) = 0; + + virtual + PSID + GetSid( + VOID + ) = 0; +}; + + +// +// IHttpServer extended interface versions +// +enum HTTP_SERVER_INTERFACE_VERSION +{ + HTTP_SERVER_INTERFACE_V2 +}; + + +// +// Global utility descriptor +// +class __declspec(uuid("eda2a40f-fb92-4d6d-b52b-c8c207380b4e")) +IHttpServer +{ + public: + virtual + BOOL + IsCommandLineLaunch( + VOID + ) const = 0; + + virtual + PCWSTR + GetAppPoolName( + VOID + ) const = 0; + + virtual + HRESULT + AssociateWithThreadPool( + IN HANDLE hHandle, + IN LPOVERLAPPED_COMPLETION_ROUTINE completionRoutine + ) = 0; + + virtual + VOID + IncrementThreadCount( + VOID + ) = 0; + + virtual + VOID + DecrementThreadCount( + VOID + ) = 0; + + virtual + VOID + ReportUnhealthy( + IN PCWSTR pszReasonString, + IN HRESULT hrReason + ) = 0; + + virtual + VOID + RecycleProcess( + PCWSTR pszReason + ) = 0; + + virtual + IAppHostAdminManager * + GetAdminManager( + VOID + ) const = 0; + + virtual + HRESULT + GetFileInfo( + IN PCWSTR pszPhysicalPath, + IN HANDLE hUserToken, + IN PSID pSid, + IN PCWSTR pszChangeNotificationPath, + IN HANDLE hChangeNotificationToken, + IN BOOL fCache, + OUT IHttpFileInfo ** ppFileInfo, + IN IHttpTraceContext * pHttpTraceContext = NULL + ) = 0; + + virtual + HRESULT + FlushKernelCache( + IN PCWSTR pszUrl + ) = 0; + + virtual + HRESULT + DoCacheOperation( + IN CACHE_OPERATION cacheOperation, + IN IHttpCacheKey * pCacheKey, + OUT IHttpCacheSpecificData ** ppCacheSpecificData, + IN IHttpTraceContext * pHttpTraceContext = NULL + ) = 0; + + virtual + GLOBAL_NOTIFICATION_STATUS + NotifyCustomNotification( + ICustomNotificationProvider * pCustomOutput + ) = 0; + + virtual + IHttpPerfCounterInfo * + GetPerfCounterInfo( + VOID + ) = 0; + + virtual + VOID + RecycleApplication( + PCWSTR pszAppConfigPath + ) = 0; + + virtual + VOID + NotifyConfigurationChange( + PCWSTR pszPath + ) = 0; + + virtual + VOID + NotifyFileChange( + PCWSTR pszFileName + ) = 0; + + virtual + IDispensedHttpModuleContextContainer * + DispenseContainer( + VOID + ) = 0; + + virtual + HRESULT + AddFragmentToCache( + IN HTTP_DATA_CHUNK * pDataChunk, + PCWSTR pszFragmentName + ) = 0; + + virtual + HRESULT + ReadFragmentFromCache( + PCWSTR pszFragmentName, + OUT BYTE * pvBuffer, + DWORD cbSize, + OUT DWORD * pcbCopied + ) = 0; + + virtual + HRESULT + RemoveFragmentFromCache( + PCWSTR pszFragmentName + ) = 0; + + virtual + HRESULT + GetWorkerProcessSettings( + OUT IWpfSettings ** ppWorkerProcessSettings + ) = 0; + + virtual + HRESULT + GetProtocolManagerCustomInterface( + IN PCWSTR pProtocolManagerDll, + IN PCWSTR pProtocolManagerDllInitFunction, + IN DWORD dwCustomInterfaceId, + OUT PVOID* ppCustomInterface + ) = 0; + + virtual + BOOL + SatisfiesPrecondition( + PCWSTR pszPrecondition, + BOOL * pfUnknownPrecondition = NULL + ) const = 0; + + virtual + IHttpTraceContext * + GetTraceContext( + VOID + ) const = 0; + + virtual + HRESULT + RegisterFileChangeMonitor( + PCWSTR pszPath, + HANDLE hToken, + IHttpFileMonitor ** ppFileMonitor + ) = 0; + + virtual + HRESULT + GetExtendedInterface( + IN HTTP_SERVER_INTERFACE_VERSION version, + OUT PVOID * ppInterface + ) = 0; +}; + +class __declspec(uuid("34af637e-afe8-4556-bcc1-767f8e0b4a4e")) +IHttpServer2 : public IHttpServer +{ + public: + + virtual + HRESULT + GetToken( + PCWSTR pszUserName, + PCWSTR pszPassword, + DWORD dwLogonMethod, + IHttpTokenEntry ** ppTokenEntry, + PCWSTR pszDefaultDomain = NULL, + PSOCKADDR pSockAddr = NULL, + IHttpTraceContext * pHttpTraceContext = NULL + ) = 0; + + virtual + PCWSTR + GetAppPoolConfigFile( + __out DWORD * pcchConfigFilePath = NULL + ) const = 0; + + virtual + HRESULT + GetExtendedInterface( + __in const GUID & Version1, + __in PVOID pInput, + __in const GUID & Version2, + __deref_out PVOID * ppOutput + ) = 0; +}; + +// +// Helper function to get extended HTTP interfaces. +// +// Template parameters (HttpType1 and HttpType2) +// can be deduced from the arguments to the function. +// +// Example: +// +// IHttpRequest * pHttpRequest = pHttpContext->GetRequest(); +// IHttpRequest2 * pHttpRequest2; +// HRESULT hr = HttpGetExtendedInterface(g_pHttpServer, pHttpRequest, &pHttpRequest2); +// if( SUCCEEDED(hr) ) +// { +// // Use pHttpRequest2. +// } +// +// Where pHttpContext is an IHttpContext pointer and +// g_pHttpServer is an IHttpServer pointer. +// + +template +HRESULT +HttpGetExtendedInterface( + __in IHttpServer * pHttpServer, + __in HttpType1 * pInput, + __deref_out HttpType2 ** ppOutput +) +{ + HRESULT hr; + IHttpServer2 * pHttpServer2; + hr = pHttpServer->GetExtendedInterface(HTTP_SERVER_INTERFACE_V2, + reinterpret_cast(&pHttpServer2) ); + if (SUCCEEDED(hr)) + { + hr = pHttpServer2->GetExtendedInterface(__uuidof(HttpType1), + pInput, + __uuidof(HttpType2), + reinterpret_cast(ppOutput) ); + } + return hr; +} + +// +// Notification specific output for notifications +// +class __declspec(uuid("6f3f657d-2fb8-43c6-a096-5064b41f0580")) +IHttpEventProvider +{ + public: + virtual + VOID + SetErrorStatus( + HRESULT hrError + ) = 0; +}; + +// +// Completion information for notifications +// +class __declspec(uuid("49dd20e3-d9c0-463c-8821-f3413b55cc00")) +IHttpCompletionInfo +{ + public: + virtual + DWORD + GetCompletionBytes( + VOID + ) const = 0; + + virtual + HRESULT + GetCompletionStatus( + VOID + ) const = 0; +}; + +// +// RQ_ and GL_ CUSTOM_NOTIFICATION outputs +// +class __declspec(uuid("671e6d34-9380-4df4-b453-91129df02b24")) +ICustomNotificationProvider : public IHttpEventProvider +{ + public: + virtual + PCWSTR + QueryNotificationType( + VOID + ) = 0; +}; + +// +// RQ_REQUEST_AUTHENTICATE descriptor +// +class __declspec(uuid("304d51d0-0307-45ed-83fd-dd3fc032fdfc")) +IAuthenticationProvider : public IHttpEventProvider +{ + public: + virtual + VOID + SetUser( + IN IHttpUser * pUser + ) = 0; +}; + +// +// RQ_MAP_REQUEST_HANDLER +// +class __declspec(uuid("fea3ce6b-e346-47e7-b2a6-ad265baeff2c")) +IMapHandlerProvider : public IHttpEventProvider +{ + public: + virtual + HRESULT + SetScriptName( + PCWSTR pszScriptName, + DWORD cchScriptName + ) = 0; + + virtual + VOID + SetScriptMap( + IN IScriptMapInfo * pScriptMap + ) = 0; + + virtual + VOID + SetFileInfo( + IN IHttpFileInfo * pFileInfo + ) = 0; +}; + +// +// RQ_MAP_PATH +// +class __declspec(uuid("8efdf557-a8f1-4bc9-b462-6df3b038a59a")) +IMapPathProvider : public IHttpEventProvider +{ + public: + virtual + PCWSTR + GetUrl( + ) const = 0; + + virtual + PCWSTR + GetPhysicalPath( + ) const = 0; + + virtual + HRESULT + SetPhysicalPath( + PCWSTR pszPhysicalPath, + DWORD cchPhysicalPath + ) = 0; +}; + +// +// RQ_SEND_RESPONSE +// +class __declspec(uuid("57f2e7bc-0bcf-4a9f-94a4-10e55c6e5b51")) +ISendResponseProvider : public IHttpEventProvider +{ + public: + virtual + BOOL + GetHeadersBeingSent( + VOID + ) const = 0; + + virtual + DWORD + GetFlags( + VOID + ) const = 0; + + virtual + VOID + SetFlags( + DWORD dwFlags + ) = 0; + + virtual + HTTP_LOG_DATA * + GetLogData( + VOID + ) const = 0; + + virtual + HRESULT + SetLogData( + IN HTTP_LOG_DATA *pLogData + ) = 0; + + virtual + BOOL + GetReadyToLogData( + VOID + ) const = 0; +}; + +// +// RQ_READ_ENTITY +// +class __declspec(uuid("fe6d905a-99b8-49fd-b389-cfc809562b81")) +IReadEntityProvider : public IHttpEventProvider +{ + public: + virtual + VOID + GetEntity( + OUT PVOID * ppBuffer, + OUT DWORD * pcbData, + OUT DWORD * pcbBuffer + ) = 0; + + virtual + VOID + SetEntity( + IN PVOID pBuffer, + DWORD cbData, + DWORD cbBuffer + ) = 0; +}; + +// +// GL_PRE_BEGIN_REQUEST provider +// +class __declspec(uuid("fb715d26-aff9-476a-8fc0-6b1acb3d1098")) +IPreBeginRequestProvider : public IHttpEventProvider +{ + public: + virtual + IHttpContext * + GetHttpContext( + VOID + ) = 0; +}; + +// +// GL_APPLICATION_START provider +// +class __declspec(uuid("1de2c71c-c126-4512-aed3-f4f885e14997")) +IHttpApplicationProvider : public IHttpEventProvider +{ + public: + virtual + IHttpApplication * + GetApplication( + VOID + ) = 0; +}; + +typedef IHttpApplicationProvider IHttpApplicationStartProvider; + +class __declspec(uuid("ba32d330-9ea8-4b9e-89f1-8c76a323277f")) +IHttpModuleFactory; + +// +// GL_APPLICATION_RESOLVE_MODULES provider +// +class __declspec(uuid("0617d9b9-e20f-4a9f-94f9-35403b3be01e")) +IHttpApplicationResolveModulesProvider : public IHttpApplicationProvider +{ + public: + virtual + HRESULT + RegisterModule( + IN HTTP_MODULE_ID parentModuleId, + IN IHttpModuleFactory * pModuleFactory, + IN PCWSTR pszModuleName, + IN PCWSTR pszModuleType, + IN PCWSTR pszModulePreCondition, + IN DWORD dwRequestNotifications, + IN DWORD dwPostRequestNotifications + ) = 0; + + virtual + HRESULT + SetPriorityForRequestNotification( + IN PCWSTR pszModuleName, + IN DWORD dwRequestNotification, + IN PCWSTR pszPriorityAlias + ) = 0; +}; + +// +// GL_APPLICATION_STOP provider +// +typedef IHttpApplicationProvider IHttpApplicationStopProvider; + +// +// GL_RSCA_QUERY provider +// +class __declspec(uuid("63fdc43f-934a-4ee5-bcd8-7e7b50b75605")) +IGlobalRSCAQueryProvider : public IHttpEventProvider +{ + public: + virtual + PCWSTR + GetFunctionName( + VOID + ) const = 0; + + virtual + PCWSTR + GetFunctionParameters( + VOID + ) const = 0; + + virtual + HRESULT + GetOutputBuffer( + DWORD cbBuffer, + OUT BYTE ** ppbBuffer + ) = 0; + + virtual + HRESULT + ResizeOutputBuffer( + DWORD cbNewBuffer, + DWORD cbBytesToCopy, + IN OUT BYTE ** ppbBuffer + ) = 0; + + virtual + VOID + SetResult( + DWORD cbData, + HRESULT hr + ) = 0; +}; + +// +// GL_STOP_LISTENING +// +class __declspec(uuid("41f9a601-e25d-4ac8-8a1f-635698a30ab9")) +IGlobalStopListeningProvider : public IHttpEventProvider +{ + public: + virtual + BOOL + DrainRequestsGracefully( + VOID + ) const = 0; +}; + +// +// GL_CACHE_OPERATION +// +class __declspec(uuid("58925fb9-7c5e-4684-833b-4a04e1286690")) +ICacheProvider : public IHttpEventProvider +{ + public: + virtual + CACHE_OPERATION + GetCacheOperation( + VOID + ) const = 0; + + virtual + IHttpCacheKey * + GetCacheKey( + VOID + ) const = 0; + + virtual + IHttpCacheSpecificData * + GetCacheRecord( + VOID + ) const = 0; + + virtual + VOID + SetCacheRecord( + IHttpCacheSpecificData * pCacheRecord + ) = 0; + + virtual + IHttpTraceContext * + GetTraceContext( + VOID + ) const = 0; +}; + +// +// GL_CONFIGURATION_CHANGE +// +class __declspec(uuid("3405f3b4-b3d6-4b73-b5f5-4d8a3cc642ce")) +IGlobalConfigurationChangeProvider : public IHttpEventProvider +{ + public: + virtual + PCWSTR + GetChangePath( + VOID + ) const = 0; +}; + +// +// GL_FILE_CHANGE +// +class __declspec(uuid("ece31ee5-0486-4fb0-a875-6739a2d7daf5")) +IGlobalFileChangeProvider : public IHttpEventProvider +{ +public: + virtual + PCWSTR + GetFileName( + VOID + ) const = 0; + + virtual + IHttpFileMonitor * + GetFileMonitor( + VOID + ) = 0; +}; + +// +// GL_TRACE_EVENT +// +class __declspec(uuid("7c6bb150-0310-4718-a01f-6faceb62dc1d")) +IGlobalTraceEventProvider : public IHttpEventProvider +{ + public: + virtual + HRESULT + GetTraceEvent( + OUT HTTP_TRACE_EVENT ** ppTraceEvent + ) = 0; + + virtual + BOOL + CheckSubscription( + IN HTTP_MODULE_ID ModuleId + ) = 0; + + virtual + HRESULT + GetCurrentHttpRequestContext( + OUT IHttpContext ** ppHttpContext + ) = 0; +}; + +// +// GL_THREAD_CLEANUP +// +class __declspec(uuid("6b36a149-8620-45a0-8197-00814a706e2e")) +IGlobalThreadCleanupProvider : public IHttpEventProvider +{ +public: + virtual + IHttpApplication * + GetApplication( + VOID + ) = 0; +}; + +// +// GL_APPLICATION_PRELOAD +// +class __declspec(uuid("2111f8d6-0c41-4ff7-bd45-5c04c7e91a73")) +IGlobalApplicationPreloadProvider : public IHttpEventProvider +{ +public: + virtual + HRESULT + CreateContext( + OUT IHttpContext ** ppHttpContext + ) = 0; + + virtual + HRESULT + ExecuteRequest( + IN IHttpContext * pHttpContext, + IN IHttpUser * pHttpUser + ) = 0; +}; + +class CHttpModule +{ +public: + // RQ_BEGIN_REQUEST + + virtual + REQUEST_NOTIFICATION_STATUS + OnBeginRequest( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostBeginRequest( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + // RQ_AUTHENTICATE_REQUEST + + virtual + REQUEST_NOTIFICATION_STATUS + OnAuthenticateRequest( + IN IHttpContext * pHttpContext, + IN IAuthenticationProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostAuthenticateRequest( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + // RQ_AUTHORIZE_REQUEST + + virtual + REQUEST_NOTIFICATION_STATUS + OnAuthorizeRequest( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostAuthorizeRequest( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + // RQ_RESOLVE_REQUEST_CACHE + + virtual + REQUEST_NOTIFICATION_STATUS + OnResolveRequestCache( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostResolveRequestCache( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + // RQ_MAP_REQUEST_HANDLER + + virtual + REQUEST_NOTIFICATION_STATUS + OnMapRequestHandler( + IN IHttpContext * pHttpContext, + IN IMapHandlerProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostMapRequestHandler( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + // RQ_ACQUIRE_REQUEST_STATE + + virtual + REQUEST_NOTIFICATION_STATUS + OnAcquireRequestState( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostAcquireRequestState( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + // RQ_PRE_EXECUTE_REQUEST_HANDLER + + virtual + REQUEST_NOTIFICATION_STATUS + OnPreExecuteRequestHandler( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostPreExecuteRequestHandler( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + // RQ_EXECUTE_REQUEST_HANDLER + + virtual + REQUEST_NOTIFICATION_STATUS + OnExecuteRequestHandler( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostExecuteRequestHandler( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + // RQ_RELEASE_REQUEST_STATE + + virtual + REQUEST_NOTIFICATION_STATUS + OnReleaseRequestState( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostReleaseRequestState( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + // RQ_UPDATE_REQUEST_CACHE + + virtual + REQUEST_NOTIFICATION_STATUS + OnUpdateRequestCache( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostUpdateRequestCache( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + // RQ_LOG_REQUEST + + virtual + REQUEST_NOTIFICATION_STATUS + OnLogRequest( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostLogRequest( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + // RQ_END_REQUEST + + virtual + REQUEST_NOTIFICATION_STATUS + OnEndRequest( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + virtual + REQUEST_NOTIFICATION_STATUS + OnPostEndRequest( + IN IHttpContext * pHttpContext, + IN IHttpEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + // RQ_SEND_RESPONSE + + virtual + REQUEST_NOTIFICATION_STATUS + OnSendResponse( + IN IHttpContext * pHttpContext, + IN ISendResponseProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + // RQ_MAP_PATH + + virtual + REQUEST_NOTIFICATION_STATUS + OnMapPath( + IN IHttpContext * pHttpContext, + IN IMapPathProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + // RQ_READ_ENTITY + + virtual + REQUEST_NOTIFICATION_STATUS + OnReadEntity( + IN IHttpContext * pHttpContext, + IN IReadEntityProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + // RQ_CUSTOM_NOTIFICATION + + virtual + REQUEST_NOTIFICATION_STATUS + OnCustomRequestNotification( + IN IHttpContext * pHttpContext, + IN ICustomNotificationProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + // Completion + + virtual + REQUEST_NOTIFICATION_STATUS + OnAsyncCompletion( + IN IHttpContext * pHttpContext, + IN DWORD dwNotification, + IN BOOL fPostNotification, + IN IHttpEventProvider * pProvider, + IN IHttpCompletionInfo * pCompletionInfo + ) + { + UNREFERENCED_PARAMETER( pHttpContext ); + UNREFERENCED_PARAMETER( dwNotification ); + UNREFERENCED_PARAMETER( fPostNotification ); + UNREFERENCED_PARAMETER( pProvider ); + UNREFERENCED_PARAMETER( pCompletionInfo ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CHttpModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return RQ_NOTIFICATION_CONTINUE; + } + + virtual + VOID + Dispose( + VOID + ) + { + delete this; + } + + protected: + + CHttpModule() + {} + + virtual + ~CHttpModule() + {} +}; + +class CGlobalModule +{ + public: + + // GL_STOP_LISTENING + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalStopListening( + IN IGlobalStopListeningProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_CACHE_CLEANUP + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalCacheCleanup( + VOID + ) + { + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_CACHE_OPERATION + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalCacheOperation( + IN ICacheProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_HEALTH_CHECK + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalHealthCheck( + VOID + ) + { + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_CONFIGURATION_CHANGE + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalConfigurationChange( + IN IGlobalConfigurationChangeProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_FILE_CHANGE + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalFileChange( + IN IGlobalFileChangeProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_PRE_BEGIN_REQUEST + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalPreBeginRequest( + IN IPreBeginRequestProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_APPLICATION_START + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalApplicationStart( + IN IHttpApplicationStartProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_APPLICATION_RESOLVE_MODULES + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalApplicationResolveModules( + IN IHttpApplicationResolveModulesProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_APPLICATION_STOP + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalApplicationStop( + IN IHttpApplicationStopProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_RSCA_QUERY + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalRSCAQuery( + IN IGlobalRSCAQueryProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_TRACE_EVENT + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalTraceEvent( + IN IGlobalTraceEventProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_CUSTOM_NOTIFICATION + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalCustomNotification( + IN ICustomNotificationProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + virtual + VOID + Terminate( + VOID + ) = 0; + + // GL_THREAD_CLEANUP + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalThreadCleanup( + IN IGlobalThreadCleanupProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + + // GL_APPLICATION_PRELOAD + + virtual + GLOBAL_NOTIFICATION_STATUS + OnGlobalApplicationPreload( + IN IGlobalApplicationPreloadProvider * pProvider + ) + { + UNREFERENCED_PARAMETER( pProvider ); + OutputDebugStringA( + "This module subscribed to event " + __FUNCTION__ + " but did not override the method in its CGlobalModule implementation." + " Please check the method signature to make sure it matches the corresponding method.\n"); + DebugBreak(); + + return GL_NOTIFICATION_CONTINUE; + } + +}; + +class __declspec(uuid("85c1679c-0b21-491c-afb5-c7b5c86464c4")) +IModuleAllocator +{ + public: + virtual + VOID * + AllocateMemory( + IN DWORD cbAllocation + ) = 0; +}; + +class __declspec(uuid("ba32d330-9ea8-4b9e-89f1-8c76a323277f")) +IHttpModuleFactory +{ + public: + virtual + HRESULT + GetHttpModule( + OUT CHttpModule ** ppModule, + IN IModuleAllocator * pAllocator + ) = 0; + + virtual + VOID + Terminate( + VOID + ) = 0; +}; + +// +// Register-module descriptor +// +class __declspec(uuid("07e5beb3-b798-459d-a98a-e6c485b2b3bc")) +IHttpModuleRegistrationInfo +{ + public: + virtual + PCWSTR + GetName( + VOID + ) const = 0; + + virtual + HTTP_MODULE_ID + GetId( + VOID + ) const = 0; + + virtual + HRESULT + SetRequestNotifications( + IN IHttpModuleFactory * pModuleFactory, + IN DWORD dwRequestNotifications, + IN DWORD dwPostRequestNotifications + ) = 0; + + virtual + HRESULT + SetGlobalNotifications( + IN CGlobalModule * pGlobalModule, + IN DWORD dwGlobalNotifications + ) = 0; + + virtual + HRESULT + SetPriorityForRequestNotification( + IN DWORD dwRequestNotification, + IN PCWSTR pszPriority + ) = 0; + + virtual + HRESULT + SetPriorityForGlobalNotification( + IN DWORD dwGlobalNotification, + IN PCWSTR pszPriority + ) = 0; +}; + + +// +// Register Module entry point +// + +typedef +HRESULT +(WINAPI * PFN_REGISTERMODULE)( + DWORD dwServerVersion, + IHttpModuleRegistrationInfo * pModuleInfo, + IHttpServer * pGlobalInfo +); + +#define MODULE_REGISTERMODULE "RegisterModule" + +#endif diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hybrid_array.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hybrid_array.h new file mode 100644 index 0000000000..4d0d5735bc --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/hybrid_array.h @@ -0,0 +1,243 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +template +class HYBRID_ARRAY +{ +public: + + HYBRID_ARRAY( + VOID + ) : m_pArray(m_InlineArray), + m_Capacity(ARRAYSIZE(m_InlineArray)) + { + } + + ~HYBRID_ARRAY() + { + if ( !QueryUsesInlineArray() ) + { + delete [] m_pArray; + m_pArray = NULL; + } + } + + SIZE_T + QueryCapacity( + VOID + ) const + { + // + // Number of elements available in the array. + // + return m_Capacity; + } + + TYPE * + QueryArray( + VOID + ) const + { + // + // Raw pointer to the current array. + // + return m_pArray; + } + + TYPE & + QueryItem( + __in const SIZE_T Index + ) + { + // + // Gets the array item giving the index. + // + return m_pArray[Index]; + } + + TYPE & + operator [] (const SIZE_T Index) + { + // + // Operator override for convenience. + // Please don't add other overloads like '++' '--' + // in order to keep it simple. + // + return m_pArray[Index]; + } + + const TYPE & + operator [] (const SIZE_T Index) const + { + return m_pArray[Index]; + } + + template + HRESULT + Copy( + __in TYPE const (&SourceArray)[SourceSize], + __in bool fHasTrivialAssign = false + ) + /*++ + + Routine Description: + + Copies a source array like: + + int source[] = { 1, 2, 3 }; + hr = hybridArray.Copy( source ); + + It will statically determinate the length of the source array. + + Arguments: + + SourceArray - The array to copy. + SourceSize - The number of array elements. + fHasTrivialAssign - True if safe to perform buffer copy. + + Return Value: + + HRESULT + + --*/ + { + return Copy( SourceArray, SourceSize, fHasTrivialAssign ); + } + + HRESULT + Copy( + __in_ecount(SourceSize) + const TYPE * pSourceArray, + __in const SIZE_T SourceSize, + __in bool fHasTrivialAssign = false + ) + /*++ + + Routine Description: + + Copies a source array. + + Arguments: + + pSourceArray - The array to copy. + SourceSize - The number of array elements. + fHasTrivialAssign - True if safe to perform buffer copy. + + Return Value: + + HRESULT + + --*/ + { + HRESULT hr; + + hr = EnsureCapacity( SourceSize, + FALSE, // fCopyPrevious + FALSE ); // fHasTrivialAssign + if ( FAILED( hr ) ) + { + return hr; + } + + if ( fHasTrivialAssign ) // Future Work: use std::tr1::has_trivial_assign + { + CopyMemory(m_pArray, pSourceArray, m_Capacity * sizeof(TYPE)); + } + else + { + for ( SIZE_T Index = 0; Index < SourceSize; ++Index ) + { + m_pArray[Index] = pSourceArray[Index]; + } + } + + return S_OK; + } + + HRESULT + EnsureCapacity( + __in const SIZE_T MinimumCapacity, + __in bool fCopyPrevious, + __in bool fHasTrivialAssign = false + ) + /*++ + + Routine Description: + + Copies a source array. + + Arguments: + + MinimumCapacity - The expected length of the array. + fCopyPrevious - Must be always explicit parameter. + True if copy previous array data. + fHasTrivialAssign - True if safe to perform buffer copy. + + Return Value: + + HRESULT + + --*/ + { + // + // Caller is responsible for calculating a length that won't cause + // too many reallocations in the future. + // + + if ( MinimumCapacity <= ARRAYSIZE(m_InlineArray) ) + { + return S_OK; + } + + TYPE * pNewArray; + + pNewArray = new TYPE[ MinimumCapacity ]; + if ( pNewArray == NULL ) + { + return E_OUTOFMEMORY; + } + + if ( fCopyPrevious ) + { + if ( fHasTrivialAssign ) + { + CopyMemory(pNewArray, m_pArray, m_Capacity * sizeof(TYPE)); + } + else + { + for ( SIZE_T Index = 0; Index < m_Capacity; ++Index ) + { + pNewArray[Index] = m_pArray[Index]; + } + } + } + + if ( QueryUsesInlineArray() ) + { + m_pArray = pNewArray; + } + else + { + delete [] m_pArray; + m_pArray = pNewArray; + } + + m_Capacity = MinimumCapacity; + + return S_OK; + } + +private: + + bool + QueryUsesInlineArray( + VOID + ) const + { + return m_pArray == m_InlineArray; + } + + TYPE m_InlineArray[SIZE]; + TYPE * m_pArray; + SIZE_T m_Capacity; +}; \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/listentry.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/listentry.h new file mode 100644 index 0000000000..04c1d1ab46 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/listentry.h @@ -0,0 +1,163 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#ifndef _LIST_ENTRY_H +#define _LIST_ENTRY_H + +// +// Doubly-linked list manipulation routines. +// + + +#define InitializeListHead32(ListHead) (\ + (ListHead)->Flink = (ListHead)->Blink = PtrToUlong((ListHead))) + + +FORCEINLINE +VOID +InitializeListHead( + IN PLIST_ENTRY ListHead + ) +{ + ListHead->Flink = ListHead->Blink = ListHead; +} + +FORCEINLINE +BOOLEAN +IsListEmpty( + IN const LIST_ENTRY * ListHead + ) +{ + return (BOOLEAN)(ListHead->Flink == ListHead); +} + +FORCEINLINE +BOOLEAN +RemoveEntryList( + IN PLIST_ENTRY Entry + ) +{ + PLIST_ENTRY Blink; + PLIST_ENTRY Flink; + + Flink = Entry->Flink; + Blink = Entry->Blink; + Blink->Flink = Flink; + Flink->Blink = Blink; + return (BOOLEAN)(Flink == Blink); +} + +FORCEINLINE +PLIST_ENTRY +RemoveHeadList( + IN PLIST_ENTRY ListHead + ) +{ + PLIST_ENTRY Flink; + PLIST_ENTRY Entry; + + Entry = ListHead->Flink; + Flink = Entry->Flink; + ListHead->Flink = Flink; + Flink->Blink = ListHead; + return Entry; +} + + + +FORCEINLINE +PLIST_ENTRY +RemoveTailList( + IN PLIST_ENTRY ListHead + ) +{ + PLIST_ENTRY Blink; + PLIST_ENTRY Entry; + + Entry = ListHead->Blink; + Blink = Entry->Blink; + ListHead->Blink = Blink; + Blink->Flink = ListHead; + return Entry; +} + + +FORCEINLINE +VOID +InsertTailList( + IN PLIST_ENTRY ListHead, + IN PLIST_ENTRY Entry + ) +{ + PLIST_ENTRY Blink; + + Blink = ListHead->Blink; + Entry->Flink = ListHead; + Entry->Blink = Blink; + Blink->Flink = Entry; + ListHead->Blink = Entry; +} + + +FORCEINLINE +VOID +InsertHeadList( + IN PLIST_ENTRY ListHead, + IN PLIST_ENTRY Entry + ) +{ + PLIST_ENTRY Flink; + + Flink = ListHead->Flink; + Entry->Flink = Flink; + Entry->Blink = ListHead; + Flink->Blink = Entry; + ListHead->Flink = Entry; +} + +FORCEINLINE +VOID +AppendTailList( + IN PLIST_ENTRY ListHead, + IN PLIST_ENTRY ListToAppend + ) +{ + PLIST_ENTRY ListEnd = ListHead->Blink; + + ListHead->Blink->Flink = ListToAppend; + ListHead->Blink = ListToAppend->Blink; + ListToAppend->Blink->Flink = ListHead; + ListToAppend->Blink = ListEnd; +} + +FORCEINLINE +PSINGLE_LIST_ENTRY +PopEntryList( + PSINGLE_LIST_ENTRY ListHead + ) +{ + PSINGLE_LIST_ENTRY FirstEntry; + FirstEntry = ListHead->Next; + if (FirstEntry != NULL) { + ListHead->Next = FirstEntry->Next; + } + + return FirstEntry; +} + + +FORCEINLINE +VOID +PushEntryList( + PSINGLE_LIST_ENTRY ListHead, + PSINGLE_LIST_ENTRY Entry + ) +{ + Entry->Next = ListHead->Next; + ListHead->Next = Entry; +} + + +#endif diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/macros.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/macros.h new file mode 100644 index 0000000000..56a67eb1c4 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/macros.h @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _MACROS_H +#define _MACROS_H + +// +// The DIFF macro should be used around an expression involving pointer +// subtraction. The expression passed to DIFF is cast to a size_t type, +// allowing the result to be easily assigned to any 32-bit variable or +// passed to a function expecting a 32-bit argument. +// + +#define DIFF(x) ((size_t)(x)) + +// Change a hexadecimal digit to its numerical equivalent +#define TOHEX( ch ) \ + ((ch) > L'9' ? \ + (ch) >= L'a' ? \ + (ch) - L'a' + 10 : \ + (ch) - L'A' + 10 \ + : (ch) - L'0') + + +// Change a number to its Hexadecimal equivalent + +#define TODIGIT( nDigit ) \ + (CHAR)((nDigit) > 9 ? \ + (nDigit) - 10 + 'A' \ + : (nDigit) + '0') + + +inline int +SAFEIsSpace(UCHAR c) +{ + return isspace( c ); +} + +inline int +SAFEIsAlNum(UCHAR c) +{ + return isalnum( c ); +} + +inline int +SAFEIsAlpha(UCHAR c) +{ + return isalpha( c ); +} + +inline int +SAFEIsXDigit(UCHAR c) +{ + return isxdigit( c ); +} + +inline int +SAFEIsDigit(UCHAR c) +{ + return isdigit( c ); +} + +#endif // _MACROS_H diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/multisz.hxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/multisz.hxx new file mode 100644 index 0000000000..dd891b3252 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/multisz.hxx @@ -0,0 +1,225 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _MULTISZ_HXX_ +#define _MULTISZ_HXX_ + +# include + + +/*++ + class MULTISZ: + + Intention: + A light-weight multi-string class supporting encapsulated string class. + + This object is derived from BUFFER class. + It maintains following state: + + m_fValid - whether this object is valid - + used only by MULTISZ() init functions + * NYI: I need to kill this someday * + m_cchLen - string length cached when we update the string. + m_cStrings - number of strings. + + Member Functions: + There are two categories of functions: + 1) Safe Functions - which do integrity checking of state + 2) UnSafe Functions - which do not do integrity checking, but + enable writing to the data stream freely. + (someday this will be enabled as Safe versions without + problem for users) + +--*/ +class MULTISZ : public BUFFER +{ +public: + + MULTISZ() + : BUFFER (), + m_cchLen ( 0), + m_cStrings(0) + { Reset(); } + + // creates a stack version of the MULTISZ object - uses passed in stack buffer + // MULTISZ does not free this pbInit on its own. + MULTISZ( __in_bcount(cbInit) WCHAR * pbInit, DWORD cbInit) + : BUFFER( (BYTE *) pbInit, cbInit), + m_cchLen (0), + m_cStrings(0) + {} + + MULTISZ( const WCHAR * pchInit ) + : BUFFER (), + m_cchLen ( 0), + m_cStrings(0) + { AuxInit(pchInit); } + + MULTISZ( const MULTISZ & str ) + : BUFFER (), + m_cchLen ( 0), + m_cStrings(0) + { AuxInit( str.QueryStr()); } + +// BOOL IsValid(VOID) const { return ( BUFFER::IsValid()) ; } + // + // Checks and returns TRUE if this string has no valid data else FALSE + // + BOOL IsEmpty( VOID) const { return ( *QueryStr() == L'\0'); } + + BOOL Append( const WCHAR * pchInit ) { + return ((pchInit != NULL) ? (AuxAppend( pchInit, + (DWORD) (::wcslen(pchInit)) * sizeof(WCHAR) + )) : + TRUE); + } + + + BOOL Append( const WCHAR * pchInit, DWORD cchLen ) { + return ((pchInit != NULL) ? (AuxAppend( pchInit, + cchLen * sizeof(WCHAR))) : + TRUE); + } + + BOOL Append( STRU & str ) + { return AuxAppend( str.QueryStr(), + (str.QueryCCH()) * sizeof(WCHAR)); } + + // Resets the internal string to be NULL string. Buffer remains cached. + VOID Reset( VOID) + { DBG_ASSERT( QueryPtr() != NULL); + QueryStr()[0] = L'\0'; + QueryStr()[1] = L'\0'; + m_cchLen = 2; + m_cStrings = 0; + } + + BOOL Copy( const WCHAR * pchInit, IN DWORD cbLen ) { + if ( QueryPtr() ) { Reset(); } + return ( (pchInit != NULL) ? + AuxAppend( pchInit, cbLen, FALSE ): + TRUE); + } + + BOOL Copy( const MULTISZ & str ) + { return ( Copy(str.QueryStr(), str.QueryCB())); } + + // + // Returns the number of bytes in the string including the terminating + // NULLs + // + UINT QueryCB( VOID ) const + { return ( m_cchLen * sizeof(WCHAR)); } + + // + // Returns # of characters in the string including the terminating NULLs + // + UINT QueryCCH( VOID ) const { return (m_cchLen); } + + // + // Returns # of strings in the multisz. + // + + DWORD QueryStringCount( VOID ) const { return m_cStrings; } + + // + // Makes a copy of the stored string in given buffer + // + BOOL CopyToBuffer( __out_ecount_opt(*lpcch) WCHAR * lpszBuffer, LPDWORD lpcch) const; + + // + // Return the string buffer + // + WCHAR * QueryStrA( VOID ) const { return ( QueryStr()); } + WCHAR * QueryStr( VOID ) const { return ((WCHAR *) QueryPtr()); } + + // + // Makes a clone of the current string in the string pointer passed in. + // + BOOL + Clone( OUT MULTISZ * pstrClone) const + { + return ((pstrClone == NULL) ? + (SetLastError(ERROR_INVALID_PARAMETER), FALSE) : + (pstrClone->Copy( *this)) + ); + } // MULTISZ::Clone() + + // + // Recalculates the length of *this because we've modified the buffers + // directly + // + + VOID RecalcLen( VOID ) + { m_cchLen = MULTISZ::CalcLength( QueryStr(), &m_cStrings ); } + + // + // Calculate total character length of a MULTI_SZ, including the + // terminating NULLs. + // + + static DWORD CalcLength( const WCHAR * str, + LPDWORD pcStrings = NULL ); + + // + // Determine if the MULTISZ contains a specific string. + // + + BOOL FindString( const WCHAR * str ); + + BOOL FindString( STRU & str ) + { return FindString( str.QueryStr() ); } + + // + // Determine if the MULTISZ contains a specific string - case-insensitive + // + + BOOL FindStringNoCase( const WCHAR * str ); + + BOOL FindStringNoCase( STRU & str ) + { return FindStringNoCase( str.QueryStr() ); } + + // + // Used for scanning a multisz. + // + + const WCHAR * First( VOID ) const + { return *QueryStr() == L'\0' ? NULL : QueryStr(); } + + const WCHAR * Next( const WCHAR * Current ) const + { Current += ::wcslen( Current ) + 1; + return *Current == L'\0' ? NULL : Current; } + + BOOL + Equals( + MULTISZ* pmszRhs + ); + +private: + + DWORD m_cchLen; + DWORD m_cStrings; + VOID AuxInit( const WCHAR * pInit ); + BOOL AuxAppend( const WCHAR * pInit, + UINT cbStr, BOOL fAddSlop = TRUE ); + +}; + +// +// Quick macro for declaring a MULTISZ that will use stack memory of +// bytes. If the buffer overflows then a heap buffer will be allocated +// + +#define STACK_MULTISZ( name, size ) WCHAR __ach##name[size]; \ + MULTISZ name( __ach##name, sizeof( __ach##name )) + +HRESULT +SplitCommaDelimitedString( + PCWSTR pszList, + BOOL fTrimEntries, + BOOL fRemoveEmptyEntries, + MULTISZ * pmszList +); + +#endif // !_MULTISZ_HXX_ + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/multisza.hxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/multisza.hxx new file mode 100644 index 0000000000..44aa802563 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/multisza.hxx @@ -0,0 +1,225 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _MULTISZA_HXX_ +#define _MULTISZA_HXX_ + +# include + + +/*++ + class MULTISZ: + + Intention: + A light-weight multi-string class supporting encapsulated string class. + + This object is derived from BUFFER class. + It maintains following state: + + m_fValid - whether this object is valid - + used only by MULTISZ() init functions + * NYI: I need to kill this someday * + m_cchLen - string length cached when we update the string. + m_cStrings - number of strings. + + Member Functions: + There are two categories of functions: + 1) Safe Functions - which do integrity checking of state + 2) UnSafe Functions - which do not do integrity checking, but + enable writing to the data stream freely. + (someday this will be enabled as Safe versions without + problem for users) + +--*/ +class MULTISZA : public BUFFER +{ +public: + + MULTISZA() + : BUFFER (), + m_cchLen ( 0), + m_cStrings(0) + { Reset(); } + + // creates a stack version of the MULTISZA object - uses passed in stack buffer + // MULTISZA does not free this pbInit on its own. + MULTISZA( __in_bcount(cbInit) CHAR * pbInit, DWORD cbInit) + : BUFFER( (BYTE *) pbInit, cbInit), + m_cchLen (0), + m_cStrings(0) + {} + + MULTISZA( const CHAR * pchInit ) + : BUFFER (), + m_cchLen ( 0), + m_cStrings(0) + { AuxInit(pchInit); } + + MULTISZA( const MULTISZA & str ) + : BUFFER (), + m_cchLen ( 0), + m_cStrings(0) + { AuxInit( str.QueryStr()); } + +// BOOL IsValid(VOID) const { return ( BUFFER::IsValid()) ; } + // + // Checks and returns TRUE if this string has no valid data else FALSE + // + BOOL IsEmpty( VOID) const { return ( *QueryStr() == L'\0'); } + + BOOL Append( const CHAR * pchInit ) { + return ((pchInit != NULL) ? (AuxAppend( pchInit, + (DWORD) (::strlen(pchInit)) * sizeof(CHAR) + )) : + TRUE); + } + + + BOOL Append( const CHAR * pchInit, DWORD cchLen ) { + return ((pchInit != NULL) ? (AuxAppend( pchInit, + cchLen * sizeof(CHAR))) : + TRUE); + } + + BOOL Append( STRA & str ) + { return AuxAppend( str.QueryStr(), + (str.QueryCCH()) * sizeof(CHAR)); } + + // Resets the internal string to be NULL string. Buffer remains cached. + VOID Reset( VOID) + { DBG_ASSERT( QueryPtr() != NULL); + QueryStr()[0] = L'\0'; + QueryStr()[1] = L'\0'; + m_cchLen = 2; + m_cStrings = 0; + } + + BOOL Copy( const CHAR * pchInit, IN DWORD cbLen ) { + if ( QueryPtr() ) { Reset(); } + return ( (pchInit != NULL) ? + AuxAppend( pchInit, cbLen, FALSE ): + TRUE); + } + + BOOL Copy( const MULTISZA & str ) + { return ( Copy(str.QueryStr(), str.QueryCB())); } + + // + // Returns the number of bytes in the string including the terminating + // NULLs + // + UINT QueryCB( VOID ) const + { return ( m_cchLen * sizeof(CHAR)); } + + // + // Returns # of characters in the string including the terminating NULLs + // + UINT QueryCCH( VOID ) const { return (m_cchLen); } + + // + // Returns # of strings in the MULTISZA. + // + + DWORD QueryStringCount( VOID ) const { return m_cStrings; } + + // + // Makes a copy of the stored string in given buffer + // + BOOL CopyToBuffer( __out_ecount_opt(*lpcch) CHAR * lpszBuffer, LPDWORD lpcch) const; + + // + // Return the string buffer + // + CHAR * QueryStrA( VOID ) const { return ( QueryStr()); } + CHAR * QueryStr( VOID ) const { return ((CHAR *) QueryPtr()); } + + // + // Makes a clone of the current string in the string pointer passed in. + // + BOOL + Clone( OUT MULTISZA * pstrClone) const + { + return ((pstrClone == NULL) ? + (SetLastError(ERROR_INVALID_PARAMETER), FALSE) : + (pstrClone->Copy( *this)) + ); + } // MULTISZA::Clone() + + // + // Recalculates the length of *this because we've modified the buffers + // directly + // + + VOID RecalcLen( VOID ) + { m_cchLen = MULTISZA::CalcLength( QueryStr(), &m_cStrings ); } + + // + // Calculate total character length of a MULTI_SZ, including the + // terminating NULLs. + // + + static DWORD CalcLength( const CHAR * str, + LPDWORD pcStrings = NULL ); + + // + // Determine if the MULTISZA contains a specific string. + // + + BOOL FindString( const CHAR * str ); + + BOOL FindString( STRA & str ) + { return FindString( str.QueryStr() ); } + + // + // Determine if the MULTISZA contains a specific string - case-insensitive + // + + BOOL FindStringNoCase( const CHAR * str ); + + BOOL FindStringNoCase( STRA & str ) + { return FindStringNoCase( str.QueryStr() ); } + + // + // Used for scanning a MULTISZA. + // + + const CHAR * First( VOID ) const + { return *QueryStr() == L'\0' ? NULL : QueryStr(); } + + const CHAR * Next( const CHAR * Current ) const + { Current += ::strlen( Current ) + 1; + return *Current == L'\0' ? NULL : Current; } + + BOOL + Equals( + MULTISZA* pmszRhs + ); + +private: + + DWORD m_cchLen; + DWORD m_cStrings; + VOID AuxInit( const CHAR * pInit ); + BOOL AuxAppend( const CHAR * pInit, + UINT cbStr, BOOL fAddSlop = TRUE ); + +}; + +// +// Quick macro for declaring a MULTISZA that will use stack memory of +// bytes. If the buffer overflows then a heap buffer will be allocated +// + +#define STACK_MULTISZA( name, size ) CHAR __ach##name[size]; \ + MULTISZA name( __ach##name, sizeof( __ach##name )) + +HRESULT +SplitCommaDelimitedString( + PCSTR pszList, + BOOL fTrimEntries, + BOOL fRemoveEmptyEntries, + MULTISZA * pmszList +); + +#endif // !_MULTISZA_HXX_ + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/normalize.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/normalize.h new file mode 100644 index 0000000000..411c3660a4 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/normalize.h @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef __NORMALIZE_URL__H__ +#define __NORMALIZE_URL__H__ + +HRESULT +NormalizeUrl( + __inout LPSTR pszUrl +); + + +HRESULT +NormalizeUrlW( + __inout LPWSTR pszUrl +); + + + +HRESULT +UlCleanAndCopyUrl( + __in LPSTR pSource, + IN ULONG SourceLength, + OUT PULONG pBytesCopied, + __inout PWSTR pDestination, + __deref_opt_out_opt PWSTR * ppQueryString OPTIONAL +); + +HRESULT +UlInitializeParsing( + VOID +); + +HRESULT +InitializeNormalizeUrl( + VOID +); + + +#endif \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/ntassert.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/ntassert.h new file mode 100644 index 0000000000..8a8d656f21 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/ntassert.h @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#ifdef _ASSERTE + #undef _ASSERTE +#endif + +#ifdef ASSERT + #undef ASSERT +#endif + +#if defined( DBG ) && DBG + #define SX_ASSERT( _x ) ( (VOID)( ( ( _x ) ) ? TRUE : ( __annotation( L"Debug", L"AssertFail", L#_x ), DbgRaiseAssertionFailure(), FALSE ) ) ) + #define SX_ASSERTMSG( _m, _x ) ( (VOID)( ( ( _x ) ) ? TRUE : ( __annotation( L"Debug", L"AssertFail", L##_m ), DbgRaiseAssertionFailure(), FALSE ) ) ) + #define SX_VERIFY( _x ) SX_ASSERT( _x ) + #define _ASSERTE( _x ) SX_ASSERT( _x ) + #define ASSERT( _x ) SX_ASSERT( _x ) + #define assert( _x ) SX_ASSERT( _x ) + #define DBG_ASSERT( _x ) SX_ASSERT( _x ) + #define DBG_REQUIRE( _x ) SX_ASSERT( _x ) +#else + #define SX_ASSERT( _x ) ( (VOID)0 ) + #define SX_ASSERTMSG( _m, _x ) ( (VOID)0 ) + #define SX_VERIFY( _x ) ( (VOID)( ( _x ) ? TRUE : FALSE ) ) + #define _ASSERTE( _x ) ( (VOID)0 ) + #define assert( _x ) ( (VOID)0 ) + #define DBG_ASSERT( _x ) ( (VOID)0 ) + #define DBG_REQUIRE( _x ) ((VOID)(_x)) +#endif + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/percpu.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/percpu.h new file mode 100644 index 0000000000..ae59b1c805 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/percpu.h @@ -0,0 +1,305 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +template +class PER_CPU +{ +public: + + template + inline + static + HRESULT + Create( + FunctionInitializer Initializer, + __deref_out PER_CPU ** ppInstance + ); + + inline + T * + GetLocal( + VOID + ); + + template + inline + VOID + ForEach( + FunctionForEach Function + ); + + inline + VOID + Dispose( + VOID + ); + +private: + + PER_CPU( + VOID + ) + { + // + // Don't perform any operation during constructor. + // Constructor will never be called. + // + } + + ~PER_CPU( + VOID + ) + { + // + // Don't perform any operation during destructor. + // Constructor will never be called. + // + } + + template + HRESULT + Initialize( + FunctionInitializer Initializer, + DWORD NumberOfVariables, + DWORD Alignment + ); + + T * + GetObject( + DWORD Index + ); + + static + HRESULT + GetProcessorInformation( + __out DWORD * pCacheLineSize, + __out DWORD * pNumberOfProcessors + ); + + // + // Pointer to the begining of the inlined array. + // + PVOID m_pVariables; + SIZE_T m_Alignment; + SIZE_T m_VariablesCount; +}; + +template +template +inline +// static +HRESULT +PER_CPU::Create( + FunctionInitializer Initializer, + __deref_out PER_CPU ** ppInstance +) +{ + HRESULT hr = S_OK; + DWORD CacheLineSize = 0; + DWORD ObjectCacheLineSize = 0; + DWORD NumberOfProcessors = 0; + PER_CPU * pInstance = NULL; + + hr = GetProcessorInformation(&CacheLineSize, + &NumberOfProcessors); + if (FAILED(hr)) + { + goto Finished; + } + + if (sizeof(T) > CacheLineSize) + { + // + // Round to the next multiple of the cache line size. + // + ObjectCacheLineSize = (sizeof(T) + CacheLineSize-1) & (CacheLineSize-1); + } + else + { + ObjectCacheLineSize = CacheLineSize; + } + + // + // Calculate the size of the PER_CPU object, including the array. + // The first cache line is for the member variables and the array + // starts in the next cache line. + // + SIZE_T Size = CacheLineSize + NumberOfProcessors * ObjectCacheLineSize; + + pInstance = (PER_CPU*) _aligned_malloc(Size, CacheLineSize); + if (pInstance == NULL) + { + hr = E_OUTOFMEMORY; + goto Finished; + } + ZeroMemory(pInstance, Size); + + // + // The array start in the 2nd cache line. + // + pInstance->m_pVariables = reinterpret_cast(pInstance) + CacheLineSize; + + // + // Pass a disposer for disposing initialized items in case of failure. + // + hr = pInstance->Initialize(Initializer, + NumberOfProcessors, + ObjectCacheLineSize); + if (FAILED(hr)) + { + goto Finished; + } + + *ppInstance = pInstance; + pInstance = NULL; + +Finished: + + if (pInstance != NULL) + { + // + // Free the instance without disposing it. + // + pInstance->Dispose(); + pInstance = NULL; + } + + return hr; +} + +template +inline +T * +PER_CPU::GetLocal( + VOID +) +{ + // Use GetCurrentProcessorNumber (up to 64 logical processors) instead of + // GetCurrentProcessorNumberEx (more than 64 logical processors) because + // the number of processors are not densely packed per group. + // The idea of distributing variables per CPU is to have + // a scalability multiplier (could be NUMA node instead). + // + // Make sure the index don't go beyond the array size, if that happens, + // there won't be even distribution, but still better + // than one single variable. + // + return GetObject(GetCurrentProcessorNumber()); +} + +template +inline +T * +PER_CPU::GetObject( + DWORD Index +) +{ + return reinterpret_cast(static_cast(m_pVariables) + Index * m_Alignment); +} + +template +template +inline +VOID +PER_CPU::ForEach( + FunctionForEach Function +) +{ + for(DWORD Index = 0; Index < m_VariablesCount; ++Index) + { + T * pObject = GetObject(Index); + Function(pObject); + } +} + +template +VOID +PER_CPU::Dispose( + VOID +) +{ + _aligned_free(this); +} + +template +template +inline +HRESULT +PER_CPU::Initialize( + FunctionInitializer Initializer, + DWORD NumberOfVariables, + DWORD Alignment +) +/*++ + +Routine Description: + + Initialize each object using the initializer function. + If initialization for any object fails, it dispose the + objects that were successfully initialized. + +Arguments: + + Initializer - Function for initialize one object. + Signature: HRESULT Func(T*) + Dispose - Function for disposing initialized objects in case of failure. + Signature: void Func(T*) + NumberOfVariables - The length of the array of variables. + Alignment - Alignment to use for avoiding false sharing. + +Return: + + HRESULT - E_OUTOFMEMORY + +--*/ +{ + HRESULT hr = S_OK; + DWORD Index = 0; + + m_VariablesCount = NumberOfVariables; + m_Alignment = Alignment; + + for (; Index < m_VariablesCount; ++Index) + { + T * pObject = GetObject(Index); + Initializer(pObject); + } + + return hr; +} + +template +// static +HRESULT +PER_CPU::GetProcessorInformation( + __out DWORD * pCacheLineSize, + __out DWORD * pNumberOfProcessors +) +/*++ + +Routine Description: + + Gets the CPU cache-line size for the current system. + This information is used for avoiding CPU false sharing. + +Arguments: + + pCacheLineSize - The processor cache-line size. + pNumberOfProcessors - Maximum number of processors per group. + +Return: + + HRESULT - E_OUTOFMEMORY + +--*/ +{ + SYSTEM_INFO SystemInfo = { }; + + GetSystemInfo(&SystemInfo); + *pNumberOfProcessors = SystemInfo.dwNumberOfProcessors; + *pCacheLineSize = SYSTEM_CACHE_ALIGNMENT_SIZE; + + return S_OK; +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/prime.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/prime.h new file mode 100644 index 0000000000..77fcb75b8a --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/prime.h @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include +#include + +// +// Pre-calculated prime numbers (up to 10,049,369). +// +extern __declspec(selectany) const DWORD g_Primes [] = { + 3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, + 761, 919, 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, + 12143, 14591, 17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, + 130363, 156437, 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, + 968897, 1162687, 1395263, 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, + 5999471, 7199369, 7849369, 8649369, 9249369, 10049369 +}; + +class PRIME +{ +public: + + static + DWORD + GetPrime( + DWORD dwMinimum + ) + { + // + // Try to use the precalculated numbers. + // + for ( DWORD Index = 0; Index < _countof( g_Primes ); Index++ ) + { + DWORD dwCandidate = g_Primes[Index]; + if ( dwCandidate >= dwMinimum ) + { + return dwCandidate; + } + } + + // + // Do calculation. + // + for ( DWORD dwCandidate = dwMinimum | 1; + dwCandidate < MAXDWORD; + dwCandidate += 2 ) + { + if ( IsPrime( dwCandidate ) ) + { + return dwCandidate; + } + } + return dwMinimum; + } + +private: + + static + BOOL + IsPrime( + DWORD dwCandidate + ) + { + if ((dwCandidate & 1) == 0) + { + return ( dwCandidate == 2 ); + } + + DWORD dwMax = static_cast(sqrt(static_cast(dwCandidate))); + + for ( DWORD Index = 3; Index <= dwMax; Index += 2 ) + { + if ( (dwCandidate % Index) == 0 ) + { + return FALSE; + } + } + return TRUE; + } + + PRIME() {} + ~PRIME() {} +}; \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/reftrace.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/reftrace.h new file mode 100644 index 0000000000..ace85dcde2 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/reftrace.h @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _REFTRACE_H_ +#define _REFTRACE_H_ + + +#if defined(__cplusplus) +extern "C" { +#endif // __cplusplus + + +#include + + +// +// This is the number of stack backtrace values captured in each +// trace log entry. This value is chosen to make the log entry +// exactly twelve dwords long, making it a bit easier to interpret +// from within the debugger without the debugger extension. +// + +#define REF_TRACE_LOG_STACK_DEPTH 9 + +// No-op value for the Context1,2,3 parameters of WriteRefTraceLogEx +//#define REF_TRACE_EMPTY_CONTEXT ((PVOID) -1) +#define REF_TRACE_EMPTY_CONTEXT NULL + + +// +// This defines the entry written to the trace log. +// + +typedef struct _REF_TRACE_LOG_ENTRY { + + LONG NewRefCount; + CONST VOID * Context; + CONST VOID * Context1; + CONST VOID * Context2; + CONST VOID * Context3; + DWORD Thread; + PVOID Stack[REF_TRACE_LOG_STACK_DEPTH]; + +} REF_TRACE_LOG_ENTRY, *PREF_TRACE_LOG_ENTRY; + + +// +// Manipulators. +// + +PTRACE_LOG +CreateRefTraceLog( + IN LONG LogSize, + IN LONG ExtraBytesInHeader + ); + +VOID +DestroyRefTraceLog( + IN PTRACE_LOG Log + ); + +LONG +__cdecl +WriteRefTraceLog( + IN PTRACE_LOG Log, + IN LONG NewRefCount, + IN CONST VOID * Context + ); + +LONG +__cdecl +WriteRefTraceLogEx( + IN PTRACE_LOG Log, + IN LONG NewRefCount, + IN CONST VOID * Context, + IN CONST VOID * Context1, + IN CONST VOID * Context2, + IN CONST VOID * Context3 + ); + + +#if defined(__cplusplus) +} // extern "C" +#endif // __cplusplus + + +#endif // _REFTRACE_H_ + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/rwlock.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/rwlock.h new file mode 100644 index 0000000000..50b9b1ca11 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/rwlock.h @@ -0,0 +1,193 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#if (_WIN32_WINNT < 0x600) + +// +// XP implementation. +// +class CWSDRWLock +{ +public: + + CWSDRWLock() + : m_bInited(FALSE) + { + } + + ~CWSDRWLock() + { + if (m_bInited) + { + DeleteCriticalSection(&m_rwLock.critsec); + CloseHandle(m_rwLock.ReadersDoneEvent); + } + } + + BOOL QueryInited() const + { + return m_bInited; + } + + HRESULT Init() + { + HRESULT hr = S_OK; + + if (FALSE == m_bInited) + { + m_rwLock.fWriterWaiting = FALSE; + m_rwLock.LockCount = 0; + if ( !InitializeCriticalSectionAndSpinCount( &m_rwLock.critsec, 0 )) + { + DWORD dwError = GetLastError(); + hr = HRESULT_FROM_WIN32(dwError); + return hr; + } + + m_rwLock.ReadersDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if( NULL == m_rwLock.ReadersDoneEvent ) + { + DWORD dwError = GetLastError(); + hr = HRESULT_FROM_WIN32(dwError); + DeleteCriticalSection(&m_rwLock.critsec); + return hr; + } + m_bInited = TRUE; + } + + return hr; + } + + void SharedAcquire() + { + EnterCriticalSection(&m_rwLock.critsec); + InterlockedIncrement(&m_rwLock.LockCount); + LeaveCriticalSection(&m_rwLock.critsec); + } + + void SharedRelease() + { + ReleaseRWLock(); + } + + void ExclusiveAcquire() + { + EnterCriticalSection( &m_rwLock.critsec ); + + m_rwLock.fWriterWaiting = TRUE; + + // check if there are any readers active + if ( InterlockedExchangeAdd( &m_rwLock.LockCount, 0 ) > 0 ) + { + // + // Wait for all the readers to get done.. + // + WaitForSingleObject( m_rwLock.ReadersDoneEvent, INFINITE ); + } + m_rwLock.LockCount = -1; + } + + void ExclusiveRelease() + { + ReleaseRWLock(); + } + +private: + + BOOL m_bInited; + + typedef struct _RW_LOCK + { + BOOL fWriterWaiting; // Is a writer waiting on the lock? + LONG LockCount; + CRITICAL_SECTION critsec; + HANDLE ReadersDoneEvent; + } RW_LOCK, *PRW_LOCK; + + RW_LOCK m_rwLock; + +private: + + void ReleaseRWLock() + { + LONG Count = InterlockedDecrement( &m_rwLock.LockCount ); + + if ( 0 <= Count ) + { + // releasing a read lock + if (( m_rwLock.fWriterWaiting ) && ( 0 == Count )) + { + SetEvent( m_rwLock.ReadersDoneEvent ); + } + } + else + { + // Releasing a write lock + m_rwLock.LockCount = 0; + m_rwLock.fWriterWaiting = FALSE; + LeaveCriticalSection(&m_rwLock.critsec); + } + } +}; + +#else + +// +// Implementation for Windows Vista or greater. +// +class CWSDRWLock +{ +public: + + CWSDRWLock() + { + InitializeSRWLock(&m_rwLock); + } + + BOOL QueryInited() + { + return TRUE; + } + + + HRESULT Init() + { + // + // Method defined to keep compatibility with CWSDRWLock class for XP. + // + return S_OK; + } + + void SharedAcquire() + { + AcquireSRWLockShared(&m_rwLock); + } + + void SharedRelease() + { + ReleaseSRWLockShared(&m_rwLock); + } + + void ExclusiveAcquire() + { + AcquireSRWLockExclusive(&m_rwLock); + } + + void ExclusiveRelease() + { + ReleaseSRWLockExclusive(&m_rwLock); + } + +private: + + SRWLOCK m_rwLock; +}; + +#endif + +// +// Rename the lock class to a more clear name. +// +typedef CWSDRWLock READ_WRITE_LOCK; \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/statichash.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/statichash.h new file mode 100644 index 0000000000..f2c7980405 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/statichash.h @@ -0,0 +1,730 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef __STATIC_HASH__H_ +#define __STATIC_HASH__H_ + +#define STATIC_STRING_HASH_BUCKETS 131 + +// +// SERVER_VARIABLE_HASH maps server variable string to routines to eval them +// + +struct STATIC_STRING_HASH_RECORD +{ + CHAR * _pszName; + STATIC_STRING_HASH_RECORD * _pNext; + USHORT _cchName; +}; + +struct STATIC_STRING_HASH_ITER +{ + STATIC_STRING_HASH_RECORD *_pCursor; + DWORD _dwBucket; + BOOL _fRemove; +}; + +class STATIC_STRING_HASH +{ + public: + + STATIC_STRING_HASH( + BOOL fCaseSensitive = FALSE + ) : _fCaseSensitive( fCaseSensitive ) + { + Reset(); + } + + VOID + Reset() + { + ZeroMemory( &_rgBuckets, sizeof( _rgBuckets ) ); + } + + static + PCSTR + ExtractKey( + __in const STATIC_STRING_HASH_RECORD * pRecord + ) + /*++ + + Routine Description: + + Get the key out of the record + + Arguments: + + record to fetch the key from + + Return Value: + + key + + --*/ + { + DBG_ASSERT( pRecord != NULL ); + return pRecord->_pszName; + } + + VOID + InsertRecord( + __in STATIC_STRING_HASH_RECORD * pRecord + ) + /*++ + + Routine Description: + + Insert record to hash table + + Note: remember this is static hash table + There is no synchronization on the table + Exclusive acess must be assured by caller + + Arguments: + + record to fetch the key from + + Return Value: + + VOID + + --*/ + { + DWORD dwIndex; + STATIC_STRING_HASH_RECORD* pCursor; + + DBG_ASSERT( pRecord != NULL ); + DBG_ASSERT( pRecord->_pszName != NULL ); + + if(NULL == pRecord->_pszName) + { + return; + } + + if (_fCaseSensitive) + { + dwIndex = HashString( pRecord->_pszName ) % STATIC_STRING_HASH_BUCKETS; + } + else + { + dwIndex = HashStringNoCase( pRecord->_pszName ) % STATIC_STRING_HASH_BUCKETS; + } + + pCursor = _rgBuckets[ dwIndex ]; + + pRecord->_pNext = pCursor; + _rgBuckets[ dwIndex ] = pRecord; + } + + STATIC_STRING_HASH_RECORD * + FindKey( + __in PCSTR pszName, + BOOL fRemove = FALSE + ) + /*++ + + Routine Description: + + Find key in the table (and remove it optionally) + + Arguments: + + key + + Return Value: + + record containing the key + + --*/ + { + DWORD dwIndex; + STATIC_STRING_HASH_RECORD* pRecord; + STATIC_STRING_HASH_RECORD* pLastRecord = NULL; + + DBG_ASSERT( pszName != NULL ); + + if (_fCaseSensitive) + { + dwIndex = HashString( pszName ) % STATIC_STRING_HASH_BUCKETS; + } + else + { + dwIndex = HashStringNoCase( pszName ) % STATIC_STRING_HASH_BUCKETS; + } + + pRecord = _rgBuckets[ dwIndex ]; + while ( pRecord != NULL ) + { + if (_fCaseSensitive) + { + if ( strcmp( pszName, pRecord->_pszName ) == 0 ) + { + break; + } + } + else if ( _stricmp( pszName, pRecord->_pszName ) == 0 ) + { + break; + } + + pLastRecord = pRecord; + pRecord = pRecord->_pNext; + } + + if (fRemove && + pRecord != NULL) + { + if (pLastRecord != NULL) + { + pLastRecord->_pNext = pRecord->_pNext; + } + else + { + _rgBuckets[dwIndex] = pRecord->_pNext; + } + } + + return pRecord; + } + + BOOL + CheckDistribution( + IN DWORD dwConflictThreshold, + IN BOOL fToDebugger + ) + /*++ + + Routine Description: + + Simple verification on conflicts within the table + + Arguments: + + dwConflictThreshold - max number of entries tolerated per bucket + fToDebbuger - spew the entries exceeding threshold into debugger + + Return Value: + + FALSE it threshold was reached (means hash funcion may not be optimal) + + --*/ + { + BOOL fThresholdReached = FALSE; + STATIC_STRING_HASH_RECORD* pRecord; + for ( DWORD dwIndex = 0; dwIndex < STATIC_STRING_HASH_BUCKETS; dwIndex++) + { + pRecord = _rgBuckets[ dwIndex ]; + DWORD countInBucket = 0; + while ( pRecord != NULL ) + { + countInBucket++; + pRecord = pRecord->_pNext; + } + // + // print out the list of multiple entries in bucket + // + if ( countInBucket > dwConflictThreshold && fToDebugger ) + { + fThresholdReached = TRUE; + + pRecord = _rgBuckets[ dwIndex ]; + while ( pRecord != NULL ) + { + pRecord = pRecord->_pNext; + } + } + } + return fThresholdReached; + } + + STATIC_STRING_HASH_RECORD * + FindFirst( + STATIC_STRING_HASH_ITER *pIterator, + BOOL fRemove = FALSE + ) + /*++ + + Routine Description: + + Begins a new hash item enumeration. + + Arguments: + + pIterator - Supplies the context for the enumeration. + + fRemove - Supplies TRUE if the items should be removed + from the hash as they are enumerated. + + Return Value: + + The first entry in the hash if successful, NULL otherwise. + + --*/ + { + pIterator->_dwBucket = 0; + pIterator->_fRemove = fRemove; + pIterator->_pCursor = FindNextBucket(&pIterator->_dwBucket); + + if (pIterator->_fRemove && pIterator->_pCursor != NULL) + { + _rgBuckets[pIterator->_dwBucket] = pIterator->_pCursor->_pNext; + } + + return pIterator->_pCursor; + } + + STATIC_STRING_HASH_RECORD * + FindNext( + STATIC_STRING_HASH_ITER *pIterator + ) + /*++ + + Routine Description: + + Continues a hash item enumeration. + + Arguments: + + pIterator - Supplies the context for the enumeration. + + Return Value: + + The next entry in the hash if successful, NULL otherwise. + + --*/ + { + if (pIterator->_pCursor != NULL) + { + if (pIterator->_fRemove) + { + pIterator->_pCursor = _rgBuckets[pIterator->_dwBucket]; + } + else + { + pIterator->_pCursor = pIterator->_pCursor->_pNext; + } + + if (pIterator->_pCursor == NULL) + { + pIterator->_dwBucket++; + pIterator->_pCursor = FindNextBucket(&pIterator->_dwBucket); + } + } + + if (pIterator->_fRemove && pIterator->_pCursor != NULL) + { + _rgBuckets[pIterator->_dwBucket] = pIterator->_pCursor->_pNext; + } + + return pIterator->_pCursor; + } + + protected: + + STATIC_STRING_HASH_RECORD * _rgBuckets[ STATIC_STRING_HASH_BUCKETS ]; + + private: + + BOOL _fCaseSensitive; + + STATIC_STRING_HASH_RECORD * + FindNextBucket( + DWORD *pdwStartingBucket + ) + /*++ + + Routine Description: + + Scan for the next non-empty bucket. + + Arguments: + + pdwStartingBucket - Supplies a pointer to the starting + bucket index. This value is updated with the index + of the next non-empty bucket if successful. + + Return Value: + + The first entry in the next non-empty bucket if successful, + NULL otherwise. + + --*/ + { + DWORD i; + STATIC_STRING_HASH_RECORD *pScan = NULL; + + for (i = *pdwStartingBucket ; i < STATIC_STRING_HASH_BUCKETS ; i++) + { + pScan = _rgBuckets[i]; + + if (pScan != NULL) + { + break; + } + } + + *pdwStartingBucket = i; + return pScan; + } +}; + + + + +struct STATIC_WSTRING_HASH_RECORD +{ + WCHAR * _pszName; + STATIC_WSTRING_HASH_RECORD * _pNext; + USHORT _cchName; +}; + + +struct STATIC_WSTRING_HASH_ITER +{ + STATIC_WSTRING_HASH_RECORD *_pCursor; + DWORD _dwBucket; + BOOL _fRemove; +}; + + +class STATIC_WSTRING_HASH +{ + public: + STATIC_WSTRING_HASH( + BOOL fCaseSensitive = FALSE + ) : _fCaseSensitive( fCaseSensitive ) + { + Reset(); + } + + VOID + Reset() + { + ZeroMemory( &_rgBuckets, sizeof( _rgBuckets ) ); + } + + static + PCWSTR + ExtractKey( + __in const STATIC_WSTRING_HASH_RECORD * pRecord + ) + /*++ + + Routine Description: + + Get the key out of the record + + Arguments: + + record to fetch the key from + + Return Value: + + key + + --*/ + { + DBG_ASSERT( pRecord != NULL ); + return pRecord->_pszName; + } + + VOID + InsertRecord( + __in STATIC_WSTRING_HASH_RECORD * pRecord + ) + /*++ + + Routine Description: + + Insert record to hash table + + Note: remember this is static hash table + There is no synchronization on the table + Exclusive acess must be assured by caller + + Arguments: + + record to fetch the key from + + Return Value: + + VOID + + --*/ + { + DWORD dwIndex; + STATIC_WSTRING_HASH_RECORD* pCursor; + + DBG_ASSERT( pRecord != NULL ); + DBG_ASSERT( pRecord->_pszName != NULL ); + + if (_fCaseSensitive) + { + dwIndex = HashString( pRecord->_pszName ) % STATIC_STRING_HASH_BUCKETS; + } + else + { + dwIndex = HashStringNoCase( pRecord->_pszName ) % STATIC_STRING_HASH_BUCKETS; + } + + pCursor = _rgBuckets[ dwIndex ]; + + pRecord->_pNext = pCursor; + _rgBuckets[ dwIndex ] = pRecord; + } + + STATIC_WSTRING_HASH_RECORD * + FindKey( + __in PCWSTR pszName, + BOOL fRemove = FALSE + ) + /*++ + + Routine Description: + + Find key in the table (and remove it optionally) + + Arguments: + + key + + Return Value: + + record containing the key + + --*/ + { + DWORD dwIndex; + STATIC_WSTRING_HASH_RECORD* pRecord; + STATIC_WSTRING_HASH_RECORD* pLastRecord = NULL; + + DBG_ASSERT( pszName != NULL ); + + if (_fCaseSensitive) + { + dwIndex = HashString( pszName ) % STATIC_STRING_HASH_BUCKETS; + } + else + { + dwIndex = HashStringNoCase( pszName ) % STATIC_STRING_HASH_BUCKETS; + } + + pRecord = _rgBuckets[ dwIndex ]; + while ( pRecord != NULL ) + { + if ( _fCaseSensitive ) + { + if ( wcscmp( pszName, pRecord->_pszName ) == 0 ) + { + break; + } + } + else if ( _wcsicmp( pszName, pRecord->_pszName ) == 0 ) + { + break; + } + + pLastRecord = pRecord; + pRecord = pRecord->_pNext; + } + + if (fRemove && + pRecord != NULL) + { + if (pLastRecord != NULL) + { + pLastRecord->_pNext = pRecord->_pNext; + } + else + { + _rgBuckets[dwIndex] = pRecord->_pNext; + } + } + + return pRecord; + } + + BOOL + CheckDistribution( + IN DWORD dwConflictThreshold, + IN BOOL fToDebugger + ) + /*++ + + Routine Description: + + Simple verification on conflicts within the table + + Arguments: + + dwConflictThreshold - max number of entries tolerated per bucket + fToDebbuger - spew the entries exceeding threshold into debugger + + Return Value: + + FALSE it threshold was reached (means hash funcion may not be optimal) + + --*/ + { + BOOL fThresholdReached = FALSE; + STATIC_WSTRING_HASH_RECORD* pRecord; + for ( DWORD dwIndex = 0; dwIndex < STATIC_STRING_HASH_BUCKETS; dwIndex++) + { + pRecord = _rgBuckets[ dwIndex ]; + DWORD countInBucket = 0; + while ( pRecord != NULL ) + { + countInBucket++; + pRecord = pRecord->_pNext; + } + // + // print out the list of multiple entries in bucket + // + if ( countInBucket > dwConflictThreshold && fToDebugger ) + { + fThresholdReached = TRUE; + + pRecord = _rgBuckets[ dwIndex ]; + while ( pRecord != NULL ) + { + pRecord = pRecord->_pNext; + } + } + } + return fThresholdReached; + } + + STATIC_WSTRING_HASH_RECORD * + FindFirst( + STATIC_WSTRING_HASH_ITER *pIterator, + BOOL fRemove = FALSE + ) + /*++ + + Routine Description: + + Begins a new hash item enumeration. + + Arguments: + + pIterator - Supplies the context for the enumeration. + + fRemove - Supplies TRUE if the items should be removed + from the hash as they are enumerated. + + Return Value: + + The first entry in the hash if successful, NULL otherwise. + + --*/ + { + pIterator->_dwBucket = 0; + pIterator->_fRemove = fRemove; + pIterator->_pCursor = FindNextBucket(&pIterator->_dwBucket); + + if (pIterator->_fRemove && pIterator->_pCursor != NULL) + { + _rgBuckets[pIterator->_dwBucket] = pIterator->_pCursor->_pNext; + } + + return pIterator->_pCursor; + } + + STATIC_WSTRING_HASH_RECORD * + FindNext( + STATIC_WSTRING_HASH_ITER *pIterator + ) + /*++ + + Routine Description: + + Continues a hash item enumeration. + + Arguments: + + pIterator - Supplies the context for the enumeration. + + Return Value: + + The next entry in the hash if successful, NULL otherwise. + + --*/ + { + if (pIterator->_pCursor != NULL) + { + if (pIterator->_fRemove) + { + pIterator->_pCursor = _rgBuckets[pIterator->_dwBucket]; + } + else + { + pIterator->_pCursor = pIterator->_pCursor->_pNext; + } + + if (pIterator->_pCursor == NULL) + { + pIterator->_dwBucket++; + pIterator->_pCursor = FindNextBucket(&pIterator->_dwBucket); + } + } + + if (pIterator->_fRemove && pIterator->_pCursor != NULL) + { + _rgBuckets[pIterator->_dwBucket] = pIterator->_pCursor->_pNext; + } + + return pIterator->_pCursor; + } + + protected: + + STATIC_WSTRING_HASH_RECORD * _rgBuckets[ STATIC_STRING_HASH_BUCKETS ]; + + private: + + BOOL _fCaseSensitive; + + STATIC_WSTRING_HASH_RECORD * + FindNextBucket( + DWORD *pdwStartingBucket + ) + /*++ + + Routine Description: + + Scan for the next non-empty bucket. + + Arguments: + + pdwStartingBucket - Supplies a pointer to the starting + bucket index. This value is updated with the index + of the next non-empty bucket if successful. + + Return Value: + + The first entry in the next non-empty bucket if successful, + NULL otherwise. + + --*/ + { + DWORD i; + STATIC_WSTRING_HASH_RECORD *pScan = NULL; + + for (i = *pdwStartingBucket ; i < STATIC_STRING_HASH_BUCKETS ; i++) + { + pScan = _rgBuckets[i]; + + if (pScan != NULL) + { + break; + } + } + + *pdwStartingBucket = i; + return pScan; + } +}; + + +#endif //__STATIC_HASH__H_ + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stdtypes.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stdtypes.h new file mode 100644 index 0000000000..53a631b036 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stdtypes.h @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +// +// Use C++ standard 'nullptr' +// + +#ifdef NULL +#undef NULL +#endif + +#ifdef __cplusplus +#ifdef _NATIVE_NULLPTR_SUPPORTED +#define NULL nullptr +#else +#define NULL 0 +#define nullptr 0 +#endif +#else +#define NULL ((void *)0) +//#define nullptr ((void *)0) +#endif diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stringa.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stringa.h new file mode 100644 index 0000000000..d38604014e --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stringa.h @@ -0,0 +1,515 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "buffer.h" +#include "macros.h" +#include + +class STRA +{ + +public: + + STRA( + VOID + ); + + STRA( + __inout_ecount(cchInit) CHAR* pbInit, + __in DWORD cchInit + ); + + BOOL + IsEmpty( + VOID + ) const; + + BOOL + Equals( + __in PCSTR pszRhs, + __in BOOL fIgnoreCase = FALSE + ) const; + + BOOL + Equals( + __in const STRA * pstrRhs, + __in BOOL fIgnoreCase = FALSE + ) const; + + BOOL + Equals( + __in const STRA & strRhs, + __in BOOL fIgnoreCase = FALSE + ) const; + + static + BOOL + Equals( + __in PCSTR pszLhs, + __in PCSTR pszRhs, + __in bool fIgnoreCase = false + ) + { + // Return FALSE if either or both strings are NULL. + if (!pszLhs || !pszRhs) return FALSE; + + if( fIgnoreCase ) + { + return ( 0 == _stricmp( pszLhs, pszRhs ) ); + } + + return ( 0 == strcmp( pszLhs, pszRhs ) ); + } + + VOID + Trim(); + + BOOL + StartsWith( + __in const STRA * pStraPrefix, + __in bool fIgnoreCase = FALSE + ) const; + + BOOL + StartsWith( + __in const STRA & straPrefix, + __in bool fIgnoreCase = FALSE + ) const; + + BOOL + StartsWith( + __in PCSTR pszPrefix, + __in bool fIgnoreCase = FALSE + ) const; + + BOOL + EndsWith( + __in const STRA * pStraSuffix, + __in bool fIgnoreCase = FALSE + ) const; + + BOOL + EndsWith( + __in const STRA & straSuffix, + __in bool fIgnoreCase = FALSE + ) const; + + BOOL + EndsWith( + __in PCSTR pszSuffix, + __in bool fIgnoreCase = FALSE + ) const; + + INT + IndexOf( + __in CHAR charValue, + __in DWORD dwStartIndex = 0 + ) const; + + INT + IndexOf( + __in PCSTR pszValue, + __in DWORD dwStartIndex = 0 + ) const; + + INT + LastIndexOf( + __in CHAR charValue, + __in DWORD dwStartIndex = 0 + ) const; + + DWORD + QueryCB( + VOID + ) const; + + DWORD + QueryCCH( + VOID + ) const; + + DWORD + QuerySizeCCH( + VOID + ) const; + + DWORD + QuerySize( + VOID + ) const; + + __nullterminated + __bcount(this->m_cchLen) + CHAR * + QueryStr( + VOID + ) const; + + VOID + Reset( + VOID + ); + + HRESULT + Resize( + __in DWORD cchSize + ); + + HRESULT + SyncWithBuffer( + VOID + ); + + HRESULT + Copy( + __in PCSTR pszCopy + ); + + HRESULT + Copy( + __in_ecount(cbLen) + PCSTR pszCopy, + __in SIZE_T cbLen + ); + + HRESULT + Copy( + __in const STRA * pstrRhs + ); + + HRESULT + Copy( + __in const STRA & strRhs + ); + + HRESULT + CopyW( + __in PCWSTR pszCopyW + ); + + HRESULT + CopyW( + __in_ecount(cchLen) + PCWSTR pszCopyW, + __in SIZE_T cchLen, + __in UINT CodePage = CP_UTF8, + __in BOOL fFailIfNoTranslation = FALSE + ) + { + _ASSERTE( cchLen <= MAXDWORD ); + + return AuxAppendW( + pszCopyW, + static_cast(cchLen), + 0, + CodePage, + fFailIfNoTranslation + ); + } + + HRESULT + CopyWTruncate( + __in PCWSTR pszCopyWTruncate + ); + + HRESULT + CopyWTruncate( + __in_ecount(cchLen) + PCWSTR pszCopyWTruncate, + __in SIZE_T cchLen + ); + + HRESULT + Append( + __in PCSTR pszAppend + ); + + HRESULT + Append( + __in_ecount(cbLen) + PCSTR pszAppend, + __in SIZE_T cbLen + ); + + HRESULT + Append( + __in const STRA * pstrRhs + ); + + HRESULT + Append( + __in const STRA & strRhs + ); + + HRESULT + AppendW( + __in PCWSTR pszAppendW + ) + { + HRESULT hr; + size_t cchLen; + hr = StringCchLengthW( pszAppendW, + STRSAFE_MAX_CCH, + &cchLen ); + if ( FAILED( hr ) ) + { + return hr; + } + return AppendW( pszAppendW, cchLen ); + } + + HRESULT + AppendW( + __in_ecount(cchLen) + PCWSTR pszAppendW, + __in SIZE_T cchLen, + __in UINT CodePage = CP_UTF8, + __in BOOL fFailIfNoTranslation = FALSE + ) + { + _ASSERTE( cchLen <= MAXDWORD ); + if ( cchLen == 0 ) + { + return S_OK; + } + return AuxAppendW( + pszAppendW, + static_cast(cchLen), + QueryCB(), + CodePage, + fFailIfNoTranslation + ); + } + + HRESULT + AppendWTruncate( + __in PCWSTR pszAppendWTruncate + ); + + HRESULT + AppendWTruncate( + __in_ecount(cchLen) + PCWSTR pszAppendWTruncate, + __in SIZE_T cchLen + ); + + HRESULT + CopyToBuffer( + __out_bcount(*pcb) CHAR* pszBuffer, + __inout DWORD * pcb + ) const; + + HRESULT + SetLen( + __in DWORD cchLen + ); + + HRESULT + SafeSnprintf( + __in __format_string + PCSTR pszFormatString, + ... + ); + + HRESULT + SafeVsnprintf( + __in __format_string + PCSTR pszFormatString, + va_list argsList + ); + + HRESULT + Escape( + VOID + ); + + HRESULT + EscapeUtf8( + VOID + ); + + VOID + Unescape( + VOID + ); + + HRESULT + CopyWToUTF8Unescaped( + __in LPCWSTR cpchStr + ); + + HRESULT + CopyWToUTF8Unescaped( + __in_ecount(cch) + LPCWSTR cpchStr, + __in DWORD cch + ); + + HRESULT + CopyWToUTF8Escaped( + __in LPCWSTR cpchStr + ); + + HRESULT + CopyWToUTF8Escaped( + __in_ecount(cch) + LPCWSTR cpchStr, + __in DWORD cch + ); + +private: + + // + // Avoid C++ errors. This object should never go through a copy + // constructor, unintended cast or assignment. + // + STRA( const STRA &); + STRA & operator = (const STRA &); + + HRESULT + AuxAppend( + __in_ecount(cbLen) + LPCSTR pStr, + __in DWORD cbLen, + __in DWORD cbOffset + ); + + HRESULT + AuxAppendW( + __in_ecount(cchAppendW) + PCWSTR pszAppendW, + __in DWORD cchAppendW, + __in DWORD cbOffset, + __in UINT CodePage, + __in BOOL fFailIfNoTranslation + ) + { + DWORD dwFlags = 0; + + if( CP_ACP == CodePage ) + { + dwFlags = WC_NO_BEST_FIT_CHARS; + } + else if( fFailIfNoTranslation && CodePage == CP_UTF8 ) + { + // + // WC_ERR_INVALID_CHARS is only supported in Longhorn or greater. + // +#if defined( NTDDI_VERSION ) && NTDDI_VERSION >= NTDDI_LONGHORN + dwFlags |= WC_ERR_INVALID_CHARS; +#else + UNREFERENCED_PARAMETER(fFailIfNoTranslation); +#endif + } + + return AuxAppendW( pszAppendW, + cchAppendW, + cbOffset, + CodePage, + fFailIfNoTranslation, + dwFlags ); + } + + HRESULT + AuxAppendW( + __in_ecount(cchAppendW) + PCWSTR pszAppendW, + __in DWORD cchAppendW, + __in DWORD cbOffset, + __in UINT CodePage, + __in BOOL fFailIfNoTranslation, + __in DWORD dwFlags + ); + + HRESULT + AuxAppendWTruncate( + __in_ecount(cchAppendW) + __in PCWSTR pszAppendW, + __in DWORD cchAppendW, + __in DWORD cbOffset + ); + + static + int + ConvertUnicodeToCodePage( + __in_ecount(dwStringLen) + LPCWSTR pszSrcUnicodeString, + __inout BUFFER_T * pbufDstAnsiString, + __in DWORD dwStringLen, + __in UINT uCodePage + ); + + static + HRESULT + ConvertUnicodeToMultiByte( + __in_ecount(dwStringLen) + LPCWSTR pszSrcUnicodeString, + __in BUFFER_T * pbufDstAnsiString, + __in DWORD dwStringLen + ); + + static + HRESULT + ConvertUnicodeToUTF8( + __in_ecount(dwStringLen) + LPCWSTR pszSrcUnicodeString, + __in BUFFER_T * pbufDstAnsiString, + __in DWORD dwStringLen + ); + + typedef bool (* PFN_F_SHOULD_ESCAPE)(BYTE ch); + + HRESULT + EscapeInternal( + PFN_F_SHOULD_ESCAPE pfnFShouldEscape + ); + + // + // Buffer with an inline buffer of 1, + // enough to hold null-terminating character. + // + BUFFER_T m_Buff; + DWORD m_cchLen; +}; + +inline +HRESULT +AppendToString( + ULONGLONG Number, + STRA & String +) +{ + // prefast complains Append requires input + // to be null terminated, so zero initialize + // and pass the size of the buffer minus one + // to _ui64toa_s + CHAR chNumber[32] = {0}; + if (_ui64toa_s(Number, + chNumber, + sizeof(chNumber) - sizeof(CHAR), + 10) != 0) + { + return E_INVALIDARG; + } + return String.Append(chNumber); +} + +template +CHAR* InitHelper(__out CHAR (&psz)[size]) +{ + psz[0] = '\0'; + return psz; +} + +// +// Heap operation reduction macros +// +#define STACK_STRA(name, size) CHAR __ach##name[size];\ + STRA name(InitHelper(__ach##name), sizeof(__ach##name)) + +#define INLINE_STRA(name, size) CHAR __ach##name[size];\ + STRA name; + +#define INLINE_STRA_INIT(name) name(InitHelper(__ach##name), sizeof(__ach##name)) diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stringu.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stringu.h new file mode 100644 index 0000000000..6c8f8f755b --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/stringu.h @@ -0,0 +1,433 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include "buffer.h" +#include + +class STRU +{ + +public: + + STRU( + VOID + ); + + STRU( + __inout_ecount(cchInit) WCHAR* pbInit, + __in DWORD cchInit + ); + + BOOL + IsEmpty( + VOID + ) const; + + BOOL + Equals( + __in const STRU * pstrRhs, + __in BOOL fIgnoreCase = FALSE + ) const + { + _ASSERTE( pstrRhs != NULL ); + return Equals( pstrRhs->QueryStr(), fIgnoreCase ); + } + + BOOL + Equals( + __in const STRU & strRhs, + __in BOOL fIgnoreCase = FALSE + ) const + { + return Equals( strRhs.QueryStr(), fIgnoreCase ); + } + + BOOL + Equals( + __in PCWSTR pszRhs, + __in BOOL fIgnoreCase = FALSE + ) const + { + _ASSERTE( NULL != pszRhs ); + if ( NULL == pszRhs ) + { + return FALSE; + } + + #if defined( NTDDI_VERSION ) && NTDDI_VERSION >= NTDDI_LONGHORN + + return ( CSTR_EQUAL == CompareStringOrdinal( QueryStr(), + QueryCCH(), + pszRhs, + -1, + fIgnoreCase ) ); + #else + + if( fIgnoreCase ) + { + return ( 0 == _wcsicmp( QueryStr(), pszRhs ) ); + } + return ( 0 == wcscmp( QueryStr(), pszRhs ) ); + + #endif + } + + + static + BOOL + Equals( + __in PCWSTR pwszLhs, + __in PCWSTR pwszRhs, + __in bool fIgnoreCase = false + ) + { + // Return FALSE if either or both strings are NULL. + if (!pwszLhs || !pwszRhs) return FALSE; + + // + // This method performs a ordinal string comparison when OS is Vista or + // greater and a culture sensitive comparison if not (XP). This is + // consistent with the existing Equals implementation (see above). + // +#if defined( NTDDI_VERSION ) && NTDDI_VERSION >= NTDDI_LONGHORN + + return ( CSTR_EQUAL == CompareStringOrdinal( pwszLhs, + -1, + pwszRhs, + -1, + fIgnoreCase ) ); +#else + + if( fIgnoreCase ) + { + return ( 0 == _wcsicmp( pwszLhs, pwszRhs ) ); + } + else + { + return ( 0 == wcscmp( pwszLhs, pwszRhs ) ); + } + +#endif + } + + VOID + Trim(); + + BOOL + StartsWith( + __in const STRU * pStruPrefix, + __in bool fIgnoreCase = FALSE + ) const + { + _ASSERTE( pStruPrefix != NULL ); + return StartsWith( pStruPrefix->QueryStr(), fIgnoreCase ); + } + + BOOL + StartsWith( + __in const STRU & struPrefix, + __in bool fIgnoreCase = FALSE + ) const + { + return StartsWith( struPrefix.QueryStr(), fIgnoreCase ); + } + + BOOL + StartsWith( + __in PCWSTR pwszPrefix, + __in bool fIgnoreCase = FALSE + ) const; + + BOOL + EndsWith( + __in const STRU * pStruSuffix, + __in bool fIgnoreCase = FALSE + ) const + { + _ASSERTE( pStruSuffix != NULL ); + return EndsWith( pStruSuffix->QueryStr(), fIgnoreCase ); + } + + BOOL + EndsWith( + __in const STRU & struSuffix, + __in bool fIgnoreCase = FALSE + ) const + { + return EndsWith( struSuffix.QueryStr(), fIgnoreCase ); + } + + BOOL + EndsWith( + __in PCWSTR pwszSuffix, + __in bool fIgnoreCase = FALSE + ) const; + + INT + IndexOf( + __in WCHAR charValue, + __in DWORD dwStartIndex = 0 + ) const; + + INT + IndexOf( + __in PCWSTR pwszValue, + __in DWORD dwStartIndex = 0 + ) const; + + INT + LastIndexOf( + __in WCHAR charValue, + __in DWORD dwStartIndex = 0 + ) const; + + DWORD + QueryCB( + VOID + ) const; + + DWORD + QueryCCH( + VOID + ) const; + + DWORD + QuerySizeCCH( + VOID + ) const; + + __nullterminated + __ecount(this->m_cchLen) + WCHAR* + QueryStr( + VOID + ) const; + + VOID + Reset( + VOID + ); + + HRESULT + Resize( + DWORD cchSize + ); + + HRESULT + SyncWithBuffer( + VOID + ); + + template + HRESULT + Copy( + __in PCWSTR const (&rgpszStrings)[size] + ) + // + // Copies an array of strings declared as stack array. For example: + // + // LPCWSTR rgExample[] { L"one", L"two" }; + // hr = str.Copy( rgExample ); + // + { + Reset(); + + return AuxAppend( rgpszStrings, _countof( rgpszStrings ) ); + } + + HRESULT + Copy( + __in PCWSTR pszCopy + ); + + HRESULT + Copy( + __in_ecount(cchLen) + PCWSTR pszCopy, + SIZE_T cchLen + ); + + HRESULT + Copy( + __in const STRU * pstrRhs + ); + + HRESULT + Copy( + __in const STRU & str + ); + + HRESULT + CopyAndExpandEnvironmentStrings( + __in PCWSTR pszSource + ); + + HRESULT + CopyA( + __in PCSTR pszCopyA + ); + + HRESULT + CopyA( + __in_bcount(cchLen) + PCSTR pszCopyA, + SIZE_T cchLen, + UINT CodePage = CP_UTF8 + ); + + template + HRESULT + Append( + __in PCWSTR const (&rgpszStrings)[size] + ) + // + // Appends an array of strings declared as stack array. For example: + // + // LPCWSTR rgExample[] { L"one", L"two" }; + // hr = str.Append( rgExample ); + // + { + return AuxAppend( rgpszStrings, _countof( rgpszStrings ) ); + } + + HRESULT + Append( + __in PCWSTR pszAppend + ); + + HRESULT + Append( + __in_ecount(cchLen) + PCWSTR pszAppend, + SIZE_T cchLen + ); + + HRESULT + Append( + __in const STRU * pstrRhs + ); + + HRESULT + Append( + __in const STRU & strRhs + ); + + HRESULT + AppendA( + __in PCSTR pszAppendA + ); + + HRESULT + AppendA( + __in_bcount(cchLen) + PCSTR pszAppendA, + SIZE_T cchLen, + UINT CodePage = CP_UTF8 + ); + + HRESULT + CopyToBuffer( + __out_bcount(*pcb) WCHAR* pszBuffer, + PDWORD pcb + ) const; + + HRESULT + CopyToBufferA( + __out_bcount(*pcb) CHAR* pszBuffer, + __inout PDWORD pcb + ) const; + + HRESULT + SetLen( + __in DWORD cchLen + ); + + HRESULT + SafeSnwprintf( + __in PCWSTR pwszFormatString, + ... + ); + + HRESULT + SafeVsnwprintf( + __in PCWSTR pwszFormatString, + va_list argsList + ); + + static + HRESULT ExpandEnvironmentVariables( + __in PCWSTR pszString, + __out STRU * pstrExpandedString + ); + +private: + + // + // Avoid C++ errors. This object should never go through a copy + // constructor, unintended cast or assignment. + // + STRU( const STRU & ); + STRU & operator = ( const STRU & ); + + HRESULT + AuxAppend( + __in_ecount(cNumStrings) + PCWSTR const rgpszStrings[], + SIZE_T cNumStrings + ); + + HRESULT + AuxAppend( + __in_bcount(cbStr) + const WCHAR* pStr, + SIZE_T cbStr, + DWORD cbOffset + ); + + HRESULT + AuxAppendA( + __in_bcount(cbStr) + const CHAR* pStr, + SIZE_T cbStr, + DWORD cbOffset, + UINT CodePage + ); + + // + // Buffer with an inline buffer of 1, + // enough to hold null-terminating character. + // + BUFFER_T m_Buff; + DWORD m_cchLen; +}; + +// +// Helps to initialize an external buffer before +// constructing the STRU object. +// +template +WCHAR* InitHelper(__out WCHAR (&psz)[size]) +{ + psz[0] = L'\0'; + return psz; +} + +// +// Heap operation reduction macros +// +#define STACK_STRU(name, size) WCHAR __ach##name[size];\ + STRU name(InitHelper(__ach##name), sizeof(__ach##name)/sizeof(*__ach##name)) + +#define INLINE_STRU(name, size) WCHAR __ach##name[size];\ + STRU name; + +#define INLINE_STRU_INIT(name) name(InitHelper(__ach##name), sizeof(__ach##name)/sizeof(*__ach##name)) + + +HRESULT +MakePathCanonicalizationProof( + IN PCWSTR pszName, + OUT STRU * pstrPath +); diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/sttimer.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/sttimer.h new file mode 100644 index 0000000000..b0fba23559 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/sttimer.h @@ -0,0 +1,243 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _STTIMER_H +#define _STTIMER_H + +class STTIMER +{ +public: + + STTIMER() + : _pTimer( NULL ) + { + fInCanel = FALSE; + } + + virtual + ~STTIMER() + { + if ( _pTimer ) + { + CancelTimer(); + + CloseThreadpoolTimer( _pTimer ); + + _pTimer = NULL; + } + } + + HRESULT + InitializeTimer( + PTP_TIMER_CALLBACK pfnCallback, + VOID * pContext, + DWORD dwInitialWait = 0, + DWORD dwPeriod = 0 + ) + { + _pTimer = CreateThreadpoolTimer( pfnCallback, + pContext, + NULL ); + + if ( !_pTimer ) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + + if ( dwInitialWait ) + { + SetTimer( dwInitialWait, + dwPeriod ); + } + + return S_OK; + } + + VOID + SetTimer( + DWORD dwInitialWait, + DWORD dwPeriod = 0 + ) + { + FILETIME ftInitialWait; + + if ( dwInitialWait == 0 && dwPeriod == 0 ) + { + // + // Special case. We are preventing new callbacks + // from being queued. Any existing callbacks in the + // queue will still run. + // + // This effectively disables the timer. It can be + // re-enabled by setting non-zero initial wait or + // period values. + // + if (_pTimer != NULL) + { + SetThreadpoolTimer(_pTimer, NULL, 0, 0); + } + + return; + } + + InitializeRelativeFileTime( &ftInitialWait, dwInitialWait ); + + SetThreadpoolTimer( _pTimer, + &ftInitialWait, + dwPeriod, + 0 ); + } + + VOID + CancelTimer() + { + // + // Disable the timer + // + if (fInCanel) + return; + + fInCanel = TRUE; + SetTimer( 0 ); + + // + // Wait until any callbacks queued prior to disabling + // have completed. + // + if (_pTimer != NULL) + WaitForThreadpoolTimerCallbacks( _pTimer, TRUE ); + + _pTimer = NULL; + fInCanel = FALSE; + } + +private: + + VOID + InitializeRelativeFileTime( + FILETIME * pft, + DWORD dwMilliseconds + ) + { + LARGE_INTEGER li; + + // + // The pftDueTime parameter expects the time to be + // expressed as the number of 100 nanosecond intervals + // times -1. + // + // To convert from milliseconds, we'll multiply by + // -10000 + // + + li.QuadPart = (LONGLONG)dwMilliseconds * -10000; + + pft->dwHighDateTime = li.HighPart; + pft->dwLowDateTime = li.LowPart; + }; + + TP_TIMER * _pTimer; + BOOL fInCanel; +}; + +class STELAPSED +{ +public: + + STELAPSED() + : _dwInitTime( 0 ), + _dwInitTickCount( 0 ), + _dwPerfCountsPerMillisecond( 0 ), + _fUsingHighResolution( FALSE ) + { + LARGE_INTEGER li; + BOOL fResult; + + _dwInitTickCount = GetTickCount64(); + + fResult = QueryPerformanceFrequency( &li ); + + if ( !fResult ) + { + goto Finished; + } + + _dwPerfCountsPerMillisecond = li.QuadPart / 1000; + + fResult = QueryPerformanceCounter( &li ); + + if ( !fResult ) + { + goto Finished; + } + + _dwInitTime = li.QuadPart / _dwPerfCountsPerMillisecond; + + _fUsingHighResolution = TRUE; + +Finished: + + return; + } + + virtual + ~STELAPSED() + { + } + + LONGLONG + QueryElapsedTime() + { + LARGE_INTEGER li; + + if ( _fUsingHighResolution && QueryPerformanceCounter( &li ) ) + { + DWORD64 dwCurrentTime = li.QuadPart / _dwPerfCountsPerMillisecond; + + if ( dwCurrentTime < _dwInitTime ) + { + // + // It's theoretically possible that QueryPerformanceCounter + // may return slightly different values on different CPUs. + // In this case, we don't want to return an unexpected value + // so we'll return zero. This is acceptable because + // presumably such a case would only happen for a very short + // time window. + // + // It would be possible to prevent this by ensuring processor + // affinity for all calls to QueryPerformanceCounter, but that + // would be undesirable in the general case because it could + // introduce unnecessary context switches and potentially a + // CPU bottleneck. + // + // Note that this issue also applies to callers doing rapid + // calls to this function. If a caller wants to mitigate + // that, they could enforce the affinitization, or they + // could implement a similar sanity check when comparing + // returned values from this function. + // + + return 0; + } + + return dwCurrentTime - _dwInitTime; + } + + return GetTickCount64() - _dwInitTickCount; + } + + BOOL + QueryUsingHighResolution() + { + return _fUsingHighResolution; + } + +private: + + DWORD64 _dwInitTime; + DWORD64 _dwInitTickCount; + DWORD64 _dwPerfCountsPerMillisecond; + BOOL _fUsingHighResolution; +}; + +#endif // _STTIMER_H \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/tracelog.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/tracelog.h new file mode 100644 index 0000000000..1caff82ce3 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/tracelog.h @@ -0,0 +1,105 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _TRACELOG_H_ +#define _TRACELOG_H_ + + +#if defined(__cplusplus) +extern "C" { +#endif // __cplusplus + + +typedef struct _TRACE_LOG { + + // + // Signature. + // + + LONG Signature; + + // + // The total number of entries available in the log. + // + + LONG LogSize; + + // + // The index of the next entry to use. + // + + LONG NextEntry; + + // + // The byte size of each entry. + // + + LONG EntrySize; + + // + // Pointer to the start of the circular buffer. + // + + PUCHAR LogBuffer; + + // + // The extra header bytes and actual log entries go here. + // + // BYTE ExtraHeaderBytes[ExtraBytesInHeader]; + // BYTE Entries[LogSize][EntrySize]; + // + +} TRACE_LOG, *PTRACE_LOG; + + +// +// Log header signature. +// + +#define TRACE_LOG_SIGNATURE ((DWORD)'gOlT') +#define TRACE_LOG_SIGNATURE_X ((DWORD)'golX') + + +// +// This macro maps a TRACE_LOG pointer to a pointer to the 'extra' +// data associated with the log. +// + +#define TRACE_LOG_TO_EXTRA_DATA(log) (PVOID)( (log) + 1 ) + + +// +// Manipulators. +// + +PTRACE_LOG +CreateTraceLog( + IN LONG LogSize, + IN LONG ExtraBytesInHeader, + IN LONG EntrySize + ); + +VOID +DestroyTraceLog( + IN PTRACE_LOG Log + ); + +LONG +WriteTraceLog( + IN PTRACE_LOG Log, + IN PVOID Entry + ); + +VOID +ResetTraceLog( + IN PTRACE_LOG Log + ); + + +#if defined(__cplusplus) +} // extern "C" +#endif // __cplusplus + + +#endif // _TRACELOG_H_ + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/treehash.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/treehash.h new file mode 100644 index 0000000000..79f5a83ead --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Include/treehash.h @@ -0,0 +1,850 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include +#include "rwlock.h" +#include "prime.h" + +template +class TREE_HASH_NODE +{ + template + friend class TREE_HASH_TABLE; + + private: + // Next node in the hash table look-aside + TREE_HASH_NODE<_Record> *_pNext; + + // links in the tree structure + TREE_HASH_NODE * _pParentNode; + TREE_HASH_NODE * _pFirstChild; + TREE_HASH_NODE * _pNextSibling; + + // actual record + _Record * _pRecord; + + // hash value + PCWSTR _pszPath; + DWORD _dwHash; +}; + +template +class TREE_HASH_TABLE +{ +protected: + typedef BOOL + (PFN_DELETE_IF)( + _Record * pRecord, + PVOID pvContext + ); + + typedef VOID + (PFN_APPLY)( + _Record * pRecord, + PVOID pvContext + ); + +public: + TREE_HASH_TABLE( + BOOL fCaseSensitive + ) : _ppBuckets( NULL ), + _nBuckets( 0 ), + _nItems( 0 ), + _fCaseSensitive( fCaseSensitive ) + { + } + + virtual + ~TREE_HASH_TABLE(); + + virtual + VOID + ReferenceRecord( + _Record * pRecord + ) = 0; + + virtual + VOID + DereferenceRecord( + _Record * pRecord + ) = 0; + + virtual + PCWSTR + GetKey( + _Record * pRecord + ) = 0; + + DWORD + Count() + { + return _nItems; + } + + virtual + VOID + Clear(); + + HRESULT + Initialize( + DWORD nBucketSize + ); + + DWORD + CalcHash( + PCWSTR pszKey + ) + { + return _fCaseSensitive ? HashString(pszKey) : HashStringNoCase(pszKey); + } + + virtual + VOID + FindKey( + PCWSTR pszKey, + _Record ** ppRecord + ); + + virtual + HRESULT + InsertRecord( + _Record * pRecord + ); + + virtual + VOID + DeleteKey( + PCWSTR pszKey + ); + + virtual + VOID + DeleteIf( + PFN_DELETE_IF pfnDeleteIf, + PVOID pvContext + ); + + VOID + Apply( + PFN_APPLY pfnApply, + PVOID pvContext + ); + +private: + + BOOL + FindNodeInternal( + PCWSTR pszKey, + DWORD dwHash, + TREE_HASH_NODE<_Record> ** ppNode, + TREE_HASH_NODE<_Record> *** pppPreviousNodeNextPointer = NULL + ); + + HRESULT + AddNodeInternal( + PCWSTR pszPath, + DWORD dwHash, + _Record * pRecord, + TREE_HASH_NODE<_Record> * pParentNode, + TREE_HASH_NODE<_Record> ** ppNewNode + ); + + HRESULT + AllocateNode( + PCWSTR pszPath, + DWORD dwHash, + _Record * pRecord, + TREE_HASH_NODE<_Record> * pParentNode, + TREE_HASH_NODE<_Record> ** ppNewNode + ); + + VOID + DeleteNode( + TREE_HASH_NODE<_Record> * pNode + ) + { + if (pNode->_pRecord != NULL) + { + DereferenceRecord(pNode->_pRecord); + pNode->_pRecord = NULL; + } + + HeapFree(GetProcessHeap(), + 0, + pNode); + } + + VOID + DeleteNodeInternal( + TREE_HASH_NODE<_Record> ** ppPreviousNodeNextPointer, + TREE_HASH_NODE<_Record> * pNode + ); + + VOID + RehashTableIfNeeded( + VOID + ); + + TREE_HASH_NODE<_Record> ** _ppBuckets; + DWORD _nBuckets; + DWORD _nItems; + BOOL _fCaseSensitive; + CWSDRWLock _tableLock; +}; + +template +HRESULT +TREE_HASH_TABLE<_Record>::AllocateNode( + PCWSTR pszPath, + DWORD dwHash, + _Record * pRecord, + TREE_HASH_NODE<_Record> * pParentNode, + TREE_HASH_NODE<_Record> ** ppNewNode +) +{ + // + // Allocate enough extra space for pszPath + // + DWORD cchPath = (DWORD) wcslen(pszPath); + if (cchPath >= ((0xffffffff - sizeof(TREE_HASH_NODE<_Record>))/sizeof(WCHAR) - 1)) + { + return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); + } + TREE_HASH_NODE<_Record> *pNode = (TREE_HASH_NODE<_Record> *)HeapAlloc( + GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(TREE_HASH_NODE<_Record>) + (cchPath+1)*sizeof(WCHAR)); + if (pNode == NULL) + { + return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); + } + + memcpy(pNode+1, pszPath, (cchPath+1)*sizeof(WCHAR)); + pNode->_pszPath = (PCWSTR)(pNode+1); + pNode->_dwHash = dwHash; + pNode->_pNext = pNode->_pNextSibling = pNode->_pFirstChild = NULL; + pNode->_pParentNode = pParentNode; + pNode->_pRecord = pRecord; + + *ppNewNode = pNode; + return S_OK; +} + +template +HRESULT +TREE_HASH_TABLE<_Record>::Initialize( + DWORD nBuckets +) +{ + HRESULT hr = S_OK; + + if ( nBuckets == 0 ) + { + hr = E_INVALIDARG; + goto Failed; + } + + hr = _tableLock.Init(); + if ( FAILED( hr ) ) + { + goto Failed; + } + + if (nBuckets >= 0xffffffff/sizeof(TREE_HASH_NODE<_Record> *)) + { + hr = E_INVALIDARG; + goto Failed; + } + + _ppBuckets = (TREE_HASH_NODE<_Record> **)HeapAlloc( + GetProcessHeap(), + HEAP_ZERO_MEMORY, + nBuckets*sizeof(TREE_HASH_NODE<_Record> *)); + if (_ppBuckets == NULL) + { + hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); + goto Failed; + } + _nBuckets = nBuckets; + + return S_OK; + +Failed: + + if (_ppBuckets) + { + HeapFree(GetProcessHeap(), + 0, + _ppBuckets); + _ppBuckets = NULL; + } + + return hr; +} + + +template +TREE_HASH_TABLE<_Record>::~TREE_HASH_TABLE() +{ + if (_ppBuckets == NULL) + { + return; + } + + _ASSERTE(_nItems == 0); + + HeapFree(GetProcessHeap(), + 0, + _ppBuckets); + _ppBuckets = NULL; + _nBuckets = 0; +} + +template +VOID +TREE_HASH_TABLE<_Record>::Clear() +{ + TREE_HASH_NODE<_Record> *pCurrent; + TREE_HASH_NODE<_Record> *pNext; + + _tableLock.ExclusiveAcquire(); + + for (DWORD i=0; i<_nBuckets; i++) + { + pCurrent = _ppBuckets[i]; + _ppBuckets[i] = NULL; + while (pCurrent != NULL) + { + pNext = pCurrent->_pNext; + DeleteNode(pCurrent); + pCurrent = pNext; + } + } + + _nItems = 0; + _tableLock.ExclusiveRelease(); +} + +template +BOOL +TREE_HASH_TABLE<_Record>::FindNodeInternal( + PCWSTR pszKey, + DWORD dwHash, + TREE_HASH_NODE<_Record> ** ppNode, + TREE_HASH_NODE<_Record> *** pppPreviousNodeNextPointer +) +/*++ + Return value indicates whether the item is found + key, dwHash - key and hash for the node to find + ppNode - on successful return, the node found, on failed return, the first + node with hash value greater than the node to be found + pppPreviousNodeNextPointer - the pointer to previous node's _pNext + + This routine may be called under either read or write lock +--*/ +{ + TREE_HASH_NODE<_Record> **ppPreviousNodeNextPointer; + TREE_HASH_NODE<_Record> *pNode; + BOOL fFound = FALSE; + + ppPreviousNodeNextPointer = _ppBuckets + (dwHash % _nBuckets); + pNode = *ppPreviousNodeNextPointer; + while (pNode != NULL) + { + if (pNode->_dwHash == dwHash) + { + if (CompareStringOrdinal(pszKey, + -1, + pNode->_pszPath, + -1, + !_fCaseSensitive) == CSTR_EQUAL) + { + fFound = TRUE; + break; + } + } + else if (pNode->_dwHash > dwHash) + { + break; + } + + ppPreviousNodeNextPointer = &(pNode->_pNext); + pNode = *ppPreviousNodeNextPointer; + } + + *ppNode = pNode; + if (pppPreviousNodeNextPointer != NULL) + { + *pppPreviousNodeNextPointer = ppPreviousNodeNextPointer; + } + return fFound; +} + +template +VOID +TREE_HASH_TABLE<_Record>::FindKey( + PCWSTR pszKey, + _Record ** ppRecord +) +{ + TREE_HASH_NODE<_Record> *pNode; + + *ppRecord = NULL; + + DWORD dwHash = CalcHash(pszKey); + + _tableLock.SharedAcquire(); + + if (FindNodeInternal(pszKey, dwHash, &pNode) && + pNode->_pRecord != NULL) + { + ReferenceRecord(pNode->_pRecord); + *ppRecord = pNode->_pRecord; + } + + _tableLock.SharedRelease(); +} + +template +HRESULT +TREE_HASH_TABLE<_Record>::AddNodeInternal( + PCWSTR pszPath, + DWORD dwHash, + _Record * pRecord, + TREE_HASH_NODE<_Record> * pParentNode, + TREE_HASH_NODE<_Record> ** ppNewNode +) +/*++ + Return value is HRESULT indicating sucess or failure + pszPath, dwHash, pRecord - path, hash value and record to be inserted + pParentNode - this will be the parent of the node being inserted + ppNewNode - on successful return, the new node created and inserted + + This function may be called under a read or write lock +--*/ +{ + TREE_HASH_NODE<_Record> *pNewNode; + TREE_HASH_NODE<_Record> *pNextNode; + TREE_HASH_NODE<_Record> **ppNextPointer; + HRESULT hr; + + // + // Ownership of pRecord is not transferred to pNewNode yet, so remember + // to either set it to null before deleting pNewNode or add an extra + // reference later - this is to make sure we do not do an extra ref/deref + // which users may view as getting flushed out of the hash-table + // + hr = AllocateNode(pszPath, + dwHash, + pRecord, + pParentNode, + &pNewNode); + if (FAILED(hr)) + { + return hr; + } + + do + { + // + // Find the right place to add this node + // + + if (FindNodeInternal(pszPath, dwHash, &pNextNode, &ppNextPointer)) + { + // + // If node already there, record may still need updating + // + if (pRecord != NULL && + InterlockedCompareExchangePointer((PVOID *)&pNextNode->_pRecord, + pRecord, + NULL) == NULL) + { + ReferenceRecord(pRecord); + hr = S_OK; + } + else + { + hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS); + } + + // ownership of pRecord has either passed to existing record or + // not to anyone at all + pNewNode->_pRecord = NULL; + DeleteNode(pNewNode); + *ppNewNode = pNextNode; + return hr; + } + + // + // If another node got inserted in betwen, we will have to retry + // + pNewNode->_pNext = pNextNode; + } while (InterlockedCompareExchangePointer((PVOID *)ppNextPointer, + pNewNode, + pNextNode) != pNextNode); + // pass ownership of pRecord now + if (pRecord != NULL) + { + ReferenceRecord(pRecord); + pRecord = NULL; + } + InterlockedIncrement((LONG *)&_nItems); + + // + // update the parent + // + if (pParentNode != NULL) + { + ppNextPointer = &pParentNode->_pFirstChild; + do + { + pNextNode = *ppNextPointer; + pNewNode->_pNextSibling = pNextNode; + } while (InterlockedCompareExchangePointer((PVOID *)ppNextPointer, + pNewNode, + pNextNode) != pNextNode); + } + + *ppNewNode = pNewNode; + return S_OK; +} + +template +HRESULT +TREE_HASH_TABLE<_Record>::InsertRecord( + _Record * pRecord +) +/*++ + This method inserts a node for this record and also empty nodes for paths + in the heirarchy leading upto this path + + The insert is done under only a read-lock - this is possible by keeping + the hashes in a bucket in increasing order and using interlocked operations + to actually insert the item in the hash-bucket lookaside list and the parent + children list + + Returns HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) if the record already exists. + Never leak this error to the end user because "*file* already exists" may be confusing. +--*/ +{ + PCWSTR pszKey = GetKey(pRecord); + STACK_STRU( strPartialPath, 256); + PWSTR pszPartialPath; + DWORD dwHash; + DWORD cchEnd; + HRESULT hr; + TREE_HASH_NODE<_Record> *pParentNode = NULL; + + hr = strPartialPath.Copy(pszKey); + if (FAILED(hr)) + { + goto Finished; + } + pszPartialPath = strPartialPath.QueryStr(); + + _tableLock.SharedAcquire(); + + // + // First find the lowest parent node present + // + for (cchEnd = strPartialPath.QueryCCH() - 1; cchEnd > 0; cchEnd--) + { + if (pszPartialPath[cchEnd] == L'/' || pszPartialPath[cchEnd] == L'\\') + { + pszPartialPath[cchEnd] = L'\0'; + + dwHash = CalcHash(pszPartialPath); + if (FindNodeInternal(pszPartialPath, dwHash, &pParentNode)) + { + pszPartialPath[cchEnd] = pszKey[cchEnd]; + break; + } + pParentNode = NULL; + } + } + + // + // Now go ahead and add the rest of the tree (including our record) + // + for (; cchEnd <= strPartialPath.QueryCCH(); cchEnd++) + { + if (pszPartialPath[cchEnd] == L'\0') + { + dwHash = CalcHash(pszPartialPath); + hr = AddNodeInternal( + pszPartialPath, + dwHash, + (cchEnd == strPartialPath.QueryCCH()) ? pRecord : NULL, + pParentNode, + &pParentNode); + if (FAILED(hr) && + hr != HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) + { + goto Finished; + } + + pszPartialPath[cchEnd] = pszKey[cchEnd]; + } + } + +Finished: + _tableLock.SharedRelease(); + + if (SUCCEEDED(hr)) + { + RehashTableIfNeeded(); + } + + return hr; +} + +template +VOID +TREE_HASH_TABLE<_Record>::DeleteNodeInternal( + TREE_HASH_NODE<_Record> ** ppNextPointer, + TREE_HASH_NODE<_Record> * pNode +) +/*++ + pNode is the node to be deleted + ppNextPointer is the pointer to the previous node's next pointer pointing + to this node + + This function should be called under write-lock +--*/ +{ + // + // First remove this node from hash table + // + *ppNextPointer = pNode->_pNext; + + // + // Now fixup parent + // + if (pNode->_pParentNode != NULL) + { + ppNextPointer = &pNode->_pParentNode->_pFirstChild; + while (*ppNextPointer != pNode) + { + ppNextPointer = &(*ppNextPointer)->_pNextSibling; + } + *ppNextPointer = pNode->_pNextSibling; + } + + // + // Now remove all children recursively + // + TREE_HASH_NODE<_Record> *pChild = pNode->_pFirstChild; + TREE_HASH_NODE<_Record> *pNextChild; + while (pChild != NULL) + { + pNextChild = pChild->_pNextSibling; + + ppNextPointer = _ppBuckets + (pChild->_dwHash % _nBuckets); + while (*ppNextPointer != pChild) + { + ppNextPointer = &(*ppNextPointer)->_pNext; + } + pChild->_pParentNode = NULL; + DeleteNodeInternal(ppNextPointer, pChild); + + pChild = pNextChild; + } + + DeleteNode(pNode); + _nItems--; +} + +template +VOID +TREE_HASH_TABLE<_Record>::DeleteKey( + PCWSTR pszKey +) +{ + TREE_HASH_NODE<_Record> *pNode; + TREE_HASH_NODE<_Record> **ppPreviousNodeNextPointer; + + DWORD dwHash = CalcHash(pszKey); + + _tableLock.ExclusiveAcquire(); + + if (FindNodeInternal(pszKey, dwHash, &pNode, &ppPreviousNodeNextPointer)) + { + DeleteNodeInternal(ppPreviousNodeNextPointer, pNode); + } + + _tableLock.ExclusiveRelease(); +} + +template +VOID +TREE_HASH_TABLE<_Record>::DeleteIf( + PFN_DELETE_IF pfnDeleteIf, + PVOID pvContext +) +{ + TREE_HASH_NODE<_Record> *pNode; + TREE_HASH_NODE<_Record> **ppPreviousNodeNextPointer; + BOOL fDelete; + + _tableLock.ExclusiveAcquire(); + + for (DWORD i=0; i<_nBuckets; i++) + { + ppPreviousNodeNextPointer = _ppBuckets + i; + pNode = *ppPreviousNodeNextPointer; + while (pNode != NULL) + { + // + // Non empty nodes deleted based on DeleteIf, empty nodes deleted + // if they have no children + // + fDelete = FALSE; + if (pNode->_pRecord != NULL) + { + if (pfnDeleteIf(pNode->_pRecord, pvContext)) + { + fDelete = TRUE; + } + } + else if (pNode->_pFirstChild == NULL) + { + fDelete = TRUE; + } + + if (fDelete) + { + if (pNode->_pFirstChild == NULL) + { + DeleteNodeInternal(ppPreviousNodeNextPointer, pNode); + } + else + { + DereferenceRecord(pNode->_pRecord); + pNode->_pRecord = NULL; + } + } + else + { + ppPreviousNodeNextPointer = &pNode->_pNext; + } + + pNode = *ppPreviousNodeNextPointer; + } + } + + _tableLock.ExclusiveRelease(); +} + +template +VOID +TREE_HASH_TABLE<_Record>::Apply( + PFN_APPLY pfnApply, + PVOID pvContext +) +{ + TREE_HASH_NODE<_Record> *pNode; + + _tableLock.SharedAcquire(); + + for (DWORD i=0; i<_nBuckets; i++) + { + pNode = _ppBuckets[i]; + while (pNode != NULL) + { + if (pNode->_pRecord != NULL) + { + pfnApply(pNode->_pRecord, pvContext); + } + + pNode = pNode->_pNext; + } + } + + _tableLock.SharedRelease(); +} + +template +VOID +TREE_HASH_TABLE<_Record>::RehashTableIfNeeded( + VOID +) +{ + TREE_HASH_NODE<_Record> **ppBuckets; + DWORD nBuckets; + TREE_HASH_NODE<_Record> *pNode; + TREE_HASH_NODE<_Record> *pNextNode; + TREE_HASH_NODE<_Record> **ppNextPointer; + TREE_HASH_NODE<_Record> *pNewNextNode; + DWORD nNewBuckets; + + // + // If number of items has become too many, we will double the hash table + // size (we never reduce it however) + // + if (_nItems <= PRIME::GetPrime(2*_nBuckets)) + { + return; + } + + _tableLock.ExclusiveAcquire(); + + nNewBuckets = PRIME::GetPrime(2*_nBuckets); + + if (_nItems <= nNewBuckets) + { + goto Finished; + } + + nBuckets = nNewBuckets; + if (nBuckets >= 0xffffffff/sizeof(TREE_HASH_NODE<_Record> *)) + { + goto Finished; + } + ppBuckets = (TREE_HASH_NODE<_Record> **)HeapAlloc( + GetProcessHeap(), + HEAP_ZERO_MEMORY, + nBuckets*sizeof(TREE_HASH_NODE<_Record> *)); + if (ppBuckets == NULL) + { + goto Finished; + } + + // + // Take out nodes from the old hash table and insert in the new one, make + // sure to keep the hashes in increasing order + // + for (DWORD i=0; i<_nBuckets; i++) + { + pNode = _ppBuckets[i]; + while (pNode != NULL) + { + pNextNode = pNode->_pNext; + + ppNextPointer = ppBuckets + (pNode->_dwHash % nBuckets); + pNewNextNode = *ppNextPointer; + while (pNewNextNode != NULL && + pNewNextNode->_dwHash <= pNode->_dwHash) + { + ppNextPointer = &pNewNextNode->_pNext; + pNewNextNode = pNewNextNode->_pNext; + } + pNode->_pNext = pNewNextNode; + *ppNextPointer = pNode; + + pNode = pNextNode; + } + } + + HeapFree(GetProcessHeap(), 0, _ppBuckets); + _ppBuckets = ppBuckets; + _nBuckets = nBuckets; + ppBuckets = NULL; + +Finished: + + _tableLock.ExclusiveRelease(); +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/LICENSE b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/LICENSE new file mode 100644 index 0000000000..21071075c2 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/MySQL/MySqlConnector.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/MySQL/MySqlConnector.cs new file mode 100644 index 0000000000..ee607e28c7 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/MySQL/MySqlConnector.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; + +namespace Microsoft.Web.Utility +{ + internal static class MySqlConnector + { + public static string[] HardCodedAssemblyVersions + { + get + { + return new string[] + { + "MySql.Data, Version=6.5.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d", + "MySql.Data, Version=6.4.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d", + "MySql.Data, Version=6.3.7.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d", + "MySql.Data, Version=6.2.3.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d", + "MySql.Data, Version=6.0.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d", + "MySql.Data, Version=6.0.3.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d", + "MySql.Data, Version=5.2.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d", + "MySql.Data, Version=5.2.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d", + }; + } + } + } +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/AdvApi32.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/AdvApi32.cs new file mode 100644 index 0000000000..9dc6dbfc23 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/AdvApi32.cs @@ -0,0 +1,386 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using System.Text; +using System.Security; +using System.Runtime.Versioning; +using System.Runtime.ConstrainedExecution; +using Microsoft.Win32.SafeHandles; + +namespace Microsoft.Web.Management.PInvoke.AdvApi32 +{ + [StructLayout(LayoutKind.Sequential, Pack = 1)] + internal struct TOKEN_PRIVILEGES + { + public UInt32 PrivilegeCount; + public long Luid; + public UInt32 Attributes; + } + + internal enum TOKEN_INFORMATION_CLASS + { + /// + /// The buffer receives a TOKEN_USER structure that contains the user account of the token. + /// + TokenUser = 1, + + /// + /// The buffer receives a TOKEN_GROUPS structure that contains the group accounts associated with the token. + /// + TokenGroups, + + /// + /// The buffer receives a TOKEN_PRIVILEGES structure that contains the privileges of the token. + /// + TokenPrivileges, + + /// + /// The buffer receives a TOKEN_OWNER structure that contains the default owner security identifier (SID) for newly created objects. + /// + TokenOwner, + + /// + /// The buffer receives a TOKEN_PRIMARY_GROUP structure that contains the default primary group SID for newly created objects. + /// + TokenPrimaryGroup, + + /// + /// The buffer receives a TOKEN_DEFAULT_DACL structure that contains the default DACL for newly created objects. + /// + TokenDefaultDacl, + + /// + /// The buffer receives a TOKEN_SOURCE structure that contains the source of the token. TOKEN_QUERY_SOURCE access is needed to retrieve this information. + /// + TokenSource, + + /// + /// The buffer receives a TOKEN_TYPE value that indicates whether the token is a primary or impersonation token. + /// + TokenType, + + /// + /// The buffer receives a SECURITY_IMPERSONATION_LEVEL value that indicates the impersonation level of the token. If the access token is not an impersonation token, the function fails. + /// + TokenImpersonationLevel, + + /// + /// The buffer receives a TOKEN_STATISTICS structure that contains various token statistics. + /// + TokenStatistics, + + /// + /// The buffer receives a TOKEN_GROUPS structure that contains the list of restricting SIDs in a restricted token. + /// + TokenRestrictedSids, + + /// + /// The buffer receives a DWORD value that indicates the Terminal Services session identifier that is associated with the token. + /// + TokenSessionId, + + /// + /// The buffer receives a TOKEN_GROUPS_AND_PRIVILEGES structure that contains the user SID, the group accounts, the restricted SIDs, and the authentication ID associated with the token. + /// + TokenGroupsAndPrivileges, + + /// + /// Reserved. + /// + TokenSessionReference, + + /// + /// The buffer receives a DWORD value that is nonzero if the token includes the SANDBOX_INERT flag. + /// + TokenSandBoxInert, + + /// + /// Reserved. + /// + TokenAuditPolicy, + + /// + /// The buffer receives a TOKEN_ORIGIN value. + /// + TokenOrigin, + + /// + /// The buffer receives a TOKEN_ELEVATION_TYPE value that specifies the elevation level of the token. + /// + TokenElevationType, + + /// + /// The buffer receives a TOKEN_LINKED_TOKEN structure that contains a handle to another token that is linked to this token. + /// + TokenLinkedToken, + + /// + /// The buffer receives a TOKEN_ELEVATION structure that specifies whether the token is elevated. + /// + TokenElevation, + + /// + /// The buffer receives a DWORD value that is nonzero if the token has ever been filtered. + /// + TokenHasRestrictions, + + /// + /// The buffer receives a TOKEN_ACCESS_INFORMATION structure that specifies security information contained in the token. + /// + TokenAccessInformation, + + /// + /// The buffer receives a DWORD value that is nonzero if virtualization is allowed for the token. + /// + TokenVirtualizationAllowed, + + /// + /// The buffer receives a DWORD value that is nonzero if virtualization is enabled for the token. + /// + TokenVirtualizationEnabled, + + /// + /// The buffer receives a TOKEN_MANDATORY_LABEL structure that specifies the token's integrity level. + /// + TokenIntegrityLevel, + + /// + /// The buffer receives a DWORD value that is nonzero if the token has the UIAccess flag set. + /// + TokenUIAccess, + + /// + /// The buffer receives a TOKEN_MANDATORY_POLICY structure that specifies the token's mandatory integrity policy. + /// + TokenMandatoryPolicy, + + /// + /// The buffer receives the token's logon security identifier (SID). + /// + TokenLogonSid, + + /// + /// The maximum value for this enumeration + /// + MaxTokenInfoClass + } + + internal enum TOKEN_ELEVATION_TYPE + { + TokenElevationTypeDefault = 1, + TokenElevationTypeFull, + TokenElevationTypeLimited + } + + [Flags] + internal enum AccessTokenRights : uint + { + STANDARD_RIGHTS_REQUIRED = 0x000F0000, + STANDARD_RIGHTS_READ = 0x00020000, + TOKEN_ASSIGN_PRIMARY = 0x0001, + TOKEN_DUPLICATE = 0x0002, + TOKEN_IMPERSONATE = 0x0004, + TOKEN_QUERY = 0x0008, + TOKEN_QUERY_SOURCE = 0x0010, + TOKEN_ADJUST_PRIVILEGES = 0x0020, + TOKEN_ADJUST_GROUPS = 0x0040, + TOKEN_ADJUST_DEFAULT = 0x0080, + TOKEN_ADJUST_SESSIONID = 0x0100, + TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY, + TOKEN_ALL_ACCESS = + STANDARD_RIGHTS_REQUIRED | + TOKEN_ASSIGN_PRIMARY | + TOKEN_DUPLICATE | + TOKEN_IMPERSONATE | + TOKEN_QUERY | + TOKEN_QUERY_SOURCE | + TOKEN_ADJUST_PRIVILEGES | + TOKEN_ADJUST_GROUPS | + TOKEN_ADJUST_DEFAULT | + TOKEN_ADJUST_SESSIONID + } + + internal static class NativeMethods + { + private const String ADVAPI32 = "advapi32.dll"; + + // TODO: Should be moved into enums? + internal const int READ_CONTROL = 0x00020000; + internal const int SYNCHRONIZE = 0x00100000; + internal const int STANDARD_RIGHTS_READ = READ_CONTROL; + internal const int STANDARD_RIGHTS_WRITE = READ_CONTROL; + + internal const int KEY_QUERY_VALUE = 0x0001; + internal const int KEY_SET_VALUE = 0x0002; + internal const int KEY_CREATE_SUB_KEY = 0x0004; + internal const int KEY_ENUMERATE_SUB_KEYS = 0x0008; + internal const int KEY_NOTIFY = 0x0010; + + internal const int KEY_READ = ((STANDARD_RIGHTS_READ | + KEY_QUERY_VALUE | + KEY_ENUMERATE_SUB_KEYS | + KEY_NOTIFY) + & + (~SYNCHRONIZE)); + + internal const int KEY_WRITE = ((STANDARD_RIGHTS_WRITE | + KEY_SET_VALUE | + KEY_CREATE_SUB_KEY) + & + (~SYNCHRONIZE)); + + internal const int KEY_WOW64_64KEY = 0x0100; + internal const int KEY_WOW64_32KEY = 0x0200; + + internal const int ERROR_MORE_DATA = 0xEA; + internal const int ERROR_ACCESS_DENIED = 0x5; + + internal const int REG_OPTION_NON_VOLATILE = 0x0000; // (default) keys are persisted beyond reboot/unload + internal const int REG_OPTION_VOLATILE = 0x0001; // All keys created by the function are volatile + internal const int REG_OPTION_CREATE_LINK = 0x0002; // They key is a symbolic link + internal const int REG_OPTION_BACKUP_RESTORE = 0x0004; // Use SE_BACKUP_NAME process special privileges + internal const int REG_NONE = 0; // No value type + internal const int REG_SZ = 1; // Unicode nul terminated string + internal const int REG_EXPAND_SZ = 2; // Unicode nul terminated string + internal const int REG_BINARY = 3; // Free form binary + internal const int REG_DWORD = 4; // 32-bit number + internal const int REG_DWORD_LITTLE_ENDIAN = 4; // 32-bit number (same as REG_DWORD) + internal const int REG_DWORD_BIG_ENDIAN = 5; // 32-bit number + internal const int REG_LINK = 6; // Symbolic Link (unicode) + internal const int REG_MULTI_SZ = 7; // Multiple Unicode strings + internal const int REG_RESOURCE_LIST = 8; // Resource list in the resource map + internal const int REG_FULL_RESOURCE_DESCRIPTOR = 9; // Resource list in the hardware description + internal const int REG_RESOURCE_REQUIREMENTS_LIST = 10; + internal const int REG_QWORD = 11; // 64-bit number + + [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool AdjustTokenPrivileges( + SafeHandleZeroIsInvalid TokenHandle, + [MarshalAs(UnmanagedType.Bool)] + bool DisableAllPrivileges, + ref TOKEN_PRIVILEGES NewState, + int len, + IntPtr prev, + IntPtr relen); + + [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid); + + [DllImport("advapi32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool GetTokenInformation( + SafeHandleZeroIsInvalid TokenHandle, + TOKEN_INFORMATION_CLASS TokenInformationClass, + HGlobalBuffer TokenInformation, + int TokenInformationLength, + out int ReturnLength); + + [DllImport("advapi32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool OpenProcessToken( + SafeHandleZeroIsInvalid ProcessHandle, + AccessTokenRights DesiredAccess, + out SafeHandleZeroIsInvalid TokenHandle); + + [DllImport("ADVAPI32.DLL"), + SuppressUnmanagedCodeSecurity, + ResourceExposure(ResourceScope.None), + ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + internal static extern int RegCloseKey(IntPtr hKey); + + [DllImport(ADVAPI32, CharSet = CharSet.Auto, BestFitMapping = false)] + internal static extern int RegOpenKeyEx(SafeRegistryHandle hKey, String lpSubKey, + int ulOptions, int samDesired, out SafeRegistryHandle hkResult); + + [DllImport(ADVAPI32, CharSet = CharSet.Auto, BestFitMapping = false)] + internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName, + int[] lpReserved, ref int lpType, [Out] byte[] lpData, + ref int lpcbData); + + [DllImport(ADVAPI32, CharSet = CharSet.Auto, BestFitMapping = false)] + internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName, + int[] lpReserved, ref int lpType, ref int lpData, + ref int lpcbData); + + [DllImport(ADVAPI32, CharSet = CharSet.Auto, BestFitMapping = false)] + internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName, + int[] lpReserved, ref int lpType, ref long lpData, + ref int lpcbData); + + [DllImport(ADVAPI32, CharSet = CharSet.Auto, BestFitMapping = false)] + internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName, + int[] lpReserved, ref int lpType, [Out] char[] lpData, + ref int lpcbData); + + [DllImport(ADVAPI32, CharSet = CharSet.Auto, BestFitMapping = false)] + internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName, + int[] lpReserved, ref int lpType, StringBuilder lpData, + ref int lpcbData); + + public static void EnableShutdownPrivilege() + { + const int SE_PRIVILEGE_ENABLED = 0x00000002; + const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege"; + + bool retVal; + + using (SafeHandleZeroIsInvalid hproc = Kernel32.NativeMethods.GetCurrentProcess()) + { + TOKEN_PRIVILEGES tp; + SafeHandleZeroIsInvalid htok; + retVal = OpenProcessToken(hproc, AccessTokenRights.TOKEN_ADJUST_PRIVILEGES | AccessTokenRights.TOKEN_QUERY, out htok); + if (!retVal) + { + throw new Win32Exception(Marshal.GetLastWin32Error()); + } + + using (htok) + { + tp.PrivilegeCount = 1; + tp.Luid = 0; + tp.Attributes = SE_PRIVILEGE_ENABLED; + retVal = LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid); + if (!retVal) + { + throw new Win32Exception(Marshal.GetLastWin32Error()); + } + + retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero); + if (!retVal) + { + throw new Win32Exception(Marshal.GetLastWin32Error()); + } + } + } + } + } + + [SecurityCritical] + internal sealed class SafeRegistryHandle : SafeHandleZeroOrMinusOneIsInvalid + { + [SecurityCritical] + internal SafeRegistryHandle() + : base(true) + { + } + + [SecurityCritical] + public SafeRegistryHandle(IntPtr preexistingHandle, bool ownsHandle) + : base(ownsHandle) + { + SetHandle(preexistingHandle); + } + + [SecurityCritical] + override protected bool ReleaseHandle() + { + return (Microsoft.Web.Management.PInvoke.AdvApi32.NativeMethods.RegCloseKey(handle) == 0); + } + } +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Common.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Common.cs new file mode 100644 index 0000000000..6d6a3209a7 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Common.cs @@ -0,0 +1,111 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Runtime.InteropServices; + +// Any reference to Common.cs should also include Kernel32.cs because +// SafeHandleZeroIsInvalid (from Common.cs) uses CloseHandle (from Kernel32.cs) +namespace Microsoft.Web.Management.PInvoke +{ + internal enum Win32ErrorCode + { + ERROR_FILE_NOT_FOUND = 2, + ERROR_PATH_NOT_FOUND = 3, + ERROR_ACCESS_DENIED = 5, + ERROR_INVALID_HANDLE = 6, + ERROR_INVALID_DRIVE = 15, + ERROR_NO_MORE_FILES = 18, + ERROR_NOT_READY = 21, + ERROR_SHARING_VIOLATION = 32, + ERROR_FILE_EXISTS = 80, + ERROR_INVALID_PARAMETER = 87, // 0x57 + ERROR_INVALID_NAME = 123, // 0x7b + ERROR_BAD_PATHNAME = 161, + ERROR_ALREADY_EXISTS = 183, + ERROR_FILENAME_EXCED_RANGE = 206, + ERROR_OPERATION_ABORTED = 995, + ELEMENT_NOT_FOUND = 0x490 + } + + internal static class Extension + { + public static int AsHRESULT(Win32ErrorCode errorCode) + { + return (int)((uint)errorCode | 0x80070000); + } + } + + internal class SafeHandleZeroIsInvalid : SafeHandle + { + public SafeHandleZeroIsInvalid() + : base(IntPtr.Zero, true) + { + } + + public SafeHandleZeroIsInvalid(IntPtr newHandle) + : base(IntPtr.Zero, true) + { + this.SetHandle(newHandle); + } + + public override bool IsInvalid + { + get + { + return this.handle == IntPtr.Zero; + } + } + + protected override bool ReleaseHandle() + { + return Kernel32.NativeMethods.CloseHandle(this.handle); + } + } + + internal class HGlobalBuffer : SafeHandle + { + private int _size; + + public HGlobalBuffer(int size) + : base(IntPtr.Zero, true) + { + _size = size; + this.handle = Marshal.AllocHGlobal(size); + } + + protected override bool ReleaseHandle() + { + if (!this.IsInvalid) + { + Marshal.FreeHGlobal(this.handle); + this.handle = IntPtr.Zero; + } + + return true; + } + + public override bool IsInvalid + { + get + { + return this.handle == IntPtr.Zero; + } + } + + public T GetCopyAs() + { + return (T)Marshal.PtrToStructure(this.handle, typeof(T)); + } + + public int Size + { + get + { + return _size; + } + } + + public static readonly HGlobalBuffer NULL = new HGlobalBuffer(0); + } +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Fusion.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Fusion.cs new file mode 100644 index 0000000000..dd3391ff94 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Fusion.cs @@ -0,0 +1,179 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using System.Text; + +namespace Microsoft.Web.Utility.PInvoke.Fusion +{ + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("CD193BC0-B4BC-11d2-9833-00C04FC31D2E")] + internal interface IAssemblyName + { + [PreserveSig()] + int SetProperty( + int PropertyId, + IntPtr pvProperty, + int cbProperty); + + [PreserveSig()] + int GetProperty( + int PropertyId, + IntPtr pvProperty, + ref int pcbProperty); + + [PreserveSig()] + int Finalize(); + + [PreserveSig()] + int GetDisplayName( + StringBuilder pDisplayName, + ref int pccDisplayName, + int displayFlags); + + [PreserveSig()] + int Reserved(ref Guid guid, + Object obj1, + Object obj2, + String string1, + Int64 llFlags, + IntPtr pvReserved, + int cbReserved, + out IntPtr ppv); + + [PreserveSig()] + int GetName( + ref int pccBuffer, + StringBuilder pwzName); + + [PreserveSig()] + int GetVersion( + out int versionHi, + out int versionLow); + [PreserveSig()] + int IsEqual( + IAssemblyName pAsmName, + int cmpFlags); + + [PreserveSig()] + int Clone(out IAssemblyName pAsmName); + }// IAssemblyName + + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("e707dcde-d1cd-11d2-bab9-00c04f8eceae")] + internal interface IAssemblyCache + { + [PreserveSig()] + int UninstallAssembly( + int flags, + [MarshalAs(UnmanagedType.LPWStr)] + string assemblyName, + IntPtr refData, + out int disposition); + + [PreserveSig()] + int QueryAssemblyInfo( + int flags, + [MarshalAs(UnmanagedType.LPWStr)] + string assemblyName, + ref AssemblyInfo assemblyInfo); + [PreserveSig()] + int Reserved( + int flags, + IntPtr pvReserved, + out object ppAsmItem, + [MarshalAs(UnmanagedType.LPWStr)] + string assemblyName); + [PreserveSig()] + int Reserved(out object ppAsmScavenger); + + [PreserveSig()] + int InstallAssembly( + int flags, + [MarshalAs(UnmanagedType.LPWStr)] + string assemblyFilePath, + IntPtr refData); + }// IAssemblyCache + + [StructLayout(LayoutKind.Sequential)] + internal struct AssemblyInfo + { + public int cbAssemblyInfo; // size of this structure for future expansion + public int assemblyFlags; + public long assemblySizeInKB; + [MarshalAs(UnmanagedType.LPWStr)] + public string currentAssemblyPath; + public int cchBuf; // size of path buf. + } + + [Flags] + internal enum AssemblyCacheFlags + { + GAC = 2, + } + + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("21b8916c-f28e-11d2-a473-00c04f8ef448")] + internal interface IAssemblyEnum + { + [PreserveSig()] + int GetNextAssembly( + IntPtr pvReserved, + out IAssemblyName ppName, + int flags); + + [PreserveSig()] + int Reset(); + [PreserveSig()] + int Clone(out IAssemblyEnum ppEnum); + } + + [Flags] + internal enum AssemblyNameDisplayFlags + { + VERSION = 0x01, + CULTURE = 0x02, + PUBLIC_KEY_TOKEN = 0x04, + PROCESSORARCHITECTURE = 0x20, + RETARGETABLE = 0x80, + + // This enum might change in the future to include + // more attributes. + ALL = + VERSION + | CULTURE + | PUBLIC_KEY_TOKEN + | PROCESSORARCHITECTURE + | RETARGETABLE + } + + internal enum CreateAssemblyNameObjectFlags + { + CANOF_DEFAULT = 0, + CANOF_PARSE_DISPLAY_NAME = 1, + } + + internal static class NativeMethods + { + [DllImport("fusion.dll")] + public static extern int CreateAssemblyCache( + out IAssemblyCache ppAsmCache, + int reserved); + + [DllImport("fusion.dll")] + public static extern int CreateAssemblyEnum( + out IAssemblyEnum ppEnum, + IntPtr pUnkReserved, + IAssemblyName pName, + AssemblyCacheFlags flags, + IntPtr pvReserved); + + [DllImport("fusion.dll")] + public static extern int CreateAssemblyNameObject( + out IAssemblyName ppAssemblyNameObj, + [MarshalAs(UnmanagedType.LPWStr)] + String szAssemblyName, + CreateAssemblyNameObjectFlags flags, + IntPtr pvReserved); + } +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Kernel32.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Kernel32.cs new file mode 100644 index 0000000000..91265956b5 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Kernel32.cs @@ -0,0 +1,99 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; + +// Any reference to Common.cs should also include Kernel32.cs because +// SafeHandleZeroIsInvalid (from Common.cs) uses CloseHandle (from Kernel32.cs) +namespace Microsoft.Web.Management.PInvoke.Kernel32 +{ + internal enum OSProductType : byte + { + VER_NT_WORKSTATION = 0x0000001, + VER_NT_SERVER = 0x0000003, + VER_NT_DOMAIN_CONTROLLER = 0x0000002, + } + + [StructLayout(LayoutKind.Sequential)] + internal struct OSVERSIONINFOEX + { + public int dwOSVersionInfoSize; + public int dwMajorVersion; + public int dwMinorVersion; + public int dwBuildNumber; + public int dwPlatformId; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string szCSDVersion; + public short wServicePackMajor; + public short wServicePackMinor; + public short wSuiteMask; + public OSProductType wProductType; + public byte wReserved; + + public bool IsServer + { + get + { + return + wProductType == OSProductType.VER_NT_SERVER || + wProductType == OSProductType.VER_NT_DOMAIN_CONTROLLER; + } + } + + public bool IsClient + { + get + { + return + wProductType == OSProductType.VER_NT_WORKSTATION; + } + } + } + + internal static class NativeMethods + { + public static OSVERSIONINFOEX GetVersionEx() + { + OSVERSIONINFOEX osVersionInfo = new OSVERSIONINFOEX(); + osVersionInfo.dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX)); + if (!GetVersionEx(ref osVersionInfo)) + { + throw new Win32Exception(); + } + + return osVersionInfo; + } + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool CloseHandle(IntPtr hHandle); + + [DllImport("kernel32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + [SuppressMessage("Microsoft.Usage", "CA2205:UseManagedEquivalentsOfWin32Api", Justification = "GetVersionEx returns more information")] + private static extern bool GetVersionEx(ref OSVERSIONINFOEX osVersionInfo); + + [DllImport("kernel32.dll", ExactSpelling = true)] + internal static extern SafeHandleZeroIsInvalid GetCurrentProcess(); + + // WARNING: Vista+ ONLY + [DllImport("kernel32.dll", CharSet = CharSet.Auto)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool GetProductInfo(uint dwOSMajorVersion, uint dwOSMinorVersion, uint dwSpMajorVersion, uint spMinorVersion, out uint pdwReturnedProductType); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr); + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool WritePrivateProfileString(string applicationName, string keyName, string stringValue, string fileName); + } +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Mlang.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Mlang.cs new file mode 100644 index 0000000000..e6e1ff51bd --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/Mlang.cs @@ -0,0 +1,768 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; + +namespace Microsoft.Web.Management.PInvoke.MLang +{ + internal enum HRESULT : uint + { + S_OK = 0x0, + S_FALSE = 0x1, + E_FAIL = 0x80004005, + } + + internal static class NativeMethods + { + [StructLayout(LayoutKind.Explicit, Pack = 4)] + public struct __MIDL_IWinTypes_0009 + { + // Fields + [FieldOffset(0)] + public int hInproc; + [FieldOffset(0)] + public int hRemote; + } + + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct _RemotableHandle + { + public int fContext; + public __MIDL_IWinTypes_0009 u; + } + + [ComImport, CoClass(typeof(CMLangConvertCharsetClass)), Guid("D66D6F98-CDAA-11D0-B822-00C04FC9B31F")] + public interface CMLangConvertCharset : IMLangConvertCharset + { + } + + [ComImport, TypeLibType((short)2), Guid("D66D6F99-CDAA-11D0-B822-00C04FC9B31F"), ClassInterface((short)0)] + public class CMLangConvertCharsetClass : IMLangConvertCharset, CMLangConvertCharset + { + // Methods + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void DoConversion([In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void DoConversionFromUnicode([In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void DoConversionToUnicode([In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetDestinationCodePage(out uint puiDstCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetProperty(out uint pdwProperty); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetSourceCodePage(out uint puiSrcCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void Initialize([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty); + } + + [ComImport, Guid("C04D65CE-B70D-11D0-B188-00AA0038C969"), CoClass(typeof(CMLangStringClass))] + public interface CMLangString : IMLangString + { + } + + [ComImport, TypeLibType((short)2), Guid("C04D65CF-B70D-11D0-B188-00AA0038C969"), ClassInterface((short)0)] + public class CMLangStringClass : IMLangString, CMLangString, IMLangStringWStr, IMLangStringAStr + { + // Methods + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetAStr([In] int lSrcPos, [In] int lSrcLen, [In] uint uCodePageIn, out uint puCodePageOut, [Out, MarshalAs(UnmanagedType.LPStr)] string pszDest, [In] int cchDest, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern int GetLength(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetLocale([In] int lSrcPos, [In] int lSrcMaxLen, out uint plocale, out int plLocalePos, out int plLocaleLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetMLStr([In] int lSrcPos, [In] int lSrcLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, [In] uint dwClsContext, [In] ref Guid piid, [MarshalAs(UnmanagedType.IUnknown)] out object ppDestMLStr, out int plDestPos, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetStrBufA([In] int lSrcPos, [In] int lSrcMaxLen, out uint puDestCodePage, [MarshalAs(UnmanagedType.Interface)] out IMLangStringBufA ppDestBuf, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetStrBufW([In] int lSrcPos, [In] int lSrcMaxLen, [MarshalAs(UnmanagedType.Interface)] out IMLangStringBufW ppDestBuf, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetWStr([In] int lSrcPos, [In] int lSrcLen, [Out, MarshalAs(UnmanagedType.LPWStr)] string pszDest, [In] int cchDest, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern int IMLangStringAStr_GetLength(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangStringAStr_GetLocale([In] int lSrcPos, [In] int lSrcMaxLen, out uint plocale, out int plLocalePos, out int plLocaleLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangStringAStr_GetMLStr([In] int lSrcPos, [In] int lSrcLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, [In] uint dwClsContext, [In] ref Guid piid, [MarshalAs(UnmanagedType.IUnknown)] out object ppDestMLStr, out int plDestPos, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangStringAStr_SetLocale([In] int lDestPos, [In] int lDestLen, [In] uint locale); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangStringAStr_SetMLStr([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pSrcMLStr, [In] int lSrcPos, [In] int lSrcLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangStringAStr_Sync([In] int fNoAccess); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern int IMLangStringWStr_GetLength(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangStringWStr_GetMLStr([In] int lSrcPos, [In] int lSrcLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, [In] uint dwClsContext, [In] ref Guid piid, [MarshalAs(UnmanagedType.IUnknown)] out object ppDestMLStr, out int plDestPos, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangStringWStr_SetMLStr([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pSrcMLStr, [In] int lSrcPos, [In] int lSrcLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangStringWStr_Sync([In] int fNoAccess); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void LockAStr([In] int lSrcPos, [In] int lSrcLen, [In] int lFlags, [In] uint uCodePageIn, [In] int cchRequest, out uint puCodePageOut, [MarshalAs(UnmanagedType.LPStr)] out string ppszDest, out int pcchDest, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void LockWStr([In] int lSrcPos, [In] int lSrcLen, [In] int lFlags, [In] int cchRequest, [MarshalAs(UnmanagedType.LPWStr)] out string ppszDest, out int pcchDest, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void SetAStr([In] int lDestPos, [In] int lDestLen, [In] uint uCodePage, [In, MarshalAs(UnmanagedType.LPStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void SetLocale([In] int lDestPos, [In] int lDestLen, [In] uint locale); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void SetMLStr([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pSrcMLStr, [In] int lSrcPos, [In] int lSrcLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void SetStrBufA([In] int lDestPos, [In] int lDestLen, [In] uint uCodePage, [In, MarshalAs(UnmanagedType.Interface)] IMLangStringBufA pSrcBuf, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void SetStrBufW([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.Interface)] IMLangStringBufW pSrcBuf, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void SetWStr([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.LPWStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void Sync([In] int fNoAccess); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void UnlockAStr([In, MarshalAs(UnmanagedType.LPStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void UnlockWStr([In, MarshalAs(UnmanagedType.LPWStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen); + } + + [ComImport, Guid("275C23E1-3747-11D0-9FEA-00AA003F8646"), CoClass(typeof(CMultiLanguageClass))] + public interface CMultiLanguage : IMultiLanguage + { + } + + [ComImport, TypeLibType(TypeLibTypeFlags.FCanCreate), ClassInterface(ClassInterfaceType.None), Guid("275C23E2-3747-11D0-9FEA-00AA003F8646")] + public class CMultiLanguageClass : IMultiLanguage, CMultiLanguage, IMLangCodePages, IMLangFontLink, IMLangLineBreakConsole, IMultiLanguage2, IMLangFontLink2, IMultiLanguage3 + { + // Methods + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void BreakLineA([In] uint locale, [In] uint uCodePage, [In] ref sbyte pszSrc, [In] int cchSrc, [In] int cMaxColumns, out int pcchLine, out int pcchSkip); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void BreakLineML([In, MarshalAs(UnmanagedType.Interface)] CMLangString pSrcMLStr, [In] int lSrcPos, [In] int lSrcLen, [In] int cMinColumns, [In] int cMaxColumns, out int plLineLen, out int plSkipLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void BreakLineW([In] uint locale, [In] ref ushort pszSrc, [In] int cchSrc, [In] int cMaxColumns, out int pcchLine, out int pcchSkip); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void CodePagesToCodePage([In] uint dwCodePages, [In] uint uDefaultCodePage, out uint puCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void CodePageToCodePages([In] uint uCodePage, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void CodePageToScriptID([In] uint uiCodePage, out byte pSid); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ConvertString([In, Out] ref uint pdwMode, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ConvertStringFromUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ConvertStringFromUnicodeEx([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize, [In] uint dwFlag, [In] ref ushort lpFallBack); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ConvertStringInIStream([In, Out] ref uint pdwMode, [In] uint dwFlag, [In] ref ushort lpFallBack, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmIn, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmOut); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ConvertStringReset(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ConvertStringToUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ConvertStringToUnicodeEx([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize, [In] uint dwFlag, [In] ref ushort lpFallBack); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void CreateConvertCharset([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty, [MarshalAs(UnmanagedType.Interface)] out CMLangConvertCharset ppMLangConvertCharset); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void DetectCodepageInIStream([In] uint dwFlag, [In] uint dwPrefWinCodePage, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmIn, out DetectEncodingInfo lpEncoding, [In, Out] ref int pnScores); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + [PreserveSig] + public virtual extern HRESULT DetectInputCodepage([In] MLDETECTCP dwFlag, [In] uint dwPrefWinCodePage, [In] ref byte pSrcStr, [In, Out] ref int pcSrcSize, ref DetectEncodingInfo lpEncoding, [In, Out] ref int pnScores); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void DetectOutboundCodePage([In] uint dwFlags, [In, MarshalAs(UnmanagedType.LPWStr)] string lpWideCharStr, [In] uint cchWideChar, [In] ref uint puiPreferredCodePages, [In] uint nPreferredCodePages, out uint puiDetectedCodePages, [In, Out] ref uint pnDetectedCodePages, [In, MarshalAs(UnmanagedType.LPWStr)] string lpSpecialChar); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void DetectOutboundCodePageInIStream([In] uint dwFlags, [In, MarshalAs(UnmanagedType.Interface)] IStream pStrIn, [In] ref uint puiPreferredCodePages, [In] uint nPreferredCodePages, out uint puiDetectedCodePages, [In, Out] ref uint pnDetectedCodePages, [In, MarshalAs(UnmanagedType.LPWStr)] string lpSpecialChar); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + [return: MarshalAs(UnmanagedType.Interface)] + public virtual extern IEnumCodePage EnumCodePages([In] NativeMethods.MIMECONTF grfFlags); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void EnumCodePages([In] uint grfFlags, [In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumCodePage ppEnumCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void EnumRfc1766([MarshalAs(UnmanagedType.Interface)] out IEnumRfc1766 ppEnumRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void EnumRfc1766([In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumRfc1766 ppEnumRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void EnumScripts([In] uint dwFlags, [In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumScript ppEnumScript); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetCharCodePages([In] ushort chSrc, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetCharsetInfo([In, MarshalAs(UnmanagedType.BStr)] string Charset, out MIMECSETINFO pCharsetInfo); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetCodePageDescription([In] uint uiCodePage, [In] uint lcid, [Out, MarshalAs(UnmanagedType.LPWStr)] string lpWideCharStr, [In] int cchWideChar); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetCodePageInfo([In] uint uiCodePage, out MIMECPINFO pCodePageInfo); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetCodePageInfo([In] uint uiCodePage, [In] ushort LangId, out MIMECPINFO pCodePageInfo); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetFamilyCodePage([In] uint uiCodePage, out uint puiFamilyCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetFontCodePages([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetFontUnicodeRanges([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In, Out] ref uint puiRanges, out UNICODERANGE pUranges); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetLcidFromRfc1766(out uint plocale, [In, MarshalAs(UnmanagedType.BStr)] string bstrRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetNumberOfCodePageInfo(out uint pcCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetNumberOfScripts(out uint pnScripts); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetRfc1766FromLcid([In] uint locale, [MarshalAs(UnmanagedType.BStr)] out string pbstrRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetRfc1766Info([In] uint locale, out RFC1766INFO pRfc1766Info); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetRfc1766Info([In] uint locale, [In] ushort LangId, out RFC1766INFO pRfc1766Info); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetScriptFontInfo([In] byte sid, [In] uint dwFlags, [In, Out] ref uint puiFonts, out SCRIPFONTINFO pScriptFont); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void GetStrCodePages([In] ref ushort pszSrc, [In] int cchSrc, [In] uint dwPriorityCodePages, out uint pdwCodePages, out int pcchCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink_CodePagesToCodePage([In] uint dwCodePages, [In] uint uDefaultCodePage, out uint puCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink_CodePageToCodePages([In] uint uCodePage, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink_GetCharCodePages([In] ushort chSrc, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink_GetStrCodePages([In] ref ushort pszSrc, [In] int cchSrc, [In] uint dwPriorityCodePages, out uint pdwCodePages, out int pcchCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink2_CodePagesToCodePage([In] uint dwCodePages, [In] uint uDefaultCodePage, out uint puCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink2_CodePageToCodePages([In] uint uCodePage, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink2_GetCharCodePages([In] ushort chSrc, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink2_GetFontCodePages([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink2_GetStrCodePages([In] ref ushort pszSrc, [In] int cchSrc, [In] uint dwPriorityCodePages, out uint pdwCodePages, out int pcchCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink2_ReleaseFont([In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMLangFontLink2_ResetFontMapping(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_ConvertString([In, Out] ref uint pdwMode, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_ConvertStringFromUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_ConvertStringReset(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_ConvertStringToUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_CreateConvertCharset([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty, [MarshalAs(UnmanagedType.Interface)] out CMLangConvertCharset ppMLangConvertCharset); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_GetCharsetInfo([In, MarshalAs(UnmanagedType.BStr)] string Charset, out MIMECSETINFO pCharsetInfo); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_GetFamilyCodePage([In] uint uiCodePage, out uint puiFamilyCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_GetLcidFromRfc1766(out uint plocale, [In, MarshalAs(UnmanagedType.BStr)] string bstrRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_GetNumberOfCodePageInfo(out uint pcCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_GetRfc1766FromLcid([In] uint locale, [MarshalAs(UnmanagedType.BStr)] out string pbstrRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage2_IsConvertible([In] uint dwSrcEncoding, [In] uint dwDstEncoding); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_ConvertString([In, Out] ref uint pdwMode, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_ConvertStringFromUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_ConvertStringFromUnicodeEx([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize, [In] uint dwFlag, [In] ref ushort lpFallBack); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_ConvertStringInIStream([In, Out] ref uint pdwMode, [In] uint dwFlag, [In] ref ushort lpFallBack, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmIn, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmOut); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_ConvertStringReset(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_ConvertStringToUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_ConvertStringToUnicodeEx([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize, [In] uint dwFlag, [In] ref ushort lpFallBack); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_CreateConvertCharset([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty, [MarshalAs(UnmanagedType.Interface)] out CMLangConvertCharset ppMLangConvertCharset); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_DetectCodepageInIStream([In] uint dwFlag, [In] uint dwPrefWinCodePage, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmIn, out DetectEncodingInfo lpEncoding, [In, Out] ref int pnScores); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_DetectInputCodepage([In] uint dwFlag, [In] uint dwPrefWinCodePage, [In] ref sbyte pSrcStr, [In, Out] ref int pcSrcSize, out DetectEncodingInfo lpEncoding, [In, Out] ref int pnScores); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_EnumCodePages([In] NativeMethods.MIMECONTF grfFlags, [In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumCodePage ppEnumCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_EnumRfc1766([In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumRfc1766 ppEnumRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_EnumScripts([In] uint dwFlags, [In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumScript ppEnumScript); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_GetCharsetInfo([In, MarshalAs(UnmanagedType.BStr)] string Charset, out MIMECSETINFO pCharsetInfo); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_GetCodePageDescription([In] uint uiCodePage, [In] uint lcid, [Out, MarshalAs(UnmanagedType.LPWStr)] string lpWideCharStr, [In] int cchWideChar); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_GetCodePageInfo([In] uint uiCodePage, [In] ushort LangId, out MIMECPINFO pCodePageInfo); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_GetFamilyCodePage([In] uint uiCodePage, out uint puiFamilyCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_GetLcidFromRfc1766(out uint plocale, [In, MarshalAs(UnmanagedType.BStr)] string bstrRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_GetNumberOfCodePageInfo(out uint pcCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_GetNumberOfScripts(out uint pnScripts); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_GetRfc1766FromLcid([In] uint locale, [MarshalAs(UnmanagedType.BStr)] out string pbstrRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_GetRfc1766Info([In] uint locale, [In] ushort LangId, out RFC1766INFO pRfc1766Info); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_IsCodePageInstallable([In] uint uiCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_IsConvertible([In] uint dwSrcEncoding, [In] uint dwDstEncoding); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_SetMimeDBSource([In] MIMECONTF dwSource); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_ValidateCodePage([In] uint uiCodePage, [In, ComAliasName("MultiLanguage.wireHWND")] ref _RemotableHandle hwnd); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IMultiLanguage3_ValidateCodePageEx([In] uint uiCodePage, [In, ComAliasName("MultiLanguage.wireHWND")] ref _RemotableHandle hwnd, [In] uint dwfIODControl); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IsCodePageInstallable([In] uint uiCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void IsConvertible([In] uint dwSrcEncoding, [In] uint dwDstEncoding); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void MapFont([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In] uint dwCodePages, [In] ushort chSrc, [Out, ComAliasName("MultiLanguage.wireHFONT")] IntPtr pFont); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void MapFont([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In] uint dwCodePages, [In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hSrcFont, [Out, ComAliasName("MultiLanguage.wireHFONT")] IntPtr phDestFont); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ReleaseFont([In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ResetFontMapping(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void SetMimeDBSource([In] MIMECONTF dwSource); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ValidateCodePage([In] uint uiCodePage, [In, ComAliasName("MultiLanguage.wireHWND")] ref _RemotableHandle hwnd); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + public virtual extern void ValidateCodePageEx([In] uint uiCodePage, [In, ComAliasName("MultiLanguage.wireHWND")] ref _RemotableHandle hwnd, [In] uint dwfIODControl); + } + + [ComImport, Guid("275C23E3-3747-11D0-9FEA-00AA003F8646"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IEnumCodePage + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Clone([MarshalAs(UnmanagedType.Interface)] out IEnumCodePage ppEnum); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + [PreserveSig] + HRESULT Next([In] uint celt, out MIMECPINFO rgelt, out uint pceltFetched); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Reset(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Skip([In] uint celt); + } + + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("3DC39D1D-C030-11D0-B81B-00C04FC9B31F")] + public interface IEnumRfc1766 + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Clone([MarshalAs(UnmanagedType.Interface)] out IEnumRfc1766 ppEnum); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Next([In] uint celt, out RFC1766INFO rgelt, out uint pceltFetched); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Reset(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Skip([In] uint celt); + } + + [ComImport, Guid("AE5F1430-388B-11D2-8380-00C04F8F5DA1"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IEnumScript + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Clone([MarshalAs(UnmanagedType.Interface)] out IEnumScript ppEnum); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Next([In] uint celt, out SCRIPTINFO rgelt, out uint pceltFetched); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Reset(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Skip([In] uint celt); + } + + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("359F3443-BD4A-11D0-B188-00AA0038C969")] + public interface IMLangCodePages + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetCharCodePages([In] ushort chSrc, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetStrCodePages([In] ref ushort pszSrc, [In] int cchSrc, [In] uint dwPriorityCodePages, out uint pdwCodePages, out int pcchCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void CodePageToCodePages([In] uint uCodePage, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void CodePagesToCodePage([In] uint dwCodePages, [In] uint uDefaultCodePage, out uint puCodePage); + } + + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("D66D6F98-CDAA-11D0-B822-00C04FC9B31F")] + public interface IMLangConvertCharset + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Initialize([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetSourceCodePage(out uint puiSrcCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetDestinationCodePage(out uint puiDstCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetProperty(out uint pdwProperty); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void DoConversion([In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void DoConversionToUnicode([In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void DoConversionFromUnicode([In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize); + } + + [ComImport, Guid("359F3441-BD4A-11D0-B188-00AA0038C969"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), ComConversionLoss] + public interface IMLangFontLink : IMLangCodePages + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetFontCodePages([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void MapFont([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In] uint dwCodePages, [In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hSrcFont, [Out, ComAliasName("MultiLanguage.wireHFONT")] IntPtr phDestFont); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ReleaseFont([In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ResetFontMapping(); + } + + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("DCCFC162-2B38-11D2-B7EC-00C04F8F5D9A"), ComConversionLoss] + public interface IMLangFontLink2 : IMLangCodePages + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetFontCodePages([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont, out uint pdwCodePages); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ReleaseFont([In, ComAliasName("MultiLanguage.wireHFONT")] ref _RemotableHandle hFont); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ResetFontMapping(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void MapFont([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In] uint dwCodePages, [In] ushort chSrc, [Out, ComAliasName("MultiLanguage.wireHFONT")] IntPtr pFont); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetFontUnicodeRanges([In, ComAliasName("MultiLanguage.wireHDC")] ref _RemotableHandle hDC, [In, Out] ref uint puiRanges, out UNICODERANGE pUranges); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetScriptFontInfo([In] byte sid, [In] uint dwFlags, [In, Out] ref uint puiFonts, out SCRIPFONTINFO pScriptFont); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void CodePageToScriptID([In] uint uiCodePage, out byte pSid); + } + + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("F5BE2EE1-BFD7-11D0-B188-00AA0038C969")] + public interface IMLangLineBreakConsole + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void BreakLineML([In, MarshalAs(UnmanagedType.Interface)] CMLangString pSrcMLStr, [In] int lSrcPos, [In] int lSrcLen, [In] int cMinColumns, [In] int cMaxColumns, out int plLineLen, out int plSkipLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void BreakLineW([In] uint locale, [In] ref ushort pszSrc, [In] int cchSrc, [In] int cMaxColumns, out int pcchLine, out int pcchSkip); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void BreakLineA([In] uint locale, [In] uint uCodePage, [In] ref sbyte pszSrc, [In] int cchSrc, [In] int cMaxColumns, out int pcchLine, out int pcchSkip); + } + + [ComImport, Guid("C04D65CE-B70D-11D0-B188-00AA0038C969"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IMLangString + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Sync([In] int fNoAccess); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + int GetLength(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void SetMLStr([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pSrcMLStr, [In] int lSrcPos, [In] int lSrcLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetMLStr([In] int lSrcPos, [In] int lSrcLen, [In, MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, [In] uint dwClsContext, [In] ref Guid piid, [MarshalAs(UnmanagedType.IUnknown)] out object ppDestMLStr, out int plDestPos, out int plDestLen); + } + + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("C04D65D2-B70D-11D0-B188-00AA0038C969")] + public interface IMLangStringAStr : IMLangString + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void SetAStr([In] int lDestPos, [In] int lDestLen, [In] uint uCodePage, [In, MarshalAs(UnmanagedType.LPStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void SetStrBufA([In] int lDestPos, [In] int lDestLen, [In] uint uCodePage, [In, MarshalAs(UnmanagedType.Interface)] IMLangStringBufA pSrcBuf, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetAStr([In] int lSrcPos, [In] int lSrcLen, [In] uint uCodePageIn, out uint puCodePageOut, [Out, MarshalAs(UnmanagedType.LPStr)] string pszDest, [In] int cchDest, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetStrBufA([In] int lSrcPos, [In] int lSrcMaxLen, out uint puDestCodePage, [MarshalAs(UnmanagedType.Interface)] out IMLangStringBufA ppDestBuf, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void LockAStr([In] int lSrcPos, [In] int lSrcLen, [In] int lFlags, [In] uint uCodePageIn, [In] int cchRequest, out uint puCodePageOut, [MarshalAs(UnmanagedType.LPStr)] out string ppszDest, out int pcchDest, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void UnlockAStr([In, MarshalAs(UnmanagedType.LPStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void SetLocale([In] int lDestPos, [In] int lDestLen, [In] uint locale); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetLocale([In] int lSrcPos, [In] int lSrcMaxLen, out uint plocale, out int plLocalePos, out int plLocaleLen); + } + + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), ComConversionLoss, Guid("D24ACD23-BA72-11D0-B188-00AA0038C969")] + public interface IMLangStringBufA + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetStatus(out int plFlags, out int pcchBuf); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void LockBuf([In] int cchOffset, [In] int cchMaxLock, [Out] IntPtr ppszBuf, out int pcchBuf); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void UnlockBuf([In] ref sbyte pszBuf, [In] int cchOffset, [In] int cchWrite); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Insert([In] int cchOffset, [In] int cchMaxInsert, out int pcchActual); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Delete([In] int cchOffset, [In] int cchDelete); + } + + [ComImport, ComConversionLoss, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("D24ACD21-BA72-11D0-B188-00AA0038C969")] + public interface IMLangStringBufW + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetStatus(out int plFlags, out int pcchBuf); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void LockBuf([In] int cchOffset, [In] int cchMaxLock, [Out] IntPtr ppszBuf, out int pcchBuf); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void UnlockBuf([In] ref ushort pszBuf, [In] int cchOffset, [In] int cchWrite); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Insert([In] int cchOffset, [In] int cchMaxInsert, out int pcchActual); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Delete([In] int cchOffset, [In] int cchDelete); + } + + [ComImport, Guid("C04D65D0-B70D-11D0-B188-00AA0038C969"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IMLangStringWStr : IMLangString + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void SetWStr([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.LPWStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void SetStrBufW([In] int lDestPos, [In] int lDestLen, [In, MarshalAs(UnmanagedType.Interface)] IMLangStringBufW pSrcBuf, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetWStr([In] int lSrcPos, [In] int lSrcLen, [Out, MarshalAs(UnmanagedType.LPWStr)] string pszDest, [In] int cchDest, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetStrBufW([In] int lSrcPos, [In] int lSrcMaxLen, [MarshalAs(UnmanagedType.Interface)] out IMLangStringBufW ppDestBuf, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void LockWStr([In] int lSrcPos, [In] int lSrcLen, [In] int lFlags, [In] int cchRequest, [MarshalAs(UnmanagedType.LPWStr)] out string ppszDest, out int pcchDest, out int plDestLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void UnlockWStr([In, MarshalAs(UnmanagedType.LPWStr)] string pszSrc, [In] int cchSrc, out int pcchActual, out int plActualLen); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void SetLocale([In] int lDestPos, [In] int lDestLen, [In] uint locale); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetLocale([In] int lSrcPos, [In] int lSrcMaxLen, out uint plocale, out int plLocalePos, out int plLocaleLen); + } + + [ComImport, Guid("275C23E1-3747-11D0-9FEA-00AA003F8646"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IMultiLanguage + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetNumberOfCodePageInfo(out uint pcCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetCodePageInfo([In] uint uiCodePage, out MIMECPINFO pCodePageInfo); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetFamilyCodePage([In] uint uiCodePage, out uint puiFamilyCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + [return: MarshalAs(UnmanagedType.Interface)] + IEnumCodePage EnumCodePages([In] NativeMethods.MIMECONTF grfFlags); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetCharsetInfo([In, MarshalAs(UnmanagedType.BStr)] string Charset, out MIMECSETINFO pCharsetInfo); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void IsConvertible([In] uint dwSrcEncoding, [In] uint dwDstEncoding); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertString([In, Out] ref uint pdwMode, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertStringToUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertStringFromUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertStringReset(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetRfc1766FromLcid([In] uint locale, [MarshalAs(UnmanagedType.BStr)] out string pbstrRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetLcidFromRfc1766(out uint plocale, [In, MarshalAs(UnmanagedType.BStr)] string bstrRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void EnumRfc1766([MarshalAs(UnmanagedType.Interface)] out IEnumRfc1766 ppEnumRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetRfc1766Info([In] uint locale, out RFC1766INFO pRfc1766Info); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void CreateConvertCharset([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty, [MarshalAs(UnmanagedType.Interface)] out CMLangConvertCharset ppMLangConvertCharset); + } + + [ComImport, Guid("DCCFC164-2B38-11D2-B7EC-00C04F8F5D9A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IMultiLanguage2 + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetNumberOfCodePageInfo(out uint pcCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetCodePageInfo([In] uint uiCodePage, [In] ushort LangId, out MIMECPINFO pCodePageInfo); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetFamilyCodePage([In] uint uiCodePage, out uint puiFamilyCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void EnumCodePages([In] uint grfFlags, [In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumCodePage ppEnumCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetCharsetInfo([In, MarshalAs(UnmanagedType.BStr)] string Charset, out MIMECSETINFO pCharsetInfo); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void IsConvertible([In] uint dwSrcEncoding, [In] uint dwDstEncoding); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertString([In, Out] ref uint pdwMode, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In] ref byte pSrcStr, [In, Out] ref uint pcSrcSize, out byte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertStringToUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertStringFromUnicode([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertStringReset(); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetRfc1766FromLcid([In] uint locale, [MarshalAs(UnmanagedType.BStr)] out string pbstrRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetLcidFromRfc1766(out uint plocale, [In, MarshalAs(UnmanagedType.BStr)] string bstrRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void EnumRfc1766([In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumRfc1766 ppEnumRfc1766); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetRfc1766Info([In] uint locale, [In] ushort LangId, out RFC1766INFO pRfc1766Info); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void CreateConvertCharset([In] uint uiSrcCodePage, [In] uint uiDstCodePage, [In] uint dwProperty, [MarshalAs(UnmanagedType.Interface)] out CMLangConvertCharset ppMLangConvertCharset); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertStringInIStream([In, Out] ref uint pdwMode, [In] uint dwFlag, [In] ref ushort lpFallBack, [In] uint dwSrcEncoding, [In] uint dwDstEncoding, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmIn, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmOut); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertStringToUnicodeEx([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref sbyte pSrcStr, [In, Out] ref uint pcSrcSize, out ushort pDstStr, [In, Out] ref uint pcDstSize, [In] uint dwFlag, [In] ref ushort lpFallBack); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ConvertStringFromUnicodeEx([In, Out] ref uint pdwMode, [In] uint dwEncoding, [In] ref ushort pSrcStr, [In, Out] ref uint pcSrcSize, out sbyte pDstStr, [In, Out] ref uint pcDstSize, [In] uint dwFlag, [In] ref ushort lpFallBack); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void DetectCodepageInIStream([In] uint dwFlag, [In] uint dwPrefWinCodePage, [In, MarshalAs(UnmanagedType.Interface)] IStream pstmIn, out DetectEncodingInfo lpEncoding, [In, Out] ref int pnScores); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + [PreserveSig] + HRESULT DetectInputCodepage([In] MLDETECTCP dwFlag, [In] uint dwPrefWinCodePage, [In] ref byte pSrcStr, [In, Out] ref int pcSrcSize, [In, Out] ref DetectEncodingInfo lpEncoding, [In, Out] ref int pnScores); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ValidateCodePage([In] uint uiCodePage, [In, ComAliasName("MultiLanguage.wireHWND")] ref _RemotableHandle hwnd); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetCodePageDescription([In] uint uiCodePage, [In] uint lcid, [Out, MarshalAs(UnmanagedType.LPWStr)] string lpWideCharStr, [In] int cchWideChar); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void IsCodePageInstallable([In] uint uiCodePage); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void SetMimeDBSource([In] MIMECONTF dwSource); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetNumberOfScripts(out uint pnScripts); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void EnumScripts([In] uint dwFlags, [In] ushort LangId, [MarshalAs(UnmanagedType.Interface)] out IEnumScript ppEnumScript); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void ValidateCodePageEx([In] uint uiCodePage, [In, ComAliasName("MultiLanguage.wireHWND")] ref _RemotableHandle hwnd, [In] uint dwfIODControl); + } + + [ComImport, Guid("4E5868AB-B157-4623-9ACC-6A1D9CAEBE04"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IMultiLanguage3 : IMultiLanguage2 + { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void DetectOutboundCodePage([In] uint dwFlags, [In, MarshalAs(UnmanagedType.LPWStr)] string lpWideCharStr, [In] uint cchWideChar, [In] ref uint puiPreferredCodePages, [In] uint nPreferredCodePages, out uint puiDetectedCodePages, [In, Out] ref uint pnDetectedCodePages, [In, MarshalAs(UnmanagedType.LPWStr)] string lpSpecialChar); + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void DetectOutboundCodePageInIStream([In] uint dwFlags, [In, MarshalAs(UnmanagedType.Interface)] IStream pStrIn, [In] ref uint puiPreferredCodePages, [In] uint nPreferredCodePages, out uint puiDetectedCodePages, [In, Out] ref uint pnDetectedCodePages, [In, MarshalAs(UnmanagedType.LPWStr)] string lpSpecialChar); + } + + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct DetectEncodingInfo + { + public uint nLangID; + public uint nCodePage; + public int nDocPercent; + public int nConfidence; + } + + public enum MIMECONTF + { + MIMECONTF_BROWSER = 2, + MIMECONTF_EXPORT = 0x400, + MIMECONTF_IMPORT = 8, + MIMECONTF_MAILNEWS = 1, + MIMECONTF_MIME_IE4 = 0x10000000, + MIMECONTF_MIME_LATEST = 0x20000000, + MIMECONTF_MIME_REGISTRY = 0x40000000, + MIMECONTF_MINIMAL = 4, + MIMECONTF_PRIVCONVERTER = 0x10000, + MIMECONTF_SAVABLE_BROWSER = 0x200, + MIMECONTF_SAVABLE_MAILNEWS = 0x100, + MIMECONTF_VALID = 0x20000, + MIMECONTF_VALID_NLS = 0x40000 + } + + [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] + public struct MIMECPINFO + { + public uint dwFlags; + public uint uiCodePage; + public uint uiFamilyCodePage; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x40)] + public string wszDescription; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] + public string wszWebCharset; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] + public string wszHeaderCharset; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] + public string wszBodyCharset; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)] + public string wszFixedWidthFont; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)] + public string wszProportionalFont; + public byte bGDICharset; + } + + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct MIMECSETINFO + { + public uint uiCodePage; + public uint uiInternetEncoding; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)] + public ushort[] wszCharset; + } + + public enum MLSTR_FLAGS + { + MLSTR_READ = 1, + MLSTR_WRITE = 2 + } + + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct RFC1766INFO + { + public uint lcid; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] + public ushort[] wszRfc1766; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)] + public ushort[] wszLocaleName; + } + + [StructLayout(LayoutKind.Sequential, Pack = 8)] + public struct SCRIPFONTINFO + { + public long scripts; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)] + public ushort[] wszFont; + } + + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct SCRIPTINFO + { + public byte ScriptId; + public uint uiCodePage; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x30)] + public ushort[] wszDescription; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)] + public ushort[] wszFixedWidthFont; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)] + public ushort[] wszProportionalFont; + } + + public enum MLDETECTCP + { + MLDETECTCP_NONE = 0, + MLDETECTCP_7BIT = 1, + MLDETECTCP_8BIT = 2, + MLDETECTCP_DBCS = 4, + MLDETECTCP_HTML = 8, + MLDETECTCP_NUMBER = 16 + } + + [StructLayout(LayoutKind.Sequential, Pack = 8)] + public struct STATSTG + { + [MarshalAs(UnmanagedType.LPWStr)] + public string pwcsName; + public uint type; + public ulong cbSize; + public System.Runtime.InteropServices.ComTypes.FILETIME mtime; + public System.Runtime.InteropServices.ComTypes.FILETIME ctime; + public System.Runtime.InteropServices.ComTypes.FILETIME atime; + public uint grfMode; + public uint grfLocksSupported; + public Guid clsid; + public uint grfStateBits; + public uint reserved; + } + + [StructLayout(LayoutKind.Sequential, Pack = 2)] + public struct UNICODERANGE + { + public ushort wcFrom; + public ushort wcTo; + } + } +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/User32.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/User32.cs new file mode 100644 index 0000000000..b158632572 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/User32.cs @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Runtime.InteropServices; + +namespace Microsoft.Web.Management.PInvoke.User32 +{ + internal enum WindowMessage + { + PBS_SMOOTH = 0x1, + PBS_MARQUEE = 0x8, + WM_SETREDRAW = 0xB, + PBM_SETMARQUEE = 0x400 + 10, + } + + [Flags] + internal enum ExitWindows : uint + { + // + // ONE of the following five: + // + LogOff = 0x00, + ShutDown = 0x01, + Reboot = 0x02, + PowerOff = 0x08, + RestartApps = 0x40, + + // + // plus AT MOST ONE of the following two: + // + Force = 0x04, + ForceIfHung = 0x10, + } + + [Flags] + internal enum ShutdownReason : uint + { + MajorApplication = 0x00040000, + MajorHardware = 0x00010000, + MajorLegacyApi = 0x00070000, + MajorOperatingSystem = 0x00020000, + MajorOther = 0x00000000, + MajorPower = 0x00060000, + MajorSoftware = 0x00030000, + MajorSystem = 0x00050000, + + MinorBlueScreen = 0x0000000F, + MinorCordUnplugged = 0x0000000b, + MinorDisk = 0x00000007, + MinorEnvironment = 0x0000000c, + MinorHardwareDriver = 0x0000000d, + MinorHotfix = 0x00000011, + MinorHung = 0x00000005, + MinorInstallation = 0x00000002, + MinorMaintenance = 0x00000001, + MinorMMC = 0x00000019, + MinorNetworkConnectivity = 0x00000014, + MinorNetworkCard = 0x00000009, + MinorOther = 0x00000000, + MinorOtherDriver = 0x0000000e, + MinorPowerSupply = 0x0000000a, + MinorProcessor = 0x00000008, + MinorReconfig = 0x00000004, + MinorSecurity = 0x00000013, + MinorSecurityFix = 0x00000012, + MinorSecurityFixUninstall = 0x00000018, + MinorServicePack = 0x00000010, + MinorServicePackUninstall = 0x00000016, + MinorTermSrv = 0x00000020, + MinorUnstable = 0x00000006, + MinorUpgrade = 0x00000003, + MinorWMI = 0x00000015, + + FlagUserDefined = 0x40000000, + FlagPlanned = 0x80000000 + } + + internal static class NativeMethods + { + [DllImport("User32.dll", CharSet = CharSet.Auto)] + public static extern IntPtr SendMessage(IntPtr hWnd, WindowMessage msg, int wParam, int lParam); + + [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool ExitWindowsEx(ExitWindows uFlags, ShutdownReason dwReason); + } +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/UxTheme.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/UxTheme.cs new file mode 100644 index 0000000000..520c923505 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/NativeMethods/UxTheme.cs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Runtime.InteropServices; +using System.Text; +using System.Diagnostics; + +namespace Microsoft.Web.Management.PInvoke.UxTheme +{ + internal static class NativeMethods + { + [DllImport("UxTheme.dll", ExactSpelling = true, CharSet = CharSet.Unicode)] + public extern static void SetWindowTheme(IntPtr hWnd, string textSubAppName, string textSubIdList); + + [DllImport("uxtheme.dll", CharSet = CharSet.Unicode, PreserveSig = true)] + private static extern int GetCurrentThemeName(StringBuilder pszThemeFileName, int dwMaxNameChars, StringBuilder pszColorBuff, int dwMaxColorChars, StringBuilder pszSizeBuff, int cchMaxSizeChars); + + public static bool TryGetCurrentThemeName(out string themeName, out string color, out string size) + { + StringBuilder nameBuilder = new StringBuilder(512); + StringBuilder colorBuilder = new StringBuilder(512); + StringBuilder sizeBuilder = new StringBuilder(512); + int hr = GetCurrentThemeName(nameBuilder, nameBuilder.Capacity, colorBuilder, colorBuilder.Capacity, sizeBuilder, sizeBuilder.Capacity); + if (hr == 0) + { + themeName = nameBuilder.ToString(); + color = colorBuilder.ToString(); + size = sizeBuilder.ToString(); + return true; + } + else + { + themeName = null; + color = null; + size = null; + if (hr != Extension.AsHRESULT(Win32ErrorCode.ELEMENT_NOT_FOUND)) + { + Debug.Fail("GetCurrentThemeName returned: " + hr.ToString()); + } + + return false; + } + } + } +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/PseudoLoc/PseudoLoc.targets b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/PseudoLoc/PseudoLoc.targets new file mode 100644 index 0000000000..0222289f2c --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/PseudoLoc/PseudoLoc.targets @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/PseudoLoc/PseudoLocalizer.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/PseudoLoc/PseudoLocalizer.cs new file mode 100644 index 0000000000..fccf038061 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/PseudoLoc/PseudoLocalizer.cs @@ -0,0 +1,456 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Reflection; +using System.Resources; + +namespace Microsoft.Web.Utility +{ +#if PSEUDOLOCALIZER_ENABLED || DEBUG + + /// + /// Class that pseudo-localizes resources from a RESX file by intercepting calls to the managed wrapper class. + /// + internal static class PseudoLocalizer + { + private static bool _shouldPseudoLocalize; + private static double _plocPaddingLengthRatio; + + static PseudoLocalizer() + { + _shouldPseudoLocalize = false; + int plocLengthPaddingPercentage = 50; +#if DEBUG + string plocValue = Environment.GetEnvironmentVariable("PSEUDOLOCALIZE"); + if (!string.IsNullOrEmpty(plocValue)) + { + _shouldPseudoLocalize = true; + int.TryParse(plocValue, out plocLengthPaddingPercentage); + if (plocLengthPaddingPercentage < 10) + { + plocLengthPaddingPercentage = 50; + } + } +#endif // DEBUG + + _plocPaddingLengthRatio = plocLengthPaddingPercentage * 0.01; + if (_plocPaddingLengthRatio < 0.1) + { + DebugTrace("ploc should be at least 10% padded"); + } + +#if PSEUDOLOCALIZER_ENABLED + _shouldPseudoLocalize = true; +#endif // PSEUDOLOCALIZER_ENABLED + } + + public static bool ShouldPseudoLocalize + { + get + { + return _shouldPseudoLocalize; + } + } + + // Need to use this method instead of tracing/debugging directly otherwise + // the application will not be able to disable asserts from the exe.config file. + // this is because this code is run very early on in the app before the + // default trace listener has had a chance to initialize its settings + // correctly + private static void DebugTrace(string format, params object[] args) + { + ////only uncomment these lines when actually debugging something + ////otherwise the application wont be able to toggle the assert ui + ////if (args == null || args.Length == 0) + ////{ + //// Debug.WriteLine(format); + ////} + ////else + ////{ + //// Debug.WriteLine(format, args); + ////} + } + + /// + /// Enables pseudo-localization on any type that is of the form {AssemblyName}.Resources + /// + /// + /// true if succeeded, false if failed. + public static bool TryEnableAssembly(Assembly assembly) + { + bool retVal = false; + if (assembly != null) + { + AssemblyName assemblyName = assembly.GetName(); + string resourceTypeName = assemblyName.Name + ".Resources"; + try + { + Type resourceType = assembly.GetType(resourceTypeName, false); + if (resourceType != null) + { + Enable(resourceType); + retVal = true; + } + else + { + DebugTrace("PLOC: no type {0} found in the assembly {1}", + resourceTypeName, + assembly.FullName); + } + } + catch (Exception ex) + { + DebugTrace(ex.ToString()); + } + } + else + { + DebugTrace("assembly should not be null"); + } + + return retVal; + } + + /// + /// Enables pseudo-localization for the specified RESX managed wrapper class. + /// + /// Type of the RESX managed wrapper class. + [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "ResourceManager", Justification = "Name of property.")] + [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "resourceMan", Justification = "Name of field.")] + public static void Enable(Type resourcesType) + { + if (null == resourcesType) + { + throw new ArgumentNullException("resourcesType"); + } + + // Get the ResourceManager property + var resourceManagerProperty = resourcesType.GetProperty("ResourceManager", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); + if (null == resourceManagerProperty) + { + throw new NotSupportedException("RESX managed wrapper class does not contain the expected internal/public static ResourceManager property."); + } + + // Get the ResourceManager value (ensures the resourceMan field gets initialized) + var resourceManagerValue = resourceManagerProperty.GetValue(null, null) as ResourceManager; + if (null == resourceManagerValue) + { + throw new NotSupportedException("RESX managed wrapper class returned null for the ResourceManager property getter."); + } + + // Get the resourceMan field + var resourceManField = resourcesType.GetField("resourceMan", BindingFlags.Static | BindingFlags.NonPublic); + if (null == resourceManField) + { + throw new NotSupportedException("RESX managed wrapper class does not contain the expected private static resourceMan field."); + } + + // Create a substitute ResourceManager to do the pseudo-localization + var resourceManSubstitute = new PseudoLocalizerResourceManager( + _plocPaddingLengthRatio, + resourceManagerValue.BaseName, + resourcesType.Assembly); + + // Replace the resourceMan field value + resourceManField.SetValue(null, resourceManSubstitute); + } + + /// + /// Enables Pseudo-localization for all assemblies that get loaded from the current + /// host. Within the assemblie, only types that are of the form {AssemblyName}.Resources + /// will get pseudo-localization enabled. + /// + public static void EnableAutoPseudoLocalizationFromHostExecutable() + { + if (ShouldPseudoLocalize) + { + //set up pseudo-localization for ourselves + TryEnableAssembly(Assembly.GetExecutingAssembly()); + + //set up pseudo-localization for anything that gets loaded later + AppDomain.CurrentDomain.AssemblyLoad += + new AssemblyLoadEventHandler(OnCurrentDomainAssemblyLoad); + } + } + + public static string PseudoLocalizeString(string str) + { + return PseudoLocalizerResourceManager.PseudoLocalizeString( + _plocPaddingLengthRatio, + str); + } + + private static void OnCurrentDomainAssemblyLoad(object sender, + AssemblyLoadEventArgs args) + { + Assembly assembly = args.LoadedAssembly; + bool isThisMyAssembly; + if (!assembly.GlobalAssemblyCache) + { + isThisMyAssembly = true; + } + else if (assembly.FullName.StartsWith("Microsoft.Web", + StringComparison.OrdinalIgnoreCase)) + { + isThisMyAssembly = true; + } + else + { + isThisMyAssembly = false; + } + + if (isThisMyAssembly) + { + TryEnableAssembly(assembly); + } + } + + /// + /// Class that overrides default ResourceManager behavior by pseudo-localizing its content. + /// + private class PseudoLocalizerResourceManager : ResourceManager + { + /// + /// Stores a Dictionary for character translations. + /// + private static Dictionary _translations = CreateTranslationsMap(); + + private static Dictionary CreateTranslationsMap() + { + // Map standard "English" characters to similar-looking counterparts from other languages + Dictionary translations = new Dictionary + { + { 'a', 'ä' }, + { 'b', 'ƃ' }, + { 'c', 'č' }, + { 'd', 'ƌ' }, + { 'e', 'ë' }, + { 'f', 'ƒ' }, + { 'g', 'ğ' }, + { 'h', 'ħ' }, + { 'i', 'ï' }, + { 'j', 'ĵ' }, + { 'k', 'ƙ' }, + { 'l', 'ł' }, + { 'm', 'ɱ' }, + { 'n', 'ň' }, + { 'o', 'ö' }, + { 'p', 'þ' }, + { 'q', 'ɋ' }, + { 'r', 'ř' }, + { 's', 'š' }, + { 't', 'ŧ' }, + { 'u', 'ü' }, + { 'v', 'ṽ' }, + { 'w', 'ŵ' }, + { 'x', 'ӿ' }, + { 'y', 'ŷ' }, + { 'z', 'ž' }, + { 'A', 'Ä' }, + { 'B', 'Ɓ' }, + { 'C', 'Č' }, + { 'D', 'Đ' }, + { 'E', 'Ë' }, + { 'F', 'Ƒ' }, + { 'G', 'Ğ' }, + { 'H', 'Ħ' }, + { 'I', 'Ï' }, + { 'J', 'Ĵ' }, + { 'K', 'Ҟ' }, + { 'L', 'Ł' }, + { 'M', 'Ӎ' }, + { 'N', 'Ň' }, + { 'O', 'Ö' }, + { 'P', 'Ҏ' }, + { 'Q', 'Ǫ' }, + { 'R', 'Ř' }, + { 'S', 'Š' }, + { 'T', 'Ŧ' }, + { 'U', 'Ü' }, + { 'V', 'Ṽ' }, + { 'W', 'Ŵ' }, + { 'X', 'Ӿ' }, + { 'Y', 'Ŷ' }, + { 'Z', 'Ž' }, + }; + + return translations; + } + + private double _paddingLengthRatio; + + /// + /// Initializes a new instance of the PseudoLocalizerResourceManager class. + /// + /// The root name of the resource file without its extension but including any fully qualified namespace name. + /// The main assembly for the resources. + public PseudoLocalizerResourceManager(double paddingLengthRatio, + string baseName, + Assembly assembly) + : base(baseName, assembly) + { + _paddingLengthRatio = paddingLengthRatio; + } + + /// + /// Returns the value of the specified String resource. + /// + /// The name of the resource to get. + /// The value of the resource localized for the caller's current culture settings. + public override string GetString(string name) + { + return PseudoLocalizeString(base.GetString(name)); + } + + /// + /// Gets the value of the String resource localized for the specified culture. + /// + /// The name of the resource to get. + /// The CultureInfo object that represents the culture for which the resource is localized. + /// The value of the resource localized for the specified culture. + public override string GetString(string name, CultureInfo culture) + { + return PseudoLocalizeString(base.GetString(name, culture)); + } + + private string PseudoLocalizeString(string str) + { + return PseudoLocalizeString(_paddingLengthRatio, str); + } + + /// + /// Pseudo-localizes a string. + /// + /// Input string. + /// Pseudo-localized string. + internal static string PseudoLocalizeString(double paddingLengthRatio, string str) + { + const string minprefix = "["; + const string minsuffix = "]"; + + // Create a new string with the "translated" values of each character + var translatedChars = new char[str.Length]; + if (IsXamlString(str)) + { + DoCaseTranslation(str, translatedChars); + } + else + { + DoFunkyCharacterTranslation(str, translatedChars); + } + + string mungedString = new string(translatedChars); + + int padLengthPerSide = GetPaddingLengthPerSide( + str.Length, + paddingLengthRatio, + minprefix.Length + minsuffix.Length); + + string extraPadding = new string('=', padLengthPerSide); + string finalString = string.Concat(minprefix, extraPadding, mungedString, extraPadding, minsuffix); + + return finalString; + } + + private static int GetPaddingLengthPerSide(int originalStringLength, double paddingRatio, int minPadLength) + { + int padLengthPerSide; + double exactTotalPadding = (originalStringLength * paddingRatio); + padLengthPerSide = (int)(exactTotalPadding + 1) / 2; + if (padLengthPerSide < 1) + { + padLengthPerSide = 1; + } + + return padLengthPerSide; + } + + private static void DoCaseTranslation(string str, char[] translatedChars) + { + bool inXamlTag = false; + for (var i = 0; i < str.Length; i++) + { + var c = str[i]; + + if (inXamlTag) + { + translatedChars[i] = c; + if (c == '>') + { + inXamlTag = false; + } + } + else + { + translatedChars[i] = (i % 2) == 0 ? char.ToUpper(c) : char.ToLower(c); + if (c == '<' && str.IndexOf('>', i) > -1) + { + inXamlTag = true; + } + } + } + } + + private static void DoFunkyCharacterTranslation(string str, char[] translatedChars) + { + for (var i = 0; i < str.Length; i++) + { + var c = str[i]; + translatedChars[i] = _translations.ContainsKey(c) ? _translations[c] : c; + } + } + + private static bool IsXamlString(string str) + { + // check if this string has a '<' followed by a '>' and assume it's a xaml string if so + int lessThanIndex = str.IndexOf('<'); + if (lessThanIndex > -1) + { + if (str.IndexOf('>', lessThanIndex) > -1) + { + return true; + } + } + + return false; + } + } + } +#else + /// + /// Dummy class needed to keep the public interface be identical in debug and retail builds + /// + internal static class PseudoLocalizer + { + public static bool ShouldPseudoLocalize + { + get + { + return false; + } + } + + public static bool TryEnableAssembly(Assembly assembly) + { + return true; + } + + public static void Enable(Type resourcesType) + { + } + + public static void EnableAutoPseudoLocalizationFromHostExecutable() + { + } + + public static string PseudoLocalizeString(string str) + { + return str; + } + } +#endif +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/References/v7Sp1/Microsoft.Web.administration.dll b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/References/v7Sp1/Microsoft.Web.administration.dll new file mode 100644 index 0000000000000000000000000000000000000000..5c786c3d92915cb26236846e500b6a03876a9c54 GIT binary patch literal 126976 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%0D@F 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 literal 0 HcmV?d00001 diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/References/v7Sp1/Microsoft.Web.management.dll b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/References/v7Sp1/Microsoft.Web.management.dll new file mode 100644 index 0000000000000000000000000000000000000000..cbae9ccf9225b6c3dc4c417edf99a33fb238211a GIT binary patch literal 999424 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:sVDf*w?58|qhsE<{5Ef2Kjhkto2=Gr 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

~~kz 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 literal 0 HcmV?d00001 diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/AuthenticationModule.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/AuthenticationModule.cs new file mode 100644 index 0000000000..f284d02d0e --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/AuthenticationModule.cs @@ -0,0 +1,111 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Net; +using System.Text; + +namespace Microsoft.WebMatrix.Utility +{ + ///

+ /// This AuthenticationModule implements basic authentication but uses UTF8 Encoding to support international characters. + /// Unfortunately the System.Net implementation uses the Default encoding which breaks with them. + /// + internal class AuthenticationModule : IAuthenticationModule + { + private const string AuthenticationTypeName = "Basic"; + private static AuthenticationModule _module = null; + private static object _lock = new object(); + + public static void InstantiateIfNeeded() + { + lock (_lock) + { + if (_module == null) + { + _module = new AuthenticationModule(); + } + } + } + + private AuthenticationModule() + { + AuthenticationManager.Unregister(AuthenticationTypeName); + AuthenticationManager.Register(this); + } + + string IAuthenticationModule.AuthenticationType + { + get + { + return AuthenticationTypeName; + } + } + + bool IAuthenticationModule.CanPreAuthenticate + { + get + { + return true; + } + } + + Authorization IAuthenticationModule.Authenticate(string challenge, WebRequest request, ICredentials credentials) + { + HttpWebRequest httpWebRequest = request as HttpWebRequest; + if (httpWebRequest == null) + { + return null; + } + + // Verify that the challenge is a Basic Challenge + if (challenge == null || !challenge.StartsWith(AuthenticationTypeName, StringComparison.OrdinalIgnoreCase)) + { + return null; + } + + return Authenticate(httpWebRequest, credentials); + } + + Authorization IAuthenticationModule.PreAuthenticate(WebRequest request, ICredentials credentials) + { + HttpWebRequest httpWebRequest = request as HttpWebRequest; + + if (httpWebRequest == null) + { + return null; + } + + return Authenticate(httpWebRequest, credentials); + } + + private Authorization Authenticate(HttpWebRequest httpWebRequest, ICredentials credentials) + { + if (credentials == null) + { + return null; + } + + // Get the username and password from the credentials + NetworkCredential nc = credentials.GetCredential(httpWebRequest.RequestUri, AuthenticationTypeName); + if (nc == null) + { + return null; + } + + ICredentialPolicy policy = AuthenticationManager.CredentialPolicy; + if (policy != null && !policy.ShouldSendCredential(httpWebRequest.RequestUri, httpWebRequest, nc, this)) + { + return null; + } + + string domain = nc.Domain; + + string basicTicket = (!String.IsNullOrEmpty(domain) ? (domain + "\\") : "") + nc.UserName + ":" + nc.Password; + byte[] bytes = Encoding.UTF8.GetBytes(basicTicket); + + string header = AuthenticationTypeName + " " + Convert.ToBase64String(bytes); + return new Authorization(header, true); + } + } +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/ExceptionHelper.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/ExceptionHelper.cs new file mode 100644 index 0000000000..b3a6c24c2e --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/ExceptionHelper.cs @@ -0,0 +1,122 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; + +namespace Microsoft.WebMatrix.Utility +{ + internal class ExceptionHelper + { + private const int PublicKeyTokenLength = 8; + + /// + /// This will return a list of assemblies that are present in the call stack for + /// the input exception. The list CAN have duplicates. + /// + /// + /// + public static IEnumerable GetAssembliesInCallStack(Exception exception) + { + // an AggregateException might have multiple inner exceptions, so we handle it specially + AggregateException aggregateException = exception as AggregateException; + if (exception == null) + { + return Enumerable.Empty(); + } + else if (aggregateException == null) + { + return GetAssembliesInSingleException(exception).Concat(GetAssembliesInCallStack(exception.InnerException)); + } + else + { + return aggregateException.Flatten().InnerExceptions.SelectMany(ex => GetAssembliesInCallStack(ex)); + } + } + + private static IEnumerable GetAssembliesInSingleException(Exception exception) + { + // some exceptions (like AggregateException) don't have an associated stacktrace + if (exception != null && exception.StackTrace != null) + { + StackTrace stackTrace = new StackTrace(exception, false); + foreach (StackFrame frame in stackTrace.GetFrames()) + { + // DeclaringType can be null for lambdas created by Reflection.Emit + Type declaringType = frame.GetMethod().DeclaringType; + if (declaringType != null) + { + Assembly currentAssembly = declaringType.Assembly; + Debug.Assert(currentAssembly != null, "currentAssembly must not be null"); + if (currentAssembly != null) + { + yield return currentAssembly; + } + } + } + } + } + + public static IEnumerable RemoveAssembliesThatAreIntheGAC(IEnumerable input) + { + foreach (Assembly assembly in input) + { + if (!assembly.GlobalAssemblyCache) + { + yield return assembly; + } + } + } + + public static IEnumerable RemoveAssembliesThatAreSignedWithToken(IEnumerable input, byte[] publicKeyToken) + { + Debug.Assert(publicKeyToken.Length == PublicKeyTokenLength, "public key tokens should be 8 bytes"); + foreach (Assembly assembly in input) + { + byte[] currentToken = assembly.GetName().GetPublicKeyToken(); + bool shouldReturn; + if (currentToken.Length == 0) + { + // unsigned assembly + shouldReturn = true; + } + else if (AreTokensTheSame(currentToken, publicKeyToken)) + { + // tokens are the same skip the assembly + shouldReturn = false; + } + else + { + // didnt match anything, return it + shouldReturn = true; + } + + if (shouldReturn) + { + yield return assembly; + } + } + } + + private static bool AreTokensTheSame(byte[] token1, byte[] token2) + { + Debug.Assert( + token1.Length == PublicKeyTokenLength && + token2.Length == PublicKeyTokenLength, + "public key tokens should be 8 bytes"); + + for (int i = 0; i < PublicKeyTokenLength; i++) + { + if (token1[i] != token2[i]) + { + return false; + } + } + + return true; + } + } +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/GACManagedAccess.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/GACManagedAccess.cs new file mode 100644 index 0000000000..2dbd5c8ff1 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/GACManagedAccess.cs @@ -0,0 +1,192 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using System.Diagnostics; + +namespace Microsoft.Web.Utility +{ + // need to include \common\Managed\NativeMethods\Fusion.cs in your project to use this class + internal static class GACManagedAccess + { + public static List GetAssemblyList(string assemblyName) + { + return GetAssemblyList(assemblyName, true); + } + + public static List GetAssemblyList(string assemblyName, bool getPhysicalPath) + { + if (string.IsNullOrEmpty(assemblyName)) + { + throw new ArgumentNullException("assemblyName"); + } + + List assemblyList = new List(); + using (GacAssembly gacAssembly = new GacAssembly(assemblyName)) + { + while (true) + { + if (gacAssembly.GetNextAssembly()) + { + if (getPhysicalPath) + { + using (GACAssemblyCache gacAssemblyCache = new GACAssemblyCache(assemblyName, gacAssembly.FullAssemblyName)) + { + assemblyList.Add(gacAssemblyCache.AssemblyPath); + } + } + else + { + assemblyList.Add(gacAssembly.FullAssemblyName); + } + } + else + { + break; + } + } + } + + return assemblyList; + } + } + + internal class GacAssembly : IDisposable + { + internal GacAssembly(string assemblyName) + { + _assemblyName = assemblyName; + int hResult = PInvoke.Fusion.NativeMethods.CreateAssemblyNameObject( + out _fusionName, + _assemblyName, + PInvoke.Fusion.CreateAssemblyNameObjectFlags.CANOF_PARSE_DISPLAY_NAME, + IntPtr.Zero); + + if (hResult >= 0) + { + hResult = PInvoke.Fusion.NativeMethods.CreateAssemblyEnum( + out _assemblyEnum, + IntPtr.Zero, + _fusionName, + PInvoke.Fusion.AssemblyCacheFlags.GAC, + IntPtr.Zero); + } + + if (hResult < 0 || _assemblyEnum == null) + { + throw Marshal.GetExceptionForHR(hResult); + } + } + + internal bool GetNextAssembly() + { + int hResult = _assemblyEnum.GetNextAssembly((IntPtr)0, out _fusionName, 0); + + if (hResult < 0 || _fusionName == null) + { + return false; + } + + return true; + } + + internal string FullAssemblyName + { + get + { + StringBuilder sDisplayName = new StringBuilder(1024); + int iLen = 1024; + + int hrLocal = _fusionName.GetDisplayName( + sDisplayName, + ref iLen, + (int)PInvoke.Fusion.AssemblyNameDisplayFlags.ALL); + + if (hrLocal < 0) + { + throw Marshal.GetExceptionForHR(hrLocal); + } + + return sDisplayName.ToString(); + } + } + + internal PInvoke.Fusion.IAssemblyName FusionName + { + get + { + return _fusionName; + } + } + + public void Dispose() + { + PInvoke.Fusion.IAssemblyName tempName = _fusionName; + if (tempName != null) + { + _fusionName = null; + Marshal.ReleaseComObject(tempName); + } + + PInvoke.Fusion.IAssemblyEnum tempEnum = _assemblyEnum; + if (tempEnum != null) + { + _assemblyEnum = null; + Marshal.ReleaseComObject(tempEnum); + } + } + + private string _assemblyName; + private PInvoke.Fusion.IAssemblyEnum _assemblyEnum; + private PInvoke.Fusion.IAssemblyName _fusionName; + } + + internal class GACAssemblyCache : IDisposable + { + internal GACAssemblyCache(string assemblyName, string fullAssemblyName) + { + PInvoke.Fusion.AssemblyInfo aInfo = new PInvoke.Fusion.AssemblyInfo(); + aInfo.cchBuf = 1024; + aInfo.currentAssemblyPath = new string('\0', aInfo.cchBuf); + + int hResult = PInvoke.Fusion.NativeMethods.CreateAssemblyCache(out _assemblyCache, 0); + + if (hResult == 0) + { + hResult = _assemblyCache.QueryAssemblyInfo(0, fullAssemblyName, ref aInfo); + } + + if (hResult != 0) + { + Marshal.GetExceptionForHR(hResult); + } + + _assemblyPath = aInfo.currentAssemblyPath; + } + + internal string AssemblyPath + { + get + { + return _assemblyPath; + } + } + + public void Dispose() + { + PInvoke.Fusion.IAssemblyCache temp = _assemblyCache; + if (temp != null) + { + _assemblyCache = null; + Marshal.ReleaseComObject(temp); + } + } + + private string _assemblyPath; + private PInvoke.Fusion.IAssemblyCache _assemblyCache; + } +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/WebUtility.cs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/WebUtility.cs new file mode 100644 index 0000000000..2f5a9c93c4 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/Managed/Util/WebUtility.cs @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Collections; +using System.Net; + +namespace Microsoft.Web.Utility +{ + internal static class WebUtility + { + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification="We want to count any error as host doesn't exist")] + public static bool IsLocalMachine(string serverName, bool useDns) + { + if (String.Equals(serverName, Environment.MachineName, StringComparison.CurrentCultureIgnoreCase) || + String.Equals(serverName, "localhost", StringComparison.OrdinalIgnoreCase) || + String.Equals(serverName, "127.0.0.1") || + String.Equals(serverName, "::1")) + { + return true; + } + + if (useDns) + { + try + { + ArrayList serverAddressesList = new ArrayList(); + ArrayList currentMachineAddressesList = new ArrayList(); + + IPAddress ownAddress = IPAddress.Parse("127.0.0.1"); + + // All the IP addresses of the hostname specified by the user + IPAddress[] serverAddress = Dns.GetHostAddresses(serverName); + serverAddressesList.AddRange(serverAddress); + + /// All the IP addresses of the current machine + IPAddress[] currentMachineAddress = Dns.GetHostAddresses(Environment.MachineName); + currentMachineAddressesList.AddRange(currentMachineAddress); + + // The address 127.0.0.1 also refers to the current machine + currentMachineAddressesList.Add(ownAddress); + + // If any of the addresses for the current machine is the same + // as the address for the hostname specified by the user + // then use a local connection + foreach (IPAddress address in currentMachineAddressesList) + { + if (serverAddressesList.Contains(address)) + { + return true; + } + } + } + catch + { + // If the Dns class throws an exception the host propbably does not + // exist so we return false + } + } + + return false; + } + } +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/README.md b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/README.md new file mode 100644 index 0000000000..77fc8404c4 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/README.md @@ -0,0 +1,18 @@ +Microsoft IIS Common +-------------------------------- + +The repository contains common resources shared by IIS Out-Of-Band (OOB) products. + +### Contributing + +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit https://cla.microsoft.com. + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/common_tests.rc b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/common_tests.rc new file mode 100644 index 0000000000..98b1593b3b --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/common_tests.rc @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#define RC_VERSION_INTERNAL_NAME "Common.UnitTests\0" +#define RC_VERSION_ORIGINAL_FILE_NAME "Common.UnitTests.dll\0" +#define RC_VERSION_FILE_DESCRIPTION "Common.UnitTests0" +#include diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/dbgutil_tests.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/dbgutil_tests.cpp new file mode 100644 index 0000000000..2fc97d6f95 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/dbgutil_tests.cpp @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.hxx" +#include "dbgutil.h" +#include + +DECLARE_DEBUG_PRINT_OBJECT( "test" ); + +VOID PrintLevel( DWORD level ) +{ + DWORD old = DEBUG_FLAGS_VAR; + DEBUG_FLAGS_VAR = level; + + DBGPRINTF(( DBG_CONTEXT, "Some Data %d\n", 47 )); + DBGINFO(( DBG_CONTEXT, "Some Info %s\n", "info" )); + DBGWARN(( DBG_CONTEXT, "Some Info %s\n", "warning" )); + DBGERROR(( DBG_CONTEXT, "Some Info %s\n", "error" )); + + DEBUG_FLAGS_VAR = old; +} + + +#pragma managed + +using namespace Microsoft::VisualStudio::TestTools::UnitTesting; + +[TestClass] +public ref class DebugUtilitiesTests +{ +public: + + [ClassInitialize] + static void InitializeDebugObjects(TestContext) + { + CREATE_DEBUG_PRINT_OBJECT; + + _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR ); + } + + [TestMethod] + void TestDbgError() + { + PrintLevel( DEBUG_FLAGS_ERROR ); + } + + [TestMethod] + void TestPrintAny() + { + PrintLevel( DEBUG_FLAGS_ANY ); + } + + [TestMethod] + void TestPrintError() + { + DBGERROR_HR( E_FAIL ); + DBGERROR_STATUS( 47 ); + } + + [TestMethod] + void TestPrintWarn() + { + PrintLevel( DEBUG_FLAGS_WARN ); + } + + [TestMethod] + void TestPrintInfo() + { + PrintLevel( DEBUG_FLAGS_INFO ); + } +}; \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/hash_tests.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/hash_tests.cpp new file mode 100644 index 0000000000..c0fb29f5a2 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/hash_tests.cpp @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.hxx" +#include "hashtable.h" +#include "hashfn.h" +#include "my_hash.h" + +VOID +CountHash( + MY_OBJ * , //pRecord, + PVOID pVoid +) +{ + DWORD * pActualCount = (DWORD*) pVoid; + ++(*pActualCount); +} + + +#pragma managed + +using namespace Microsoft::VisualStudio::TestTools::UnitTesting; + +[TestClass] +public ref class HashTableTests +{ +public: + + [TestMethod] + void AddTwoRecordsTest() + { + MY_HASH hash; + HRESULT hr; + hr = hash.Initialize(32); + + Assert::AreEqual(S_OK, hr, L"Invalid hash table initialization"); + + MY_OBJ one(L"one"); + hr = hash.InsertRecord(&one); + Assert::AreEqual(S_OK, hr, L"Cannot add element 'one'"); + + MY_OBJ two(L"two"); + hr = hash.InsertRecord(&two); + Assert::AreEqual(S_OK, hr, L"Cannot add element 'two'"); + + DWORD ActualCount = 0; + hash.Apply(CountHash, &ActualCount); + Assert::AreEqual((DWORD)2, ActualCount, L"ActualCount != 2"); + + hash.Clear(); + } +}; diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/hybrid_array_tests.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/hybrid_array_tests.cpp new file mode 100644 index 0000000000..9f54467e77 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/hybrid_array_tests.cpp @@ -0,0 +1,95 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.hxx" +#include "hybrid_array.h" + +// +// Cannot support mixed native/managed code for BUFFER class +// because of alignment. We need to run the test as native. +// +#include + + +void HybridArrayTest() +{ + HRESULT hr; + + { + HYBRID_ARRAY arrPointers; + Assert::AreEqual(32, arrPointers.QueryCapacity(), L"Invalid initial length"); + } + + { + HYBRID_ARRAY arrIntegers; + int SourceArray[] = {1, 2, 3, 4}; + hr = arrIntegers.Copy( SourceArray ); + Assert::AreEqual(S_OK, hr, L"Copy failed."); + Assert::AreEqual(_countof(SourceArray), arrIntegers.QueryCapacity()); + } + + { + HYBRID_ARRAY arrIntegers; + int* pOriginal = arrIntegers.QueryArray(); + int SourceArray[] = {1, 2, 3, 4}; + hr = arrIntegers.Copy( SourceArray ); + int* pNew = arrIntegers.QueryArray(); + Assert::AreEqual(S_OK, hr, L"Copy failed."); + Assert::AreEqual(_countof(SourceArray), arrIntegers.QueryCapacity(), L"Size should be like source"); + Assert::AreNotEqual((__int64)pNew, (__int64)pOriginal, L"Pointer should be different"); + + Assert::AreEqual(1, arrIntegers[0], L"Index 0 failed."); + Assert::AreEqual(2, arrIntegers.QueryItem(1), L"Index 1 failed."); + Assert::AreEqual(3, arrIntegers.QueryItem(2), L"Index 2 failed."); + Assert::AreEqual(4, arrIntegers[3], L"Index 3 failed."); + } + + { + HYBRID_ARRAY arrIntegers; + hr = arrIntegers.EnsureCapacity(100, false); + Assert::AreEqual(S_OK, hr, L"Copy failed."); + Assert::AreEqual(100, arrIntegers.QueryCapacity()); + } + + { + HYBRID_ARRAY arrIntegers; + arrIntegers[0] = 123; + arrIntegers[1] = 999; + hr = arrIntegers.EnsureCapacity(100, true /*copy previous*/); + Assert::AreEqual(S_OK, hr, L"Copy failed."); + Assert::AreEqual(100, arrIntegers.QueryCapacity()); + Assert::AreEqual(123, arrIntegers[0], L"Index resize 0 failed."); + Assert::AreEqual(999, arrIntegers[1], L"Index resize 1 failed."); + + } + + { + HYBRID_ARRAY arrIntegers; + arrIntegers[0] = 123; + arrIntegers[1] = 999; + hr = arrIntegers.EnsureCapacity(100, true /*copy previous*/, true /*trivial assign*/); + Assert::AreEqual(S_OK, hr, L"Copy failed."); + Assert::AreEqual(100, arrIntegers.QueryCapacity()); + Assert::AreEqual(123, arrIntegers[0], L"Index resize trivial 0 failed."); + Assert::AreEqual(999, arrIntegers[1], L"Index resize trivial 1 failed."); + + } +} + + +#pragma managed + +using namespace Microsoft::VisualStudio::TestTools::UnitTesting; + +[TestClass] +public ref class ArrayTests +{ +public: + + [TestMethod] + void HybridArrayTest() + { + ::HybridArrayTest(); + } + +}; diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/my_hash.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/my_hash.h new file mode 100644 index 0000000000..71417dc77b --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/my_hash.h @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +class MY_OBJ +{ + public: + MY_OBJ(PCWSTR pstr) + : _pstr(pstr) + {} + + PCWSTR GetString() + { + return _pstr; + } + + private: + PCWSTR _pstr; +}; + +class MY_HASH : public HASH_TABLE +{ + public: + VOID + ReferenceRecord( + MY_OBJ * //pRecord + ) + {} + + VOID + DereferenceRecord( + MY_OBJ * //pRecord + ) + {} + + PCWSTR + ExtractKey( + MY_OBJ * pRecord + ) + { + return pRecord->GetString(); + } + + DWORD + CalcKeyHash( + PCWSTR key + ) + { + return HashString(key); + } + + BOOL + EqualKeys( + PCWSTR key1, + PCWSTR key2 + ) + { + return (wcscmp(key1, key2) == 0); + } +}; + +void TestHash(); \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/precomp.hxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/precomp.hxx new file mode 100644 index 0000000000..16c76d9540 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/precomp.hxx @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once +// Native-only by default +#pragma unmanaged +#include diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/string_tests.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/string_tests.cpp new file mode 100644 index 0000000000..0b987e9b58 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/UnitTests/string_tests.cpp @@ -0,0 +1,680 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.hxx" +#include "buffer.h" +#include "stringu.h" +#include "stringa.h" + +// +// Cannot support mixed native/managed code for BUFFER class +// because of alignment. We need to run the test as native. +// +#include + +void TestBuffer() +{ + // + // 104 == 8 byte size rounded, why is this needed? + // + STACK_BUFFER( bufStack, 104 ); + BUFFER bufReg; + BUFFER* pBuf = new BUFFER; + + // + // QueryPtr + // + Assert::IsNotNull( bufStack.QueryPtr( ) ); + Assert::IsNotNull( bufReg.QueryPtr( ) ); + Assert::IsNotNull( pBuf->QueryPtr( ) ); + + // + // QuerySize + // + Assert::IsTrue( 104 == bufStack.QuerySize( ) ); + Assert::IsTrue( INLINED_BUFFER_LEN == bufReg.QuerySize( ) ); + Assert::IsTrue( INLINED_BUFFER_LEN == pBuf->QuerySize( ) ); + + // + // Resize + // + Assert::IsTrue( bufStack.Resize( 64 ) ); + Assert::IsTrue( bufReg.Resize( 128) ); + Assert::IsTrue( pBuf->Resize( 256 ) ); + + // + // Resize again + // + Assert::IsTrue( bufStack.Resize( 512, true ) ); + Assert::IsTrue( bufReg.Resize( 512, true ) ); + Assert::IsTrue( pBuf->Resize( 512, true ) ); + + // + // Resize again + // + Assert::IsTrue( bufStack.Resize( 1024, false ) ); + Assert::IsTrue( bufReg.Resize( 1024, false ) ); + Assert::IsTrue( pBuf->Resize( 1024, false ) ); + + // + // write to mem + // + ZeroMemory( bufStack.QueryPtr( ), bufStack.QuerySize( ) ); + ZeroMemory( bufReg.QueryPtr( ), bufReg.QuerySize( ) ); + ZeroMemory( pBuf->QueryPtr( ), pBuf->QuerySize( ) ); + + delete pBuf; +} + +void TestStraOverrun() +{ + STACK_STRA( straStack, 3 ); + wchar_t Input[] = {0x65f6, 0x0}; + HRESULT hr; + + hr = straStack.CopyW(Input); + Assert::IsTrue( SUCCEEDED(hr) ); + Assert::AreEqual( 3, straStack.QueryCCH(), L"Invalid string length." ); + Assert::AreEqual( 4, straStack.QuerySizeCCH(), L"Invalid buffer length." ); +} + +#define LOWER_A_THING L"ä" +#define UPPER_A_THING L"Ä" + +void TestStru() +{ + STACK_STRU( struStack, 104 ); + STRU struReg; + wchar_t buf[100]; + DWORD cbBuf = sizeof( buf ); + + // + // IsEmpty + // + Assert::IsTrue( struStack.IsEmpty( ) ); + Assert::IsTrue( L'\0' == struStack.QueryStr()[0] ); + Assert::IsTrue( struReg.IsEmpty( ) ); + + // + // Copy psz + // CopyA psz + // + Assert::IsTrue( SUCCEEDED( struStack.Copy( L"hello" ) ) ); + Assert::IsTrue( SUCCEEDED( struReg.CopyA( "hello" ) ) ); + + // + // Equal + // + Assert::IsTrue( struStack.Equals( L"hello" ) ); + Assert::IsTrue( !struStack.Equals( L"goodbye" ) ); + Assert::IsTrue( !struStack.Equals( L"" ) ); + + STRU strHELLO; + Assert::IsTrue( SUCCEEDED( strHELLO.Copy( L"HELLO" ) ) ); + + Assert::IsTrue( struStack.Equals( &struReg ) ); + Assert::IsTrue( struStack.Equals( struReg ) ); + + Assert::IsTrue( !struStack.Equals( &strHELLO ) ); + Assert::IsTrue( !struStack.Equals( strHELLO ) ); + + Assert::IsTrue( struStack.Equals( &strHELLO, TRUE ) ); + Assert::IsTrue( struStack.Equals( strHELLO, TRUE ) ); + + Assert::IsTrue( struStack.Equals( L"helLO", TRUE ) ); + + + Assert::IsTrue( STRU::Equals( L"Hello", L"Hello" ) ); + Assert::IsTrue( STRU::Equals( L"Hello", L"Hello", FALSE ) ); + Assert::IsTrue( STRU::Equals( L"Hello", L"Hello", TRUE ) ); + + Assert::IsFalse( STRU::Equals( L"hello", L"Hello" ) ); + Assert::IsFalse( STRU::Equals( L"hello", L"Hello", FALSE ) ); + Assert::IsTrue( STRU::Equals( L"hello", L"Hello", TRUE ) ); + + Assert::IsFalse( STRU::Equals( L"hello", L"goodbye" ) ); + Assert::IsFalse( STRU::Equals( L"hello", L"goodbye", FALSE ) ); + Assert::IsFalse( STRU::Equals( L"hello", L"goodbye", TRUE ) ); + + Assert::IsFalse( STRU::Equals( (PCWSTR)NULL, (PCWSTR)NULL ) ); + Assert::IsFalse( STRU::Equals( L"hello", (PCWSTR)NULL ) ); + Assert::IsFalse( STRU::Equals( (PCWSTR)NULL, L"hello" ) ); + + + + // + // Query* + // + Assert::IsTrue( 5 * sizeof( wchar_t ) == struStack.QueryCB( ) ); + Assert::IsTrue( 5 == struStack.QueryCCH( ) ); + Assert::IsTrue( 6 <= struStack.QuerySizeCCH( ) ); + Assert::IsTrue( L'h' == *( struStack.QueryStr( ) ) ); + + // + // Resize + // + Assert::IsTrue( SUCCEEDED( struReg.Resize( 7 ) ) ); + Assert::IsTrue( 7 == struReg.QuerySizeCCH( ) ); + + // + // SyncWithBuffer + // + *(struStack.QueryStr() + 5) = L'\0'; + Assert::AreEqual(S_OK, struStack.SyncWithBuffer( )); + Assert::IsTrue( 5 == struStack.QueryCCH( ) ); + + // + // Reset + // + struStack.Reset( ); + Assert::IsTrue( 0 == wcslen( struStack.QueryStr( ) ) ); + + // + // Append* + // + Assert::IsTrue( SUCCEEDED( struStack.Append( L"hell" ) ) ); + Assert::IsTrue( SUCCEEDED( struStack.Append( L"o", 1 ) ) ); + Assert::IsTrue( SUCCEEDED( struStack.Append( &struReg ) ) ); + Assert::IsTrue( SUCCEEDED( struStack.AppendA( "hell" ) ) ); + Assert::IsTrue( SUCCEEDED( struStack.AppendA( "0", 1, CP_ACP ) ) ); + Assert::IsTrue( 15 == wcslen( struStack.QueryStr( ) ) ); + + // + // CopyToBuffer + // + Assert::IsTrue( SUCCEEDED( struStack.CopyToBuffer( buf, &cbBuf ) ) ); + Assert::IsTrue( 15 == wcslen( buf ) ); + Assert::IsTrue( 16 * sizeof( wchar_t ) == cbBuf ); + + // + // Trim + // + Assert::IsTrue( SUCCEEDED( struStack.Copy(L" \n\tHello World! \n\t ") ) ); + struStack.Trim(); + Assert::IsTrue( struStack.Equals(L"Hello World!")); + + Assert::IsTrue( SUCCEEDED( struStack.Copy(L" Test test") ) ); + struStack.Trim(); + Assert::IsTrue( struStack.Equals(L"Test test")); + + Assert::IsTrue( SUCCEEDED( struStack.Copy(L"Test test ") ) ); + struStack.Trim(); + Assert::IsTrue( struStack.Equals(L"Test test")); + + Assert::IsTrue( SUCCEEDED( struStack.Copy(L" Test test ") ) ); + struStack.Trim(); + Assert::IsTrue( struStack.Equals(L"Test test")); + + Assert::IsTrue( SUCCEEDED( struStack.Copy(L" ") ) ); + struStack.Trim(); + Assert::IsTrue( struStack.Equals(L"")); + + Assert::IsTrue( SUCCEEDED( struStack.Copy(L" ") ) ); + struStack.Trim(); + Assert::IsTrue( struStack.Equals(L"")); + + Assert::IsTrue( SUCCEEDED( struStack.Copy(L"") ) ); + struStack.Trim(); + Assert::IsTrue( struStack.Equals(L"")); + + // + // StartsWith + // + Assert::IsTrue( SUCCEEDED( struStack.Copy(L"Just the facts, please.") ) ); + Assert::IsTrue( struStack.StartsWith(L"Just the facts, please.") ); + Assert::IsTrue( struStack.StartsWith(L"Just") ); + Assert::IsTrue( struStack.StartsWith(L"Just the") ); + Assert::IsTrue( !struStack.StartsWith(L"just the") ); + Assert::IsTrue( struStack.StartsWith(L"just The", TRUE) ); + Assert::IsTrue( !struStack.StartsWith((LPCWSTR) NULL, TRUE) ); + Assert::IsTrue( !struStack.StartsWith(L"Just the facts, please...") ); + + // + // EndsWith + // + Assert::IsTrue( SUCCEEDED( struStack.Copy(L"The beginning of the end of the beginning.") ) ); + Assert::IsTrue( struStack.EndsWith(L"The beginning of the end of the beginning.") ); + Assert::IsTrue( struStack.EndsWith(L".") ); + Assert::IsTrue( struStack.EndsWith(L"of the beginning.") ); + Assert::IsTrue( !struStack.EndsWith(L"Beginning.") ); + Assert::IsTrue( struStack.EndsWith(L"Beginning.", TRUE) ); + Assert::IsTrue( struStack.EndsWith(L"tHe BeGiNnIng.", TRUE) ); + Assert::IsTrue( !struStack.EndsWith((LPCWSTR) NULL, TRUE) ); + Assert::IsTrue( !struStack.EndsWith(L" The beginning of the end of the beginning.") ); + + // + // IndexOf + // + Assert::IsTrue( SUCCEEDED( struStack.Copy(L"01234567890") ) ); + Assert::IsTrue( 0 == struStack.IndexOf( L'0' ) ); + Assert::IsTrue( 1 == struStack.IndexOf( L'1' ) ); + Assert::IsTrue( 2 == struStack.IndexOf( L'2', 1 ) ); + Assert::IsTrue( 10 == struStack.IndexOf( L'0', 1 ) ); + Assert::IsTrue( -1 == struStack.IndexOf( L'A' ) ); + Assert::IsTrue( -1 == struStack.IndexOf( L'0', 20 ) ); + + Assert::IsTrue( 0 == struStack.IndexOf( L"0123" ) ); + Assert::IsTrue( -1 == struStack.IndexOf( L"0123", 1 ) ); + Assert::IsTrue( 0 == struStack.IndexOf( L"01234567890" ) ); + Assert::IsTrue( -1 == struStack.IndexOf( L"012345678901" ) ); + Assert::IsTrue( 1 == struStack.IndexOf( L"1234" ) ); + Assert::IsTrue( 1 == struStack.IndexOf( L"1234", 1 ) ); + Assert::IsTrue( -1 == struStack.IndexOf( (PCWSTR)NULL ) ); + Assert::IsTrue( 0 == struStack.IndexOf( L"" ) ); + Assert::IsTrue( -1 == struStack.IndexOf( L"", 20 ) ); + + // + // LastIndexOf + // + Assert::IsTrue( 10 == struStack.LastIndexOf( L'0' ) ); + Assert::IsTrue( 1 == struStack.LastIndexOf( L'1' ) ); + Assert::IsTrue( 2 == struStack.LastIndexOf( L'2', 1 ) ); + Assert::IsTrue( 10 == struStack.LastIndexOf( L'0', 1 ) ); + Assert::IsTrue( -1 == struStack.LastIndexOf( L'A' ) ); + Assert::IsTrue( -1 == struStack.LastIndexOf( L'0', 20 ) ); + + // + // SetLen + // + Assert::IsTrue( SUCCEEDED( struStack.SetLen( 2 ) ) ); + Assert::IsTrue( 2 == struStack.QueryCCH( ) ); + +#if defined( NTDDI_VERSION ) && NTDDI_VERSION >= NTDDI_LONGHORN + + // + // OS-locale case-insensitive compare + // Note how the two case-insensitive comparisons have different expected results + // + Assert::IsTrue( SUCCEEDED( struStack.Copy( LOWER_A_THING ) ) ); + Assert::IsTrue( SUCCEEDED( struReg.Copy( UPPER_A_THING ) ) ); + Assert::IsTrue( !struStack.Equals( &struReg ) ); + Assert::IsTrue( struStack.Equals( &struReg, TRUE ) ); + Assert::IsTrue( 0 != _wcsicmp( LOWER_A_THING, UPPER_A_THING ) ); + +#endif + + Assert::IsTrue( SUCCEEDED( struReg.SafeSnwprintf( L"%s%d", L"Hello", 10 ) ) ); + + // + // Fail since there is no null-terminating char. + // + struStack.Reset(); + struStack.Resize(200); + memset(struStack.QueryStr(), 'x', 200 * sizeof(WCHAR)); + Assert::AreNotEqual(S_OK, struStack.SyncWithBuffer()); +} + +void TestStra() +{ + STACK_STRA( straStack, 104 ); + STRA straReg; + char buf[100]; + DWORD cbBuf = sizeof( buf ); + + // + // IsEmpty + // + Assert::IsTrue( straStack.IsEmpty( ) ); + Assert::IsTrue( '\0' == straStack.QueryStr()[0] ); + Assert::IsTrue( straReg.IsEmpty( ) ); + + // + // Copy psz + // CopyW psz + // + Assert::IsTrue( SUCCEEDED( straStack.Copy( "hello" ) ) ); + Assert::IsTrue( SUCCEEDED( straReg.CopyW( L"hello" ) ) ); + + // + // Equal + // + Assert::IsTrue( straStack.Equals( "hello" ) ); + Assert::IsTrue( straStack.Equals( &straReg ) ); + Assert::IsTrue( straStack.Equals( "helLO", TRUE ) ); + + + Assert::IsTrue( STRA::Equals( "Hello", "Hello" ) ); + Assert::IsTrue( STRA::Equals( "Hello", "Hello", FALSE ) ); + Assert::IsTrue( STRA::Equals( "Hello", "Hello", TRUE ) ); + + Assert::IsFalse( STRA::Equals( "hello", "Hello" ) ); + Assert::IsFalse( STRA::Equals( "hello", "Hello", FALSE ) ); + Assert::IsTrue( STRA::Equals( "hello", "Hello", TRUE ) ); + + Assert::IsFalse( STRA::Equals( "hello", "goodbye" ) ); + Assert::IsFalse( STRA::Equals( "hello", "goodbye", FALSE ) ); + Assert::IsFalse( STRA::Equals( "hello", "goodbye", TRUE ) ); + + Assert::IsFalse( STRA::Equals( (PCSTR)NULL, (PCSTR)NULL ) ); + Assert::IsFalse( STRA::Equals( "hello", (PCSTR)NULL ) ); + Assert::IsFalse( STRA::Equals( (PCSTR)NULL, "hello" ) ); + + // + // Query* + // + Assert::IsTrue( 5 * sizeof( char ) == straStack.QueryCB( ) ); + Assert::IsTrue( 5 == straStack.QueryCCH( ) ); + Assert::IsTrue( 6 <= straStack.QuerySizeCCH( ) ); + Assert::IsTrue( 'h' == *( straStack.QueryStr( ) ) ); + + // + // Resize + // + Assert::IsTrue( SUCCEEDED( straReg.Resize( 7 ) ) ); + Assert::IsTrue( 7 == straReg.QuerySizeCCH( ) ); + + // + // SyncWithBuffer + // + *(straStack.QueryStr() + 5) = L'\0'; + Assert::AreEqual(S_OK, straStack.SyncWithBuffer( )); + Assert::IsTrue( 5 == straStack.QueryCCH( ) ); + + // + // Reset + // + straStack.Reset( ); + Assert::IsTrue( 0 == strlen( straStack.QueryStr( ) ) ); + + // + // Append* + // + Assert::IsTrue( SUCCEEDED( straStack.Append( "hell" ) ) ); + Assert::IsTrue( SUCCEEDED( straStack.Append( "o", 1 ) ) ); + Assert::IsTrue( SUCCEEDED( straStack.Append( &straReg ) ) ); + Assert::IsTrue( SUCCEEDED( straStack.AppendW( L"hell" ) ) ); + Assert::IsTrue( SUCCEEDED( straStack.AppendW( L"0", 1, CP_ACP ) ) ); + Assert::IsTrue( 15 == strlen( straStack.QueryStr( ) ) ); + + // + // CopyToBuffer + // + Assert::IsTrue( SUCCEEDED( straStack.CopyToBuffer( buf, &cbBuf ) ) ); + Assert::IsTrue( 15 == strlen( buf ) ); + Assert::IsTrue( 16 * sizeof( char ) == cbBuf ); + + // + // Trim + // + Assert::IsTrue( SUCCEEDED( straStack.Copy(" \n\tHello World! \n\t ") ) ); + straStack.Trim(); + Assert::IsTrue( straStack.Equals("Hello World!")); + + Assert::IsTrue( SUCCEEDED( straStack.Copy(" Test test") ) ); + straStack.Trim(); + Assert::IsTrue( straStack.Equals("Test test")); + + Assert::IsTrue( SUCCEEDED( straStack.Copy("Test test ") ) ); + straStack.Trim(); + Assert::IsTrue( straStack.Equals("Test test")); + + Assert::IsTrue( SUCCEEDED( straStack.Copy(" Test test ") ) ); + straStack.Trim(); + Assert::IsTrue( straStack.Equals("Test test")); + + Assert::IsTrue( SUCCEEDED( straStack.Copy(" ") ) ); + straStack.Trim(); + Assert::IsTrue( straStack.Equals("")); + + Assert::IsTrue( SUCCEEDED( straStack.Copy(" ") ) ); + straStack.Trim(); + Assert::IsTrue( straStack.Equals("")); + + Assert::IsTrue( SUCCEEDED( straStack.Copy("") ) ); + straStack.Trim(); + Assert::IsTrue( straStack.Equals("")); + + // + // StartsWith + // + Assert::IsTrue( SUCCEEDED( straStack.Copy("Just the facts, please.") ) ); + Assert::IsTrue( straStack.StartsWith("Just the facts, please.") ); + Assert::IsTrue( straStack.StartsWith("Just") ); + Assert::IsTrue( straStack.StartsWith("Just the") ); + Assert::IsTrue( !straStack.StartsWith("just the") ); + Assert::IsTrue( straStack.StartsWith("just The", TRUE) ); + Assert::IsTrue( !straStack.StartsWith((LPCSTR) NULL, TRUE) ); + Assert::IsTrue( !straStack.StartsWith("Just the facts, please...") ); + + // + // EndsWith + // + Assert::IsTrue( SUCCEEDED( straStack.Copy("The beginning of the end of the beginning.") ) ); + Assert::IsTrue( straStack.EndsWith("The beginning of the end of the beginning.") ); + Assert::IsTrue( straStack.EndsWith(".") ); + Assert::IsTrue( straStack.EndsWith("of the beginning.") ); + Assert::IsTrue( !straStack.EndsWith("Beginning.") ); + Assert::IsTrue( straStack.EndsWith("Beginning.", TRUE) ); + Assert::IsTrue( straStack.EndsWith("tHe BeGiNnIng.", TRUE) ); + Assert::IsTrue( !straStack.EndsWith((LPCSTR) NULL, TRUE) ); + Assert::IsTrue( !straStack.EndsWith(" The beginning of the end of the beginning.") ); + + // + // IndexOf + // + Assert::IsTrue( SUCCEEDED( straStack.Copy("01234567890") ) ); + Assert::IsTrue( 0 == straStack.IndexOf( '0' ) ); + Assert::IsTrue( 1 == straStack.IndexOf( '1' ) ); + Assert::IsTrue( 2 == straStack.IndexOf( '2', 1 ) ); + Assert::IsTrue( 10 == straStack.IndexOf( '0', 1 ) ); + Assert::IsTrue( -1 == straStack.IndexOf( 'A' ) ); + Assert::IsTrue( -1 == straStack.IndexOf( '0', 20 ) ); + + Assert::IsTrue( 0 == straStack.IndexOf( "0123" ) ); + Assert::IsTrue( -1 == straStack.IndexOf( "0123", 1 ) ); + Assert::IsTrue( 0 == straStack.IndexOf( "01234567890" ) ); + Assert::IsTrue( -1 == straStack.IndexOf( "012345678901" ) ); + Assert::IsTrue( 1 == straStack.IndexOf( "1234" ) ); + Assert::IsTrue( 1 == straStack.IndexOf( "1234", 1 ) ); + Assert::IsTrue( -1 == straStack.IndexOf( (PCSTR)NULL ) ); + Assert::IsTrue( 0 == straStack.IndexOf( "" ) ); + Assert::IsTrue( -1 == straStack.IndexOf( "", 20 ) ); + + // + // LastIndexOf + // + Assert::IsTrue( 10 == straStack.LastIndexOf( '0' ) ); + Assert::IsTrue( 1 == straStack.LastIndexOf( '1' ) ); + Assert::IsTrue( 2 == straStack.LastIndexOf( '2', 1 ) ); + Assert::IsTrue( 10 == straStack.LastIndexOf( '0', 1 ) ); + Assert::IsTrue( -1 == straStack.LastIndexOf( 'A' ) ); + Assert::IsTrue( -1 == straStack.LastIndexOf( '0', 20 ) ); + + // + // SetLen + // + Assert::IsTrue( SUCCEEDED( straStack.SetLen( 2 ) ) ); + Assert::IsTrue( 2 == straStack.QueryCCH( ) ); + + + // + // Convert. + // + { + STRA str; + wchar_t psz[] = {0x41, L'Ã', 0x0}; + char pszA[] = {0x41, 'Ã', 0x0}; + Assert::IsTrue( SUCCEEDED(str.CopyW((LPCWSTR)psz, 2, CP_ACP )) ); + Assert::IsTrue( 0 == strcmp( pszA, str.QueryStr() ) ); + } + // + // Empty + // + { + STRA str; + wchar_t psz[] = {0x0}; + char pszA[] = {0x0}; + Assert::IsTrue( SUCCEEDED(str.CopyW((LPCWSTR)psz, 0, CP_ACP )) ); + Assert::IsTrue( 0 == strcmp( pszA, str.QueryStr() ) ); + } + + // + // Fail since there is no null-terminating char. + // + straStack.Reset(); + straStack.Resize(200); + memset(straStack.QueryStr(), 'x', 200); + Assert::AreNotEqual(S_OK, straStack.SyncWithBuffer()); +} + +VOID +AsciiAssert(char * str1, char * str2, size_t length) +{ + for ( size_t index = 0; index < length; ++index ) + { + Assert::AreEqual(str1[index], str2[index]); + } +} + +void +TestStraUnicode() +{ + STRA str; + HRESULT hr = S_OK; + + // + // Tool used to convert unicode to UTF-8 code points and hexadecimal code points: + // http://rishida.net/scripts/uniview/conversion.php + // + + // + // Input values to play with. + // + + // Real unicode string. + LPCWSTR InputRealUnicode = L"?q=世加"; + + // This is the same value than InputRealUnicode, but represented as an array. + wchar_t InputRealUnicodeArray[] = + { + 0x3F, // ? + 0x71, // q + 0x3D, // = + 0x4E16, // 世 + 0x52A0, // 加 + 0x00 // L'\0' + }; + + wchar_t InputAscii[] = + { + 0x3F, // ? + 0x71, // q + 0x3D, // = + 0x7F, // 127 + 0x00 // L'\0' + }; + + // Fake unicode + // UTF-8 code units in 'wchar_t' chars instead of 'char' chars. + // This is how WinHttp returns the query string. + wchar_t InputFakeUnicode[] = + { + 0x3F, // ? + 0x71, // q + 0x3D, // = + 0xE4, // 1st code unit for '世' + 0xB8, // 2nd code unit for '世' + 0x96, // 3rd code unit for '世' + 0xE5, // 1st code unit for '加' + 0x8A, // 2nd code unit for '加' + 0xA0, // 3rd code unit for '加' + 0x00 // L'\0' + }; + + // + // Expected values after translation. + // + + unsigned char ExpectedAsciiCodeUnits[] = + { + 0x3F, // ? + 0x71, // q + 0x3D, // = + 0xE4, // 1st code unit for '世' + 0xB8, // 2nd code unit for '世' + 0x96, // 3rd code unit for '世' + 0xE5, // 1st code unit for '加' + 0x8A, // 2nd code unit for '加' + 0xA0, // 3rd code unit for '加' + 0x00 // L'\0' + }; + + char ExpectedAscii[] = + { + 0x3F, // ? + 0x71, // q + 0x3D, // = + 0x7F, // 127 + 0x00 // L'\0' + }; + + // + // Act and Assert. + // + + hr = str.CopyW(InputRealUnicode); + Assert::AreEqual(S_OK, hr); + Assert::AreEqual(9UL, str.QueryCCH(), L"Invalid real unicode query string length."); + AsciiAssert( (char*)ExpectedAsciiCodeUnits, str.QueryStr(), str.QueryCCH() ); + + hr = str.CopyW(InputRealUnicodeArray); + Assert::AreEqual(S_OK, hr); + Assert::AreEqual(9UL, str.QueryCCH(), L"Invalid real unicode query string length."); + AsciiAssert( (char*)ExpectedAsciiCodeUnits, str.QueryStr(), str.QueryCCH() ); + + hr = str.CopyWTruncate(InputFakeUnicode); + Assert::AreEqual(S_OK, hr); + Assert::AreEqual(9UL, str.QueryCCH(), L"Invalid truncated fake unicode query string length."); + AsciiAssert( (char*)ExpectedAsciiCodeUnits, str.QueryStr(), str.QueryCCH() ); + + hr = str.CopyWTruncate(InputAscii); + Assert::AreEqual(S_OK, hr); + Assert::AreEqual(4UL, str.QueryCCH(), L"Invalid truncated ASCII query string length."); + AsciiAssert( ExpectedAscii, str.QueryStr(), str.QueryCCH() ); + + hr = str.CopyW(InputAscii); + Assert::AreEqual(S_OK, hr); + Assert::AreEqual(4UL, str.QueryCCH(), L"Invalid CopyW ASCII query string length."); + AsciiAssert( ExpectedAscii, str.QueryStr(), str.QueryCCH() ); + +} + +#pragma managed + +using namespace Microsoft::VisualStudio::TestTools::UnitTesting; + +[TestClass] +public ref class StringTests +{ +public: + + [TestMethod] + void BufferTest() + { + ::TestBuffer(); + } + + [TestMethod] + void StruTest() + { + ::TestStru(); + } + + [TestMethod] + void StraTest() + { + ::TestStra(); + } + + [TestMethod] + void TestStraOverrun() + { + ::TestStraOverrun(); + } + + [TestMethod] + void StraUnicodeTest() + { + ::TestStraUnicode(); + } +}; diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/CommonLib.vcxproj b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/CommonLib.vcxproj new file mode 100644 index 0000000000..908ef42d1a --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/CommonLib.vcxproj @@ -0,0 +1,79 @@ + + + + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {B54A8F61-60DE-4AD9-87CA-D102F230678E} + Win32Proj + Lib + CommonLib + + + + StaticLibrary + v141 + + + false + + + + $(ProjectDir)..\include;$(IncludePath) + iiscommon + + + + true + precomp.h + _LIB;%(PreprocessorDefinitions) + + + Windows + + + + + + + + + + + + + + + + + + + + + + This project is trying to import a missing file: {0}. + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/acache.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/acache.cxx new file mode 100644 index 0000000000..262c010a2a --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/acache.cxx @@ -0,0 +1,443 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +LONG ALLOC_CACHE_HANDLER::sm_nFillPattern = 0xACA50000; +HANDLE ALLOC_CACHE_HANDLER::sm_hHeap; + +// +// This class is used to implement the free list. We cast the free'd +// memory block to a FREE_LIST_HEADER*. The signature is used to guard against +// double deletion. We also fill memory with a pattern. +// +class FREE_LIST_HEADER +{ +public: + SLIST_ENTRY ListEntry; + DWORD dwSignature; + + enum + { + FREE_SIGNATURE = (('A') | ('C' << 8) | ('a' << 16) | (('$' << 24) | 0x80)), + }; +}; + +ALLOC_CACHE_HANDLER::ALLOC_CACHE_HANDLER( + VOID +) : m_nThreshold(0), + m_cbSize(0), + m_pFreeLists(NULL), + m_nTotal(0) +{ +} + +ALLOC_CACHE_HANDLER::~ALLOC_CACHE_HANDLER( + VOID +) +{ + if (m_pFreeLists != NULL) + { + CleanupLookaside(); + m_pFreeLists->Dispose(); + m_pFreeLists = NULL; + } +} + +HRESULT +ALLOC_CACHE_HANDLER::Initialize( + DWORD cbSize, + LONG nThreshold +) +{ + HRESULT hr = S_OK; + + m_nThreshold = nThreshold; + if ( m_nThreshold > 0xffff) + { + // + // This will be compared against QueryDepthSList return value (USHORT). + // + m_nThreshold = 0xffff; + } + + if ( IsPageheapEnabled() ) + { + // + // Disable acache. + // + m_nThreshold = 0; + } + + // + // Make sure the block is big enough to hold a FREE_LIST_HEADER. + // + m_cbSize = cbSize; + m_cbSize = max(m_cbSize, sizeof(FREE_LIST_HEADER)); + + // + // Round up the block size to a multiple of the size of a LONG (for + // the fill pattern in Free()). + // + m_cbSize = (m_cbSize + sizeof(LONG) - 1) & ~(sizeof(LONG) - 1); + +#if defined(_MSC_VER) && _MSC_VER >= 1600 // VC10 + auto Init = [] (SLIST_HEADER* pHead) + { + InitializeSListHead(pHead); + }; +#else + class Functor + { + public: + void operator()(SLIST_HEADER* pHead) + { + InitializeSListHead(pHead); + } + } Init; +#endif + + hr = PER_CPU::Create(Init, + &m_pFreeLists ); + if (FAILED(hr)) + { + goto Finished; + } + + m_nFillPattern = InterlockedIncrement(&sm_nFillPattern); + +Finished: + + return hr; +} + +// static +HRESULT +ALLOC_CACHE_HANDLER::StaticInitialize( + VOID +) +{ + // + // Since the memory allocated is fixed size, + // a heap is not really needed, allocations can be done + // using VirtualAllocEx[Numa]. For now use Windows Heap. + // + // Be aware that creating one private heap consumes more + // virtual address space for the worker process. + // + sm_hHeap = GetProcessHeap(); + return S_OK; +} + + +// static +VOID +ALLOC_CACHE_HANDLER::StaticTerminate( + VOID +) +{ + sm_hHeap = NULL; +} + +VOID +ALLOC_CACHE_HANDLER::CleanupLookaside( + VOID +) +/*++ + Description: + This function cleans up the lookaside list by removing storage space. + + Arguments: + None. + + Returns: + None +--*/ +{ + // + // Free up all the entries in the list. + // Don't use InterlockedFlushSList, in order to work + // memory must be 16 bytes aligned and currently it is 64. + // + +#if defined(_MSC_VER) && _MSC_VER >= 1600 // VC10 + auto Predicate = [=] (SLIST_HEADER * pListHeader) + { + PSLIST_ENTRY pl; + LONG NodesToDelete = QueryDepthSList( pListHeader ); + + pl = InterlockedPopEntrySList( pListHeader ); + while ( pl != NULL && --NodesToDelete >= 0 ) + { + InterlockedDecrement( &m_nTotal); + + ::HeapFree( sm_hHeap, 0, pl ); + + pl = InterlockedPopEntrySList(pListHeader); + } + }; +#else + class Functor + { + public: + explicit Functor(ALLOC_CACHE_HANDLER * pThis) : _pThis(pThis) + { + } + void operator()(SLIST_HEADER * pListHeader) + { + PSLIST_ENTRY pl; + LONG NodesToDelete = QueryDepthSList( pListHeader ); + + pl = InterlockedPopEntrySList( pListHeader ); + while ( pl != NULL && --NodesToDelete >= 0 ) + { + InterlockedDecrement( &_pThis->m_nTotal); + + ::HeapFree( sm_hHeap, 0, pl ); + + pl = InterlockedPopEntrySList(pListHeader); + } + } + private: + ALLOC_CACHE_HANDLER * _pThis; + } Predicate(this); +#endif + + m_pFreeLists ->ForEach(Predicate); +} + +LPVOID +ALLOC_CACHE_HANDLER::Alloc( + VOID +) +{ + LPVOID pMemory = NULL; + + if ( m_nThreshold > 0 ) + { + SLIST_HEADER * pListHeader = m_pFreeLists ->GetLocal(); + pMemory = (LPVOID) InterlockedPopEntrySList(pListHeader); // get the real object + + if (pMemory != NULL) + { + FREE_LIST_HEADER* pfl = (FREE_LIST_HEADER*) pMemory; + // + // If the signature is wrong then somebody's been scribbling + // on memory that they've freed. + // + DBG_ASSERT(pfl->dwSignature == FREE_LIST_HEADER::FREE_SIGNATURE); + } + } + + if ( pMemory == NULL ) + { + // + // No free entry. Need to alloc a new object. + // + pMemory = (LPVOID) ::HeapAlloc( sm_hHeap, + 0, + m_cbSize ); + + if ( pMemory != NULL ) + { + // + // Update counters. + // + m_nTotal++; + } + } + + if ( pMemory == NULL ) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + } + else + { + FREE_LIST_HEADER* pfl = (FREE_LIST_HEADER*) pMemory; + pfl->dwSignature = 0; // clear; just in case caller never overwrites + } + + return pMemory; +} + +VOID +ALLOC_CACHE_HANDLER::Free( + __in LPVOID pMemory +) +{ + // + // Assume that this is allocated using the Alloc() function. + // + DBG_ASSERT(NULL != pMemory); + + // + // Use a signature to check against double deletions. + // + FREE_LIST_HEADER* pfl = (FREE_LIST_HEADER*) pMemory; + DBG_ASSERT(pfl->dwSignature != FREE_LIST_HEADER::FREE_SIGNATURE); + + // + // Start filling the space beyond the portion overlaid by the initial + // FREE_LIST_HEADER. Fill at most 6 DWORDS. + // + LONG* pl = (LONG*) (pfl+1); + + for (LONG cb = (LONG)min(6 * sizeof(LONG),m_cbSize) - sizeof(FREE_LIST_HEADER); + cb > 0; + cb -= sizeof(LONG)) + { + *pl++ = m_nFillPattern; + } + + // + // Now, set the signature. + // + pfl->dwSignature = FREE_LIST_HEADER::FREE_SIGNATURE; + + // + // Store the items in the alloc cache. + // + SLIST_HEADER * pListHeader = m_pFreeLists ->GetLocal(); + + if ( QueryDepthSList(pListHeader) >= m_nThreshold ) + { + // + // Threshold for free entries is exceeded. Free the object to + // process pool. + // + ::HeapFree( sm_hHeap, 0, pMemory ); + } + else + { + // + // Store the given pointer in the single linear list + // + InterlockedPushEntrySList(pListHeader, &pfl->ListEntry); + } +} + +DWORD +ALLOC_CACHE_HANDLER::QueryDepthForAllSLists( + VOID +) +/*++ + +Description: + + Aggregates the total count of elements in all lists. + +Arguments: + + None. + +Return Value: + + Total count (snapshot). + +--*/ +{ + DWORD Count = 0; + + if (m_pFreeLists != NULL) + { +#if defined(_MSC_VER) && _MSC_VER >= 1600 // VC10 + auto Predicate = [&Count] (SLIST_HEADER * pListHeader) + { + Count += QueryDepthSList(pListHeader); + }; +#else + class Functor + { + public: + explicit Functor(DWORD& Count) : _Count(Count) + { + } + void operator()(SLIST_HEADER * pListHeader) + { + _Count += QueryDepthSList(pListHeader); + } + private: + DWORD& _Count; + } Predicate(Count); +#endif + // + // [&Count] means that the method can modify local variable Count. + // + m_pFreeLists ->ForEach(Predicate); + } + + return Count; +} + +// static +BOOL +ALLOC_CACHE_HANDLER::IsPageheapEnabled( + VOID +) +{ + BOOL fRet = FALSE; + BOOL fLockedHeap = FALSE; + HMODULE hModule = NULL; + HANDLE hHeap = NULL; + PROCESS_HEAP_ENTRY heapEntry = {0}; + + // + // If verifier.dll is loaded - we are running under app verifier == pageheap is enabled + // + hModule = GetModuleHandle( L"verifier.dll" ); + if ( hModule != NULL ) + { + hModule = NULL; + fRet = TRUE; + goto Finished; + } + + // + // Create a heap for calling heapwalk + // otherwise HeapWalk turns off lookasides for a useful heap + // + hHeap = ::HeapCreate( 0, 0, 0 ); + if ( hHeap == NULL ) + { + fRet = FALSE; + goto Finished; + } + + fRet = ::HeapLock( hHeap ); + if ( !fRet ) + { + goto Finished; + } + fLockedHeap = TRUE; + + // + // If HeapWalk is unsupported -> then running page heap + // + fRet = ::HeapWalk( hHeap, &heapEntry ); + if ( !fRet ) + { + if ( GetLastError() == ERROR_INVALID_FUNCTION ) + { + fRet = TRUE; + goto Finished; + } + } + + fRet = FALSE; + +Finished: + + if ( fLockedHeap ) + { + fLockedHeap = FALSE; + DBG_REQUIRE( ::HeapUnlock( hHeap ) ); + } + + if ( hHeap ) + { + DBG_REQUIRE( ::HeapDestroy( hHeap ) ); + hHeap = NULL; + } + + return fRet; +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/ahutil.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/ahutil.cpp new file mode 100644 index 0000000000..9685b233c8 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/ahutil.cpp @@ -0,0 +1,1734 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +HRESULT +SetElementProperty( + IN IAppHostElement * pElement, + IN CONST WCHAR * szPropName, + IN CONST VARIANT * varPropValue + ) +{ + HRESULT hr = NOERROR; + + CComPtr pPropElement; + + BSTR bstrPropName = SysAllocString( szPropName ); + + if( !bstrPropName ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto exit; + } + + hr = pElement->GetPropertyByName( bstrPropName, + &pPropElement ); + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = pPropElement->put_Value( *varPropValue ); + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + +exit: + + if( bstrPropName ) + { + SysFreeString( bstrPropName ); + bstrPropName = NULL; + } + + return hr; +} + +HRESULT +SetElementStringProperty( + IN IAppHostElement * pElement, + IN CONST WCHAR * szPropName, + IN CONST WCHAR * szPropValue + ) +{ + HRESULT hr; + VARIANT varPropValue; + VariantInit(&varPropValue); + + hr = VariantAssign(&varPropValue, szPropValue); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = SetElementProperty(pElement, szPropName, &varPropValue); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + VariantClear(&varPropValue); + return hr; +} + +HRESULT +GetElementStringProperty( + IN IAppHostElement * pElement, + IN CONST WCHAR * szPropName, + OUT BSTR * pbstrPropValue + ) +{ + HRESULT hr = S_OK; + BSTR bstrPropName = SysAllocString( szPropName ); + IAppHostProperty* pProperty = NULL; + + *pbstrPropValue = NULL; + + if (!bstrPropName) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto exit; + } + + hr = pElement->GetPropertyByName( bstrPropName, &pProperty ); + if (FAILED(hr)) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = pProperty->get_StringValue( pbstrPropValue ); + if (FAILED(hr)) + { + DBGERROR_HR( hr ); + goto exit; + } + +exit: + + if (pProperty) + { + pProperty->Release(); + } + + if (bstrPropName) + { + SysFreeString( bstrPropName ); + } + + return hr; +} + + +HRESULT +GetElementStringProperty( + IN IAppHostElement * pElement, + IN CONST WCHAR * szPropName, + OUT STRU * pstrPropValue + ) +{ + HRESULT hr = S_OK; + BSTR bstrPropName = SysAllocString( szPropName ); + IAppHostProperty* pProperty = NULL; + BSTR bstrPropValue = NULL; + + if (!bstrPropName) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto exit; + } + + hr = pElement->GetPropertyByName( bstrPropName, &pProperty ); + if (FAILED(hr)) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = pProperty->get_StringValue( &bstrPropValue ); + if (FAILED(hr)) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = pstrPropValue->Copy(bstrPropValue); + if (FAILED(hr)) + { + DBGERROR_HR( hr ); + goto exit; + } + +exit: + + if (pProperty) + { + pProperty->Release(); + } + + if (bstrPropValue) + { + SysFreeString( bstrPropValue ); + } + + if (bstrPropName) + { + SysFreeString( bstrPropName ); + } + + return hr; +} + +HRESULT +GetElementChildByName( + IN IAppHostElement * pElement, + IN LPCWSTR pszElementName, + OUT IAppHostElement ** ppChildElement +) +{ + BSTR bstrElementName = SysAllocString(pszElementName); + if (bstrElementName == NULL) + { + return E_OUTOFMEMORY; + } + HRESULT hr = pElement->GetElementByName(bstrElementName, + ppChildElement); + SysFreeString(bstrElementName); + return hr; +} + +HRESULT +GetElementBoolProperty( + IN IAppHostElement * pElement, + IN LPCWSTR pszPropertyName, + OUT bool * pBool +) +{ + BOOL fValue; + HRESULT hr = GetElementBoolProperty(pElement, + pszPropertyName, + &fValue); + if (SUCCEEDED(hr)) + { + *pBool = !!fValue; + } + return hr; +} + +HRESULT +GetElementBoolProperty( + IN IAppHostElement * pElement, + IN LPCWSTR pszPropertyName, + OUT BOOL * pBool +) +{ + HRESULT hr = S_OK; + BSTR bstrPropertyName = NULL; + IAppHostProperty * pProperty = NULL; + VARIANT varValue; + + VariantInit( &varValue ); + + bstrPropertyName = SysAllocString( pszPropertyName ); + if ( bstrPropertyName == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + // Now ask for the property and if it succeeds it is returned directly back. + hr = pElement->GetPropertyByName( bstrPropertyName, &pProperty ); + if ( FAILED ( hr ) ) + { + goto exit; + } + + // Now let's get the property and then extract it from the Variant. + hr = pProperty->get_Value( &varValue ); + if ( FAILED ( hr ) ) + { + goto exit; + } + + hr = VariantChangeType( &varValue, &varValue, 0, VT_BOOL ); + if ( FAILED ( hr ) ) + { + goto exit; + } + + // extract the value + *pBool = ( V_BOOL( &varValue ) == VARIANT_TRUE ); + +exit: + + VariantClear( &varValue ); + + if ( bstrPropertyName != NULL ) + { + SysFreeString( bstrPropertyName ); + bstrPropertyName = NULL; + } + + if ( pProperty != NULL ) + { + pProperty->Release(); + pProperty = NULL; + } + + return hr; + +} + +HRESULT +GetElementDWORDProperty( + IN IAppHostElement * pSitesCollectionEntry, + IN LPCWSTR pwszName, + OUT DWORD * pdwValue +) +{ + HRESULT hr = S_OK; + IAppHostProperty * pProperty = NULL; + BSTR bstrName = NULL; + VARIANT varValue; + + VariantInit( &varValue ); + + bstrName = SysAllocString( pwszName ); + if ( bstrName == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto error; + } + + hr = pSitesCollectionEntry->GetPropertyByName( bstrName, + &pProperty ); + if ( FAILED ( hr ) ) + { + goto error; + } + + hr = pProperty->get_Value( &varValue ); + if ( FAILED ( hr ) ) + { + goto error; + } + + hr = VariantChangeType( &varValue, &varValue, 0, VT_UI4 ); + if ( FAILED ( hr ) ) + { + goto error; + } + + // extract the value + *pdwValue = varValue.ulVal; + +error: + + VariantClear( &varValue ); + + if ( pProperty != NULL ) + { + pProperty->Release(); + pProperty = NULL; + } + + if ( bstrName != NULL ) + { + SysFreeString( bstrName ); + bstrName = NULL; + } + + return hr; +} + +HRESULT +GetElementINTProperty( + IN IAppHostElement * pElement, + IN LPCWSTR pszPropertyName, + OUT INT * pintValue +) +{ + HRESULT hr = S_OK; + IAppHostProperty * pProperty = NULL; + BSTR bstrName = NULL; + VARIANT varValue; + + VariantInit( &varValue ); + + bstrName = SysAllocString( pszPropertyName ); + if ( bstrName == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto error; + } + + hr = pElement->GetPropertyByName( bstrName, + &pProperty ); + if ( FAILED( hr ) ) + { + goto error; + } + + hr = pProperty->get_Value( &varValue ); + if ( FAILED( hr ) ) + { + goto error; + } + + hr = VariantChangeType( &varValue, &varValue, 0, VT_I4 ); + if ( FAILED( hr ) ) + { + goto error; + } + + // extract the value + *pintValue = varValue.intVal; + +error: + + VariantClear( &varValue ); + + if ( pProperty != NULL ) + { + pProperty->Release(); + pProperty = NULL; + } + + if ( bstrName != NULL ) + { + SysFreeString( bstrName ); + bstrName = NULL; + } + + return hr; +} + +HRESULT +GetElementLONGLONGProperty( + IN IAppHostElement * pSitesCollectionEntry, + IN LPCWSTR pwszName, + OUT LONGLONG * pllValue +) +{ + HRESULT hr = S_OK; + IAppHostProperty * pProperty = NULL; + BSTR bstrName = NULL; + VARIANT varValue; + + VariantInit( &varValue ); + + bstrName = SysAllocString( pwszName ); + if ( bstrName == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto error; + } + + hr = pSitesCollectionEntry->GetPropertyByName( bstrName, + &pProperty ); + if ( FAILED ( hr ) ) + { + goto error; + } + + hr = pProperty->get_Value( &varValue ); + if ( FAILED ( hr ) ) + { + goto error; + } + + hr = VariantChangeType( &varValue, &varValue, 0, VT_I8 ); + if ( FAILED ( hr ) ) + { + goto error; + } + + // extract the value + *pllValue = varValue.ulVal; + +error: + + VariantClear( &varValue ); + + if ( pProperty != NULL ) + { + pProperty->Release(); + pProperty = NULL; + } + + if ( bstrName != NULL ) + { + SysFreeString( bstrName ); + bstrName = NULL; + } + + return hr; +} + +HRESULT +GetElementRawTimeSpanProperty( + IN IAppHostElement * pElement, + IN LPCWSTR pszPropertyName, + OUT ULONGLONG * pulonglong +) +{ + HRESULT hr = S_OK; + BSTR bstrPropertyName = NULL; + IAppHostProperty * pProperty = NULL; + VARIANT varValue; + + VariantInit( &varValue ); + + bstrPropertyName = SysAllocString( pszPropertyName ); + if ( bstrPropertyName == NULL ) + { + hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY ); + goto Finished; + } + + // Now ask for the property and if it succeeds it is returned directly back + hr = pElement->GetPropertyByName( bstrPropertyName, &pProperty ); + if ( FAILED ( hr ) ) + { + goto Finished; + } + + // Now let's get the property and then extract it from the Variant. + hr = pProperty->get_Value( &varValue ); + if ( FAILED ( hr ) ) + { + goto Finished; + } + + hr = VariantChangeType( &varValue, &varValue, 0, VT_UI8 ); + if ( FAILED ( hr ) ) + { + goto Finished; + } + + // extract the value + *pulonglong = varValue.ullVal; + + +Finished: + + VariantClear( &varValue ); + + if ( bstrPropertyName != NULL ) + { + SysFreeString( bstrPropertyName ); + bstrPropertyName = NULL; + } + + if ( pProperty != NULL ) + { + pProperty->Release(); + pProperty = NULL; + } + + return hr; + +} // end of Config_GetRawTimeSpanProperty + +HRESULT +DeleteElementFromCollection( + IAppHostElementCollection *pCollection, + CONST WCHAR * szKeyName, + CONST WCHAR * szKeyValue, + ULONG BehaviorFlags, + BOOL * pfDeleted + ) +{ + HRESULT hr = NOERROR; + ULONG index; + + VARIANT varIndex; + VariantInit( &varIndex ); + + *pfDeleted = FALSE; + + hr = FindElementInCollection( + pCollection, + szKeyName, + szKeyValue, + BehaviorFlags, + &index + ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + if (hr == S_FALSE) + { + // + // Not found. + // + + goto exit; + } + + varIndex.vt = VT_UI4; + varIndex.ulVal = index; + + hr = pCollection->DeleteElement( varIndex ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + *pfDeleted = TRUE; + +exit: + + return hr; +} + +HRESULT +DeleteAllElementsFromCollection( + IAppHostElementCollection *pCollection, + CONST WCHAR * szKeyName, + CONST WCHAR * szKeyValue, + ULONG BehaviorFlags, + UINT * pNumDeleted + ) +{ + HRESULT hr = S_OK; + UINT numDeleted = 0; + BOOL fDeleted = TRUE; + + while (fDeleted) + { + hr = DeleteElementFromCollection( + pCollection, + szKeyName, + szKeyValue, + BehaviorFlags, + &fDeleted + ); + + if (hr == S_FALSE) + { + hr = S_OK; + break; + } + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + break; + } + + if (fDeleted) + { + numDeleted++; + } + } + + *pNumDeleted = numDeleted; + return hr; +} + +BOOL +FindCompareCaseSensitive( + CONST WCHAR * szLookupValue, + CONST WCHAR * szKeyValue + ) +{ + return !wcscmp(szLookupValue, szKeyValue); +} + +BOOL +FindCompareCaseInsensitive( + CONST WCHAR * szLookupValue, + CONST WCHAR * szKeyValue + ) +{ + return !_wcsicmp(szLookupValue, szKeyValue); +} + +typedef +BOOL +(*PFN_FIND_COMPARE_PROC)( + CONST WCHAR *szLookupValue, + CONST WCHAR *szKeyValue + ); + +HRESULT +FindElementInCollection( + IAppHostElementCollection *pCollection, + CONST WCHAR * szKeyName, + CONST WCHAR * szKeyValue, + ULONG BehaviorFlags, + OUT ULONG * pIndex + ) +{ + HRESULT hr = NOERROR; + + CComPtr pElement; + CComPtr pKeyProperty; + + VARIANT varIndex; + VariantInit( &varIndex ); + + VARIANT varKeyValue; + VariantInit( &varKeyValue ); + + DWORD count; + DWORD i; + + BSTR bstrKeyName = NULL; + PFN_FIND_COMPARE_PROC compareProc; + + compareProc = (BehaviorFlags & FIND_ELEMENT_CASE_INSENSITIVE) + ? &FindCompareCaseInsensitive + : &FindCompareCaseSensitive; + + bstrKeyName = SysAllocString( szKeyName ); + if( !bstrKeyName ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pCollection->get_Count( &count ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + for( i = 0; i < count; i++ ) + { + varIndex.vt = VT_UI4; + varIndex.ulVal = i; + + hr = pCollection->get_Item( varIndex, + &pElement ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto tryNext; + } + + hr = pElement->GetPropertyByName( bstrKeyName, + &pKeyProperty ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto tryNext; + } + + hr = pKeyProperty->get_Value( &varKeyValue ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto tryNext; + } + + if ((compareProc)(szKeyValue, varKeyValue.bstrVal)) + { + *pIndex = i; + break; + } + +tryNext: + + pElement.Release(); + pKeyProperty.Release(); + + VariantClear( &varKeyValue ); + } + + if (i >= count) + { + hr = S_FALSE; + } + +exit: + + SysFreeString( bstrKeyName ); + VariantClear( &varKeyValue ); + + return hr; +} + +HRESULT +VariantAssign( + IN OUT VARIANT * pv, + IN CONST WCHAR * sz + ) +{ + if( !pv || !sz ) + { + return E_INVALIDARG; + } + + HRESULT hr = NOERROR; + + BSTR bstr = SysAllocString( sz ); + if( !bstr ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto exit; + } + + hr = VariantClear( pv ); + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + pv->vt = VT_BSTR; + pv->bstrVal = bstr; + bstr = NULL; + +exit: + + SysFreeString( bstr ); + + return hr; +} + +HRESULT +GetLocationFromFile( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szLocationPath, + OUT IAppHostConfigLocation ** ppLocation, + OUT BOOL * pFound + ) +{ + HRESULT hr = NOERROR; + + CComPtr pLocationCollection; + CComPtr pLocation; + + BSTR bstrLocationPath = NULL; + + *ppLocation = NULL; + *pFound = FALSE; + + hr = GetLocationCollection( pAdminMgr, + szConfigPath, + &pLocationCollection ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + DWORD count; + DWORD i; + VARIANT varIndex; + VariantInit( &varIndex ); + + hr = pLocationCollection->get_Count( &count ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + for( i = 0; i < count; i++ ) + { + varIndex.vt = VT_UI4; + varIndex.ulVal = i; + + hr = pLocationCollection->get_Item( varIndex, + &pLocation ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pLocation->get_Path( &bstrLocationPath ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if( 0 == wcscmp ( szLocationPath, bstrLocationPath ) ) + { + *pFound = TRUE; + *ppLocation = pLocation.Detach(); + break; + } + + + pLocation.Release(); + + SysFreeString( bstrLocationPath ); + bstrLocationPath = NULL; + } + +exit: + + SysFreeString( bstrLocationPath ); + + return hr; +} + +HRESULT +GetSectionFromLocation( + IN IAppHostConfigLocation * pLocation, + IN CONST WCHAR * szSectionName, + OUT IAppHostElement ** ppSectionElement, + OUT BOOL * pFound + ) +{ + HRESULT hr = NOERROR; + + CComPtr pSectionElement; + + DWORD count; + DWORD i; + + VARIANT varIndex; + VariantInit( &varIndex ); + + BSTR bstrSectionName = NULL; + + *pFound = FALSE; + *ppSectionElement = NULL; + + hr = pLocation->get_Count( &count ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + for( i = 0; i < count; i++ ) + { + varIndex.vt = VT_UI4; + varIndex.ulVal = i; + + + hr = pLocation->get_Item( varIndex, + &pSectionElement ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pSectionElement->get_Name( &bstrSectionName ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if( 0 == wcscmp ( szSectionName, bstrSectionName ) ) + { + *pFound = TRUE; + *ppSectionElement = pSectionElement.Detach(); + break; + } + + pSectionElement.Release(); + + SysFreeString( bstrSectionName ); + bstrSectionName = NULL; + } + +exit: + + SysFreeString( bstrSectionName ); + + return hr; +} + + +HRESULT +GetAdminElement( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szElementName, + OUT IAppHostElement ** pElement +) +{ + HRESULT hr = S_OK; + BSTR bstrConfigPath = NULL; + BSTR bstrElementName = NULL; + + bstrConfigPath = SysAllocString(szConfigPath); + bstrElementName = SysAllocString(szElementName); + + if (bstrConfigPath == NULL || bstrElementName == NULL) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->GetAdminSection( bstrElementName, + bstrConfigPath, + pElement ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + if ( bstrElementName != NULL ) + { + SysFreeString(bstrElementName); + bstrElementName = NULL; + } + if ( bstrConfigPath != NULL ) + { + SysFreeString(bstrConfigPath); + bstrConfigPath = NULL; + } + + return hr; +} + + +HRESULT +ClearAdminElement( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szElementName + ) +{ + HRESULT hr; + CComPtr pElement; + + hr = GetAdminElement( + pAdminMgr, + szConfigPath, + szElementName, + &pElement + ); + + if (FAILED(hr)) + { + if (hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND)) + { + hr = S_OK; + } + else + { + DBGERROR_HR(hr); + } + + goto exit; + } + + hr = pElement->Clear(); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return hr; +} + + +HRESULT +ClearElementFromAllSites( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szElementName + ) +{ + HRESULT hr; + CComPtr pSitesCollection; + CComPtr pSiteElement; + CComPtr pChildCollection; + ENUM_INDEX index; + BOOL found; + + // + // Enumerate the sites, remove the specified elements. + // + + hr = GetSitesCollection( + pAdminMgr, + szConfigPath, + &pSitesCollection + ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + for (hr = FindFirstElement(pSitesCollection, &index, &pSiteElement) ; + SUCCEEDED(hr) ; + hr = FindNextElement(pSitesCollection, &index, &pSiteElement)) + { + if (hr == S_FALSE) + { + hr = S_OK; + break; + } + + hr = pSiteElement->get_ChildElements(&pChildCollection); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + if (pChildCollection) + { + hr = ClearChildElementsByName( + pChildCollection, + szElementName, + &found + ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + } + + pSiteElement.Release(); + } + +exit: + + return hr; + +} + + +HRESULT +ClearElementFromAllLocations( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szElementName + ) +{ + HRESULT hr; + CComPtr pLocationCollection; + CComPtr pLocation; + CComPtr pChildCollection; + ENUM_INDEX index; + + // + // Enum the tags, remove the specified elements. + // + + hr = GetLocationCollection( + pAdminMgr, + szConfigPath, + &pLocationCollection + ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + for (hr = FindFirstLocation(pLocationCollection, &index, &pLocation) ; + SUCCEEDED(hr) ; + hr = FindNextLocation(pLocationCollection, &index, &pLocation)) + { + if (hr == S_FALSE) + { + hr = S_OK; + break; + } + + hr = ClearLocationElements(pLocation, szElementName); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + pLocation.Release(); + } + +exit: + + return hr; + +} + +HRESULT +ClearLocationElements( + IN IAppHostConfigLocation * pLocation, + IN CONST WCHAR * szElementName + ) +{ + HRESULT hr; + CComPtr pElement; + ENUM_INDEX index; + BOOL matched; + + for (hr = FindFirstLocationElement(pLocation, &index, &pElement) ; + SUCCEEDED(hr) ; + hr = FindNextLocationElement(pLocation, &index, &pElement)) + { + if (hr == S_FALSE) + { + hr = S_OK; + break; + } + + hr = CompareElementName(pElement, szElementName, &matched); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + if (matched) + { + pElement->Clear(); + } + + pElement.Release(); + } + +exit: + + return hr; +} + +HRESULT +CompareElementName( + IN IAppHostElement * pElement, + IN CONST WCHAR * szNameToMatch, + OUT BOOL * pMatched + ) +{ + HRESULT hr; + BSTR bstrElementName = NULL; + + *pMatched = FALSE; // until proven otherwise + + hr = pElement->get_Name(&bstrElementName); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + if( 0 == wcscmp ( szNameToMatch, bstrElementName ) ) + { + *pMatched = TRUE; + } + +exit: + + SysFreeString(bstrElementName); + return hr; +} + + +HRESULT +ClearChildElementsByName( + IN IAppHostChildElementCollection * pCollection, + IN CONST WCHAR * szElementName, + OUT BOOL * pFound + ) +{ + HRESULT hr; + CComPtr pElement; + ENUM_INDEX index; + BOOL matched; + + *pFound = FALSE; + + for (hr = FindFirstChildElement(pCollection, &index, &pElement) ; + SUCCEEDED(hr) ; + hr = FindNextChildElement(pCollection, &index, &pElement)) + { + if (hr == S_FALSE) + { + hr = S_OK; + break; + } + + hr = CompareElementName(pElement, szElementName, &matched); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + if (matched) + { + hr = pElement->Clear(); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + *pFound = TRUE; + } + + pElement.Release(); + } + +exit: + + return hr; +} + + +HRESULT +GetSitesCollection( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + OUT IAppHostElementCollection ** pSitesCollection + ) +{ + HRESULT hr; + CComPtr pSitesElement; + BSTR bstrConfigPath; + BSTR bstrSitesSectionName; + + bstrConfigPath = SysAllocString(szConfigPath); + bstrSitesSectionName = SysAllocString(L"system.applicationHost/sites"); + *pSitesCollection = NULL; + + if (bstrConfigPath == NULL || bstrSitesSectionName == NULL) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + // + // Chase down the sites collection. + // + + hr = pAdminMgr->GetAdminSection( bstrSitesSectionName, + bstrConfigPath, + &pSitesElement ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pSitesElement->get_Collection(pSitesCollection); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + SysFreeString(bstrSitesSectionName); + SysFreeString(bstrConfigPath); + return hr; +} + + +HRESULT +GetLocationCollection( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + OUT IAppHostConfigLocationCollection ** pLocationCollection + ) +{ + HRESULT hr; + BSTR bstrConfigPath; + CComPtr pConfigMgr; + CComPtr pConfigFile; + + bstrConfigPath = SysAllocString(szConfigPath); + *pLocationCollection = NULL; + + if (bstrConfigPath == NULL) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->get_ConfigManager(&pConfigMgr); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pConfigMgr->GetConfigFile(bstrConfigPath, &pConfigFile); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pConfigFile->get_Locations(pLocationCollection); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + SysFreeString(bstrConfigPath); + return hr; +} + + +HRESULT +FindFirstElement( + IN IAppHostElementCollection * pCollection, + OUT ENUM_INDEX * pIndex, + OUT IAppHostElement ** pElement + ) +{ + HRESULT hr; + + hr = pCollection->get_Count(&pIndex->Count); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + return hr; + } + + VariantInit(&pIndex->Index); + pIndex->Index.vt = VT_UI4; + pIndex->Index.ulVal = 0; + + return FindNextElement(pCollection, pIndex, pElement); +} + +HRESULT +FindNextElement( + IN IAppHostElementCollection * pCollection, + IN OUT ENUM_INDEX * pIndex, + OUT IAppHostElement ** pElement + ) +{ + HRESULT hr; + + *pElement = NULL; + + if (pIndex->Index.ulVal >= pIndex->Count) + { + return S_FALSE; + } + + hr = pCollection->get_Item(pIndex->Index, pElement); + + if (SUCCEEDED(hr)) + { + pIndex->Index.ulVal++; + } + + return hr; +} + +HRESULT +FindFirstChildElement( + IN IAppHostChildElementCollection * pCollection, + OUT ENUM_INDEX * pIndex, + OUT IAppHostElement ** pElement + ) +{ + HRESULT hr; + + hr = pCollection->get_Count(&pIndex->Count); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + return hr; + } + + VariantInit(&pIndex->Index); + pIndex->Index.vt = VT_UI4; + pIndex->Index.ulVal = 0; + + return FindNextChildElement(pCollection, pIndex, pElement); +} + +HRESULT +FindNextChildElement( + IN IAppHostChildElementCollection * pCollection, + IN OUT ENUM_INDEX * pIndex, + OUT IAppHostElement ** pElement + ) +{ + HRESULT hr; + + *pElement = NULL; + + if (pIndex->Index.ulVal >= pIndex->Count) + { + return S_FALSE; + } + + hr = pCollection->get_Item(pIndex->Index, pElement); + + if (SUCCEEDED(hr)) + { + pIndex->Index.ulVal++; + } + + return hr; +} + +HRESULT +FindFirstLocation( + IN IAppHostConfigLocationCollection * pCollection, + OUT ENUM_INDEX * pIndex, + OUT IAppHostConfigLocation ** pLocation + ) +{ + HRESULT hr; + + hr = pCollection->get_Count(&pIndex->Count); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + return hr; + } + + VariantInit(&pIndex->Index); + pIndex->Index.vt = VT_UI4; + pIndex->Index.ulVal = 0; + + return FindNextLocation(pCollection, pIndex, pLocation); +} + +HRESULT +FindNextLocation( + IN IAppHostConfigLocationCollection * pCollection, + IN OUT ENUM_INDEX * pIndex, + OUT IAppHostConfigLocation ** pLocation + ) +{ + HRESULT hr; + + *pLocation = NULL; + + if (pIndex->Index.ulVal >= pIndex->Count) + { + return S_FALSE; + } + + hr = pCollection->get_Item(pIndex->Index, pLocation); + + if (SUCCEEDED(hr)) + { + pIndex->Index.ulVal++; + } + + return hr; +} + +HRESULT +FindFirstLocationElement( + IN IAppHostConfigLocation * pLocation, + OUT ENUM_INDEX * pIndex, + OUT IAppHostElement ** pElement + ) +{ + HRESULT hr; + + hr = pLocation->get_Count(&pIndex->Count); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + return hr; + } + + VariantInit(&pIndex->Index); + pIndex->Index.vt = VT_UI4; + pIndex->Index.ulVal = 0; + + return FindNextLocationElement(pLocation, pIndex, pElement); +} + +HRESULT +FindNextLocationElement( + IN IAppHostConfigLocation * pLocation, + IN OUT ENUM_INDEX * pIndex, + OUT IAppHostElement ** pElement + ) +{ + HRESULT hr; + + *pElement = NULL; + + if (pIndex->Index.ulVal >= pIndex->Count) + { + return S_FALSE; + } + + hr = pLocation->get_Item(pIndex->Index, pElement); + + if (SUCCEEDED(hr)) + { + pIndex->Index.ulVal++; + } + + return hr; +} + +HRESULT +GetSharedConfigEnabled( + BOOL * pfIsSharedConfig +) +/*++ + +Routine Description: + Search the configuration for the shared configuration property. + +Arguments: + + pfIsSharedConfig - true if shared configuration is enabled + +Return Value: + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + IAppHostAdminManager *pAdminManager = NULL; + + BSTR bstrSectionName = NULL; + BSTR bstrConfigPath = NULL; + + IAppHostElement * pConfigRedirSection = NULL; + + + bstrSectionName = SysAllocString( L"configurationRedirection" ); + + if ( bstrSectionName == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + bstrConfigPath = SysAllocString( L"MACHINE/REDIRECTION" ); + if ( bstrConfigPath == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = CoCreateInstance( CLSID_AppHostAdminManager, + NULL, + CLSCTX_INPROC_SERVER, + IID_IAppHostAdminManager, + (VOID **)&pAdminManager ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminManager->GetAdminSection( bstrSectionName, + bstrConfigPath, + &pConfigRedirSection ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = GetElementBoolProperty( pConfigRedirSection, + L"enabled", + pfIsSharedConfig ); + + if ( FAILED( hr ) ) + { + DBGERROR_HR(hr); + goto exit; + } + + pConfigRedirSection->Release(); + pConfigRedirSection = NULL; + + +exit: + + // + // dump config exception to setup log file (if available) + // + + if ( pConfigRedirSection != NULL ) + { + pConfigRedirSection->Release(); + } + + if ( pAdminManager != NULL ) + { + pAdminManager->Release(); + } + + if ( bstrConfigPath != NULL ) + { + SysFreeString( bstrConfigPath ); + } + + if ( bstrSectionName != NULL ) + { + SysFreeString( bstrSectionName ); + } + + return hr; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/base64.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/base64.cxx new file mode 100644 index 0000000000..26e601fac4 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/base64.cxx @@ -0,0 +1,482 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +DWORD +Base64Encode( + __in_bcount(cbDecodedBufferSize) VOID * pDecodedBuffer, + IN DWORD cbDecodedBufferSize, + __out_ecount_opt(cchEncodedStringSize) PWSTR pszEncodedString, + IN DWORD cchEncodedStringSize, + __out_opt DWORD * pcchEncoded + ) +/*++ + +Routine Description: + + Decode a base64-encoded string. + +Arguments: + + pDecodedBuffer (IN) - buffer to encode. + cbDecodedBufferSize (IN) - size of buffer to encode. + cchEncodedStringSize (IN) - size of the buffer for the encoded string. + pszEncodedString (OUT) = the encoded string. + pcchEncoded (OUT) - size in characters of the encoded string. + +Return Values: + + 0 - success. + E_OUTOFMEMORY + +--*/ +{ + static WCHAR rgchEncodeTable[64] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' + }; + + DWORD ib; + DWORD ich; + DWORD cchEncoded; + BYTE b0, b1, b2; + BYTE * pbDecodedBuffer = (BYTE *) pDecodedBuffer; + + // Calculate encoded string size. + cchEncoded = 1 + (cbDecodedBufferSize + 2) / 3 * 4; + + if (NULL != pcchEncoded) { + *pcchEncoded = cchEncoded; + } + + if (cchEncodedStringSize == 0 && pszEncodedString == NULL) { + return ERROR_SUCCESS; + } + + if (cchEncodedStringSize < cchEncoded) { + // Given buffer is too small to hold encoded string. + return ERROR_INSUFFICIENT_BUFFER; + } + + // Encode data byte triplets into four-byte clusters. + ib = ich = 0; + while (ib < cbDecodedBufferSize) { + b0 = pbDecodedBuffer[ib++]; + b1 = (ib < cbDecodedBufferSize) ? pbDecodedBuffer[ib++] : 0; + b2 = (ib < cbDecodedBufferSize) ? pbDecodedBuffer[ib++] : 0; + + // + // The checks below for buffer overflow seems redundant to me. + // But it's the only way I can find to keep OACR quiet so it + // will have to do. + // + + pszEncodedString[ich++] = rgchEncodeTable[b0 >> 2]; + if ( ich >= cchEncodedStringSize ) + { + DBG_ASSERT( FALSE ); + return ERROR_BUFFER_OVERFLOW; + } + + pszEncodedString[ich++] = rgchEncodeTable[((b0 << 4) & 0x30) | ((b1 >> 4) & 0x0f)]; + if ( ich >= cchEncodedStringSize ) + { + DBG_ASSERT( FALSE ); + return ERROR_BUFFER_OVERFLOW; + } + + pszEncodedString[ich++] = rgchEncodeTable[((b1 << 2) & 0x3c) | ((b2 >> 6) & 0x03)]; + if ( ich >= cchEncodedStringSize ) + { + DBG_ASSERT( FALSE ); + return ERROR_BUFFER_OVERFLOW; + } + + pszEncodedString[ich++] = rgchEncodeTable[b2 & 0x3f]; + if ( ich >= cchEncodedStringSize ) + { + DBG_ASSERT( FALSE ); + return ERROR_BUFFER_OVERFLOW; + } + } + + // Pad the last cluster as necessary to indicate the number of data bytes + // it represents. + switch (cbDecodedBufferSize % 3) { + case 0: + break; + case 1: + pszEncodedString[ich - 2] = '='; + __fallthrough; + case 2: + pszEncodedString[ich - 1] = '='; + break; + } + + // Null-terminate the encoded string. + pszEncodedString[ich++] = '\0'; + + DBG_ASSERT(ich == cchEncoded); + + return ERROR_SUCCESS; +} + + +DWORD +Base64Decode( + __in PCWSTR pszEncodedString, + __out_opt VOID * pDecodeBuffer, + __in DWORD cbDecodeBufferSize, + __out_opt DWORD * pcbDecoded + ) +/*++ + +Routine Description: + + Decode a base64-encoded string. + +Arguments: + + pszEncodedString (IN) - base64-encoded string to decode. + cbDecodeBufferSize (IN) - size in bytes of the decode buffer. + pbDecodeBuffer (OUT) - holds the decoded data. + pcbDecoded (OUT) - number of data bytes in the decoded data (if success or + STATUS_BUFFER_TOO_SMALL). + +Return Values: + + 0 - success. + E_OUTOFMEMORY + E_INVALIDARG + +--*/ +{ +#define NA (255) +#define DECODE(x) (((ULONG)(x) < sizeof(rgbDecodeTable)) ? rgbDecodeTable[x] : NA) + + static BYTE rgbDecodeTable[128] = { + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, // 0-15 + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, // 16-31 + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 62, NA, NA, NA, 63, // 32-47 + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, NA, NA, NA, 0, NA, NA, // 48-63 + NA, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79 + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, NA, NA, NA, NA, NA, // 80-95 + NA, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111 + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, NA, NA, NA, NA, NA, // 112-127 + }; + + DWORD cbDecoded; + DWORD cchEncodedSize; + DWORD ich; + DWORD ib; + BYTE b0, b1, b2, b3; + BYTE * pbDecodeBuffer = (BYTE *) pDecodeBuffer; + + cchEncodedSize = (DWORD)wcslen(pszEncodedString); + if (NULL != pcbDecoded) { + *pcbDecoded = 0; + } + + if ((0 == cchEncodedSize) || (0 != (cchEncodedSize % 4))) { + // Input string is not sized correctly to be base64. + return ERROR_INVALID_PARAMETER; + } + + // Calculate decoded buffer size. + cbDecoded = (cchEncodedSize + 3) / 4 * 3; + if (pszEncodedString[cchEncodedSize-1] == '=') { + if (pszEncodedString[cchEncodedSize-2] == '=') { + // Only one data byte is encoded in the last cluster. + cbDecoded -= 2; + } + else { + // Only two data bytes are encoded in the last cluster. + cbDecoded -= 1; + } + } + + if (NULL != pcbDecoded) { + *pcbDecoded = cbDecoded; + } + + if (cbDecodeBufferSize == 0 && pDecodeBuffer == NULL) { + return ERROR_SUCCESS; + } + + if (cbDecoded > cbDecodeBufferSize) { + // Supplied buffer is too small. + return ERROR_INSUFFICIENT_BUFFER; + } + + // Decode each four-byte cluster into the corresponding three data bytes. + ich = ib = 0; + while (ich < cchEncodedSize) { + b0 = DECODE(pszEncodedString[ich]); ich++; + b1 = DECODE(pszEncodedString[ich]); ich++; + b2 = DECODE(pszEncodedString[ich]); ich++; + b3 = DECODE(pszEncodedString[ich]); ich++; + + if ((NA == b0) || (NA == b1) || (NA == b2) || (NA == b3)) { + // Contents of input string are not base64. + return ERROR_INVALID_PARAMETER; + } + + pbDecodeBuffer[ib++] = (b0 << 2) | (b1 >> 4); + + if (ib < cbDecoded) { + pbDecodeBuffer[ib++] = (b1 << 4) | (b2 >> 2); + + if (ib < cbDecoded) { + pbDecodeBuffer[ib++] = (b2 << 6) | b3; + } + } + } + + DBG_ASSERT(ib == cbDecoded); + + return ERROR_SUCCESS; +} + + +DWORD +Base64Encode( + __in_bcount(cbDecodedBufferSize) VOID * pDecodedBuffer, + IN DWORD cbDecodedBufferSize, + __out_ecount_opt(cchEncodedStringSize) PSTR pszEncodedString, + IN DWORD cchEncodedStringSize, + __out_opt DWORD * pcchEncoded + ) +/*++ + +Routine Description: + + Decode a base64-encoded string. + +Arguments: + + pDecodedBuffer (IN) - buffer to encode. + cbDecodedBufferSize (IN) - size of buffer to encode. + cchEncodedStringSize (IN) - size of the buffer for the encoded string. + pszEncodedString (OUT) = the encoded string. + pcchEncoded (OUT) - size in characters of the encoded string. + +Return Values: + + 0 - success. + E_OUTOFMEMORY + +--*/ +{ + static CHAR rgchEncodeTable[64] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' + }; + + DWORD ib; + DWORD ich; + DWORD cchEncoded; + BYTE b0, b1, b2; + BYTE * pbDecodedBuffer = (BYTE *) pDecodedBuffer; + + // Calculate encoded string size. + cchEncoded = 1 + (cbDecodedBufferSize + 2) / 3 * 4; + + if (NULL != pcchEncoded) { + *pcchEncoded = cchEncoded; + } + + if (cchEncodedStringSize == 0 && pszEncodedString == NULL) { + return ERROR_SUCCESS; + } + + if (cchEncodedStringSize < cchEncoded) { + // Given buffer is too small to hold encoded string. + return ERROR_INSUFFICIENT_BUFFER; + } + + // Encode data byte triplets into four-byte clusters. + ib = ich = 0; + while (ib < cbDecodedBufferSize) { + b0 = pbDecodedBuffer[ib++]; + b1 = (ib < cbDecodedBufferSize) ? pbDecodedBuffer[ib++] : 0; + b2 = (ib < cbDecodedBufferSize) ? pbDecodedBuffer[ib++] : 0; + + // + // The checks below for buffer overflow seems redundant to me. + // But it's the only way I can find to keep OACR quiet so it + // will have to do. + // + + pszEncodedString[ich++] = rgchEncodeTable[b0 >> 2]; + if ( ich >= cchEncodedStringSize ) + { + DBG_ASSERT( FALSE ); + return ERROR_BUFFER_OVERFLOW; + } + + pszEncodedString[ich++] = rgchEncodeTable[((b0 << 4) & 0x30) | ((b1 >> 4) & 0x0f)]; + if ( ich >= cchEncodedStringSize ) + { + DBG_ASSERT( FALSE ); + return ERROR_BUFFER_OVERFLOW; + } + + pszEncodedString[ich++] = rgchEncodeTable[((b1 << 2) & 0x3c) | ((b2 >> 6) & 0x03)]; + if ( ich >= cchEncodedStringSize ) + { + DBG_ASSERT( FALSE ); + return ERROR_BUFFER_OVERFLOW; + } + + pszEncodedString[ich++] = rgchEncodeTable[b2 & 0x3f]; + if ( ich >= cchEncodedStringSize ) + { + DBG_ASSERT( FALSE ); + return ERROR_BUFFER_OVERFLOW; + } + } + + // Pad the last cluster as necessary to indicate the number of data bytes + // it represents. + switch (cbDecodedBufferSize % 3) { + case 0: + break; + case 1: + pszEncodedString[ich - 2] = '='; + __fallthrough; + case 2: + pszEncodedString[ich - 1] = '='; + break; + } + + // Null-terminate the encoded string. + pszEncodedString[ich++] = '\0'; + + DBG_ASSERT(ich == cchEncoded); + + return ERROR_SUCCESS; +} + + +DWORD +Base64Decode( + __in PCSTR pszEncodedString, + __out_opt VOID * pDecodeBuffer, + __in DWORD cbDecodeBufferSize, + __out_opt DWORD * pcbDecoded + ) +/*++ + +Routine Description: + + Decode a base64-encoded string. + +Arguments: + + pszEncodedString (IN) - base64-encoded string to decode. + cbDecodeBufferSize (IN) - size in bytes of the decode buffer. + pbDecodeBuffer (OUT) - holds the decoded data. + pcbDecoded (OUT) - number of data bytes in the decoded data (if success or + STATUS_BUFFER_TOO_SMALL). + +Return Values: + + 0 - success. + E_OUTOFMEMORY + E_INVALIDARG + +--*/ +{ +#define NA (255) +#define DECODE(x) (((ULONG)(x) < sizeof(rgbDecodeTable)) ? rgbDecodeTable[x] : NA) + + static BYTE rgbDecodeTable[128] = { + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, // 0-15 + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, // 16-31 + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 62, NA, NA, NA, 63, // 32-47 + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, NA, NA, NA, 0, NA, NA, // 48-63 + NA, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79 + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, NA, NA, NA, NA, NA, // 80-95 + NA, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111 + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, NA, NA, NA, NA, NA, // 112-127 + }; + + DWORD cbDecoded; + DWORD cchEncodedSize; + DWORD ich; + DWORD ib; + BYTE b0, b1, b2, b3; + BYTE * pbDecodeBuffer = (BYTE *) pDecodeBuffer; + + cchEncodedSize = (DWORD)strlen(pszEncodedString); + if (NULL != pcbDecoded) { + *pcbDecoded = 0; + } + + if ((0 == cchEncodedSize) || (0 != (cchEncodedSize % 4))) { + // Input string is not sized correctly to be base64. + return ERROR_INVALID_PARAMETER; + } + + // Calculate decoded buffer size. + cbDecoded = (cchEncodedSize + 3) / 4 * 3; + if (pszEncodedString[cchEncodedSize-1] == '=') { + if (pszEncodedString[cchEncodedSize-2] == '=') { + // Only one data byte is encoded in the last cluster. + cbDecoded -= 2; + } + else { + // Only two data bytes are encoded in the last cluster. + cbDecoded -= 1; + } + } + + if (NULL != pcbDecoded) { + *pcbDecoded = cbDecoded; + } + + if (cbDecodeBufferSize == 0 && pDecodeBuffer == NULL) { + return ERROR_SUCCESS; + } + + if (cbDecoded > cbDecodeBufferSize) { + // Supplied buffer is too small. + return ERROR_INSUFFICIENT_BUFFER; + } + + // Decode each four-byte cluster into the corresponding three data bytes. + ich = ib = 0; + while (ich < cchEncodedSize) { + b0 = DECODE(pszEncodedString[ich]); ich++; + b1 = DECODE(pszEncodedString[ich]); ich++; + b2 = DECODE(pszEncodedString[ich]); ich++; + b3 = DECODE(pszEncodedString[ich]); ich++; + + if ((NA == b0) || (NA == b1) || (NA == b2) || (NA == b3)) { + // Contents of input string are not base64. + return ERROR_INVALID_PARAMETER; + } + + pbDecodeBuffer[ib++] = (b0 << 2) | (b1 >> 4); + + if (ib < cbDecoded) { + pbDecodeBuffer[ib++] = (b1 << 4) | (b2 >> 2); + + if (ib < cbDecoded) { + pbDecodeBuffer[ib++] = (b2 << 6) | b3; + } + } + } + + DBG_ASSERT(ib == cbDecoded); + + return ERROR_SUCCESS; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/datetime.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/datetime.cxx new file mode 100644 index 0000000000..a856b997f1 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/datetime.cxx @@ -0,0 +1,247 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +static const CHAR* s_rgchMonths[] = { + "Jan", "Feb", "Mar", "Apr", + "May", "Jun", "Jul", "Aug", + "Sep", "Oct", "Nov", "Dec" +}; + +// Custom hash table for make_month() for mapping "Apr" to 4 +static const CHAR MonthIndexTable[64] = { + -1,'A', 2, 12, -1, -1, -1, 8, // A to G + -1, -1, -1, -1, 7, -1,'N', -1, // F to O + 9, -1,'R', -1, 10, -1, 11, -1, // P to W + -1, 5, -1, -1, -1, -1, -1, -1, // X to Z + -1,'A', 2, 12, -1, -1, -1, 8, // a to g + -1, -1, -1, -1, 7, -1,'N', -1, // f to o + 9, -1,'R', -1, 10, -1, 11, -1, // p to w + -1, 5, -1, -1, -1, -1, -1, -1 // x to z +}; + +static const BYTE TensDigit[10] = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 }; + +WORD +iis_2atoi( + __in_ecount(2) PCHAR s + ) +/*++ + + Converts a 2 character string to integer + + Arguments: + s String to convert + + Returns: + numeric equivalent, 0 on failure. +--*/ +{ + + DWORD tens = s[0] - '0'; + DWORD ones = s[1] - '0'; + + if ( (tens <= 9) && (ones <= 9) ) { + return((WORD)(TensDigit[tens] + ones)); + } + return(0); +} + +WORD +make_month( + __in_ecount(3) PCHAR s + ) +{ + UCHAR monthIndex; + UCHAR c; + LPCSTR monthString; + + // + // use the third character as the index + // + + c = (s[2] - 0x40) & 0x3F; + + monthIndex = MonthIndexTable[c]; + + if ( monthIndex < 13 ) { + goto verify; + } + + // + // ok, we need to look at the second character + // + + if ( monthIndex == 'N' ) { + + // + // we got an N which we need to resolve further + // + + // + // if s[1] is 'u' then Jun, if 'a' then Jan + // + + if ( MonthIndexTable[(s[1]-0x40) & 0x3f] == 'A' ) { + monthIndex = 1; + } else { + monthIndex = 6; + } + + } else if ( monthIndex == 'R' ) { + + // + // if s[1] is 'a' then March, if 'p' then April + // + + if ( MonthIndexTable[(s[1]-0x40) & 0x3f] == 'A' ) { + monthIndex = 3; + } else { + monthIndex = 4; + } + } else { + goto error_exit; + } + +verify: + + monthString = s_rgchMonths[monthIndex-1]; + + if ( (s[0] == monthString[0]) && + (s[1] == monthString[1]) && + (s[2] == monthString[2]) ) { + + return(monthIndex); + + } else if ( (toupper(s[0]) == monthString[0]) && + (tolower(s[1]) == monthString[1]) && + (tolower(s[2]) == monthString[2]) ) { + + return monthIndex; + } + +error_exit: + return(0); + +} // make_month + +BOOL +StringTimeToFileTime( + IN const CHAR * pszTime, + OUT ULONGLONG * pulTime + ) +/*++ + + Converts a string representation of a GMT time (three different + varieties) to an NT representation of a file time. + + We handle the following variations: + + Sun, 06 Nov 1994 08:49:37 GMT (RFC 822 updated by RFC 1123) + Sunday, 06-Nov-94 08:49:37 GMT (RFC 850) + Sun Nov 6 08:49:37 1994 (ANSI C's asctime() format + + Arguments: + pszTime String representation of time field + pliTime large integer containing the time in NT format. + + Returns: + TRUE on success and FALSE on failure. + + History: + + Johnl 24-Jan-1995 Modified from WWW library + +--*/ +{ + + CHAR * s; + SYSTEMTIME st; + + if (pszTime == NULL) { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + st.wMilliseconds = 0; + + if ((s = (CHAR*) strchr(pszTime, ','))) { + + DWORD len; + + // + // Thursday, 10-Jun-93 01:29:59 GMT + // or: Thu, 10 Jan 1993 01:29:59 GMT */ + // + + s++; + + while (*s && *s==' ') s++; + len = (DWORD)strlen(s); + + if (len < 18) { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + if ( *(s+2) == '-' ) { /* First format */ + + st.wDay = (WORD) atoi(s); + st.wMonth = (WORD) make_month(s+3); + st.wYear = (WORD) atoi(s+7); + st.wHour = (WORD) atoi(s+10); + st.wMinute = (WORD) atoi(s+13); + st.wSecond = (WORD) atoi(s+16); + + } else { /* Second format */ + + if (len < 20) { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + st.wDay = iis_2atoi(s); + st.wMonth = make_month(s+3); + st.wYear = iis_2atoi(s+7) * 100 + iis_2atoi(s+9); + st.wHour = iis_2atoi(s+12); + st.wMinute = iis_2atoi(s+15); + st.wSecond = iis_2atoi(s+18); + + } + } else { /* Try the other format: Wed Jun 9 01:29:59 1993 GMT */ + + s = (CHAR *) pszTime; + while (*s && *s==' ') s++; + + if ((int)strlen(s) < 24) { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + st.wDay = (WORD) atoi(s+8); + st.wMonth = (WORD) make_month(s+4); + st.wYear = (WORD) atoi(s+20); + st.wHour = (WORD) atoi(s+11); + st.wMinute = (WORD) atoi(s+14); + st.wSecond = (WORD) atoi(s+17); + } + + // + // Adjust for dates with only two digits + // + + if ( st.wYear < 1000 ) { + if ( st.wYear < 50 ) { + st.wYear += 2000; + } else { + st.wYear += 1900; + } + } + + if (!SystemTimeToFileTime(&st, (FILETIME *)pulTime)) { + return FALSE; + } + return(TRUE); +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/multisz.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/multisz.cxx new file mode 100644 index 0000000000..26eacdb244 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/multisz.cxx @@ -0,0 +1,480 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + + +//#include +#include +//# include + +#include + +// +// Private Definitions +// + +#define MAXULONG 4294967295 +#define ISWHITE( ch ) ((ch) == L' ' || (ch) == L'\t' || (ch) == L'\r') + +// +// When appending data, this is the extra amount we request to avoid +// reallocations +// +#define STR_SLOP 128 + + +DWORD +MULTISZ::CalcLength( const WCHAR * str, + LPDWORD pcStrings ) +{ + DWORD count = 0; + DWORD total = 1; + DWORD len; + + while( *str ) { + len = (DWORD)(::wcslen( str ) + 1); + total += len; + str += len; + count++; + } + + if( pcStrings != NULL ) { + *pcStrings = count; + } + + return total; + +} // MULTISZ::CalcLength + + +BOOL +MULTISZ::FindString( const WCHAR * str ) +{ + + WCHAR * multisz; + + // + // Sanity check. + // + + DBG_ASSERT( QueryStr() != NULL ); + DBG_ASSERT( str != NULL ); + DBG_ASSERT( *str != '\0' ); + + // + // Scan it. + // + + multisz = QueryStr(); + + while( *multisz != '\0' ) { + + if( !::wcscmp( multisz, str ) ) { + + return TRUE; + + } + + multisz += ::wcslen( multisz ) + 1; + + } + + return FALSE; + +} // MULTISZ::FindString + + +BOOL +MULTISZ::FindStringNoCase( const WCHAR * str ) +{ + + WCHAR * multisz; + + // + // Sanity check. + // + + DBG_ASSERT( QueryStr() != NULL ); + DBG_ASSERT( str != NULL ); + DBG_ASSERT( *str != '\0' ); + + // + // Scan it. + // + + multisz = QueryStr(); + + while( *multisz != '\0' ) { + + if( !_wcsicmp( multisz, str ) ) { + + return TRUE; + + } + + multisz += wcslen( multisz ) + 1; + + } + + return FALSE; + +} // MULTISZ::FindStringNoCase + + +VOID +MULTISZ::AuxInit( const WCHAR * pInit ) +{ + BOOL fRet; + + if ( pInit ) + { + DWORD cStrings; + int cbCopy = CalcLength( pInit, &cStrings ) * sizeof(WCHAR); + fRet = Resize( cbCopy ); + + if ( fRet ) { + CopyMemory( QueryPtr(), pInit, cbCopy ); + m_cchLen = (cbCopy)/sizeof(WCHAR); + m_cStrings = cStrings; + } else { +// BUFFER::SetValid( FALSE); + } + + } else { + + Reset(); + + } + +} // MULTISZ::AuxInit() + + +/******************************************************************* + + NAME: MULTISZ::AuxAppend + + SYNOPSIS: Appends the string onto the multisz. + + ENTRY: Object to append +********************************************************************/ + +BOOL MULTISZ::AuxAppend( const WCHAR * pStr, UINT cbStr, BOOL fAddSlop ) +{ + DBG_ASSERT( pStr != NULL ); + + UINT cbThis = QueryCB(); + + DBG_ASSERT( cbThis >= 2 ); + + if( cbThis == 4 ) { + + // + // It's empty, so start at the beginning. + // + + cbThis = 0; + + } else { + + // + // It's not empty, so back up over the final terminating NULL. + // + + cbThis -= sizeof(WCHAR); + + } + + // + // Only resize when we have to. When we do resize, we tack on + // some extra space to avoid extra reallocations. + // + // Note: QuerySize returns the requested size of the string buffer, + // *not* the strlen of the buffer + // + + //AcIncrement( CacMultiszAppend); + + // + // Check for the arithmetic overflow + // + // ( 2 * sizeof( WCHAR ) ) is for the double terminator + // + ULONGLONG cb64Required = (ULONGLONG)cbThis + cbStr + 2 * sizeof(WCHAR); + if ( cb64Required > MAXULONG ) + { + SetLastError( ERROR_ARITHMETIC_OVERFLOW ); + return FALSE; + } + if ( QuerySize() < (DWORD) cb64Required ) + { + ULONGLONG cb64AllocSize = cb64Required + (fAddSlop ? STR_SLOP : 0 ); + // + // Check for the arithmetic overflow + // + if ( cb64AllocSize > MAXULONG ) + { + SetLastError( ERROR_ARITHMETIC_OVERFLOW ); + return FALSE; + } + if ( !Resize( (DWORD) cb64AllocSize ) ) + return FALSE; + } + + // copy the exact string and tack on the double terminator + memcpy( (BYTE *) QueryPtr() + cbThis, + pStr, + cbStr); + *(WCHAR *)((BYTE *)QueryPtr() + cbThis + cbStr) = L'\0'; + *(WCHAR *)((BYTE *)QueryPtr() + cbThis + cbStr + sizeof(WCHAR) ) = L'\0'; + + m_cchLen = CalcLength( (const WCHAR *)QueryPtr(), &m_cStrings ); + return TRUE; + +} // MULTISZ::AuxAppend() + + +#if 0 + +BOOL +MULTISZ::CopyToBuffer( WCHAR * lpszBuffer, LPDWORD lpcch) const +/*++ + Description: + Copies the string into the WCHAR buffer passed in if the buffer + is sufficient to hold the translated string. + If the buffer is small, the function returns small and sets *lpcch + to contain the required number of characters. + + Arguments: + lpszBuffer pointer to WCHAR buffer which on return contains + the UNICODE version of string on success. + lpcch pointer to DWORD containing the length of the buffer. + If *lpcch == 0 then the function returns TRUE with + the count of characters required stored in *lpcch. + Also in this case lpszBuffer is not affected. + Returns: + TRUE on success. + FALSE on failure. Use GetLastError() for further details. + + History: + MuraliK 11-30-94 +--*/ +{ + BOOL fReturn = TRUE; + + if ( lpcch == NULL) { + SetLastError( ERROR_INVALID_PARAMETER); + return ( FALSE); + } + + if ( *lpcch == 0) { + + // + // Inquiring the size of buffer alone + // + *lpcch = QueryCCH() + 1; // add one character for terminating null + } else { + + // + // Copy after conversion from ANSI to Unicode + // + int iRet; + iRet = MultiByteToWideChar( CP_ACP, + MB_PRECOMPOSED | MB_ERR_INVALID_CHARS, + QueryStrA(), QueryCCH() + 1, + lpszBuffer, (int )*lpcch); + + if ( iRet == 0 || iRet != (int ) *lpcch) { + + // + // Error in conversion. + // + fReturn = FALSE; + } + } + + return ( fReturn); +} // MULTISZ::CopyToBuffer() +#endif + +BOOL +MULTISZ::CopyToBuffer( __out_ecount_opt(*lpcch) WCHAR * lpszBuffer, LPDWORD lpcch) const +/*++ + Description: + Copies the string into the WCHAR buffer passed in if the buffer + is sufficient to hold the translated string. + If the buffer is small, the function returns small and sets *lpcch + to contain the required number of characters. + + Arguments: + lpszBuffer pointer to WCHAR buffer which on return contains + the string on success. + lpcch pointer to DWORD containing the length of the buffer. + If *lpcch == 0 then the function returns TRUE with + the count of characters required stored in lpcch. + Also in this case lpszBuffer is not affected. + Returns: + TRUE on success. + FALSE on failure. Use GetLastError() for further details. + + History: + MuraliK 20-Nov-1996 +--*/ +{ + BOOL fReturn = TRUE; + + if ( lpcch == NULL) { + SetLastError( ERROR_INVALID_PARAMETER); + return ( FALSE); + } + + register DWORD cch = QueryCCH(); + + if ( *lpcch >= cch) { + + DBG_ASSERT( lpszBuffer); + memcpy( lpszBuffer, QueryStr(), cch * sizeof(WCHAR)); + } else { + DBG_ASSERT( *lpcch < cch); + SetLastError( ERROR_INSUFFICIENT_BUFFER); + fReturn = FALSE; + } + + *lpcch = cch; + + return ( fReturn); +} // MULTISZ::CopyToBuffer() + +BOOL +MULTISZ::Equals( + MULTISZ* pmszRhs +) +// +// Compares this to pmszRhs, returns TRUE if equal +// +{ + DBG_ASSERT( NULL != pmszRhs ); + + PCWSTR pszLhs = First( ); + PCWSTR pszRhs = pmszRhs->First( ); + + if( m_cStrings != pmszRhs->m_cStrings ) + { + return FALSE; + } + + while( NULL != pszLhs ) + { + DBG_ASSERT( NULL != pszRhs ); + + if( 0 != wcscmp( pszLhs, pszRhs ) ) + { + return FALSE; + } + + pszLhs = Next( pszLhs ); + pszRhs = pmszRhs->Next( pszRhs ); + } + + return TRUE; +} + +HRESULT +SplitCommaDelimitedString( + PCWSTR pszList, + BOOL fTrimEntries, + BOOL fRemoveEmptyEntries, + MULTISZ * pmszList +) +/*++ + +Routine Description: + + Split comma delimited string into a multisz. Additional leading empty + entries after the first are discarded. + +Arguments: + + pszList - List to split up + fTrimEntries - Whether each entry should be trimmed before added to multisz + fRemoveEmptyEntries - Whether empty entires should be discarded + pmszList - Filled with MULTISZ list + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + + if ( pszList == NULL || + pmszList == NULL ) + { + DBG_ASSERT( FALSE ); + hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); + goto Finished; + } + + pmszList->Reset(); + + /* + pszCurrent: start of the current entry which may be the comma that + precedes the next entry if the entry is empty + + pszNext: the comma that precedes the next entry. If + pszCurrent == pszNext, then the entry is empty + + pszEnd: just past the end of the current entry + */ + + for ( PCWSTR pszCurrent = pszList, + pszNext = wcschr( pszCurrent, L',' ) + ; + ; + pszCurrent = pszNext + 1, + pszNext = wcschr( pszCurrent, L',' ) ) + { + PCWSTR pszEnd = NULL; + + if ( pszNext != NULL ) + { + pszEnd = pszNext; + } + else + { + pszEnd = pszCurrent + wcslen( pszCurrent ); + } + + if ( fTrimEntries ) + { + while ( pszCurrent < pszEnd && ISWHITE( pszCurrent[ 0 ] ) ) + { + pszCurrent++; + } + + while ( pszEnd > pszCurrent && ISWHITE( pszEnd[ -1 ] ) ) + { + pszEnd--; + } + } + + if ( pszCurrent != pszEnd || !fRemoveEmptyEntries ) + { + if ( !pmszList->Append( pszCurrent, (DWORD) ( pszEnd - pszCurrent ) ) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Finished; + } + } + + if ( pszNext == NULL ) + { + break; + } + } + +Finished: + + return hr; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/multisza.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/multisza.cxx new file mode 100644 index 0000000000..e6972534bb --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/multisza.cxx @@ -0,0 +1,414 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + + +//#include +#include +//# include + +#include + +// +// Private Definitions +// + +#define MAXULONG 4294967295 +#define ISWHITE( ch ) ((ch) == L' ' || (ch) == L'\t' || (ch) == L'\r') + +// +// When appending data, this is the extra amount we request to avoid +// reallocations +// +#define STR_SLOP 128 + + +DWORD +MULTISZA::CalcLength( const CHAR * str, + LPDWORD pcStrings ) +{ + DWORD count = 0; + DWORD total = 1; + DWORD len; + + while( *str ) { + len = (DWORD)(::strlen( str ) + 1); + total += len; + str += len; + count++; + } + + if( pcStrings != NULL ) { + *pcStrings = count; + } + + return total; + +} // MULTISZA::CalcLength + + +BOOL +MULTISZA::FindString( const CHAR * str ) +{ + + CHAR * multisz; + + // + // Sanity check. + // + + DBG_ASSERT( QueryStr() != NULL ); + DBG_ASSERT( str != NULL ); + DBG_ASSERT( *str != '\0' ); + + // + // Scan it. + // + + multisz = QueryStr(); + + while( *multisz != '\0' ) { + + if( !::strcmp( multisz, str ) ) { + + return TRUE; + + } + + multisz += ::strlen( multisz ) + 1; + + } + + return FALSE; + +} // MULTISZA::FindString + + +BOOL +MULTISZA::FindStringNoCase( const CHAR * str ) +{ + + CHAR * multisz; + + // + // Sanity check. + // + + DBG_ASSERT( QueryStr() != NULL ); + DBG_ASSERT( str != NULL ); + DBG_ASSERT( *str != '\0' ); + + // + // Scan it. + // + + multisz = QueryStr(); + + while( *multisz != '\0' ) { + + if( !_stricmp( multisz, str ) ) { + + return TRUE; + + } + + multisz += strlen( multisz ) + 1; + + } + + return FALSE; + +} // MULTISZA::FindStringNoCase + + +VOID +MULTISZA::AuxInit( const CHAR * pInit ) +{ + BOOL fRet; + + if ( pInit ) + { + DWORD cStrings; + int cbCopy = CalcLength( pInit, &cStrings ) * sizeof(CHAR); + fRet = Resize( cbCopy ); + + if ( fRet ) { + CopyMemory( QueryPtr(), pInit, cbCopy ); + m_cchLen = (cbCopy)/sizeof(CHAR); + m_cStrings = cStrings; + } else { +// BUFFER::SetValid( FALSE); + } + + } else { + + Reset(); + + } + +} // MULTISZA::AuxInit() + + +/******************************************************************* + + NAME: MULTISZA::AuxAppend + + SYNOPSIS: Appends the string onto the MULTISZA. + + ENTRY: Object to append +********************************************************************/ + +BOOL MULTISZA::AuxAppend( const CHAR * pStr, UINT cbStr, BOOL fAddSlop ) +{ + DBG_ASSERT( pStr != NULL ); + + UINT cbThis = QueryCB(); + + if( cbThis == 2 ) { + + // + // It's empty, so start at the beginning. + // + + cbThis = 0; + + } else { + + // + // It's not empty, so back up over the final terminating NULL. + // + + cbThis -= sizeof(CHAR); + + } + + // + // Only resize when we have to. When we do resize, we tack on + // some extra space to avoid extra reallocations. + // + // Note: QuerySize returns the requested size of the string buffer, + // *not* the strlen of the buffer + // + + //AcIncrement( CacMultiszAppend); + + // + // Check for the arithmetic overflow + // + // ( 2 * sizeof( CHAR ) ) is for the double terminator + // + ULONGLONG cb64Required = (ULONGLONG)cbThis + cbStr + 2 * sizeof(CHAR); + if ( cb64Required > MAXULONG ) + { + SetLastError( ERROR_ARITHMETIC_OVERFLOW ); + return FALSE; + } + if ( QuerySize() < (DWORD) cb64Required ) + { + ULONGLONG cb64AllocSize = cb64Required + (fAddSlop ? STR_SLOP : 0 ); + // + // Check for the arithmetic overflow + // + if ( cb64AllocSize > MAXULONG ) + { + SetLastError( ERROR_ARITHMETIC_OVERFLOW ); + return FALSE; + } + if ( !Resize( (DWORD) cb64AllocSize ) ) + return FALSE; + } + + // copy the exact string and tack on the double terminator + memcpy( (BYTE *) QueryPtr() + cbThis, + pStr, + cbStr); + *(CHAR *)((BYTE *)QueryPtr() + cbThis + cbStr) = L'\0'; + *(CHAR *)((BYTE *)QueryPtr() + cbThis + cbStr + sizeof(CHAR) ) = L'\0'; + + m_cchLen = CalcLength( (const CHAR *)QueryPtr(), &m_cStrings ); + return TRUE; + +} // MULTISZA::AuxAppend() + +BOOL +MULTISZA::CopyToBuffer( __out_ecount_opt(*lpcch) CHAR * lpszBuffer, LPDWORD lpcch) const +/*++ + Description: + Copies the string into the CHAR buffer passed in if the buffer + is sufficient to hold the translated string. + If the buffer is small, the function returns small and sets *lpcch + to contain the required number of characters. + + Arguments: + lpszBuffer pointer to CHAR buffer which on return contains + the string on success. + lpcch pointer to DWORD containing the length of the buffer. + If *lpcch == 0 then the function returns TRUE with + the count of characters required stored in lpcch. + Also in this case lpszBuffer is not affected. + Returns: + TRUE on success. + FALSE on failure. Use GetLastError() for further details. + + History: + MuraliK 20-Nov-1996 +--*/ +{ + BOOL fReturn = TRUE; + + if ( lpcch == NULL) { + SetLastError( ERROR_INVALID_PARAMETER); + return ( FALSE); + } + + register DWORD cch = QueryCCH(); + + if ( *lpcch >= cch) { + + DBG_ASSERT( lpszBuffer); + memcpy( lpszBuffer, QueryStr(), cch * sizeof(CHAR)); + } else { + DBG_ASSERT( *lpcch < cch); + SetLastError( ERROR_INSUFFICIENT_BUFFER); + fReturn = FALSE; + } + + *lpcch = cch; + + return ( fReturn); +} // MULTISZA::CopyToBuffer() + +BOOL +MULTISZA::Equals( + MULTISZA* pmszRhs +) +// +// Compares this to pmszRhs, returns TRUE if equal +// +{ + DBG_ASSERT( NULL != pmszRhs ); + + PCSTR pszLhs = First( ); + PCSTR pszRhs = pmszRhs->First( ); + + if( m_cStrings != pmszRhs->m_cStrings ) + { + return FALSE; + } + + while( NULL != pszLhs ) + { + DBG_ASSERT( NULL != pszRhs ); + + if( 0 != strcmp( pszLhs, pszRhs ) ) + { + return FALSE; + } + + pszLhs = Next( pszLhs ); + pszRhs = pmszRhs->Next( pszRhs ); + } + + return TRUE; +} + +HRESULT +SplitCommaDelimitedString( + PCSTR pszList, + BOOL fTrimEntries, + BOOL fRemoveEmptyEntries, + MULTISZA * pmszList +) +/*++ + +Routine Description: + + Split comma delimited string into a MULTISZA. Additional leading empty + entries after the first are discarded. + +Arguments: + + pszList - List to split up + fTrimEntries - Whether each entry should be trimmed before added to MULTISZA + fRemoveEmptyEntries - Whether empty entires should be discarded + pmszList - Filled with MULTISZA list + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + + if ( pszList == NULL || + pmszList == NULL ) + { + DBG_ASSERT( FALSE ); + hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); + goto Finished; + } + + pmszList->Reset(); + + /* + pszCurrent: start of the current entry which may be the comma that + precedes the next entry if the entry is empty + + pszNext: the comma that precedes the next entry. If + pszCurrent == pszNext, then the entry is empty + + pszEnd: just past the end of the current entry + */ + + for ( PCSTR pszCurrent = pszList, + pszNext = strchr( pszCurrent, L',' ) + ; + ; + pszCurrent = pszNext + 1, + pszNext = strchr( pszCurrent, L',' ) ) + { + PCSTR pszEnd = NULL; + + if ( pszNext != NULL ) + { + pszEnd = pszNext; + } + else + { + pszEnd = pszCurrent + strlen( pszCurrent ); + } + + if ( fTrimEntries ) + { + while ( pszCurrent < pszEnd && ISWHITE( pszCurrent[ 0 ] ) ) + { + pszCurrent++; + } + + while ( pszEnd > pszCurrent && ISWHITE( pszEnd[ -1 ] ) ) + { + pszEnd--; + } + } + + if ( pszCurrent != pszEnd || !fRemoveEmptyEntries ) + { + if ( !pmszList->Append( pszCurrent, (DWORD) ( pszEnd - pszCurrent ) ) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Finished; + } + } + + if ( pszNext == NULL ) + { + break; + } + } + +Finished: + + return hr; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/normalize.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/normalize.cxx new file mode 100644 index 0000000000..48b41fdd1c --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/normalize.cxx @@ -0,0 +1,890 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" +#include "normalize.h" +#include "stringa.h" + +BOOL g_fEnableNonUTF8; +BOOL g_fEnableDBCS; +BOOL g_fIsSystemDBCS; +static BOOL g_fFavorDBCS; + +#ifndef STACK_STRA +#define STACK_STRA(name, size) CHAR __ach##name[size]; \ + STRA name(__ach##name, sizeof(__ach##name) / sizeof(CHAR)) +#endif + +HRESULT +InitializeNormalizeUrl( + VOID +) +{ + HKEY hKey; + DWORD dwType; + DWORD dwData; + DWORD cbData; + WORD wPrimaryLangID; + + // + // Read the registry settings on how to handle URLs + // + + g_fEnableNonUTF8 = TRUE; + g_fEnableDBCS = FALSE; + g_fFavorDBCS = FALSE; + + if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, + L"System\\CurrentControlSet\\Services\\http\\Parameters", + 0, + KEY_READ, + &hKey ) == ERROR_SUCCESS ) + { + cbData = sizeof( dwData ); + if ( RegQueryValueEx( hKey, + L"EnableNonUTF8", + NULL, + &dwType, + (LPBYTE) &dwData, + &cbData ) == ERROR_SUCCESS && + dwType == REG_DWORD ) + { + g_fEnableNonUTF8 = !!dwData; + } + + if ( g_fEnableNonUTF8 ) + { + cbData = sizeof( dwData ); + + if ( RegQueryValueEx( hKey, + L"EnableDBCS", + NULL, + &dwType, + (LPBYTE) &dwData, + &cbData ) == ERROR_SUCCESS && + dwType == REG_DWORD ) + { + g_fEnableDBCS = !!dwData; + } + } + else + { + g_fEnableDBCS = FALSE; + } + + if ( g_fEnableDBCS ) + { + cbData = sizeof( dwData ); + + if ( RegQueryValueEx( hKey, + L"FavorDBCS", + NULL, + &dwType, + (LPBYTE) &dwData, + &cbData ) == ERROR_SUCCESS && + dwType == REG_DWORD ) + { + g_fFavorDBCS = !!dwData; + } + } + else + { + g_fFavorDBCS = FALSE; + } + + RegCloseKey( hKey ); + } + + + wPrimaryLangID = PRIMARYLANGID( GetSystemDefaultLangID() ); + + g_fIsSystemDBCS = ( wPrimaryLangID == LANG_JAPANESE || + wPrimaryLangID == LANG_CHINESE || + wPrimaryLangID == LANG_KOREAN ); + + return NO_ERROR; +} + +// +// Private constants. +// + +#define ACTION_NOTHING 0x00000000 +#define ACTION_EMIT_CH 0x00010000 +#define ACTION_EMIT_DOT_CH 0x00020000 +#define ACTION_EMIT_DOT_DOT_CH 0x00030000 +#define ACTION_BACKUP 0x00040000 +#define ACTION_MASK 0xFFFF0000 + + +// +// Private globals. +// + +INT p_StateTable[16] = + { + // state 0 + 0 , // other + 0 , // "." + 4 , // EOS + 1 , // "\" + + // state 1 + 0 , // other + 2 , // "." + 4 , // EOS + 1 , // "\" + + // state 2 + 0 , // other + 3 , // "." + 4 , // EOS + 1 , // "\" + + // state 3 + 0 , // other + 0 , // "." + 4 , // EOS + 1 // "\" + }; + + + +INT p_ActionTable[16] = + { + // state 0 + ACTION_EMIT_CH, // other + ACTION_EMIT_CH, // "." + ACTION_EMIT_CH, // EOS + ACTION_EMIT_CH, // "\" + + // state 1 + ACTION_EMIT_CH, // other + ACTION_NOTHING, // "." + ACTION_EMIT_CH, // EOS + ACTION_NOTHING, // "\" + + // state 2 + ACTION_EMIT_DOT_CH, // other + ACTION_NOTHING, // "." + ACTION_EMIT_CH, // EOS + ACTION_NOTHING, // "\" + + // state 3 + ACTION_EMIT_DOT_DOT_CH, // other + ACTION_EMIT_DOT_DOT_CH, // "." + ACTION_BACKUP, // EOS + ACTION_BACKUP // "\" + }; + +// since max states = 4, we calculat the index by multiplying with 4. +# define IndexFromState( st) ( (st) * 4) + + +// the following table provides the index for various ISA Latin1 characters +// in the incoming URL. +// It assumes that the URL is ISO Latin1 == ASCII +INT p_rgIndexForChar[] = { + + 2, // null char + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 thru 10 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 11 thru 20 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 21 thru 30 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 31 thru 40 + 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, // 41 thru 50 46 = '.' 47 = '/' + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 51 thru 60 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 61 thru 70 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 71 thru 80 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 81 thru 90 + 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, // 91 thru 100 92 = '\\' + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 101 thru 110 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 111 thru 120 + 0, 0, 0, 0, 0, 0, 0, 0 // 121 thru 128 +}; + +#define IS_UTF8_TRAILBYTE(ch) (((ch) & 0xc0) == 0x80) + + +/******************************************************************* + + NAME: IsUTF8URL + + ENTRY: pszPath - The path to sanitize. + + HISTORY: + atsusk 06-Jan-1998 Created. + +********************************************************************/ + +BOOL IsUTF8URL(__in LPSTR pszPath) +{ + CHAR ch; + + if ( g_fFavorDBCS ) + { + return ( MultiByteToWideChar( CP_ACP, + MB_ERR_INVALID_CHARS, + pszPath, + -1, + NULL, + 0) == 0); + } + + while (ch = *pszPath++) { + + if (ch & 0x80) { + wchar_t wch; + int iLen; + BOOL bDefault = FALSE; + char chTrail1; + char chTrail2; + + chTrail1 = *pszPath++; + if (chTrail1) { + chTrail2 = *pszPath; + } else { + chTrail2 = 0; + } + + if ( ((ch & 0xF0) == 0xE0) && + IS_UTF8_TRAILBYTE(chTrail1) && + IS_UTF8_TRAILBYTE(chTrail2) ) { + + // handle three byte case + // 1110xxxx 10xxxxxx 10xxxxxx + wch = (wchar_t) (((ch & 0x0f) << 12) | + ((chTrail1 & 0x3f) << 6) | + (chTrail2 & 0x3f)); + pszPath++; + + } else + if ( ((ch & 0xE0) == 0xC0) && + IS_UTF8_TRAILBYTE(chTrail1) ) { + + // handle two byte case + // 110xxxxx 10xxxxxx + + wch = (wchar_t) (((ch & 0x1f) << 6) | (chTrail1 & 0x3f)); + + } else + return FALSE; + + iLen = WideCharToMultiByte( CP_ACP, + WC_NO_BEST_FIT_CHARS, + &wch, + 1, + NULL, + 0, + NULL, + &bDefault ); + + if (bDefault == TRUE || iLen == 0 || iLen > 2) + return FALSE; + } + } + + return TRUE; +} // IsUTF8URL() + + +/******************************************************************* + + NAME: CanonURL + + SYNOPSIS: Sanitizes a path by removing bogus path elements. + + As expected, "/./" entries are simply removed, and + "/../" entries are removed along with the previous + path element. + + To maintain compatibility with URL path semantics + additional transformations are required. All backward + slashes "\\" are converted to forward slashes. Any + repeated forward slashes (such as "///") are mapped to + single backslashes. + + A state table (see the p_StateTable global at the + beginning of this file) is used to perform most of + the transformations. The table's rows are indexed + by current state, and the columns are indexed by + the current character's "class" (either slash, dot, + NULL, or other). Each entry in the table consists + of the new state tagged with an action to perform. + See the ACTION_* constants for the valid action + codes. + + ENTRY: pszPath - The path to sanitize. + fIsDBCSLocale - Indicates the server is in a + locale that uses DBCS. + + HISTORY: + KeithMo 07-Sep-1994 Created. + MuraliK 28-Apr-1995 Adopted this for symbolic paths + +********************************************************************/ +INT +CanonURL( + __inout LPSTR pszPath, + BOOL fIsDBCSLocale + ) +{ + UCHAR * pszSrc; + UCHAR * pszDest; + DWORD ch; + INT index; + BOOL fDBCS = FALSE; + DWORD cchMultiByte = 0; + + DBG_ASSERT( pszPath != NULL ); + + // + // Always look for UTF8 except when DBCS characters are detected + // + BOOL fScanForUTF8 = IsUTF8URL(pszPath); + + // If fScanForUTF8 is true, this URL is UTF8. don't recognize DBCS. + if (fIsDBCSLocale && fScanForUTF8) { + fIsDBCSLocale = FALSE; + } + + // + // Start our scan at the first character + // + + pszSrc = pszDest = (UCHAR *) pszPath; + + // + // State 0 is the initial state. + // + index = 0; // State = 0 + + // + // Loop until we enter state 4 (the final, accepting state). + // + + do { + + // + // Grab the next character from the path and compute its + // next state. While we're at it, map any forward + // slashes to backward slashes. + // + + index = IndexFromState( p_StateTable[index]); // 4 = # states + ch = (DWORD ) *pszSrc++; + + // + // If this is a DBCS trailing byte - skip it + // + + if ( !fIsDBCSLocale ) + { + index += (( ch >= 0x80) ? 0 : p_rgIndexForChar[ch]); + } + else + { + if ( fDBCS ) + { + // + // If this is a 0 terminator, we need to set next + // state accordingly + // + + if ( ch == 0 ) + { + index += p_rgIndexForChar[ ch ]; + } + + // + // fDBCS == TRUE means this byte was a trail byte. + // index is implicitly set to zero. + // + fDBCS = FALSE; + } + else + { + index += (( ch >= 0x80) ? 0 : p_rgIndexForChar[ch]); + + if ( IsDBCSLeadByte( (UCHAR)ch ) ) + { + // + // This is a lead byte, so the next is a trail. + // + fDBCS = TRUE; + } + } + } + + // + // Interesting UTF8 characters always have the top bit set + // + + if ( (ch & 0x80) && fScanForUTF8 ) + { + wchar_t wch; + UCHAR mbstr[2]; + + // + // This is a UTF8 character, convert it here. + // index is implicitly set to zero. + // + if ( cchMultiByte < 2 ) + { + char chTrail1; + char chTrail2; + + chTrail1 = *pszSrc; + if (chTrail1) { + chTrail2 = *(pszSrc+1); + } else { + chTrail2 = 0; + } + wch = 0; + + if ((ch & 0xf0) == 0xe0) + { + // handle three byte case + // 1110xxxx 10xxxxxx 10xxxxxx + + wch = (wchar_t) (((ch & 0x0f) << 12) | + ((chTrail1 & 0x3f) << 6) | + (chTrail2 & 0x3f)); + + cchMultiByte = WideCharToMultiByte( CP_ACP, + WC_NO_BEST_FIT_CHARS, + &wch, + 1, + (LPSTR) mbstr, + 2, + NULL, + NULL ); + + ch = mbstr[0]; + pszSrc += (3 - cchMultiByte); + + // WinSE 12843: Security Fix, Index should be updated for this character + index += (( ch >= 0x80) ? 0 : p_rgIndexForChar[ch]); + + } else if ((ch & 0xe0) == 0xc0) + { + // handle two byte case + // 110xxxxx 10xxxxxx + + wch = (wchar_t) (((ch & 0x1f) << 6) | (chTrail1 & 0x3f)); + + cchMultiByte = WideCharToMultiByte( CP_ACP, + WC_NO_BEST_FIT_CHARS, + &wch, + 1, + (LPSTR) mbstr, + 2, + NULL, + NULL ); + + ch = mbstr[0]; + pszSrc += (2 - cchMultiByte); + + // WinSE 12843: Security Fix, Index should be updated for this character + index += (( ch >= 0x80) ? 0 : p_rgIndexForChar[ch]); + } + + } else { + // + // get ready to emit 2nd byte of converted character + // + ch = mbstr[1]; + cchMultiByte = 0; + } + } + + + // + // Perform the action associated with the state. + // + + switch( p_ActionTable[index] ) + { + case ACTION_EMIT_DOT_DOT_CH : + *pszDest++ = '.'; + /* fall through */ + + case ACTION_EMIT_DOT_CH : + *pszDest++ = '.'; + /* fall through */ + + case ACTION_EMIT_CH : + *pszDest++ = (CHAR ) ch; + /* fall through */ + + case ACTION_NOTHING : + break; + + case ACTION_BACKUP : + if( (pszDest > ( (UCHAR *) pszPath + 1 ) ) && (*pszPath == '/')) + { + pszDest--; + DBG_ASSERT( *pszDest == '/' ); + + *pszDest = '\0'; + pszDest = (UCHAR *) strrchr( pszPath, '/') + 1; + } + + *pszDest = '\0'; + break; + + default : + DBG_ASSERT( !"Invalid action code in state table!" ); + index = IndexFromState(0) + 2; // move to invalid state + DBG_ASSERT( p_StateTable[index] == 4); + *pszDest++ = '\0'; + break; + } + + } while( p_StateTable[index] != 4 ); + + // + // point to terminating nul + // only do the check if we aren't about to go outside of the number + // of elements in the table. + // + if ( ( index < ( sizeof(p_ActionTable) / sizeof(p_ActionTable[0]) ) ) + && p_ActionTable[index] == ACTION_EMIT_CH ) + { + pszDest--; + } + + DBG_ASSERT(*pszDest == '\0' && pszDest > (UCHAR*) pszPath); + + return (INT)DIFF(pszDest - (UCHAR*)pszPath); +} // CanonURL() + + + +HRESULT +NormalizeUrl( + __inout LPSTR pszStart + ) +/*++ + +Routine Description: + + Normalize URL + +Arguments: + + strUrl - URL to be updated to a canonical URI + +Return value: + + TRUE if no error, otherwise FALSE + +--*/ +{ + CHAR * pchParams; + LPSTR pszSlash; + LPSTR pszURL; + LPSTR pszValue; + STACK_STRA( strChgUrl, MAX_PATH ); + HRESULT hr; + DWORD cchInput; + + if ( pszStart == NULL ) + { + return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); + } + + cchInput = (DWORD)strlen( pszStart ); + + if ( *pszStart != '/' ) + { + // + // assume HTTP URL, skip protocol & host name by + // searching for 1st '/' following "//" + // + // We handle this information as a "Host:" header. + // It will be overwritten by the real header if it is + // present. + // + // We do not check for a match in this case. + // + + if ( (pszSlash = strchr( pszStart, '/' )) && pszSlash[1] == '/' ) + { + pszSlash += 2; + if ( pszURL = strchr( pszSlash, '/' ) ) + { + // + // update pointer to URL to point to the 1st slash + // following host name + // + + pszValue = pszURL; + } + else + { + // + // if no single slash following host name + // consider the URL to be empty. + // + + pszValue = pszSlash + strlen( pszSlash ); + } + + memmove( pszStart, pszValue, strlen(pszValue)+1 ); + } + + // + // if no double slash, this is not a fully qualified URL + // and we leave it alone. + // + } + + // + // Check for a question mark which indicates this URL contains some + // parameters and break the two apart if found + // + + if ( (pchParams = strchr( pszStart, '?' )) ) + { + *pchParams = '\0'; + } + + // + // Unescape wants a STR ( sigh ) + // + + hr = strChgUrl.Copy( (CHAR*)pszStart ); + + if ( FAILED( hr ) ) + { + return hr; + } + + strChgUrl.Unescape(); + + hr = StringCchCopyNA( pszStart, cchInput + 1, strChgUrl.QueryStr(), cchInput ); + if ( FAILED( hr ) ) + { + return hr; + } + + // + // Canonicalize the URL + // + + CanonURL( pszStart, g_fIsSystemDBCS ); + + return NO_ERROR; +} + + + + +HRESULT +NormalizeUrlOld( + __inout LPSTR pszUrl +) +/*++ + +Routine Description: + + NormalizeUrl wrapper (used by ISAPI filter and extension support functions) + +Parameters: + + pszUrl - On entry, the URL to be normalized + On return, the normalized URL + (size of normalized URL is always <= not normalized URL) + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = NO_ERROR; + + if ( pszUrl ) + { + STACK_BUFFER( buffUrlOutput, MAX_PATH ); + STACK_STRA( strUrlA, MAX_PATH ); + LPWSTR szQueryString; + DWORD cchData; + DWORD cbOutput; + + cchData = (DWORD)strlen( pszUrl ); + + // + // Prepare the Output string + // + + if ( !buffUrlOutput.Resize( ( cchData + 1 ) *sizeof( WCHAR ) ) ) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + + // + // Normalize it + // + + hr = UlCleanAndCopyUrl( + pszUrl, + cchData, + &cbOutput, + (WCHAR *) buffUrlOutput.QueryPtr(), + &szQueryString + ); + + if ( FAILED( hr ) ) + { + return hr; + } + + // + // Terminate the string at the query so that the + // query string doesn't appear in the output. IIS 5 + // truncated in this way. + // + + if ( szQueryString != NULL ) + { + ((WCHAR *) buffUrlOutput.QueryPtr())[ cbOutput - wcslen( szQueryString )] = 0; + } + + // + // Write the normalized URL over the input data + // + + hr = strUrlA.CopyW( (WCHAR *) buffUrlOutput.QueryPtr() ); + + if ( FAILED( hr ) ) + { + return hr; + } + + // + // Normalized string will never be longer than the original one + // + + DBG_ASSERT( strUrlA.QueryCCH() <= cchData ); + + hr = StringCchCopyA( pszUrl, cchData + 1, strUrlA.QueryStr() ); + if ( FAILED( hr ) ) + { + return hr; + } + + hr = NO_ERROR; + } + else + { + hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); + } + return hr; +} + + +HRESULT +NormalizeUrlW( + __inout LPWSTR pszUrl +) +/*++ + +Routine Description: + + unicode version of NormalizeUrl wrapper (used by ISAPI filter and extension support functions) + +Parameters: + + pszUrl - On entry, the URL to be normalized + On return, the normalized URL + (size of normalized URL is always <= not normalized URL) + +Return Value: + + HRESULT + +--*/ +{ + + HRESULT hr = NO_ERROR; + + if ( pszUrl ) + { + STACK_BUFFER( buffUrlOutput, MAX_PATH ); + STACK_STRA( strUrlA, MAX_PATH ); + LPWSTR szQueryString; + DWORD cchData; + DWORD cbOutput; + + cchData = (DWORD)wcslen( pszUrl ); + + hr = strUrlA.CopyWToUTF8Escaped( pszUrl ); + + if ( FAILED( hr ) ) + { + return hr; + } + + // + // Prepare Output string + // + + if ( !buffUrlOutput.Resize( ( cchData + 1 ) *sizeof( WCHAR ) ) ) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + + // + // Normalize it + // + + hr = UlCleanAndCopyUrl( + strUrlA.QueryStr(), + strUrlA.QueryCB(), + &cbOutput, + (WCHAR *) buffUrlOutput.QueryPtr(), + &szQueryString + ); + + if ( FAILED( hr ) ) + { + return hr; + } + + + // + // Terminate the string at the query so that the + // query string doesn't appear in the output. IIS 5 + // truncated in this way. + // + + if ( szQueryString != NULL ) + { + ((WCHAR *) buffUrlOutput.QueryPtr())[ cbOutput - wcslen( szQueryString )] = 0; + } + + // + // normalized string will never be longer than the original one + // + + DBG_ASSERT( cbOutput <= cchData * sizeof( WCHAR ) ); + + // + // Write the normalized URL over the input data + // + + hr = StringCchCopyW( pszUrl, cchData+1, (WCHAR *) buffUrlOutput.QueryPtr() ); + if ( FAILED( hr ) ) + { + return hr; + } + + hr = NO_ERROR; + } + else + { + hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); + } + return hr; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/packages.config b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/packages.config new file mode 100644 index 0000000000..21d9344493 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/packages.config @@ -0,0 +1,4 @@ + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/precomp.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/precomp.h new file mode 100644 index 0000000000..8f578b2ad3 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/precomp.h @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include +#include +#pragma warning( disable:4127 ) +#include +#include +#include + +#include "macros.h" +#include "stringu.h" +#include "stringa.h" +#include "dbgutil.h" +#include "ntassert.h" +#include "ahutil.h" +#include "acache.h" +#include "base64.hxx" diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/stringa.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/stringa.cpp new file mode 100644 index 0000000000..6380535473 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/stringa.cpp @@ -0,0 +1,1767 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +STRA::STRA( + VOID +) : m_cchLen( 0 ) +{ + *( QueryStr() ) = '\0'; +} + +STRA::STRA( + __inout_ecount(cchInit) CHAR* pbInit, + __in DWORD cchInit +) : m_Buff( pbInit, cchInit * sizeof( CHAR ) ), + m_cchLen(0) +/*++ + Description: + + Used by STACK_STRA. Initially populates underlying buffer with pbInit. + + pbInit is not freed. + + Arguments: + + pbInit - initial memory to use + cchInit - count, in characters, of pbInit + + Returns: + + None. + +--*/ +{ + _ASSERTE( NULL != pbInit ); + _ASSERTE( cchInit > 0 ); + _ASSERTE( pbInit[0] == '\0' ); +} + +BOOL +STRA::IsEmpty( + VOID +) const +{ + return ( m_cchLen == 0 ); +} + +BOOL +STRA::Equals( + __in PCSTR pszRhs, + __in BOOL fIgnoreCase /*= FALSE*/ +) const +{ + _ASSERTE( NULL != pszRhs ); + + if( fIgnoreCase ) + { + return ( 0 == _stricmp( QueryStr(), pszRhs ) ); + } + + return ( 0 == strcmp( QueryStr(), pszRhs ) ); +} + +BOOL +STRA::Equals( + __in const STRA * pstrRhs, + __in BOOL fIgnoreCase /*= FALSE*/ +) const +{ + _ASSERTE( NULL != pstrRhs ); + return Equals( pstrRhs->QueryStr(), fIgnoreCase ); +} + +BOOL +STRA::Equals( + __in const STRA & strRhs, + __in BOOL fIgnoreCase /*= FALSE*/ +) const +{ + return Equals( strRhs.QueryStr(), fIgnoreCase ); +} + +DWORD +STRA::QueryCB( + VOID +) const +// +// Returns the number of bytes in the string excluding the terminating NULL +// +{ + return m_cchLen * sizeof( CHAR ); +} + +DWORD +STRA::QueryCCH( + VOID +) const +// +// Returns the number of characters in the string excluding the terminating NULL +// +{ + return m_cchLen; +} + +DWORD +STRA::QuerySizeCCH( + VOID +) const +// +// Returns size of the underlying storage buffer, in characters +// +{ + return m_Buff.QuerySize() / sizeof( CHAR ); +} + +DWORD +STRA::QuerySize( + VOID +) const +// +// Returns the size of the storage buffer in bytes +// +{ + return m_Buff.QuerySize(); +} + +__nullterminated +__bcount(this->m_cchLen) +CHAR * +STRA::QueryStr( + VOID +) const +// +// Return the string buffer +// +{ + return m_Buff.QueryPtr(); +} + +VOID +STRA::Reset( + VOID +) +// +// Resets the internal string to be NULL string. Buffer remains cached. +// +{ + _ASSERTE( QueryStr() != NULL ); + *(QueryStr()) = '\0'; + m_cchLen = 0; +} + +HRESULT +STRA::Resize( + __in DWORD cchSize +) +{ + if( !m_Buff.Resize( cchSize * sizeof( CHAR ) ) ) + { + return E_OUTOFMEMORY; + } + + return S_OK; +} + +HRESULT +STRA::SyncWithBuffer( + VOID +) +// +// Recalculate the length of the string, etc. because we've modified +// the buffer directly. +// +{ + HRESULT hr; + size_t size; + hr = StringCchLengthA( QueryStr(), + QuerySizeCCH(), + &size ); + if ( SUCCEEDED( hr ) ) + { + m_cchLen = static_cast(size); + } + return hr; +} + +HRESULT +STRA::Copy( + __in PCSTR pszCopy +) +{ + HRESULT hr; + size_t cbLen; + hr = StringCbLengthA( pszCopy, + STRSAFE_MAX_CCH, + &cbLen ); + if ( FAILED( hr ) ) + { + return hr; + } + return Copy( pszCopy, cbLen ); +} + + +HRESULT +STRA::Copy( + __in_ecount(cchLen) + PCSTR pszCopy, + __in SIZE_T cbLen +) +// +// Copy the contents of another string to this one +// +{ + _ASSERTE( cbLen <= MAXDWORD ); + + return AuxAppend( + pszCopy, + static_cast(cbLen), + 0 + ); +} + +HRESULT +STRA::Copy( + __in const STRA * pstrRhs +) +{ + _ASSERTE( pstrRhs != NULL ); + return Copy( pstrRhs->QueryStr(), pstrRhs->QueryCCH() ); +} + +HRESULT +STRA::Copy( + __in const STRA & strRhs +) +{ + return Copy( strRhs.QueryStr(), strRhs.QueryCCH() ); +} + +HRESULT +STRA::CopyW( + __in PCWSTR pszCopyW +) +{ + HRESULT hr; + size_t cchLen; + hr = StringCchLengthW( pszCopyW, + STRSAFE_MAX_CCH, + &cchLen ); + if ( FAILED( hr ) ) + { + return hr; + } + return CopyW( pszCopyW, cchLen ); +} + +HRESULT +STRA::CopyWTruncate( + __in PCWSTR pszCopyWTruncate +) +{ + HRESULT hr; + size_t cchLen; + hr = StringCchLengthW( pszCopyWTruncate, + STRSAFE_MAX_CCH, + &cchLen ); + if ( FAILED( hr ) ) + { + return hr; + } + return CopyWTruncate( pszCopyWTruncate, cchLen ); +} + +HRESULT +STRA::CopyWTruncate( + __in_ecount(cchLen) + PCWSTR pszCopyWTruncate, + __in SIZE_T cchLen +) +// +// The "Truncate" methods do not do proper conversion. They do a (CHAR) caste +// +{ + _ASSERTE( cchLen <= MAXDWORD ); + + return AuxAppendWTruncate( + pszCopyWTruncate, + static_cast(cchLen), + 0 + ); +} + +HRESULT +STRA::Append( + __in PCSTR pszAppend +) +{ + HRESULT hr; + size_t cbLen; + hr = StringCbLengthA( pszAppend, + STRSAFE_MAX_CCH, + &cbLen ); + if ( FAILED( hr ) ) + { + return hr; + } + return Append( pszAppend, cbLen ); +} + +HRESULT +STRA::Append( + __in_ecount(cchLen) + PCSTR pszAppend, + __in SIZE_T cbLen +) +{ + _ASSERTE( cbLen <= MAXDWORD ); + if ( cbLen == 0 ) + { + return S_OK; + } + return AuxAppend( + pszAppend, + static_cast(cbLen), + QueryCB() + ); +} + +HRESULT +STRA::Append( + __in const STRA * pstrRhs +) +{ + _ASSERTE( pstrRhs != NULL ); + return Append( pstrRhs->QueryStr(), pstrRhs->QueryCCH() ); +} + +HRESULT +STRA::Append( + __in const STRA & strRhs +) +{ + return Append( strRhs.QueryStr(), strRhs.QueryCCH() ); +} + +HRESULT +STRA::AppendWTruncate( + __in PCWSTR pszAppendWTruncate +) +{ + HRESULT hr; + size_t cchLen; + hr = StringCchLengthW( pszAppendWTruncate, + STRSAFE_MAX_CCH, + &cchLen ); + if ( FAILED( hr ) ) + { + return hr; + } + return AppendWTruncate( pszAppendWTruncate, cchLen ); +} + +HRESULT +STRA::AppendWTruncate( + __in_ecount(cchLen) + PCWSTR pszAppendWTruncate, + __in SIZE_T cchLen +) +// +// The "Truncate" methods do not do proper conversion. They do a (CHAR) caste +// +{ + _ASSERTE( cchLen <= MAXDWORD ); + if ( cchLen == 0 ) + { + return S_OK; + } + return AuxAppendWTruncate( + pszAppendWTruncate, + static_cast(cchLen), + QueryCB() + ); +} + +HRESULT +STRA::CopyToBuffer( + __out_bcount(*pcb) CHAR* pszBuffer, + __inout DWORD * pcb +) const +// +// Makes a copy of the stored string into the given buffer +// +{ + _ASSERTE( NULL != pszBuffer ); + _ASSERTE( NULL != pcb ); + + HRESULT hr = S_OK; + DWORD cbNeeded = QueryCB() + sizeof( CHAR ); + + if( *pcb < cbNeeded ) + { + hr = HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ); + goto Finished; + } + + memcpy( pszBuffer, QueryStr(), cbNeeded ); + +Finished: + + *pcb = cbNeeded; + + return hr; +} + +HRESULT +STRA::SetLen( + __in DWORD cchLen +) +/*++ + * +Routine Description: + + Set the length of the string and null terminate, if there + is sufficient buffer already allocated. Will not reallocate. + +Arguments: + + cchLen - The number of characters in the new string. + +Return Value: + + HRESULT + +--*/ +{ + if( cchLen >= QuerySizeCCH() ) + { + return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); + } + + *( QueryStr() + cchLen ) = '\0'; + m_cchLen = cchLen; + + return S_OK; +} + + +HRESULT +STRA::SafeSnprintf( + __in __format_string + PCSTR pszFormatString, + ... +) +/*++ + +Routine Description: + + Writes to a STRA, growing it as needed. It arbitrarily caps growth at 64k chars. + +Arguments: + + pszFormatString - printf format + ... - printf args + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + va_list argsList; + va_start( argsList, pszFormatString ); + + hr = SafeVsnprintf(pszFormatString, argsList); + + va_end( argsList ); + return hr; +} + +HRESULT +STRA::SafeVsnprintf( + __in __format_string + PCSTR pszFormatString, + va_list argsList +) +/*++ + +Routine Description: + + Writes to a STRA, growing it as needed. It arbitrarily caps growth at 64k chars. + +Arguments: + + pszFormatString - printf format + argsList - printf va_list + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + int cchOutput; + int cchNeeded; + + // + // Format the incoming message using vsnprintf() + // so that the overflows are captured + // + cchOutput = _vsnprintf_s( + QueryStr(), + QuerySizeCCH(), + QuerySizeCCH() - 1, + pszFormatString, + argsList + ); + + if( cchOutput == -1 ) + { + // + // Couldn't fit this in the original STRU size. + // + cchNeeded = _vscprintf( pszFormatString, argsList ); + if( cchNeeded > 64 * 1024 ) + { + // + // If we're trying to produce a string > 64k chars, then + // there is probably a problem + // + hr = HRESULT_FROM_WIN32( ERROR_INVALID_DATA ); + goto Finished; + } + + // + // _vscprintf doesn't include terminating null character + // + cchNeeded++; + + hr = Resize( cchNeeded ); + if( FAILED( hr ) ) + { + goto Finished; + } + + cchOutput = _vsnprintf_s( + QueryStr(), + QuerySizeCCH(), + QuerySizeCCH() - 1, + pszFormatString, + argsList + ); + if( -1 == cchOutput ) + { + // + // This should never happen, cause we should already have correctly sized memory + // + _ASSERTE( FALSE ); + + hr = HRESULT_FROM_WIN32( ERROR_INVALID_DATA ); + goto Finished; + } + } + + // + // always null terminate at the last WCHAR + // + QueryStr()[ QuerySizeCCH() - 1 ] = L'\0'; + + // + // we directly touched the buffer - therefore: + // + hr = SyncWithBuffer(); + if( FAILED( hr ) ) + { + goto Finished; + } + +Finished: + + if( FAILED( hr ) ) + { + Reset(); + } + + return hr; +} + +bool +FShouldEscapeUtf8( + BYTE ch + ) +{ + if ( ( ch >= 128 ) ) + { + return true; + } + + return false; +} + +bool +FShouldEscapeUrl( + BYTE ch + ) +{ + if ( ( ch >= 128 || + ch <= 32 || + ch == '<' || + ch == '>' || + ch == '%' || + ch == '?' || + ch == '#' ) && + !( ch == '\n' || ch == '\r' ) ) + { + return true; + } + + return false; +} + +HRESULT +STRA::Escape( + VOID +) +/*++ + +Routine Description: + + Escapes a STRA + +Arguments: + + None + +Return Value: + + None + +--*/ +{ + return EscapeInternal( FShouldEscapeUrl ); +} + +HRESULT +STRA::EscapeUtf8( + VOID +) +/*++ + +Routine Description: + + Escapes the high-bit chars in a STRA. LWS, CR, LF & controls are untouched. + +Arguments: + + None + +Return Value: + + None + +--*/ +{ + return EscapeInternal( FShouldEscapeUtf8 ); +} + + +HRESULT +STRA::EscapeInternal( + PFN_F_SHOULD_ESCAPE pfnFShouldEscape +) +/*++ + +Routine Description: + + Escapes a STRA according to the predicate function passed in + +Arguments: + + None + +Return Value: + + None + +--*/ +{ + LPCSTR pch = QueryStr(); + __analysis_assume( pch != NULL ); + int i = 0; + BYTE ch; + HRESULT hr = S_OK; + BOOL fRet = FALSE; + SIZE_T NewSize = 0; + + // Set to true if any % escaping occurs + BOOL fEscapingDone = FALSE; + + // + // If there are any characters that need to be escaped we copy the entire string + // character by character into straTemp, escaping as we go, then at the end + // copy all of straTemp over. Don't modify InlineBuffer directly. + // + CHAR InlineBuffer[512]; + InlineBuffer[0] = '\0'; + STRA straTemp(InlineBuffer, sizeof(InlineBuffer)/sizeof(*InlineBuffer)); + + _ASSERTE( pch ); + + while (ch = pch[i]) + { + // + // Escape characters that are in the non-printable range + // but ignore CR and LF + // + + if ( pfnFShouldEscape( ch ) ) + { + if (FALSE == fEscapingDone) + { + // first character in the string that needed escaping + fEscapingDone = TRUE; + + // guess that the size needs to be larger than + // what we used to have times two + NewSize = QueryCCH() * 2; + if ( NewSize > MAXDWORD ) + { + hr = HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW ); + return hr; + } + + hr = straTemp.Resize( static_cast(NewSize) ); + + if (FAILED(hr)) + { + return hr; + } + + // Copy all of the previous buffer into buffTemp, only if it is not the first character: + + if ( i > 0) + { + hr = straTemp.Copy(QueryStr(), + i * sizeof(CHAR)); + if (FAILED(hr)) + { + return hr; + } + } + } + + // resize the temporary (if needed) with the slop of the entire buffer length + // this fixes constant reallocation if the entire string needs to be escaped + NewSize = QueryCCH() + 2 * sizeof(CHAR) + 1 * sizeof(CHAR); + if ( NewSize > MAXDWORD ) + { + hr = HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW ); + return hr; + } + + fRet = straTemp.m_Buff.Resize( NewSize ); + if ( !fRet ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + return hr; + } + + // + // Create the string to append for the current character + // + + CHAR chHex[3]; + chHex[0] = '%'; + + // + // Convert the low then the high character to hex + // + + UINT nLowDigit = (UINT)(ch % 16); + chHex[2] = TODIGIT( nLowDigit ); + + ch /= 16; + + UINT nHighDigit = (UINT)(ch % 16); + + chHex[1] = TODIGIT( nHighDigit ); + + // + // Actually append the converted character to the end of the temporary + // + hr = straTemp.Append(chHex, 3); + if (FAILED(hr)) + { + return hr; + } + } + else + { + // if no escaping done, no need to copy + if (fEscapingDone) + { + // if ANY escaping done, copy current character into new buffer + straTemp.Append(&pch[i], 1); + } + } + + // inspect the next character in the string + i++; + } + + if (fEscapingDone) + { + // the escaped string is now in straTemp + hr = Copy(straTemp); + } + + return hr; + +} // EscapeInternal() + +VOID +STRA::Unescape( + VOID +) +/*++ + +Routine Description: + + Unescapes a STRA + + Supported escape sequences are: + %uxxxx unescapes Unicode character xxxx into system codepage + %xx unescapes character xx + % without following hex digits is ignored + +Arguments: + + None + +Return Value: + + None + +--*/ +{ + CHAR *pScan; + CHAR *pDest; + CHAR *pNextScan; + WCHAR wch; + DWORD dwLen; + BOOL fChanged = FALSE; + + // + // Now take care of any escape characters + // + pDest = pScan = strchr(QueryStr(), '%'); + + while (pScan) + { + if ((pScan[1] == 'u' || pScan[1] == 'U') && + SAFEIsXDigit(pScan[2]) && + SAFEIsXDigit(pScan[3]) && + SAFEIsXDigit(pScan[4]) && + SAFEIsXDigit(pScan[5])) + { + wch = TOHEX(pScan[2]) * 4096 + TOHEX(pScan[3]) * 256 + + TOHEX(pScan[4]) * 16 + TOHEX(pScan[5]); + + dwLen = WideCharToMultiByte(CP_ACP, + WC_NO_BEST_FIT_CHARS, + &wch, + 1, + (LPSTR) pDest, + 6, + NULL, + NULL); + + pDest += dwLen; + pScan += 6; + fChanged = TRUE; + } + else if (SAFEIsXDigit(pScan[1]) && SAFEIsXDigit(pScan[2])) + { + *pDest = TOHEX(pScan[1]) * 16 + TOHEX(pScan[2]); + + pDest ++; + pScan += 3; + fChanged = TRUE; + } + else // Not an escaped char, just a '%' + { + if (fChanged) + { + *pDest = *pScan; + } + + pDest++; + pScan++; + } + + // + // Copy all the information between this and the next escaped char + // + pNextScan = strchr(pScan, '%'); + + if (fChanged) // pScan!=pDest, so we have to copy the char's + { + if (!pNextScan) // That was the last '%' in the string + { + memmove(pDest, + pScan, + QueryCCH() - DIFF(pScan - QueryStr()) + 1); + } + else + { + // There is another '%', move intermediate chars + if ((dwLen = (DWORD)DIFF(pNextScan - pScan)) != 0) + { + memmove(pDest, + pScan, + dwLen); + pDest += dwLen; + } + } + } + + pScan = pNextScan; + } + + if (fChanged) + { + m_cchLen = (DWORD)strlen(QueryStr()); // for safety recalc the length + } + + return; +} + +HRESULT +STRA::CopyWToUTF8Unescaped( + __in LPCWSTR cpchStr +) +{ + return STRA::CopyWToUTF8Unescaped(cpchStr, (DWORD) wcslen(cpchStr)); +} + +HRESULT +STRA::CopyWToUTF8Unescaped( + __in_ecount(cch) + LPCWSTR cpchStr, + __in DWORD cch +) +{ + HRESULT hr = S_OK; + int iRet; + + if (cch == 0) + { + Reset(); + return S_OK; + } + + iRet = ConvertUnicodeToUTF8(cpchStr, + &m_Buff, + cch); + if (-1 == iRet) + { + // could not convert + hr = HRESULT_FROM_WIN32(GetLastError()); + goto Finished; + } + + m_cchLen = iRet; + + _ASSERTE(strlen(m_Buff.QueryPtr()) == m_cchLen); +Finished: + return hr; +} + +HRESULT +STRA::CopyWToUTF8Escaped( + __in LPCWSTR cpchStr +) +{ + return STRA::CopyWToUTF8Escaped(cpchStr, (DWORD) wcslen(cpchStr)); +} + +HRESULT +STRA::CopyWToUTF8Escaped( + __in_ecount(cch) + LPCWSTR cpchStr, + __in DWORD cch +) +{ + HRESULT hr = S_OK; + + hr = CopyWToUTF8Unescaped(cpchStr, cch); + if (FAILED(hr)) + { + goto Finished; + } + + hr = Escape(); + if (FAILED(hr)) + { + goto Finished; + } + + hr = S_OK; +Finished: + return hr; +} + +HRESULT +STRA::AuxAppend( + __in_ecount(cbLen) + LPCSTR pStr, + __in DWORD cbLen, + __in DWORD cbOffset +) +{ + _ASSERTE( NULL != pStr ); + _ASSERTE( cbOffset <= QueryCB() ); + + ULONGLONG cb64NewSize = (ULONGLONG)cbOffset + cbLen + sizeof( CHAR ); + if( cb64NewSize > MAXDWORD ) + { + return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW ); + } + + if( m_Buff.QuerySize() < cb64NewSize ) + { + if( !m_Buff.Resize( static_cast(cb64NewSize) ) ) + { + return E_OUTOFMEMORY; + } + } + + memcpy( reinterpret_cast(m_Buff.QueryPtr()) + cbOffset, pStr, cbLen ); + + m_cchLen = cbLen + cbOffset; + + *( QueryStr() + m_cchLen ) = '\0'; + + return S_OK; +} + +HRESULT +STRA::AuxAppendW( + __in_ecount(cchAppendW) + PCWSTR pszAppendW, + __in DWORD cchAppendW, + __in DWORD cbOffset, + __in UINT CodePage, + __in BOOL fFailIfNoTranslation, + __in DWORD dwFlags +) +{ + HRESULT hr = S_OK; + DWORD cbAvailable = 0; + DWORD cbRet = 0; + + // + // There are only two expect places to append + // + _ASSERTE( 0 == cbOffset || QueryCB() == cbOffset ); + + if ( cchAppendW == 0 ) + { + goto Finished; + } + + // + // start by assuming 1 char to 1 char will be enough space + // + if( !m_Buff.Resize( cbOffset + cchAppendW + sizeof( CHAR ) ) ) + { + hr = E_OUTOFMEMORY; + goto Finished; + } + + cbAvailable = m_Buff.QuerySize() - cbOffset; + + cbRet = WideCharToMultiByte( + CodePage, + dwFlags, + pszAppendW, + cchAppendW, + QueryStr() + cbOffset, + cbAvailable, + NULL, + NULL + ); + if( 0 != cbRet ) + { + if(!m_Buff.Resize(cbOffset + cbRet + 1)) + { + hr = E_OUTOFMEMORY; + } + + // + // not zero --> success, so we're done + // + goto Finished; + } + + // + // We only know how to handle ERROR_INSUFFICIENT_BUFFER + // + hr = HRESULT_FROM_WIN32( GetLastError() ); + if( hr != HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) ) + { + goto Finished; + } + + // + // Reset HResult because we need to get the number of bytes needed + // + hr = S_OK; + cbRet = WideCharToMultiByte( + CodePage, + dwFlags, + pszAppendW, + cchAppendW, + NULL, + 0, + NULL, + NULL + ); + if( 0 == cbRet ) + { + // + // no idea how we could ever reach here + // + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Finished; + } + + if( !m_Buff.Resize( cbOffset + cbRet + 1) ) + { + hr = E_OUTOFMEMORY; + goto Finished; + } + + cbAvailable = m_Buff.QuerySize() - cbOffset; + + cbRet = WideCharToMultiByte( + CodePage, + dwFlags, + pszAppendW, + cchAppendW, + QueryStr() + cbOffset, + cbAvailable, + NULL, + NULL + ); + if( 0 == cbRet ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Finished; + } + +Finished: + + if( SUCCEEDED( hr ) && 0 != cbRet ) + { + m_cchLen = cbRet + cbOffset; + } + + // + // ensure we're still NULL terminated in the right spot + // (regardless of success or failure) + // + QueryStr()[m_cchLen] = '\0'; + + return hr; +} + +HRESULT +STRA::AuxAppendWTruncate( + __in_ecount(cchAppendW) + __in PCWSTR pszAppendW, + __in DWORD cchAppendW, + __in DWORD cbOffset +) +// +// Cheesey WCHAR --> CHAR conversion +// +{ + HRESULT hr = S_OK; + CHAR* pszBuffer; + + _ASSERTE( NULL != pszAppendW ); + _ASSERTE( 0 == cbOffset || cbOffset == QueryCB() ); + + if( !pszAppendW ) + { + hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); + goto Finished; + } + + ULONGLONG cbNeeded = (ULONGLONG)cbOffset + cchAppendW + sizeof( CHAR ); + if( cbNeeded > MAXDWORD ) + { + hr = HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW ); + goto Finished; + } + + if( !m_Buff.Resize( static_cast(cbNeeded) ) ) + { + hr = E_OUTOFMEMORY; + goto Finished; + } + + // + // Copy/convert the UNICODE string over (by making two bytes into one) + // + pszBuffer = QueryStr() + cbOffset; + for( DWORD i = 0; i < cchAppendW; i++ ) + { + pszBuffer[i] = static_cast(pszAppendW[i]); + } + + m_cchLen = cchAppendW + cbOffset; + *( QueryStr() + m_cchLen ) = '\0'; + +Finished: + + return hr; +} + +// static +int +STRA::ConvertUnicodeToCodePage( + __in_ecount(dwStringLen) + LPCWSTR pszSrcUnicodeString, + __inout BUFFER_T * pbufDstAnsiString, + __in DWORD dwStringLen, + __in UINT uCodePage +) +{ + _ASSERTE(NULL != pszSrcUnicodeString); + _ASSERTE(NULL != pbufDstAnsiString); + + BOOL bTemp; + int iStrLen = 0; + DWORD dwFlags; + + if (uCodePage == CP_ACP) + { + dwFlags = WC_NO_BEST_FIT_CHARS; + } + else + { + dwFlags = 0; + } + + iStrLen = WideCharToMultiByte(uCodePage, + dwFlags, + pszSrcUnicodeString, + dwStringLen, + (LPSTR)pbufDstAnsiString->QueryPtr(), + (int)pbufDstAnsiString->QuerySize(), + NULL, + NULL); + if ((iStrLen == 0) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { + iStrLen = WideCharToMultiByte(uCodePage, + dwFlags, + pszSrcUnicodeString, + dwStringLen, + NULL, + 0, + NULL, + NULL); + if (iStrLen != 0) { + // add one just for the extra NULL + bTemp = pbufDstAnsiString->Resize(iStrLen + 1); + if (!bTemp) + { + iStrLen = 0; + } + else + { + iStrLen = WideCharToMultiByte(uCodePage, + dwFlags, + pszSrcUnicodeString, + dwStringLen, + (LPSTR)pbufDstAnsiString->QueryPtr(), + (int)pbufDstAnsiString->QuerySize(), + NULL, + NULL); + } + + } + } + + if (0 != iStrLen && + pbufDstAnsiString->Resize(iStrLen + 1)) + { + // insert a terminating NULL into buffer for the dwStringLen+1 in the case that the dwStringLen+1 was not a NULL. + ((CHAR*)pbufDstAnsiString->QueryPtr())[iStrLen] = '\0'; + } + else + { + iStrLen = -1; + } + + return iStrLen; +} + +// static +HRESULT +STRA::ConvertUnicodeToMultiByte( + __in_ecount(dwStringLen) + LPCWSTR pszSrcUnicodeString, + __in BUFFER_T * pbufDstAnsiString, + __in DWORD dwStringLen +) +{ + return ConvertUnicodeToCodePage( pszSrcUnicodeString, + pbufDstAnsiString, + dwStringLen, + CP_ACP ); +} + +// static +HRESULT +STRA::ConvertUnicodeToUTF8( + __in_ecount(dwStringLen) + LPCWSTR pszSrcUnicodeString, + __in BUFFER_T * pbufDstAnsiString, + __in DWORD dwStringLen +) +{ + return ConvertUnicodeToCodePage( pszSrcUnicodeString, + pbufDstAnsiString, + dwStringLen, + CP_UTF8 ); +} + +/*++ + +Routine Description: + + Removes leading and trailing whitespace + +--*/ + +VOID +STRA::Trim() +{ + PSTR pszString = QueryStr(); + DWORD cchNewLength = m_cchLen; + DWORD cchLeadingWhitespace = 0; + DWORD cchTempLength = 0; + + for (LONG ixString = m_cchLen - 1; ixString >= 0; ixString--) + { + if (isspace((unsigned char) pszString[ixString]) != 0) + { + pszString[ixString] = '\0'; + cchNewLength--; + } + else + { + break; + } + } + + cchTempLength = cchNewLength; + for (DWORD ixString = 0; ixString < cchTempLength; ixString++) + { + if (isspace((unsigned char) pszString[ixString]) != 0) + { + cchLeadingWhitespace++; + cchNewLength--; + } + else + { + break; + } + } + + if (cchNewLength == 0) + { + + Reset(); + } + else if (cchLeadingWhitespace > 0) + { + memmove(pszString, pszString + cchLeadingWhitespace, cchNewLength * sizeof(CHAR)); + pszString[cchNewLength] = '\0'; + } + + SyncWithBuffer(); +} + +/*++ + +Routine Description: + + Compares the string to the provided prefix to check for equality + +Arguments: + + pStraPrefix - string to compare with + fIgnoreCase - indicates whether the string comparison should be case-sensitive + +Return Value: + + TRUE if prefix string matches with internal string, FALSE otherwise + +--*/ +BOOL +STRA::StartsWith( + __in const STRA * pStraPrefix, + __in bool fIgnoreCase) const +{ + _ASSERTE( pStraPrefix != NULL ); + return StartsWith(pStraPrefix->QueryStr(), fIgnoreCase); +} + +/*++ + +Routine Description: + + Compares the string to the provided prefix to check for equality + +Arguments: + + straPrefix - string to compare with + fIgnoreCase - indicates whether the string comparison should be case-sensitive + +Return Value: + + TRUE if prefix string matches with internal string, FALSE otherwise + +--*/ +BOOL +STRA::StartsWith( + __in const STRA & straPrefix, + __in bool fIgnoreCase) const +{ + return StartsWith(straPrefix.QueryStr(), fIgnoreCase); +} + +/*++ + +Routine Description: + + Compares the string to the provided prefix to check for equality + +Arguments: + + pszPrefix - string to compare with + fIgnoreCase - indicates whether the string comparison should be case-sensitive + +Return Value: + + TRUE if prefix string matches with internal string, FALSE otherwise + +--*/ +BOOL +STRA::StartsWith( + __in PCSTR pszPrefix, + __in bool fIgnoreCase) const +{ + HRESULT hr = S_OK; + BOOL fMatch = FALSE; + size_t cchPrefix = 0; + + if (pszPrefix == NULL) + { + goto Finished; + } + + hr = StringCchLengthA( pszPrefix, + STRSAFE_MAX_CCH, + &cchPrefix ); + if (FAILED(hr)) + { + goto Finished; + } + + _ASSERTE( cchPrefix <= MAXDWORD ); + + if (cchPrefix > m_cchLen) + { + goto Finished; + } + + if( fIgnoreCase ) + { + fMatch = ( 0 == _strnicmp( QueryStr(), pszPrefix, cchPrefix ) ); + } + else + { + fMatch = ( 0 == strncmp( QueryStr(), pszPrefix, cchPrefix ) ); + } + + +Finished: + + return fMatch; +} + +/*++ + +Routine Description: + + Compares the string to the provided suffix to check for equality + +Arguments: + + pStraSuffix - string to compare with + fIgnoreCase - indicates whether the string comparison should be case-sensitive + +Return Value: + + TRUE if suffix string matches with internal string, FALSE otherwise + +--*/ +BOOL +STRA::EndsWith( + __in const STRA * pStraSuffix, + __in bool fIgnoreCase) const +{ + _ASSERTE( pStraSuffix != NULL ); + return EndsWith(pStraSuffix->QueryStr(), fIgnoreCase); +} + + +/*++ + +Routine Description: + + Compares the string to the provided suffix to check for equality + +Arguments: + + straSuffix - string to compare with + fIgnoreCase - indicates whether the string comparison should be case-sensitive + +Return Value: + + TRUE if suffix string matches with internal string, FALSE otherwise + +--*/ +BOOL +STRA::EndsWith( + __in const STRA & straSuffix, + __in bool fIgnoreCase) const +{ + return EndsWith(straSuffix.QueryStr(), fIgnoreCase); +} + + +/*++ + +Routine Description: + + Compares the string to the provided suffix to check for equality + +Arguments: + + pszSuffix - string to compare with + fIgnoreCase - indicates whether the string comparison should be case-sensitive + +Return Value: + + TRUE if suffix string matches with internal string, FALSE otherwise + +--*/ +BOOL +STRA::EndsWith( + __in PCSTR pszSuffix, + __in bool fIgnoreCase) const +{ + HRESULT hr = S_OK; + PSTR pszString = QueryStr(); + BOOL fMatch = FALSE; + size_t cchSuffix = 0; + ptrdiff_t ixOffset = 0; + + if (pszSuffix == NULL) + { + goto Finished; + } + + hr = StringCchLengthA( pszSuffix, + STRSAFE_MAX_CCH, + &cchSuffix ); + if (FAILED(hr)) + { + goto Finished; + } + + _ASSERTE( cchSuffix <= MAXDWORD ); + + if (cchSuffix > m_cchLen) + { + goto Finished; + } + + ixOffset = m_cchLen - cchSuffix; + _ASSERTE(ixOffset >= 0 && ixOffset <= MAXDWORD); + + if( fIgnoreCase ) + { + fMatch = ( 0 == _strnicmp( pszString + ixOffset, pszSuffix, cchSuffix ) ); + } + else + { + fMatch = ( 0 == strncmp( pszString + ixOffset, pszSuffix, cchSuffix ) ); + } + +Finished: + + return fMatch; +} + + +/*++ + +Routine Description: + + Searches the string for the first occurrence of the specified character. + +Arguments: + + charValue - character to find + dwStartIndex - the initial index. + +Return Value: + + The index for the first character occurence in the string. + + -1 if not found. + +--*/ +INT +STRA::IndexOf( + __in CHAR charValue, + __in DWORD dwStartIndex + ) const +{ + INT nIndex = -1; + + // Make sure that there are no buffer overruns. + if( dwStartIndex >= QueryCCH() ) + { + goto Finished; + } + + const CHAR* pChar = strchr( QueryStr() + dwStartIndex, charValue ); + + // Determine the index if found + if( pChar ) + { + // nIndex will be set to -1 on failure. + (VOID)SizeTToInt( pChar - QueryStr(), &nIndex ); + } + +Finished: + + return nIndex; +} + + +/*++ + +Routine Description: + + Searches the string for the first occurrence of the specified substring. + +Arguments: + + pszValue - substring to find + dwStartIndex - initial index. + +Return Value: + + The index for the first character occurence in the string. + + -1 if not found. + +--*/ +INT +STRA::IndexOf( + __in PCSTR pszValue, + __in DWORD dwStartIndex + ) const +{ + HRESULT hr = S_OK; + INT nIndex = -1; + SIZE_T cchValue = 0; + + // Validate input parameters + if( dwStartIndex >= QueryCCH() || !pszValue ) + { + goto Finished; + } + + const CHAR* pChar = strstr( QueryStr() + dwStartIndex, pszValue ); + + // Determine the index if found + if( pChar ) + { + // nIndex will be set to -1 on failure. + (VOID)SizeTToInt( pChar - QueryStr(), &nIndex ); + } + +Finished: + + return nIndex; +} + + +/*++ + +Routine Description: + + Searches the string for the last occurrence of the specified character. + +Arguments: + + charValue - character to find + dwStartIndex - initial index. + +Return Value: + + The index for the last character occurence in the string. + + -1 if not found. + +--*/ +INT +STRA::LastIndexOf( + __in CHAR charValue, + __in DWORD dwStartIndex + ) const +{ + INT nIndex = -1; + + // Make sure that there are no buffer overruns. + if( dwStartIndex >= QueryCCH() ) + { + goto Finished; + } + + const CHAR* pChar = strrchr( QueryStr() + dwStartIndex, charValue ); + + // Determine the index if found + if( pChar ) + { + // nIndex will be set to -1 on failure. + (VOID)SizeTToInt( pChar - QueryStr(), &nIndex ); + } + +Finished: + + return nIndex; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/stringu.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/stringu.cpp new file mode 100644 index 0000000000..4fd2a052f2 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/stringu.cpp @@ -0,0 +1,1289 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +STRU::STRU( + VOID +) : m_cchLen( 0 ) +{ + *(QueryStr()) = L'\0'; +} + +STRU::STRU( + __inout_ecount(cchInit) WCHAR* pbInit, + __in DWORD cchInit +) : m_Buff( pbInit, cchInit * sizeof( WCHAR ) ), + m_cchLen( 0 ) +/*++ + Description: + + Used by STACK_STRU. Initially populates underlying buffer with pbInit. + + pbInit is not freed. + + Arguments: + + pbInit - initial memory to use + cchInit - count, in characters, of pbInit + + Returns: + + None. + +--*/ +{ + _ASSERTE( cchInit <= (MAXDWORD / sizeof( WCHAR )) ); + _ASSERTE( NULL != pbInit ); + _ASSERTE(cchInit > 0 ); + _ASSERTE(pbInit[0] == L'\0'); +} + +BOOL +STRU::IsEmpty( + VOID +) const +{ + return ( m_cchLen == 0 ); +} + +DWORD +STRU::QueryCB( + VOID +) const +// +// Returns the number of bytes in the string excluding the terminating NULL +// +{ + return m_cchLen * sizeof( WCHAR ); +} + +DWORD +STRU::QueryCCH( + VOID +) const +// +// Returns the number of characters in the string excluding the terminating NULL +// +{ + return m_cchLen; +} + +DWORD +STRU::QuerySizeCCH( + VOID +) const +// +// Returns size of the underlying storage buffer, in characters +// +{ + return m_Buff.QuerySize() / sizeof( WCHAR ); +} + +__nullterminated +__ecount(this->m_cchLen) +WCHAR* +STRU::QueryStr( + VOID +) const +// +// Return the string buffer +// +{ + return m_Buff.QueryPtr(); +} + +VOID +STRU::Reset( + VOID +) +// +// Resets the internal string to be NULL string. Buffer remains cached. +// +{ + _ASSERTE( QueryStr() != NULL ); + *(QueryStr()) = L'\0'; + m_cchLen = 0; +} + +HRESULT +STRU::Resize( + DWORD cchSize +) +{ + SIZE_T cbSize = cchSize * sizeof( WCHAR ); + if ( cbSize > MAXDWORD ) + { + return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW ); + } + if( !m_Buff.Resize( cbSize ) ) + { + return E_OUTOFMEMORY; + } + + return S_OK; +} + +HRESULT +STRU::SyncWithBuffer( + VOID +) +// +// Recalculate the length of the string, etc. because we've modified +// the buffer directly. +// +{ + HRESULT hr; + size_t size; + hr = StringCchLengthW( QueryStr(), + QuerySizeCCH(), + &size ); + if ( SUCCEEDED( hr ) ) + { + m_cchLen = static_cast(size); + } + return hr; +} + +HRESULT +STRU::Copy( + __in PCWSTR pszCopy +) +{ + HRESULT hr; + size_t cbStr; + + hr = StringCchLengthW( pszCopy, + STRSAFE_MAX_CCH, + &cbStr ); + if ( FAILED( hr ) ) + { + return hr; + } + + _ASSERTE( cbStr <= MAXDWORD ); + return Copy( pszCopy, + cbStr ); +} + +HRESULT +STRU::Copy( + __in_ecount(cchLen) + PCWSTR pszCopy, + SIZE_T cchLen +) +// +// Copy the contents of another string to this one +// +{ + return AuxAppend( pszCopy, + cchLen * sizeof(WCHAR), + 0); +} + +HRESULT +STRU::Copy( + __in const STRU * pstrRhs +) +{ + _ASSERTE( NULL != pstrRhs ); + return Copy( pstrRhs->QueryStr(), pstrRhs->QueryCCH() ); +} + +HRESULT +STRU::Copy( + __in const STRU & str +) +{ + return Copy( str.QueryStr(), str.QueryCCH() ); +} + +HRESULT +STRU::CopyAndExpandEnvironmentStrings( + __in PCWSTR pszSource +) +{ + HRESULT hr = S_OK; + DWORD cchDestReqBuff = 0; + + Reset(); + + cchDestReqBuff = ExpandEnvironmentStringsW( pszSource, + QueryStr(), + QuerySizeCCH() ); + if ( cchDestReqBuff == 0 ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Finished; + } + else if ( cchDestReqBuff > QuerySizeCCH() ) + { + hr = Resize( cchDestReqBuff ); + if ( FAILED( hr ) ) + { + goto Finished; + } + + cchDestReqBuff = ExpandEnvironmentStringsW( pszSource, + QueryStr(), + QuerySizeCCH() ); + + if ( cchDestReqBuff == 0 || cchDestReqBuff > QuerySizeCCH() ) + { + _ASSERTE( FALSE ); + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Finished; + } + } + + hr = SyncWithBuffer(); + if ( FAILED( hr ) ) + { + goto Finished; + } + +Finished: + + return hr; + +} + +HRESULT +STRU::CopyA( + __in PCSTR pszCopyA +) +{ + HRESULT hr; + size_t cbStr; + + hr = StringCbLengthA( pszCopyA, + STRSAFE_MAX_CCH, + &cbStr ); + if ( FAILED( hr ) ) + { + return hr; + } + + _ASSERTE( cbStr <= MAXDWORD ); + return CopyA( pszCopyA, + cbStr ); +} + +HRESULT +STRU::CopyA( + __in_bcount(cchLen) + PCSTR pszCopyA, + SIZE_T cchLen, + UINT CodePage /*= CP_UTF8*/ +) +{ + return AuxAppendA( + pszCopyA, + cchLen, + 0, + CodePage + ); +} + +HRESULT +STRU::Append( + __in PCWSTR pszAppend +) +{ + HRESULT hr; + size_t cbStr; + + hr = StringCchLengthW( pszAppend, + STRSAFE_MAX_CCH, + &cbStr ); + if ( FAILED( hr ) ) + { + return hr; + } + + _ASSERTE( cbStr <= MAXDWORD ); + return Append( pszAppend, + cbStr ); +} + +HRESULT +STRU::Append( + __in_ecount(cchLen) + PCWSTR pszAppend, + SIZE_T cchLen +) +// +// Append something to the end of the string +// +{ + if ( cchLen == 0 ) + { + return S_OK; + } + return AuxAppend( pszAppend, + cchLen * sizeof(WCHAR), + QueryCB() ); +} + +HRESULT +STRU::Append( + __in const STRU * pstrRhs +) +{ + _ASSERTE( NULL != pstrRhs ); + return Append( pstrRhs->QueryStr(), pstrRhs->QueryCCH() ); +} + +HRESULT +STRU::Append( + __in const STRU & strRhs +) +{ + return Append( strRhs.QueryStr(), strRhs.QueryCCH() ); +} + +HRESULT +STRU::AppendA( + __in PCSTR pszAppendA +) +{ + HRESULT hr; + size_t cbStr; + + hr = StringCbLengthA( pszAppendA, + STRSAFE_MAX_CCH, + &cbStr ); + if ( FAILED( hr ) ) + { + return hr; + } + + _ASSERTE( cbStr <= MAXDWORD ); + return AppendA( pszAppendA, + cbStr ); +} + +HRESULT +STRU::AppendA( + __in_bcount(cchLen) + PCSTR pszAppendA, + SIZE_T cchLen, + UINT CodePage /*= CP_UTF8*/ +) +{ + if ( cchLen == 0 ) + { + return S_OK; + } + return AuxAppendA( + pszAppendA, + cchLen, + QueryCB(), + CodePage + ); +} + +HRESULT +STRU::CopyToBuffer( + __out_bcount(*pcb) WCHAR* pszBuffer, + PDWORD pcb +) const +// +// Makes a copy of the stored string into the given buffer +// +{ + _ASSERTE( NULL != pszBuffer ); + _ASSERTE( NULL != pcb ); + + HRESULT hr = S_OK; + DWORD cbNeeded = QueryCB() + sizeof( WCHAR ); + + if( *pcb < cbNeeded ) + { + hr = HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ); + goto Finished; + } + + // + // BUGBUG: StringCchCopy? + // + memcpy( pszBuffer, QueryStr(), cbNeeded ); + +Finished: + + *pcb = cbNeeded; + + return hr; +} + +HRESULT +STRU::CopyToBufferA( + __out_bcount(*pcb) CHAR* pszBuffer, + __inout PDWORD pcb +) const +{ + HRESULT hr = S_OK; + STACK_STRA( straBuffer, 256 ); + hr = straBuffer.CopyW( QueryStr() ); + if ( FAILED( hr ) ) + { + goto Finished; + } + hr = straBuffer.CopyToBuffer( pszBuffer, pcb ); + if ( FAILED( hr ) ) + { + goto Finished; + } +Finished: + return hr; +} + +HRESULT +STRU::SetLen( + __in DWORD cchLen +) +/*++ + * +Routine Description: + + Set the length of the string and null terminate, if there + is sufficient buffer already allocated. Will not reallocate. + +Arguments: + + cchLen - The number of characters in the new string. + +Return Value: + + HRESULT + +--*/ +{ + if( cchLen >= QuerySizeCCH() ) + { + return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); + } + + *( QueryStr() + cchLen ) = L'\0'; + m_cchLen = cchLen; + + return S_OK; +} + +HRESULT +STRU::SafeSnwprintf( + __in PCWSTR pwszFormatString, + ... +) +/*++ + +Routine Description: + + Writes to a STRU, growing it as needed. It arbitrarily caps growth at 64k chars. + +Arguments: + + pwszFormatString - printf format + ... - printf args + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + va_list argsList; + va_start( argsList, pwszFormatString ); + + hr = SafeVsnwprintf(pwszFormatString, argsList); + + va_end( argsList ); + return hr; +} + +HRESULT +STRU::SafeVsnwprintf( + __in PCWSTR pwszFormatString, + va_list argsList +) +/*++ + +Routine Description: + + Writes to a STRU, growing it as needed. It arbitrarily caps growth at 64k chars. + +Arguments: + + pwszFormatString - printf format + argsList - printf va_list + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + int cchOutput; + int cchNeeded; + + // + // Format the incoming message using vsnprintf() + // so that the overflows are captured + // + cchOutput = _vsnwprintf_s( + QueryStr(), + QuerySizeCCH(), + QuerySizeCCH() - 1, + pwszFormatString, + argsList + ); + + if( cchOutput == -1 ) + { + // + // Couldn't fit this in the original STRU size. + // + cchNeeded = _vscwprintf( pwszFormatString, argsList ); + if( cchNeeded > 64 * 1024 ) + { + // + // If we're trying to produce a string > 64k chars, then + // there is probably a problem + // + hr = HRESULT_FROM_WIN32( ERROR_INVALID_DATA ); + goto Finished; + } + + // + // _vscprintf doesn't include terminating null character + // + cchNeeded++; + + hr = Resize( cchNeeded ); + if( FAILED( hr ) ) + { + goto Finished; + } + + cchOutput = _vsnwprintf_s( + QueryStr(), + QuerySizeCCH(), + QuerySizeCCH() - 1, + pwszFormatString, + argsList + ); + if( -1 == cchOutput ) + { + // + // This should never happen, cause we should already have correctly sized memory + // + _ASSERTE( FALSE ); + + hr = HRESULT_FROM_WIN32( ERROR_INVALID_DATA ); + goto Finished; + } + } + + // + // always null terminate at the last WCHAR + // + QueryStr()[ QuerySizeCCH() - 1 ] = L'\0'; + + // + // we directly touched the buffer - therefore: + // + hr = SyncWithBuffer(); + if ( FAILED( hr ) ) + { + goto Finished; + } + +Finished: + + if( FAILED( hr ) ) + { + Reset(); + } + + return hr; +} + +HRESULT +STRU::AuxAppend( + __in_ecount(cNumStrings) + PCWSTR const rgpszStrings[], + SIZE_T cNumStrings +) +/*++ + +Routine Description: + + Appends an array of strings of length cNumStrings + +Arguments: + + rgStrings - The array of strings to be appened + cNumStrings - The count of String + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + size_t cbStringsTotal = sizeof( WCHAR ); // Account for null-terminator + + // + // Compute total size of the string. + // Resize internal buffer + // Copy each array element one by one to backing buffer + // Update backing buffer string length + // + for ( SIZE_T i = 0; i < cNumStrings; i++ ) + { + _ASSERTE( rgpszStrings[ i ] != NULL ); + if ( NULL == rgpszStrings[ i ] ) + { + return E_INVALIDARG; + } + + size_t cbString = 0; + + hr = StringCbLengthW( rgpszStrings[ i ], + STRSAFE_MAX_CCH * sizeof( WCHAR ), + &cbString ); + if ( FAILED( hr ) ) + { + return hr; + } + + cbStringsTotal += cbString; + + if ( cbStringsTotal > MAXDWORD ) + { + return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW ); + } + } + + size_t cbBufSizeRequired = QueryCB() + cbStringsTotal; + if ( cbBufSizeRequired > MAXDWORD ) + { + return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW ); + } + + if( m_Buff.QuerySize() < cbBufSizeRequired ) + { + if( !m_Buff.Resize( cbBufSizeRequired ) ) + { + return E_OUTOFMEMORY; + } + } + + STRSAFE_LPWSTR pszStringEnd = QueryStr() + QueryCCH(); + size_t cchRemaining = QuerySizeCCH() - QueryCCH(); + for ( SIZE_T i = 0; i < cNumStrings; i++ ) + { + hr = StringCchCopyExW( pszStringEnd, // pszDest + cchRemaining, // cchDest + rgpszStrings[ i ], // pszSrc + &pszStringEnd, // ppszDestEnd + &cchRemaining, // pcchRemaining + 0 ); // dwFlags + if ( FAILED( hr ) ) + { + _ASSERTE( FALSE ); + HRESULT hr2 = SyncWithBuffer(); + if ( FAILED( hr2 ) ) + { + return hr2; + } + return hr; + } + } + + m_cchLen = static_cast< DWORD >( cbBufSizeRequired ) / sizeof( WCHAR ) - 1; + + return S_OK; +} + +HRESULT +STRU::AuxAppend( + __in_bcount(cbStr) + const WCHAR* pStr, + SIZE_T cbStr, + DWORD cbOffset +) +/*++ + +Routine Description: + + Appends to the string starting at the (byte) offset cbOffset. + +Arguments: + + pStr - A unicode string to be appended + cbStr - Length, in bytes, of pStr + cbOffset - Offset, in bytes, at which to begin the append + +Return Value: + + HRESULT + +--*/ +{ + _ASSERTE( NULL != pStr ); + _ASSERTE( 0 == cbStr % sizeof( WCHAR ) ); + _ASSERTE( cbOffset <= QueryCB() ); + _ASSERTE( 0 == cbOffset % sizeof( WCHAR ) ); + + ULONGLONG cb64NewSize = (ULONGLONG)cbOffset + cbStr + sizeof( WCHAR ); + if( cb64NewSize > MAXDWORD ) + { + return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW ); + } + + if( m_Buff.QuerySize() < cb64NewSize ) + { + if( !m_Buff.Resize( static_cast(cb64NewSize) ) ) + { + return E_OUTOFMEMORY; + } + } + + memcpy( reinterpret_cast(m_Buff.QueryPtr()) + cbOffset, pStr, cbStr ); + + m_cchLen = (static_cast(cbStr) + cbOffset) / sizeof(WCHAR); + + *( QueryStr() + m_cchLen ) = L'\0'; + + return S_OK; +} + +HRESULT +STRU::AuxAppendA( + __in_bcount(cbStr) + const CHAR* pStr, + SIZE_T cbStr, + DWORD cbOffset, + UINT CodePage +) +/*++ + +Routine Description: + + Convert and append an ANSI string to the string starting at + the (byte) offset cbOffset + +Arguments: + + pStr - An ANSI string to be appended + cbStr - Length, in bytes, of pStr + cbOffset - Offset, in bytes, at which to begin the append + CodePage - code page to use for conversion + +Return Value: + + HRESULT + +--*/ +{ + WCHAR* pszBuffer; + DWORD cchBuffer; + DWORD cchCharsCopied = 0; + + _ASSERTE( NULL != pStr ); + _ASSERTE( cbOffset <= QueryCB() ); + _ASSERTE( 0 == cbOffset % sizeof( WCHAR ) ); + + if ( NULL == pStr ) + { + return E_INVALIDARG; + } + + if( 0 == cbStr ) + { + return S_OK; + } + + // + // Only resize when we have to. When we do resize, we tack on + // some extra space to avoid extra reallocations. + // + if( m_Buff.QuerySize() < (ULONGLONG)cbOffset + (cbStr * sizeof( WCHAR )) + sizeof(WCHAR) ) + { + ULONGLONG cb64NewSize = (ULONGLONG)( cbOffset + cbStr * sizeof(WCHAR) + sizeof( WCHAR ) ); + + // + // Check for the arithmetic overflow + // + if( cb64NewSize > MAXDWORD ) + { + return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW ); + } + + if( !m_Buff.Resize( static_cast(cb64NewSize) ) ) + { + return E_OUTOFMEMORY; + } + } + + pszBuffer = reinterpret_cast(reinterpret_cast(m_Buff.QueryPtr()) + cbOffset); + cchBuffer = ( m_Buff.QuerySize() - cbOffset - sizeof( WCHAR ) ) / sizeof( WCHAR ); + + cchCharsCopied = MultiByteToWideChar( + CodePage, + MB_ERR_INVALID_CHARS, + pStr, + static_cast(cbStr), + pszBuffer, + cchBuffer + ); + if( 0 == cchCharsCopied ) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + + // + // set the new length + // + m_cchLen = cchCharsCopied + cbOffset/sizeof(WCHAR); + + // + // Must be less than, cause still need to add NULL + // + _ASSERTE( m_cchLen < QuerySizeCCH() ); + + // + // append NULL character + // + *(QueryStr() + m_cchLen) = L'\0'; + + return S_OK; +} + + +/*++ + +Routine Description: + + Removes leading and trailing whitespace + +--*/ + +VOID +STRU::Trim() +{ + PWSTR pwszString = QueryStr(); + DWORD cchNewLength = m_cchLen; + DWORD cchLeadingWhitespace = 0; + DWORD cchTempLength = 0; + + for (LONG ixString = m_cchLen - 1; ixString >= 0; ixString--) + { + if (iswspace(pwszString[ixString]) != 0) + { + pwszString[ixString] = L'\0'; + cchNewLength--; + } + else + { + break; + } + } + + cchTempLength = cchNewLength; + for (DWORD ixString = 0; ixString < cchTempLength; ixString++) + { + if (iswspace(pwszString[ixString]) != 0) + { + cchLeadingWhitespace++; + cchNewLength--; + } + else + { + break; + } + } + + if (cchNewLength == 0) + { + + Reset(); + } + else if (cchLeadingWhitespace > 0) + { + memmove(pwszString, pwszString + cchLeadingWhitespace, cchNewLength * sizeof(WCHAR)); + pwszString[cchNewLength] = L'\0'; + } + + SyncWithBuffer(); +} + +/*++ + +Routine Description: + + Compares the string to the provided prefix to check for equality + +Arguments: + + pwszPrefix - wide char string to compare with + fIgnoreCase - indicates whether the string comparison should be case-sensitive + +Return Value: + + TRUE if prefix string matches with internal string, FALSE otherwise + +--*/ + +BOOL +STRU::StartsWith( + __in PCWSTR pwszPrefix, + __in bool fIgnoreCase) const +{ + HRESULT hr = S_OK; + BOOL fMatch = FALSE; + size_t cchPrefix = 0; + + if (pwszPrefix == NULL) + { + goto Finished; + } + + hr = StringCchLengthW( pwszPrefix, + STRSAFE_MAX_CCH, + &cchPrefix ); + if (FAILED(hr)) + { + goto Finished; + } + + _ASSERTE( cchPrefix <= MAXLONG ); + + if (cchPrefix > m_cchLen) + { + goto Finished; + } + + #if defined( NTDDI_VERSION ) && NTDDI_VERSION >= NTDDI_LONGHORN + + fMatch = ( CSTR_EQUAL == CompareStringOrdinal( QueryStr(), + (int)cchPrefix, + pwszPrefix, + (int)cchPrefix, + fIgnoreCase ) ); + #else + + if( fIgnoreCase ) + { + fMatch = ( 0 == _wcsnicmp( QueryStr(), pwszPrefix, cchPrefix ) ); + } + else + { + fMatch = ( 0 == wcsncmp( QueryStr(), pwszPrefix, cchPrefix ) ); + } + + #endif + +Finished: + + return fMatch; +} + +/*++ + +Routine Description: + + Compares the string to the provided suffix to check for equality + +Arguments: + + pwszSuffix - wide char string to compare with + fIgnoreCase - indicates whether the string comparison should be case-sensitive + +Return Value: + + TRUE if suffix string matches with internal string, FALSE otherwise + +--*/ + + +BOOL +STRU::EndsWith( + __in PCWSTR pwszSuffix, + __in bool fIgnoreCase) const +{ + HRESULT hr = S_OK; + PWSTR pwszString = QueryStr(); + BOOL fMatch = FALSE; + size_t cchSuffix = 0; + ptrdiff_t ixOffset = 0; + + if (pwszSuffix == NULL) + { + goto Finished; + } + + hr = StringCchLengthW( pwszSuffix, + STRSAFE_MAX_CCH, + &cchSuffix ); + if (FAILED(hr)) + { + goto Finished; + } + + _ASSERTE( cchSuffix <= MAXLONG ); + + if (cchSuffix > m_cchLen) + { + goto Finished; + } + + ixOffset = m_cchLen - cchSuffix; + _ASSERTE(ixOffset >= 0 && ixOffset <= MAXDWORD); + + #if defined( NTDDI_VERSION ) && NTDDI_VERSION >= NTDDI_LONGHORN + + fMatch = ( CSTR_EQUAL == CompareStringOrdinal( pwszString + ixOffset, + (int)cchSuffix, + pwszSuffix, + (int)cchSuffix, + fIgnoreCase ) ); + #else + + if( fIgnoreCase ) + { + fMatch = ( 0 == _wcsnicmp( pwszString + ixOffset, pwszSuffix, cchSuffix ) ); + } + else + { + fMatch = ( 0 == wcsncmp( pwszString + ixOffset, pwszSuffix, cchSuffix ) ); + } + + #endif + +Finished: + + return fMatch; +} + +/*++ + +Routine Description: + + Searches the string for the first occurrence of the specified character. + +Arguments: + + charValue - character to find + dwStartIndex - the initial index. + +Return Value: + + The index for the first character occurence in the string. + + -1 if not found. + +--*/ +INT +STRU::IndexOf( + __in WCHAR charValue, + __in DWORD dwStartIndex + ) const +{ + INT nIndex = -1; + + // Make sure that there are no buffer overruns. + if( dwStartIndex >= QueryCCH() ) + { + goto Finished; + } + + const WCHAR* pwChar = wcschr( QueryStr() + dwStartIndex, charValue ); + + // Determine the index if found + if( pwChar ) + { + // nIndex will be set to -1 on failure. + (VOID)SizeTToInt( pwChar - QueryStr(), &nIndex ); + } + +Finished: + + return nIndex; +} + + +/*++ + +Routine Description: + + Searches the string for the first occurrence of the specified substring. + +Arguments: + + pwszValue - substring to find + dwStartIndex - initial index. + +Return Value: + + The index for the first character occurence in the string. + + -1 if not found. + +--*/ +INT +STRU::IndexOf( + __in PCWSTR pwszValue, + __in DWORD dwStartIndex + ) const +{ + HRESULT hr = S_OK; + INT nIndex = -1; + SIZE_T cchValue = 0; + + // Validate input parameters + if( dwStartIndex >= QueryCCH() || !pwszValue ) + { + goto Finished; + } + + const WCHAR* pwChar = wcsstr( QueryStr() + dwStartIndex, pwszValue ); + + // Determine the index if found + if( pwChar ) + { + // nIndex will be set to -1 on failure. + (VOID)SizeTToInt( pwChar - QueryStr(), &nIndex ); + } + +Finished: + + return nIndex; +} + + +/*++ + +Routine Description: + + Searches the string for the last occurrence of the specified character. + +Arguments: + + charValue - character to find + dwStartIndex - initial index. + +Return Value: + + The index for the last character occurence in the string. + + -1 if not found. + +--*/ +INT +STRU::LastIndexOf( + __in WCHAR charValue, + __in DWORD dwStartIndex + ) const +{ + INT nIndex = -1; + + // Make sure that there are no buffer overruns. + if( dwStartIndex >= QueryCCH() ) + { + goto Finished; + } + + const WCHAR* pwChar = wcsrchr( QueryStr() + dwStartIndex, charValue ); + + // Determine the index if found + if( pwChar ) + { + // nIndex will be set to -1 on failure. + (VOID)SizeTToInt( pwChar - QueryStr(), &nIndex ); + } + +Finished: + + return nIndex; +} + +//static +HRESULT +STRU::ExpandEnvironmentVariables( + __in PCWSTR pszString, + __out STRU * pstrExpandedString + ) +/*++ + +Routine Description: + + Expand the environment variables in a string + +Arguments: + + pszString - String with environment variables to expand + pstrExpandedString - Receives expanded string on success + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + DWORD cchNewSize = 0; + + if ( pszString == NULL || + pstrExpandedString == NULL ) + { + DBG_ASSERT( FALSE ); + hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); + goto Exit; + } + + cchNewSize = ExpandEnvironmentStrings( pszString, + pstrExpandedString->QueryStr(), + pstrExpandedString->QuerySizeCCH() ); + if ( cchNewSize == 0 ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Exit; + } + + if ( cchNewSize > pstrExpandedString->QuerySizeCCH() ) + { + hr = pstrExpandedString->Resize( + ( cchNewSize + 1 ) * sizeof( WCHAR ) + ); + if ( FAILED( hr ) ) + { + goto Exit; + } + + cchNewSize = ExpandEnvironmentStrings( + pszString, + pstrExpandedString->QueryStr(), + pstrExpandedString->QuerySizeCCH() + ); + + if ( cchNewSize == 0 || + cchNewSize > pstrExpandedString->QuerySizeCCH() ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Exit; + } + } + + pstrExpandedString->SyncWithBuffer(); + + hr = S_OK; + +Exit: + + return hr; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/ulparse.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/ulparse.cxx new file mode 100644 index 0000000000..69b42e6250 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/ulparse.cxx @@ -0,0 +1,1416 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +// +// BUGBUG: Turn off optimization on ia64 builds due to a compiler bug +// +#if (defined(_M_IA64) && (_MSC_FULL_VER == 13009286)) +#pragma optimize("",off) +#endif + +#define LF 0x0A +#define SP 0x20 +#define HT 0x09 + +#define HTTP_CHAR 0x001 +#define HTTP_UPCASE 0x002 +#define HTTP_LOCASE 0x004 +#define HTTP_ALPHA (HTTP_UPCASE | HTTP_LOCASE) +#define HTTP_DIGIT 0x008 +#define HTTP_CTL 0x010 +#define HTTP_LWS 0x020 +#define HTTP_HEX 0x040 +#define HTTP_SEPERATOR 0x080 +#define HTTP_TOKEN 0x100 + +#define URL_LEGAL 0x200 +#define URL_TOKEN (HTTP_ALPHA | HTTP_DIGIT | URL_LEGAL) + +#define IS_HTTP_UPCASE(c) (HttpChars[(UCHAR)(c)] & HTTP_UPCASE) +#define IS_HTTP_LOCASE(c) (HttpChars[(UCHAR)(c)] & HTTP_UPCASE) +#define IS_HTTP_ALPHA(c) (HttpChars[(UCHAR)(c)] & HTTP_ALPHA) +#define IS_HTTP_DIGIT(c) (HttpChars[(UCHAR)(c)] & HTTP_DIGIT) +#define IS_HTTP_HEX(c) (HttpChars[(UCHAR)(c)] & HTTP_HEX) +#define IS_HTTP_CTL(c) (HttpChars[(UCHAR)(c)] & HTTP_CTL) +#define IS_HTTP_LWS(c) (HttpChars[(UCHAR)(c)] & HTTP_LWS) +#define IS_HTTP_SEPERATOR(c) (HttpChars[(UCHAR)(c)] & HTTP_SEPERATOR) +#define IS_HTTP_TOKEN(c) (HttpChars[(UCHAR)(c)] & HTTP_TOKEN) +#define IS_URL_TOKEN(c) (HttpChars[(UCHAR)(c)] & URL_TOKEN) + +// Some stuff not defined in VS SDK +#ifndef NT_SUCCESS +#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) +#endif + +// Copied from ntstatus.h, otherwise we will have double definition for +// number of macros that are both in ntstatus.h and winnt.h +#ifndef STATUS_SUCCESS +#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) // ntsubauth +#endif +#ifndef STATUS_OBJECT_PATH_SYNTAX_BAD +#define STATUS_OBJECT_PATH_SYNTAX_BAD ((NTSTATUS)0xC000003BL) +#endif +#ifndef STATUS_OBJECT_PATH_INVALID +#define STATUS_OBJECT_PATH_INVALID ((NTSTATUS)0xC0000039L) +#endif +// +// Constant Declarations for UTF8 Encoding +// + +#define ASCII 0x007f + +#define UTF8_2_MAX 0x07ff // max UTF8 2-byte sequence (32 * 64 =2048) +#define UTF8_1ST_OF_2 0xc0 // 110x xxxx +#define UTF8_1ST_OF_3 0xe0 // 1110 xxxx +#define UTF8_1ST_OF_4 0xf0 // 1111 xxxx +#define UTF8_TRAIL 0x80 // 10xx xxxx + +#define HIGHER_6_BIT(u) ((u) >> 12) +#define MIDDLE_6_BIT(u) (((u) & 0x0fc0) >> 6) +#define LOWER_6_BIT(u) ((u) & 0x003f) + +#define BIT7(a) ((a) & 0x80) +#define BIT6(a) ((a) & 0x40) + +#define HIGH_SURROGATE_START 0xd800 +#define HIGH_SURROGATE_END 0xdbff +#define LOW_SURROGATE_START 0xdc00 +#define LOW_SURROGATE_END 0xdfff + +#define EMIT_CHAR(ch) \ + do { \ + pDest[0] = (ch); \ + pDest += 1; \ + BytesCopied += 2; \ + } while (0) + +typedef enum _URL_TYPE +{ + UrlTypeUtf8, + UrlTypeAnsi, + UrlTypeDbcs +} URL_TYPE; + +typedef enum _URL_PART +{ + Scheme, + HostName, + AbsPath, + QueryString + +} URL_PART; + +#define IS_UTF8_TRAILBYTE(ch) (((ch) & 0xc0) == 0x80) + +// +// These are copied from RTL NLS routines. +// + +#define DBCS_TABLE_SIZE 256 +extern PUSHORT NlsLeadByteInfo; + +#define LeadByteTable (*(PUSHORT *)NlsLeadByteInfo) +#define IS_LEAD_BYTE(c) (IsDBCSLeadByte(c)) + +ULONG HttpChars[256]; +USHORT FastPopChars[256]; +USHORT DummyPopChars[256]; +WCHAR FastUpcaseChars[256]; +BOOL g_UlEnableNonUTF8; +BOOL g_UlEnableDBCS; +BOOL g_UlFavorDBCS; + +// RtlNtStatusToDosError is nowhere defined, should be used through +// native code "reflection" +typedef ULONG (RTL_NT_STATUS_TO_DOS_ERROR_PROC)(NTSTATUS); +static RTL_NT_STATUS_TO_DOS_ERROR_PROC* rtlNtStatusToDosErrorProc = NULL; +static HMODULE lib = NULL; + +HRESULT +WIN32_FROM_NTSTATUS( + __in NTSTATUS status, + __out DWORD * pResult + ) +{ + HRESULT hr = S_OK; + if (pResult == NULL) + { + hr = E_INVALIDARG; + goto Finished; + } + if (lib == NULL) + { + lib = GetModuleHandle(L"Ntdll.dll"); + if (lib == NULL) + { + hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + goto Finished; + } + } + if (rtlNtStatusToDosErrorProc == NULL) + { + rtlNtStatusToDosErrorProc = + (RTL_NT_STATUS_TO_DOS_ERROR_PROC*)GetProcAddress( + lib, "RtlNtStatusToDosError"); + if (rtlNtStatusToDosErrorProc == NULL) + { + hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + goto Finished; + } + } + *pResult = rtlNtStatusToDosErrorProc(status); + +Finished: + return hr; +} + +NTSTATUS +Unescape( + IN PUCHAR pChar, + OUT PUCHAR pOutChar + ) + +{ + UCHAR Result, Digit; + + if (pChar[0] != '%' || + SAFEIsXDigit(pChar[1]) == FALSE || + SAFEIsXDigit(pChar[2]) == FALSE) + { + return STATUS_OBJECT_PATH_SYNTAX_BAD; + } + + // + // HexToChar() inlined + // + + // uppercase #1 + // + if (SAFEIsAlpha(pChar[1])) + Digit = (UCHAR) toupper(pChar[1]); + else + Digit = pChar[1]; + + Result = ((Digit >= 'A') ? (Digit - 'A' + 0xA) : (Digit - '0')) << 4; + + // uppercase #2 + // + if (SAFEIsAlpha(pChar[2])) + Digit = (UCHAR) toupper(pChar[2]); + else + Digit = pChar[2]; + + Result |= (Digit >= 'A') ? (Digit - 'A' + 0xA) : (Digit - '0'); + + *pOutChar = Result; + + return STATUS_SUCCESS; + +} // Unescape + +// +// PopChar is used only if the string is not UTF-8, or UrlPart != QueryString, +// or the current character is '%' or its high bit is set. In all other cases, +// the FastPopChars table is used for fast conversion. +// + +__inline +NTSTATUS +PopChar( + IN URL_TYPE UrlType, + IN URL_PART UrlPart, + __in LPSTR pChar, + __out WCHAR * pUnicodeChar, + __out WCHAR * pUnicodeChar2, + OUT PULONG pCharToSkip + ) +{ + NTSTATUS Status; + WCHAR UnicodeChar = L'\0'; + WCHAR UnicodeChar2 = L'\0'; + UCHAR Char; + UCHAR Trail1; + UCHAR Trail2; + UCHAR Trail3; + ULONG CharToSkip; + + // + // validate it as a valid url character + // + + if (UrlPart != QueryString) + { + if (IS_URL_TOKEN((UCHAR)pChar[0]) == FALSE) + { + Status = STATUS_OBJECT_PATH_SYNTAX_BAD; + goto end; + } + } + else + { + // + // Allow anything but linefeed in the query string. + // + + if (pChar[0] == LF) + { + Status = STATUS_OBJECT_PATH_SYNTAX_BAD; + goto end; + } + + UnicodeChar = (USHORT) (UCHAR)pChar[0]; + CharToSkip = 1; + + // skip all the decoding stuff + goto slash; + } + + // + // need to unescape ? + // + // can't decode the query string. that would be lossy decodeing + // as '=' and '&' characters might be encoded, but have meaning + // to the usermode parser. + // + + if (pChar[0] == '%') + { + Status = Unescape((PUCHAR)pChar, &Char); + if (NT_SUCCESS(Status) == FALSE) + goto end; + CharToSkip = 3; + } + else + { + Char = pChar[0]; + CharToSkip = 1; + } + + if (UrlType == UrlTypeUtf8) + { + // + // convert to unicode, checking for utf8 . + // + // 3 byte runs are the largest we can have. 16 bits in UCS-2 = + // 3 bytes of (4+4,2+6,2+6) where it's code + char. + // for a total of 6+6+4 char bits = 16 bits. + // + + // + // NOTE: we'll only bother to decode utf if it was escaped + // thus the (CharToSkip == 3) + // + if ((CharToSkip == 3) && ((Char & 0xf8) == 0xf0)) + { + // 4 byte run + // + + // Unescape the next 3 trail bytes + // + + Status = Unescape((PUCHAR)pChar+CharToSkip, &Trail1); + if (NT_SUCCESS(Status) == FALSE) + goto end; + + CharToSkip += 3; // %xx + + Status = Unescape((PUCHAR)pChar+CharToSkip, &Trail2); + if (NT_SUCCESS(Status) == FALSE) + goto end; + + CharToSkip += 3; // %xx + + Status = Unescape((PUCHAR)pChar+CharToSkip, &Trail3); + if (NT_SUCCESS(Status) == FALSE) + goto end; + + CharToSkip += 3; // %xx + + if (IS_UTF8_TRAILBYTE(Trail1) == FALSE || + IS_UTF8_TRAILBYTE(Trail2) == FALSE || + IS_UTF8_TRAILBYTE(Trail3) == FALSE) + { + // bad utf! + // + Status = STATUS_OBJECT_PATH_SYNTAX_BAD; + goto end; + } + + // handle four byte case - convert to utf-16 + // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + + UnicodeChar = ((USHORT) ((Char & 0x07) << 8) | + ((Trail1 & 0x3f) << 2) | + ((Trail2 & 0x30) >> 4)) + 0xD7C0; + UnicodeChar2 = ((USHORT) ((Trail2 & 0x0f) << 6) | + (Trail3 & 0x3f)) | 0xDC00; + } + else if ((CharToSkip == 3) && ((Char & 0xf0) == 0xe0)) + { + // 3 byte run + // + + // Unescape the next 2 trail bytes + // + + Status = Unescape((PUCHAR)pChar+CharToSkip, &Trail1); + if (NT_SUCCESS(Status) == FALSE) + goto end; + + CharToSkip += 3; // %xx + + Status = Unescape((PUCHAR)pChar+CharToSkip, &Trail2); + if (NT_SUCCESS(Status) == FALSE) + goto end; + + CharToSkip += 3; // %xx + + if (IS_UTF8_TRAILBYTE(Trail1) == FALSE || + IS_UTF8_TRAILBYTE(Trail2) == FALSE) + { + // bad utf! + // + Status = STATUS_OBJECT_PATH_SYNTAX_BAD; + goto end; + } + + // handle three byte case + // 1110xxxx 10xxxxxx 10xxxxxx + + UnicodeChar = (USHORT) (((Char & 0x0f) << 12) | + ((Trail1 & 0x3f) << 6) | + (Trail2 & 0x3f)); + + } + else if ((CharToSkip == 3) && ((Char & 0xe0) == 0xc0)) + { + // 2 byte run + // + + // Unescape the next 1 trail byte + // + + Status = Unescape((PUCHAR)pChar+CharToSkip, &Trail1); + if (NT_SUCCESS(Status) == FALSE) + goto end; + + CharToSkip += 3; // %xx + + if (IS_UTF8_TRAILBYTE(Trail1) == FALSE) + { + // bad utf! + // + Status = STATUS_OBJECT_PATH_SYNTAX_BAD; + goto end; + } + + // handle two byte case + // 110xxxxx 10xxxxxx + + UnicodeChar = (USHORT) (((Char & 0x1f) << 6) | + (Trail1 & 0x3f)); + + } + + // now this can either be unescaped high-bit (bad) + // or escaped high-bit. (also bad) + // + // thus not checking CharToSkip + // + + else if ((Char & 0x80) == 0x80) + { + // high bit set ! bad utf! + // + Status = STATUS_OBJECT_PATH_SYNTAX_BAD; + goto end; + + } + // + // Normal character (again either escaped or unescaped) + // + else + { + // + // Simple conversion to unicode, it's 7-bit ascii. + // + + UnicodeChar = (USHORT)Char; + } + + } + else // UrlType != UrlTypeUtf8 + { + UCHAR AnsiChar[2]; + ULONG AnsiCharSize; + + // + // Convert ANSI character to Unicode. + // If the UrlType is UrlTypeDbcs, then we may have + // a DBCS lead/trail pair. + // + + if (UrlType == UrlTypeDbcs && IS_LEAD_BYTE(Char)) + { + UCHAR SecondByte; + + // + // This is a double-byte character. + // + + SecondByte = *(pChar+CharToSkip); + + AnsiCharSize = 2; + AnsiChar[0] = Char; + + if (SecondByte == '%') + { + Status = Unescape((PUCHAR)pChar+CharToSkip, &AnsiChar[1]); + if (!NT_SUCCESS(Status)) + { + goto end; + } + + CharToSkip += 3; // %xx + } + else + { + AnsiChar[1] = SecondByte; + CharToSkip += 1; + } + + } + else + { + // + // This is a single-byte character. + // + + AnsiCharSize = 1; + AnsiChar[0] = Char; + + } + /* + Status = RtlMultiByteToUnicodeN( + &UnicodeChar, + sizeof(WCHAR), + NULL, + (PCHAR) &AnsiChar[0], + AnsiCharSize + ); + */ + Status = MultiByteToWideChar( + CP_ACP, + 0, + (PCHAR) &AnsiChar[0], + AnsiCharSize, + &UnicodeChar, + sizeof(WCHAR) + ); + + if (!NT_SUCCESS(Status)) + { + goto end; + } + } + + +slash: + // + // turn backslashes into forward slashes + // + + if (UrlPart != QueryString && UnicodeChar == L'\\') + { + UnicodeChar = L'/'; + } + else if (UnicodeChar == UNICODE_NULL) + { + // + // we pop'd a NULL. bad! + // + Status = STATUS_OBJECT_PATH_SYNTAX_BAD; + goto end; + } + + *pCharToSkip = CharToSkip; + *pUnicodeChar = UnicodeChar; + *pUnicodeChar2 = UnicodeChar2; + + Status = STATUS_SUCCESS; + +end: + return Status; + +} // PopChar + + +// +// Private constants. +// + +#define ACTION_NOTHING 0x00000000 +#define ACTION_EMIT_CH 0x00010000 +#define ACTION_EMIT_DOT_CH 0x00020000 +#define ACTION_EMIT_DOT_DOT_CH 0x00030000 +#define ACTION_BACKUP 0x00040000 +#define ACTION_MASK 0xFFFF0000 + +// +// Private globals +// + +// +// this table says what to do based on the current state and the current +// character +// +ULONG pActionTable[16] = +{ + // + // state 0 = fresh, seen nothing exciting yet + // + ACTION_EMIT_CH, // other = emit it state = 0 + ACTION_EMIT_CH, // "." = emit it state = 0 + ACTION_NOTHING, // EOS = normal finish state = 4 + ACTION_EMIT_CH, // "/" = we saw the "/", emit it state = 1 + + // + // state 1 = we saw a "/" ! + // + ACTION_EMIT_CH, // other = emit it, state = 0 + ACTION_NOTHING, // "." = eat it, state = 2 + ACTION_NOTHING, // EOS = normal finish state = 4 + ACTION_NOTHING, // "/" = extra slash, eat it, state = 1 + + // + // state 2 = we saw a "/" and ate a "." ! + // + ACTION_EMIT_DOT_CH, // other = emit the dot we ate. state = 0 + ACTION_NOTHING, // "." = eat it, a .. state = 3 + ACTION_NOTHING, // EOS = normal finish state = 4 + ACTION_NOTHING, // "/" = we ate a "/./", swallow it state = 1 + + // + // state 3 = we saw a "/" and ate a ".." ! + // + ACTION_EMIT_DOT_DOT_CH, // other = emit the "..". state = 0 + ACTION_EMIT_DOT_DOT_CH, // "." = 3 dots, emit the ".." state = 0 + ACTION_BACKUP, // EOS = we have a "/..\0", backup! state = 4 + ACTION_BACKUP // "/" = we have a "/../", backup! state = 1 +}; + +// +// this table says which newstate to be in given the current state and the +// character we saw +// +ULONG pNextStateTable[16] = +{ + // state 0 + 0 , // other + 0 , // "." + 4 , // EOS + 1 , // "\" + + // state 1 + 0 , // other + 2 , // "." + 4 , // EOS + 1 , // "\" + + // state 2 + 0 , // other + 3 , // "." + 4 , // EOS + 1 , // "\" + + // state 3 + 0 , // other + 0 , // "." + 4 , // EOS + 1 // "\" +}; + +// +// this says how to index into pNextStateTable given our current state. +// +// since max states = 4, we calculate the index by multiplying with 4. +// +#define IndexFromState( st) ( (st) * 4) + + +/***************************************************************************++ + +Routine Description: + + This function can be told to clean up UTF-8, ANSI, or DBCS URLs. + + Unescape + Convert backslash to forward slash + Remove double slashes (empty directiories names) - e.g. // or \\ + Handle /./ + Handle /../ + Convert to unicode + computes the case insensitive hash + +Arguments: + + +Return Value: + + NTSTATUS - Completion status. + + +--***************************************************************************/ +NTSTATUS +UlpCleanAndCopyUrlByType( + IN URL_TYPE UrlType, + IN URL_PART UrlPart, + __inout PWSTR pDestination, + __in_ecount(SourceLength) LPSTR pSource, + IN ULONG SourceLength, + OUT PULONG pBytesCopied, + __deref_opt_out_opt PWSTR * ppQueryString + ) +{ + NTSTATUS Status; + PWSTR pDest; + PUCHAR pChar; + ULONG CharToSkip; + ULONG BytesCopied; + PWSTR pQueryString; + ULONG StateIndex; + WCHAR UnicodeChar; + WCHAR UnicodeChar2 = L'\0'; + BOOLEAN MakeCanonical; + PUSHORT pFastPopChar; + + pDest = pDestination; + pQueryString = NULL; + BytesCopied = 0; + + pChar = (PUCHAR)pSource; + CharToSkip = 0; + + StateIndex = 0; + + MakeCanonical = (UrlPart == AbsPath) ? TRUE : FALSE; + + if (UrlType == UrlTypeUtf8 && UrlPart != QueryString) + { + pFastPopChar = FastPopChars; + } + else + { + pFastPopChar = DummyPopChars; + } + + while (SourceLength > 0) + { + // + // advance ! it's at the top of the loop to enable ANSI_NULL to + // come through ONCE + // + + pChar += CharToSkip; + SourceLength -= CharToSkip; + + // + // well? have we hit the end? + // + + if (SourceLength == 0) + { + UnicodeChar = UNICODE_NULL; + UnicodeChar2 = UNICODE_NULL; + } + else + { + // + // Nope. Peek briefly to see if we hit the query string + // + + if (UrlPart == AbsPath && pChar[0] == '?') + { + DBG_ASSERT(pQueryString == NULL); + + // + // remember it's location + // + + pQueryString = pDest; + + // + // let it fall through ONCE to the canonical + // in order to handle a trailing "/.." like + // "http://hostname:80/a/b/..?v=1&v2" + // + + UnicodeChar = L'?'; + UnicodeChar2 = UNICODE_NULL; + CharToSkip = 1; + + // + // now we are cleaning the query string + // + + UrlPart = QueryString; + + // + // cannot use fast path for PopChar anymore + // + + pFastPopChar = DummyPopChars; + } + else + { + USHORT NextUnicodeChar = pFastPopChar[*pChar]; + + // + // Grab the next character. Try to be fast for the + // normal character case. Otherwise call PopChar. + // + + if (NextUnicodeChar == 0) + { + Status = PopChar( + UrlType, + UrlPart, + (LPSTR)pChar, + &UnicodeChar, + &UnicodeChar2, + &CharToSkip + ); + + if (NT_SUCCESS(Status) == FALSE) + goto end; + } + else + { +#if DBG + Status = PopChar( + UrlType, + UrlPart, + (LPSTR)pChar, + &UnicodeChar, + &UnicodeChar2, + &CharToSkip + ); + + DBG_ASSERT(NT_SUCCESS(Status)); + DBG_ASSERT(UnicodeChar == NextUnicodeChar); + DBG_ASSERT(CharToSkip == 1); +#endif + UnicodeChar = NextUnicodeChar; + UnicodeChar2 = UNICODE_NULL; + CharToSkip = 1; + } + } + } + + if (MakeCanonical) + { + // + // now use the state machine to make it canonical . + // + + // + // from the old value of StateIndex, figure out our new base StateIndex + // + StateIndex = IndexFromState(pNextStateTable[StateIndex]); + + // + // did we just hit the query string? this will only happen once + // that we take this branch after hitting it, as we stop + // processing after hitting it. + // + + if (UrlPart == QueryString) + { + // + // treat this just like we hit a NULL, EOS. + // + + StateIndex += 2; + } + else + { + // + // otherwise based the new state off of the char we + // just popped. + // + + switch (UnicodeChar) + { + case UNICODE_NULL: StateIndex += 2; break; + case L'.': StateIndex += 1; break; + case L'/': StateIndex += 3; break; + default: StateIndex += 0; break; + } + } + + } + else + { + StateIndex = (UnicodeChar == UNICODE_NULL) ? 2 : 0; + } + + // + // Perform the action associated with the state. + // + + switch (pActionTable[StateIndex]) + { + case ACTION_EMIT_DOT_DOT_CH: + + EMIT_CHAR(L'.'); + + // fall through + + case ACTION_EMIT_DOT_CH: + + EMIT_CHAR(L'.'); + + // fall through + + case ACTION_EMIT_CH: + + EMIT_CHAR(UnicodeChar); + if (UnicodeChar2 != UNICODE_NULL) + { + EMIT_CHAR(UnicodeChar2); + } + + // fall through + + case ACTION_NOTHING: + break; + + case ACTION_BACKUP: + + // + // pDest currently points 1 past the last '/'. backup over it and + // find the preceding '/', set pDest to 1 past that one. + // + + // + // backup to the '/' + // + + pDest -= 1; + BytesCopied -= 2; + + DBG_ASSERT(pDest[0] == L'/'); + + // + // are we at the start of the string? that's bad, can't go back! + // + + if (pDest == pDestination) + { + DBG_ASSERT(BytesCopied == 0); + Status = STATUS_OBJECT_PATH_INVALID; + goto end; + } + + // + // back up over the '/' + // + + pDest -= 1; + BytesCopied -= 2; + + DBG_ASSERT(pDest > pDestination); + + // + // now find the previous slash + // + + while (pDest > pDestination && pDest[0] != L'/') + { + pDest -= 1; + BytesCopied -= 2; + } + + // + // we already have a slash, so don't have to store 1. + // + + DBG_ASSERT(pDest[0] == L'/'); + + // + // simply skip it, as if we had emitted it just now + // + + pDest += 1; + BytesCopied += 2; + + break; + + default: + DBG_ASSERT(!"http!UlpCleanAndCopyUrl: Invalid action code in state table!"); + Status = STATUS_OBJECT_PATH_SYNTAX_BAD; + goto end; + } + + // + // Just hit the query string ? + // + + if (MakeCanonical && UrlPart == QueryString) + { + // + // Stop canonical processing + // + + MakeCanonical = FALSE; + + // + // Need to emit the '?', it wasn't emitted above + // + + DBG_ASSERT(pActionTable[StateIndex] != ACTION_EMIT_CH); + + EMIT_CHAR(L'?'); + + } + + } + + // + // terminate the string, it hasn't been done in the loop + // + + DBG_ASSERT((pDest-1)[0] != UNICODE_NULL); + + pDest[0] = UNICODE_NULL; + *pBytesCopied = BytesCopied; + + if (ppQueryString != NULL) + { + *ppQueryString = pQueryString; + } + + Status = STATUS_SUCCESS; + + +end: + return Status; + +} // UlpCleanAndCopyUrlByType + + +/***************************************************************************++ + +Routine Description: + + + Unescape + Convert backslash to forward slash + Remove double slashes (empty directiories names) - e.g. // or \\ + Handle /./ + Handle /../ + Convert to unicode + +Arguments: + +Return Value: + + HRESULT + + +--***************************************************************************/ +HRESULT +UlCleanAndCopyUrl( + __in LPSTR pSource, + IN ULONG SourceLength, + OUT PULONG pBytesCopied, + __inout PWSTR pDestination, + __deref_opt_out_opt PWSTR * ppQueryString OPTIONAL + ) +{ + NTSTATUS Status; + URL_TYPE AnsiUrlType = g_UlEnableDBCS ? UrlTypeDbcs : UrlTypeAnsi; + + if (!g_UlEnableNonUTF8) + { + // + // Only accept UTF-8 URLs. + // + + Status = UlpCleanAndCopyUrlByType( + UrlTypeUtf8, + AbsPath, + pDestination, + pSource, + SourceLength, + pBytesCopied, + ppQueryString + ); + + } + else if (!g_UlFavorDBCS) + { + // + // The URL may be either UTF-8 or ANSI. First + // try UTF-8, and if that fails go for ANSI. + // + + Status = UlpCleanAndCopyUrlByType( + UrlTypeUtf8, + AbsPath, + pDestination, + pSource, + SourceLength, + pBytesCopied, + ppQueryString + ); + + if (!NT_SUCCESS(Status)) + { + Status = UlpCleanAndCopyUrlByType( + AnsiUrlType, + AbsPath, + pDestination, + pSource, + SourceLength, + pBytesCopied, + ppQueryString + ); + + } + + } + else + { + // + // The URL may be either ANSI or UTF-8. First + // try the ANSI interpretation, and if that fails + // go for UTF-8. + // + Status = UlpCleanAndCopyUrlByType( + AnsiUrlType, + AbsPath, + pDestination, + pSource, + SourceLength, + pBytesCopied, + ppQueryString + ); + + if (!NT_SUCCESS(Status)) + { + Status = UlpCleanAndCopyUrlByType( + UrlTypeUtf8, + AbsPath, + pDestination, + pSource, + SourceLength, + pBytesCopied, + ppQueryString + ); + + } + } + + // + // Convert NTSTATUS to HRESULT + // + + if ( Status == STATUS_SUCCESS ) + { + return S_OK; + } + else + { + DWORD dwErr = 0; + if (SUCCEEDED(WIN32_FROM_NTSTATUS( Status, &dwErr ))) + { + return HRESULT_FROM_WIN32( dwErr ); + } + else + { + return Status; + } + } +} + +HRESULT +UlInitializeParsing( + VOID +) +{ + ULONG i; + UCHAR c; + HKEY hKey; + DWORD dwType; + DWORD dwData; + DWORD cbData; + + // + // First read the HTTP registry settings on how to handle URLs + // + + g_UlEnableNonUTF8 = TRUE; + g_UlEnableDBCS = FALSE; + g_UlFavorDBCS = FALSE; + + if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, + L"System\\CurrentControlSet\\Services\\http\\Parameters", + 0, + KEY_READ, + &hKey ) == ERROR_SUCCESS ) + { + cbData = sizeof( dwData ); + + if ( RegQueryValueEx( hKey, + L"EnableNonUTF8", + NULL, + &dwType, + (LPBYTE) &dwData, + &cbData ) == ERROR_SUCCESS && + dwType == REG_DWORD ) + { + g_UlEnableNonUTF8 = !!dwData; + } + + cbData = sizeof( dwData ); + + if ( g_UlEnableNonUTF8 ) + { + if ( RegQueryValueEx( hKey, + L"EnableDBCS", + NULL, + &dwType, + (LPBYTE) &dwData, + &cbData ) == ERROR_SUCCESS && + dwType == REG_DWORD ) + { + g_UlEnableDBCS = !!dwData; + } + } + else + { + g_UlEnableDBCS = FALSE; + } + + cbData = sizeof( dwData ); + + if ( g_UlEnableDBCS ) + { + if ( RegQueryValueEx( hKey, + L"FavorDBCS", + NULL, + &dwType, + (LPBYTE) &dwData, + &cbData ) == ERROR_SUCCESS && + dwType == REG_DWORD ) + { + g_UlFavorDBCS = !!dwData; + } + } + else + { + g_UlFavorDBCS = FALSE; + } + + RegCloseKey( hKey ); + } + + + // Initialize the HttpChars array appropriately. + + for (i = 0; i < 128; i++) + { + HttpChars[i] = HTTP_CHAR; + } + + for (i = 'A'; i <= 'Z'; i++) + { + HttpChars[i] |= HTTP_UPCASE; + } + + for (i = 'a'; i <= 'z'; i++) + { + HttpChars[i] |= HTTP_LOCASE; + } + + for (i = '0'; i <= '9'; i++) + { + HttpChars[i] |= (HTTP_DIGIT | HTTP_HEX); + } + + + for (i = 0; i <= 31; i++) + { + HttpChars[i] |= HTTP_CTL; + } + + HttpChars[127] |= HTTP_CTL; + + HttpChars[SP] |= HTTP_LWS; + HttpChars[HT] |= HTTP_LWS; + + + for (i = 'A'; i <= 'F'; i++) + { + HttpChars[i] |= HTTP_HEX; + } + + for (i = 'a'; i <= 'f'; i++) + { + HttpChars[i] |= HTTP_HEX; + } + + HttpChars['('] |= HTTP_SEPERATOR; + HttpChars[')'] |= HTTP_SEPERATOR; + HttpChars['<'] |= HTTP_SEPERATOR; + HttpChars['>'] |= HTTP_SEPERATOR; + HttpChars['@'] |= HTTP_SEPERATOR; + HttpChars[','] |= HTTP_SEPERATOR; + HttpChars[';'] |= HTTP_SEPERATOR; + HttpChars[':'] |= HTTP_SEPERATOR; + HttpChars['\\'] |= HTTP_SEPERATOR; + HttpChars['"'] |= HTTP_SEPERATOR; + HttpChars['/'] |= HTTP_SEPERATOR; + HttpChars['['] |= HTTP_SEPERATOR; + HttpChars[']'] |= HTTP_SEPERATOR; + HttpChars['?'] |= HTTP_SEPERATOR; + HttpChars['='] |= HTTP_SEPERATOR; + HttpChars['{'] |= HTTP_SEPERATOR; + HttpChars['}'] |= HTTP_SEPERATOR; + HttpChars[SP] |= HTTP_SEPERATOR; + HttpChars[HT] |= HTTP_SEPERATOR; + + + // + // URL "reserved" characters (rfc2396) + // + + HttpChars[';'] |= URL_LEGAL; + HttpChars['/'] |= URL_LEGAL; + HttpChars['\\'] |= URL_LEGAL; + HttpChars['?'] |= URL_LEGAL; + HttpChars[':'] |= URL_LEGAL; + HttpChars['@'] |= URL_LEGAL; + HttpChars['&'] |= URL_LEGAL; + HttpChars['='] |= URL_LEGAL; + HttpChars['+'] |= URL_LEGAL; + HttpChars['$'] |= URL_LEGAL; + HttpChars[','] |= URL_LEGAL; + + + // + // URL escape character + // + + HttpChars['%'] |= URL_LEGAL; + + // + // URL "mark" characters (rfc2396) + // + + HttpChars['-'] |= URL_LEGAL; + HttpChars['_'] |= URL_LEGAL; + HttpChars['.'] |= URL_LEGAL; + HttpChars['!'] |= URL_LEGAL; + HttpChars['~'] |= URL_LEGAL; + HttpChars['*'] |= URL_LEGAL; + HttpChars['\''] |= URL_LEGAL; + HttpChars['('] |= URL_LEGAL; + HttpChars[')'] |= URL_LEGAL; + + + // + // RFC2396 describes these characters as `unwise' "because gateways and + // other transport agents are known to sometimes modify such characters, + // or they are used as delimiters". However, for compatibility with + // IIS 5.0 and DAV, we must allow these unwise characters in URLs. + // + + HttpChars['{'] |= URL_LEGAL; + HttpChars['}'] |= URL_LEGAL; + HttpChars['|'] |= URL_LEGAL; + HttpChars['^'] |= URL_LEGAL; + HttpChars['['] |= URL_LEGAL; + HttpChars[']'] |= URL_LEGAL; + HttpChars['`'] |= URL_LEGAL; + + // + // '#', '%', and '"' are not considered URL_LEGAL, according to the RFC. + // However, IIS 5.0 allowed them, so we should too. + // + + HttpChars['#'] |= URL_LEGAL; + HttpChars['%'] |= URL_LEGAL; + HttpChars['"'] |= URL_LEGAL; + + // + // In DBCS locales we need to explicitly accept lead bytes which + // we would normally reject. + // + + if (0) // BUGBUG + { + for (i = 0; i < DBCS_TABLE_SIZE; i++) + { + if (IS_LEAD_BYTE((BYTE)i)) + { + HttpChars[i] |= URL_LEGAL; + } + } + } + + // + // These US-ASCII characters are "excluded"; i.e. not URL_LEGAL (see RFC): + // '<' | '>' | ' ' (0x20) + // In addition, control characters (0x00-0x1F and 0x7F) and + // non US-ASCII characters (0x80-0xFF) are not URL_LEGAL. + // + + for (i = 0; i < 128; i++) + { + if (!IS_HTTP_SEPERATOR(i) && !IS_HTTP_CTL(i)) + { + HttpChars[i] |= HTTP_TOKEN; + } + } + + + // + // Fast path for PopChar + // + + RtlZeroMemory(FastPopChars, 256 * sizeof(USHORT)); + RtlZeroMemory(DummyPopChars, 256 * sizeof(USHORT)); + + for (i = 0; i < 256; i++) + { + c = (UCHAR)i; + + if (IS_URL_TOKEN(c) && c != '%' && (c & 0x80) != 0x80) + { + FastPopChars[i] = (USHORT)c; + } + } + + // + // Turn backslashes into forward slashes + // + + FastPopChars['\\'] = L'/'; + + + // + // Fast path for UpcaseUnicodeChar + // + + for (i = 0; i < 256; i++) + { + FastUpcaseChars[i] = towupper((WCHAR)i); + } + + + return S_OK; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/util.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/util.cxx new file mode 100644 index 0000000000..22c31a0ed2 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/util.cxx @@ -0,0 +1,74 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +HRESULT +MakePathCanonicalizationProof( + IN PCWSTR pszName, + OUT STRU * pstrPath +) +/*++ + +Routine Description: + + This functions adds a prefix + to the string, which is "\\?\UNC\" for a UNC path, and "\\?\" for + other paths. This prefix tells Windows not to parse the path. + +Arguments: + + IN pszName - The path to be converted + OUT pstrPath - Output path created + +Return Values: + + HRESULT + +--*/ +{ + HRESULT hr; + + if (pszName[0] == L'\\' && pszName[1] == L'\\') + { + // + // If the path is already canonicalized, just return + // + + if ((pszName[2] == '?' || pszName[2] == '.') && + pszName[3] == '\\') + { + hr = pstrPath->Copy(pszName); + + if (SUCCEEDED(hr)) + { + // + // If the path was in DOS form ("\\.\"), + // we need to change it to Win32 from ("\\?\") + // + + pstrPath->QueryStr()[2] = L'?'; + } + + return hr; + } + + pszName += 2; + + + if (FAILED(hr = pstrPath->Copy(L"\\\\?\\UNC\\"))) + { + return hr; + } + } + else + { + if (FAILED(hr = pstrPath->Copy(L"\\\\?\\"))) + { + return hr; + } + } + + return pstrPath->Append(pszName); +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stbuff.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stbuff.h new file mode 100644 index 0000000000..04e13789f0 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stbuff.h @@ -0,0 +1,1013 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _STBUFF_H +#define _STBUFF_H + +#include +#include + +#define STB_INLINE_SIZE 64 +#define STB_MAX_ALLOC 16*1024 + +#define TO_UPPER(ch) (isupper(ch) ? ch : toupper(ch)) + +class STBUFF +{ +public: + + STBUFF( + BOOL fZeroInit = TRUE + ) : _pData( _Inline ), + _cbData( 0 ), + _cbBuffer( STB_INLINE_SIZE ), + _cbMaxAlloc( STB_MAX_ALLOC ) + { + if ( fZeroInit ) + { + ZeroInit(); + } + + _Inline[STB_INLINE_SIZE] = 0; + _Inline[STB_INLINE_SIZE+1] = 0; + } + + virtual + ~STBUFF() + { + Reset( TRUE ); + } + + VOID + Reset( + BOOL fFreeAlloc = FALSE + ) + { + // + // If we are supposed to free any heap + // allocations, do so now. + // + + if ( fFreeAlloc && + _pData != _Inline ) + { + LocalFree( _pData ); + _pData = _Inline; + _cbBuffer = STB_INLINE_SIZE; + } + + // + // Reset the data size + // + + _cbData = 0; + } + + HRESULT + Resize( + DWORD cbSize + ) + { + HRESULT hr = S_OK; + BYTE * pTemp; + + // + // If the buffer is large enough, just return + // + + if ( cbSize < _cbBuffer ) + { + goto Finished; + } + + // + // If the requested size exceeds our maximum + // allocation, then fail this call. + // + + if ( cbSize > _cbMaxAlloc ) + { + hr = E_OUTOFMEMORY; + goto Finished; + } + + // + // Adjust the allocation size so that we allocate + // in chunks of MINITOOLS_INLINE_SIZE. Don't + // exeed _cbMaxAlloc. + // + + if ( cbSize % STB_INLINE_SIZE ) + { + cbSize = ( cbSize / STB_INLINE_SIZE + 1 ) * + STB_INLINE_SIZE; + } + + if ( cbSize > _cbMaxAlloc ) + { + cbSize = _cbMaxAlloc; + } + + // + // Allocate the new storage and copy any existing + // data into it. + // + // Allocate two extra bytes so that we can guarantee + // NULL termination when someone queries the data + // pointer as a string. + // + + pTemp = (BYTE*)LocalAlloc( LPTR, cbSize + 2 ); + + if ( !pTemp ) + { + hr = E_OUTOFMEMORY; + goto Finished; + } + + if ( _cbData ) + { + CopyMemory( pTemp, _pData, _cbData ); + } + + // + // If the original buffer is not the inline + // storage, then free it. + // + + if ( _pData != _Inline ) + { + LocalFree( _pData ); + } + + // + // Save the new storage pointer + // + + _pData = pTemp; + _cbBuffer = cbSize; + + // + // Set the extra two bytes as 0 + // + + _pData[_cbBuffer] = 0; + _pData[_cbBuffer+1] = 0; + +Finished: + return hr; + } + + HRESULT + AppendData( + VOID * pData, + DWORD cbData, + DWORD Offset = 0xffffffff + ) + { + DWORD cbNeeded; + HRESULT hr = S_OK; + + // + // Resize the buffer if necessary + // + + cbNeeded = Offset + cbData; + + hr = Resize( cbNeeded ); + + if ( FAILED( hr ) ) + { + goto Finished; + } + + // + // Copy the new data + // + + if ( cbData ) + { + CopyMemory( _pData + Offset, pData, cbData ); + } + + _cbData = cbNeeded; + + // + // NULL terminate the data + // + + GuaranteeNullTermination(); + +Finished: + + return hr; + } + + + HRESULT + AppendData( + LPCSTR szData, + DWORD cchData = 0xffffffff, + DWORD Offset = 0xffffffff + ) + { + // + // If cchData is 0xffffffff, then calculate size + // + + if ( cchData == 0xffffffff ) + { + cchData = (DWORD)strlen( szData ); + } + + // + // If offset is 0xffffffff, then assume + // that we are appending to the end of the + // string. + // + + if ( Offset == 0xffffffff ) + { + Offset = _cbData; + } + + return AppendData( (VOID*)szData, + cchData, + Offset ); + } + + HRESULT + AppendData( + LPCWSTR szData, + DWORD cchData = 0xffffffff, + DWORD cchOffset = 0xffffffff + ) + { + DWORD cbData; + DWORD cbOffset; + // + // If cchData is 0xffffffff, then calculate size + // + + if ( cchData == 0xffffffff ) + { + cchData = (DWORD)wcslen( szData ); + } + + cbData = cchData * sizeof(WCHAR); + + // + // If offset is 0xffffffff, then assume + // that we are appending to the end of the + // string. + // + + if ( cchOffset == 0xffffffff ) + { + cchOffset = _cbData; + } + + cbOffset = cchOffset * sizeof(WCHAR); + + return AppendData( (VOID*)szData, + cbData, + cbOffset ); + } + + HRESULT + AppendData( + STBUFF *pbuff + ) + { + return AppendData( pbuff->QueryPtr(), + pbuff->QueryDataSize() ); + } + + HRESULT + SetData( + VOID * pData, + DWORD cbData + ) + { + // + // Set data is just an append to offset zero + // + + return AppendData( pData, + cbData, + 0 ); + } + + HRESULT + SetData( + LPCSTR pData, + DWORD cchData = 0xffffffff + ) + { + // + // If cbData is 0xffffffff, then assume that + // pData is a NULL terminated string. + // + + if ( cchData == 0xffffffff ) + { + cchData = (DWORD)strlen( (LPSTR)pData ); + } + + return SetData( (VOID*)pData, cchData ); + } + + HRESULT + SetData( + LPCWSTR pData, + DWORD cchData = 0xffffffff + ) + { + // + // If cbData is 0xffffffff, then assume that + // pData is a NULL terminated string. + // + + if ( cchData == 0xffffffff ) + { + cchData = (DWORD)wcslen( (LPWSTR)pData ); + } + + return SetData( (VOID*)pData, cchData * sizeof(WCHAR) ); + } + + + HRESULT + SetData( + STBUFF *pbuff + ) + { + return AppendData( pbuff->QueryPtr(), + pbuff->QueryDataSize(), + 0 ); + } + + HRESULT + AnsiToUnicode( + LPCSTR szString, + UINT codepage = CP_UTF8 + ) + { + DWORD cchString = (DWORD)strlen( szString ); + HRESULT hr = S_OK; + + hr = Resize( cchString * sizeof(WCHAR) ); + + if ( FAILED( hr ) ) + { + goto Finished; + } + + if ( !MultiByteToWideChar( codepage, + MB_ERR_INVALID_CHARS, + szString, + cchString, + (LPWSTR)_pData, + cchString ) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Finished; + } + + _cbData = cchString * sizeof(WCHAR); + +Finished: + + return hr; + } + + HRESULT + UnicodeToAnsi( + LPCWSTR szStringW, + UINT codepage = CP_UTF8 + ) + { + DWORD cchString = (DWORD)wcslen( szStringW ); + HRESULT hr = S_OK; + + hr = Resize( cchString ); + + if ( FAILED( hr ) ) + { + goto Finished; + } + + if ( !WideCharToMultiByte( codepage, + 0, + szStringW, + cchString, + (LPSTR)_pData, + cchString, + NULL, + NULL ) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Finished; + } + + _cbData = cchString; + +Finished: + + return hr; + } + + HRESULT + ExpandEnvironmentStrings( + VOID + ) + { + STBUFF Temp; + DWORD cbNeeded; + HRESULT hr = S_OK; + + cbNeeded = ::ExpandEnvironmentStringsA( QueryStr(), + Temp.QueryStr(), + Temp.QueryBufferSize() ); + + if ( cbNeeded > Temp.QueryBufferSize() ) + { + hr = Temp.Resize ( cbNeeded ); + if ( FAILED (hr) ) + { + goto Finished; + } + + cbNeeded = ::ExpandEnvironmentStringsA( QueryStr(), + Temp.QueryStr(), + Temp.QueryBufferSize() ); + + } + + Temp.CalcDataSize(); + + hr = SetData( &Temp ); + if ( FAILED (hr) ) + { + goto Finished; + } + + Finished: + + return hr; + } + + HRESULT + Vsprintf( + LPCSTR szFormat, + va_list args + ) + { + DWORD cchWritten; + HRESULT hr = S_OK; + + DWORD cbNeeded = _vscprintf( szFormat, args ); + + hr = Resize( cbNeeded + 1 ); + + if ( FAILED( hr ) ) + { + goto Finished; + } + + cchWritten = _vsnprintf_s( QueryStr(), + QueryBufferSize(), + QueryBufferSize(), + szFormat, + args ); + + _cbData = cchWritten; + +Finished: + + return hr; + } + + HRESULT + Vsprintf( + LPCWSTR szFormat, + va_list args + ) + { + DWORD cchWritten; + HRESULT hr = S_OK; + + DWORD cbNeeded = _vscwprintf( szFormat, args ) * sizeof(WCHAR); + + hr = Resize( cbNeeded + 1 ); + + if ( FAILED( hr ) ) + { + goto Finished; + } + + cchWritten = _vsnwprintf_s( QueryStrW(), + QueryBufferSize() / sizeof(WCHAR), + _TRUNCATE, + szFormat, + args ); + + _cbData = cchWritten * sizeof(WCHAR); + +Finished: + + return hr; + } + + HRESULT + Printf( + LPCSTR szFormat, + ... + ) + { + HRESULT hr; + + // + // Let Vsprintf do the work + // + + va_list args; + + va_start( args, szFormat ); + + hr = Vsprintf( szFormat, + args ); + + va_end( args ); + + return hr; + } + + HRESULT + Printf( + LPCWSTR szFormat, + ... + ) + { + HRESULT hr; + + // + // Let Vsprintf do the work + // + + va_list args; + + va_start( args, szFormat ); + + hr = Vsprintf( szFormat, + args ); + + va_end( args ); + + return hr; + } + + VOID * + QueryPtr() + { + return (VOID*)_pData; + } + + LPSTR + QueryStr() + { + GuaranteeNullTermination(); + + return (LPSTR)_pData; + } + + LPWSTR + QueryStrW() + { + GuaranteeNullTermination(); + + return (LPWSTR)_pData; + } + + DWORD + QueryDataSize() + { + return _cbData; + } + + HRESULT + SetDataSize( + DWORD cbData + ) + { + HRESULT hr = S_OK; + + if ( cbData > _cbBuffer ) + { + hr = HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ); + goto Finished; + } + + _cbData = cbData; + + Finished: + return hr; + } + + VOID + CalcDataSize() + { + _cbData = (DWORD)strlen( (LPSTR)_pData ); + } + + VOID + CalcDataSizeW() + { + _cbData = (DWORD)wcslen( (LPWSTR)_pData ); + } + + DWORD + QueryBufferSize() + { + return _cbBuffer; + } + + DWORD + QueryMaxAlloc() + { + return _cbMaxAlloc; + } + + VOID + SetMaxAlloc( + DWORD cbMaxAlloc + ) + { + _cbMaxAlloc = cbMaxAlloc; + } + + VOID + ZeroInit( + VOID + ) + { + FillMemory( _Inline, STB_INLINE_SIZE, 0x00 ); + + if ( _pData != _Inline ) + { + FillMemory( _pData, _cbBuffer, 0x00 ); + } + } + + HRESULT + Escape( + BOOL fAllowDoubleEscaping = FALSE + ) + { + STBUFF Temp; + DWORD dwNumEscapes = 0; + CHAR szHex[3] = {0}; + BYTE * pRead; + BYTE * pWrite; + HRESULT hr = S_OK; + + // + // Walk through the string once. If there + // are no escapes, then we can just return. + // + + GuaranteeNullTermination(); + + pRead = (BYTE*)_pData; + + while ( *pRead != '\0' ) + { + if ( ( fAllowDoubleEscaping || + !IsEscapeSequence( (CHAR*)pRead ) ) && + ShouldEscape( *pRead ) ) + { + dwNumEscapes++; + } + + pRead++; + } + + if ( dwNumEscapes == 0 ) + { + goto Finished; + } + + // + // Make sure that our cooked string buffer is big enough, so + // we can manipulate its pointer directly. + // + + hr = Temp.Resize( _cbData + dwNumEscapes * 2 ); + if ( FAILED (hr) ) + { + goto Finished; + } + + pRead = (BYTE*)_pData; + pWrite = (BYTE*)Temp.QueryStr(); + + while ( *pRead != '\0' ) + { + if ( ( fAllowDoubleEscaping || + !IsEscapeSequence( (CHAR*)pRead ) ) && + ShouldEscape( *pRead ) ) + { + _snprintf_s( szHex, 3, 2, "%02x", *pRead ); + + *pWrite = '%'; + *(pWrite+1) = szHex[0]; + *(pWrite+2) = szHex[1]; + + pRead++; + pWrite += 3; + + continue; + } + + *pWrite = *pRead; + + pRead++; + pWrite++; + } + + *pWrite = '\0'; + + Temp.CalcDataSize(); + + hr = SetData( Temp.QueryStr() ); + if ( FAILED (hr) ) + { + goto Finished; + } + + Finished: + + return hr; + } + + VOID + Unescape( + VOID + ) + { + CHAR * pRead; + CHAR * pWrite; + CHAR szHex[3] = {0}; + BYTE c; + + pRead = (CHAR*)_pData; + pWrite = pRead; + + while ( *pRead ) + { + if ( IsEscapeSequence( pRead ) ) + { + szHex[0] = *(pRead+1); + szHex[1] = *(pRead+2); + + c = (BYTE)strtoul( szHex, NULL, 16 ); + + *pWrite = c; + + pRead += 3; + pWrite++; + + continue; + } + + *pWrite = *pRead; + + pRead++; + pWrite++; + } + + *pWrite = '\0'; + + CalcDataSize(); + + return; + } + + VOID + MoveToFront( + DWORD cbOffset + ) + { + if ( cbOffset >= _cbData ) + { + Reset(); + + return; + } + + MoveMemory( _pData, _pData + cbOffset, _cbData - cbOffset ); + + _cbData -= cbOffset; + } + + BOOL + IsWildcardMatch( + LPCSTR szExpr + ) + { + LPCSTR pExpr = szExpr; + LPCSTR pString = QueryStr(); + LPCSTR pSubMatch; + DWORD cchSubMatch; + + if ( !pExpr ) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + while ( *pExpr ) + { + switch ( *pExpr ) + { + case '*': + + // + // Eat '*' characters + // + + while ( *pExpr == '*' ) + { + pExpr++; + } + + // + // Find the next wildcard + // + + pSubMatch = strchr( pExpr, '*' ); + + cchSubMatch = (DWORD)(pSubMatch ? + pSubMatch - pExpr : + strlen( pExpr )); + + if ( cchSubMatch == 0 ) + { + // + // No submatch. The rest of + // pString automatically matches + // + + return TRUE; + } + + // + // Ensure that the current submatch exists + // + + while ( _strnicmp( pString, pExpr, cchSubMatch ) ) + { + pString++; + + if ( *pString == '\0' ) + { + // + // Not found + // + + return FALSE; + } + } + + pExpr += cchSubMatch; + pString += cchSubMatch; + + break; + + default: + + if ( TO_UPPER( *pExpr ) != TO_UPPER( *pString ) ) + { + return FALSE; + } + + pExpr++; + pString++; + } + } + + if ( *pString != '\0' ) + { + return FALSE; + } + + return TRUE; + } + +private: + + LPBYTE _pData; + DWORD _cbData; + DWORD _cbBuffer; + DWORD _cbMaxAlloc; + BYTE _Inline[STB_INLINE_SIZE+2]; + + VOID + GuaranteeNullTermination() + { + _pData[_cbData] = 0; + _pData[_cbData+1] = 0; + } + + BOOL + IsEscapeSequence( + CHAR * str + ) + { + if ( *str == '%' && + isxdigit( *(str+1) ) && + isxdigit( *(str+2) ) ) + { + return TRUE; + } + + return FALSE; + } + + BOOL + ShouldEscape( + BYTE c + ) + { + // + // If the character is listed in RFC2396, section + // 2.4.3 as control, space, delims or unwise, we + // should escape it. Also, we should escape characters + // with the high bit set. + // + + if ( c <= 0x1f || + c == 0x7f ) + { + // + // Control character + // + + goto ReturnTrue; + } + + if ( c >= 0x80 ) + { + // + // High bit set + // + + goto ReturnTrue; + } + + switch ( c ) + { + + // + // space + // + case ' ': + + // + // delims + // + case '<': + case '>': + case '#': + case '%': + case '\"': + + // + // unwise + // + case '{': + case '}': + case '|': + case '\\': + case '^': + case '[': + case ']': + case '`': + + goto ReturnTrue; + } + + // + // If we get here, then the character should not be + // escaped + // + + return FALSE; + + ReturnTrue: + + return TRUE; + } +}; + +#endif // _STBUFF_H diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stlist.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stlist.h new file mode 100644 index 0000000000..916c8576a8 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stlist.h @@ -0,0 +1,87 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _STLIST_H +#define _STLIST_H + +#ifndef IsListEmpty + +#include + +#define IsListEmpty(ListHead) ((ListHead)->Flink == (ListHead)) + +VOID +inline +InitializeListHead( + LIST_ENTRY * ListHead + ) +{ + ListHead->Flink = ListHead->Blink = ListHead; +} + +BOOL +inline +RemoveEntryList( + LIST_ENTRY * Entry + ) +{ + LIST_ENTRY * Blink; + LIST_ENTRY * Flink; + + Flink = Entry->Flink; + Blink = Entry->Blink; + Blink->Flink = Flink; + Flink->Blink = Blink; + return (Flink == Blink); +} + +PLIST_ENTRY +inline +RemoveHeadList( + LIST_ENTRY * ListHead + ) +{ + LIST_ENTRY * Flink; + LIST_ENTRY * Entry; + + Entry = ListHead->Flink; + Flink = Entry->Flink; + ListHead->Flink = Flink; + Flink->Blink = ListHead; + return Entry; +} + +VOID +inline +InsertHeadList( + LIST_ENTRY * ListHead, + LIST_ENTRY * Entry + ) +{ + LIST_ENTRY * Flink; + + Flink = ListHead->Flink; + Entry->Flink = Flink; + Entry->Blink = ListHead; + Flink->Blink = Entry; + ListHead->Flink = Entry; +} + +VOID +inline +InsertTailList( + LIST_ENTRY * ListHead, + LIST_ENTRY * Entry + ) +{ + LIST_ENTRY * Blink; + + Blink = ListHead->Blink; + Entry->Flink = ListHead; + Entry->Blink = Blink; + Blink->Flink = Entry; + ListHead->Blink = Entry; +} + +#endif // IsListEmpty +#endif // _STLIST_H diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stlock.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stlock.h new file mode 100644 index 0000000000..6571489187 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/stlock.h @@ -0,0 +1,149 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _STLOCK_H +#define _STLOCK_H + +class STLOCK +{ +public: + + STLOCK() + : _fInitialized( FALSE ) + { + } + + ~STLOCK() + { + if ( _fInitialized ) + { + DeleteCriticalSection( &_cs ); + CloseHandle( _hReadersDone ); + } + } + + HRESULT + Initialize( + VOID + ) + { + HRESULT hr = S_OK; + BOOL fResult = FALSE; + + if ( !_fInitialized ) + { + _fWriterWaiting = FALSE; + _cReaders = 0; + + fResult = InitializeCriticalSectionAndSpinCount( &_cs, 100 ); + + if ( !fResult ) + { + hr = E_FAIL; + goto Finished; + } + + _hReadersDone = CreateEvent( NULL, + FALSE, + FALSE, + NULL ); + + if ( !_hReadersDone ) + { + DeleteCriticalSection( &_cs ); + hr = E_FAIL; + goto Finished; + } + + _fInitialized = TRUE; + } + +Finished: + return hr; + } + + BOOL + QueryInitialized() const + { + return _fInitialized; + } + + void SharedAcquire() + { + EnterCriticalSection( &_cs ); + InterlockedIncrement( &_cReaders ); + LeaveCriticalSection( &_cs ); + } + + void SharedRelease() + { + ReleaseInternal(); + } + + void ExclusiveAcquire() + { + EnterCriticalSection( &_cs ); + + _fWriterWaiting = TRUE; + + // + // If there are any readers, wait for them + // to release + // + + if ( InterlockedExchangeAdd( &_cReaders, 0 ) > 0 ) + { + WaitForSingleObject( _hReadersDone, INFINITE ); + } + + // + // Reader count -1 indicates that a writer has the lock + // + + _cReaders = -1; + } + + void ExclusiveRelease() + { + ReleaseInternal(); + } + +private: + + BOOL _fInitialized; + BOOL _fWriterWaiting; + LONG _cReaders; + CRITICAL_SECTION _cs; + HANDLE _hReadersDone; + + void ReleaseInternal() + { + LONG cReaders = InterlockedDecrement( &_cReaders ); + + if ( cReaders >= 0 ) + { + // + // Released a read lock. If this was the last + // reader and writers are waiting, set the + // readers done event + // + + if ( ( _fWriterWaiting ) && ( cReaders == 0 ) ) + { + SetEvent( _hReadersDone ); + } + } + else + { + // + // Released a write lock + // + + _cReaders = 0; + _fWriterWaiting = FALSE; + LeaveCriticalSection( &_cs ); + } + } +}; + +#endif // _STLOCK_H \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/sttable.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/sttable.h new file mode 100644 index 0000000000..0fd629af3d --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/sttable.h @@ -0,0 +1,599 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _STTABLE_H +#define _STTABLE_H + +#include +#include +#include "stbuff.h" +#include "stlock.h" +#include "stlist.h" + +#define DEFAULT_BUCKETS 97 // largest prime under 100 + +class ITEM; +class STTABLE_ITEM; + +typedef DWORD (WINAPI * PFN_HASH)(STBUFF*); +typedef BOOL (WINAPI * PFN_COMPARE_KEYS)(STBUFF*,STBUFF*); +typedef VOID (WINAPI * PFN_ITER)(STTABLE_ITEM*, BOOL*); + +class STTABLE_ITEM +{ +public: + + STTABLE_ITEM() + : _cRefs( 1 ) + { + InitializeListHead( &le ); + } + + VOID + Reference() + { + InterlockedIncrement( &_cRefs ); + } + + VOID + Dereference() + { + LONG cRefs = InterlockedDecrement( &_cRefs ); + + if ( cRefs == 0 ) + { + delete this; + } + } + + HRESULT + Initialize( + STBUFF * pKey + ) + { + return _buffKey.SetData( pKey->QueryPtr(), + pKey->QueryDataSize() ); + } + + STBUFF * + QueryKey() + { + return &_buffKey; + } + + virtual + ~STTABLE_ITEM() + {} + + LIST_ENTRY le; + +private: + + LONG _cRefs; + STBUFF _buffKey; +}; + +class STTABLE_BUCKET +{ +public: + + STTABLE_BUCKET() + : _pfnCompareKeys( NULL ) + {} + + virtual + ~STTABLE_BUCKET() + { + LIST_ENTRY * pEntry; + STTABLE_ITEM * pItem; + + while ( !IsListEmpty( &_Head ) ) + { + pEntry = RemoveHeadList( &_Head ); + + pItem = CONTAINING_RECORD( pEntry, + STTABLE_ITEM, + le ); + + pItem->Dereference(); + pItem = NULL; + } + } + + HRESULT + Initialize( + PFN_COMPARE_KEYS pfnCompareKeys = NULL + ) + { + InitializeListHead( &_Head ); + + _pfnCompareKeys = pfnCompareKeys; + + return _BucketLock.Initialize(); + } + + HRESULT + Insert( + STTABLE_ITEM * pNewItem + ) + { + LIST_ENTRY * pEntry; + STTABLE_ITEM * pItem; + HRESULT hr = S_OK; + + _BucketLock.ExclusiveAcquire(); + + // + // Check to see if the item is already in the list + // + + pEntry = _Head.Flink; + + while ( pEntry != &_Head ) + { + pItem = CONTAINING_RECORD( pEntry, + STTABLE_ITEM, + le ); + + if ( CompareKeys( pNewItem->QueryKey(), + pItem->QueryKey() ) ) + { + hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS); + goto Finished; + } + + pEntry = pEntry->Flink; + } + + // + // It's not in the list. Add it now + // + + pNewItem->Reference(); + InsertTailList( &_Head, &pNewItem->le ); + +Finished: + + _BucketLock.ExclusiveRelease(); + + return hr; + } + + HRESULT + Remove( + STTABLE_ITEM * pItemToRemove + ) + { + LIST_ENTRY * pEntry; + STTABLE_ITEM * pItem; + + _BucketLock.ExclusiveAcquire(); + + // + // Find the item in the list + // + + pEntry = _Head.Flink; + + while ( pEntry != &_Head ) + { + pItem = CONTAINING_RECORD( pEntry, + STTABLE_ITEM, + le ); + + if ( CompareKeys( pItemToRemove->QueryKey(), + pItem->QueryKey() ) ) + { + RemoveEntryList( &pItemToRemove->le ); + pItemToRemove->Dereference(); + pItemToRemove = NULL; + + goto Finished; + } + + pEntry = pEntry->Flink; + } + + // + // Item was not found. Set error code, but + // don't fail function. + // + + SetLastError (ERROR_FILE_NOT_FOUND); + +Finished: + + _BucketLock.ExclusiveRelease(); + + return S_OK; + } + + HRESULT + GetItem( + STBUFF * pKey, + STTABLE_ITEM **ppItem + ) + { + LIST_ENTRY * pEntry; + STTABLE_ITEM * pItem; + HRESULT hr = S_OK; + + _BucketLock.SharedAcquire(); + + // + // Find the item in the list + // + + pEntry = _Head.Flink; + + while ( pEntry != &_Head ) + { + pItem = CONTAINING_RECORD( pEntry, + STTABLE_ITEM, + le ); + + if ( CompareKeys( pKey, + pItem->QueryKey() ) ) + { + pItem->Reference(); + goto Finished; + } + + pEntry = pEntry->Flink; + } + + // + // Item was not found. + // + + pItem = NULL; + + hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + +Finished: + + _BucketLock.SharedRelease(); + + *ppItem = pItem; + + return hr; + } + + VOID + Iterate( + PFN_ITER pIterFunction + ) + { + LIST_ENTRY * pEntry; + STTABLE_ITEM * pItem; + BOOL fRemoveItem; + + //////////////////////////////////////// + // + // It is assumed that this function will + // be called under a write lock + // + //////////////////////////////////////// + + // + // Walk the list and call the provided + // function on each item + // + + pEntry = _Head.Flink; + + while ( pEntry != &_Head ) + { + pItem = CONTAINING_RECORD( pEntry, + STTABLE_ITEM, + le ); + + // + // The iterator function might remove + // the item from the list, so we need + // to get the next link first + // + + pEntry = pEntry->Flink; + + pItem->Reference(); + pIterFunction( pItem, &fRemoveItem ); + + if ( fRemoveItem ) + { + RemoveEntryList( &pItem->le ); + pItem->Dereference(); + pItem = NULL; + } + } + + } + +private: + + LIST_ENTRY _Head; + STLOCK _BucketLock; + PFN_COMPARE_KEYS _pfnCompareKeys; + + BOOL + CompareKeys( + STBUFF * pKey1, + STBUFF * pKey2 + ) + { + if ( _pfnCompareKeys ) + { + return _pfnCompareKeys( pKey1, + pKey2 ); + } + + return ( strcmp( pKey1->QueryStr(), + pKey2->QueryStr() ) == 0 ); + } +}; + + +class STTABLE +{ +public: + + STTABLE() + : _cBuckets( 0 ), + _pfnHash( NULL ) + {} + + virtual + ~STTABLE() + { + STTABLE_BUCKET ** rgBuckets; + STTABLE_BUCKET * pBucket; + DWORD n; + + rgBuckets = (STTABLE_BUCKET**)_buffBucketPtrs.QueryPtr(); + + for( n = 0; n < _cBuckets; n++ ) + { + pBucket = rgBuckets[n]; + + delete pBucket; + pBucket = NULL; + } + } + + HRESULT + Initialize( + DWORD cBuckets = DEFAULT_BUCKETS, + PFN_HASH pfnHash = NULL, + PFN_COMPARE_KEYS pfnCompareKeys = NULL + ) + { + STTABLE_BUCKET ** rgBuckets; + DWORD n; + HRESULT hr = S_OK; + + // + // Create a buffer for the bucket array + // + + hr = _buffBucketPtrs.Resize( cBuckets * sizeof(STTABLE_BUCKET*) ); + + if ( FAILED (hr) ) + { + goto Finished; + } + + rgBuckets = (STTABLE_BUCKET**)_buffBucketPtrs.QueryPtr(); + + // + // Create the buckets + // + + for ( n = 0; n < cBuckets; n++ ) + { + STTABLE_BUCKET * pNewBucket = new STTABLE_BUCKET; + + if ( !pNewBucket ) + { + hr = E_OUTOFMEMORY; + goto Finished; + } + + hr = pNewBucket->Initialize( pfnCompareKeys ); + + if ( FAILED (hr) ) + { + delete pNewBucket; + pNewBucket = NULL; + + goto Finished; + } + + rgBuckets[n] = pNewBucket; + pNewBucket = NULL; + + _cBuckets++; + } + + // + // Initialize the table lock + // + + _TableLock.Initialize(); + + // + // Set the hash function + // + + _pfnHash = pfnHash; + +Finished: + return hr; + } + + HRESULT + Insert( + STTABLE_ITEM * pNewItem + ) + { + + DWORD dwHash; + STTABLE_BUCKET * pBucket; + HRESULT hr = S_OK; + + dwHash = ComputeHash( pNewItem->QueryKey() ); + + pBucket = GetBucket( dwHash ); + + _TableLock.SharedAcquire(); + + hr = pBucket->Insert( pNewItem ); + + _TableLock.SharedRelease(); + + return hr; + } + + HRESULT + Remove( + STTABLE_ITEM * pItemToRemove + ) + { + DWORD dwHash; + STTABLE_BUCKET * pBucket; + HRESULT hr = S_OK; + + dwHash = ComputeHash( pItemToRemove->QueryKey() ); + + pBucket = GetBucket( dwHash ); + + _TableLock.SharedAcquire(); + + hr = pBucket->Remove( pItemToRemove ); + + _TableLock.SharedRelease(); + + return hr; + } + + HRESULT + GetItem( + STBUFF * pKey, + STTABLE_ITEM **ppItem + ) + { + DWORD dwHash; + STTABLE_BUCKET * pBucket; + STTABLE_ITEM * pRet; + HRESULT hr = S_OK; + + dwHash = ComputeHash( pKey ); + + pBucket = GetBucket( dwHash ); + + _TableLock.SharedAcquire(); + + hr = pBucket->GetItem( pKey, &pRet ); + if(FAILED( hr)) + { + pRet = NULL; + goto Finished; + } + + Finished: + + _TableLock.SharedRelease(); + + *ppItem = pRet; + + return hr; + } + + VOID + Iterate( + PFN_ITER pIterFunction + ) + { + STTABLE_BUCKET ** rgBuckets; + DWORD n; + + _TableLock.ExclusiveAcquire(); + + rgBuckets = (STTABLE_BUCKET**)_buffBucketPtrs.QueryPtr(); + + // + // Iterate each bucket + // + + for ( n = 0; n < _cBuckets; n++ ) + { + STTABLE_BUCKET * pBucket; + + pBucket = rgBuckets[n]; + + pBucket->Iterate( pIterFunction ); + + pBucket = NULL; + } + + _TableLock.ExclusiveRelease(); + } + +private: + + STBUFF _buffBucketPtrs; + DWORD _cBuckets; + STLOCK _TableLock; + PFN_HASH _pfnHash; + + DWORD + ComputeHash( + STBUFF * pKey + ) + { + if ( _pfnHash ) + { + return _pfnHash( pKey ); + } + + return HashString( pKey->QueryStr() ); + } + + STTABLE_BUCKET * + GetBucket( + DWORD dwHash + ) + { + STTABLE_BUCKET ** rgBuckets; + + rgBuckets = (STTABLE_BUCKET**)_buffBucketPtrs.QueryPtr(); + + return rgBuckets[dwHash % _cBuckets]; + } + + DWORD + WINAPI + HashString( + LPCSTR szString + ) + { + DWORD dwRet = 0; + + // + // Create a hash by adding up the ascii values + // of each character in a case-insensitive manner + // + + if ( szString ) + { + while ( *szString ) + { + dwRet += ( (*szString) | 0x20 ); + szString++; + } + } + + return dwRet; + } +}; + +#endif // _STTABLE_H diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/sttimer.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/sttimer.h new file mode 100644 index 0000000000..f5a10817a5 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/open-inc/sttimer.h @@ -0,0 +1,232 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _STTIMER_H +#define _STTIMER_H + +class STTIMER +{ +public: + + STTIMER() + : _pTimer( NULL ) + { + } + + virtual + ~STTIMER() + { + if ( _pTimer ) + { + CancelTimer(); + + CloseThreadpoolTimer( _pTimer ); + + _pTimer = NULL; + } + } + + HRESULT + InitializeTimer( + PTP_TIMER_CALLBACK pfnCallback, + VOID * pContext, + DWORD dwInitialWait = 0, + DWORD dwPeriod = 0 + ) + { + _pTimer = CreateThreadpoolTimer( pfnCallback, + pContext, + NULL ); + + if ( !_pTimer ) + { + return HRESULT_FROM_WIN32( GetLastError() ); + } + + if ( dwInitialWait ) + { + SetTimer( dwInitialWait, + dwPeriod ); + } + + return S_OK; + } + + VOID + SetTimer( + DWORD dwInitialWait, + DWORD dwPeriod = 0 + ) + { + FILETIME ftInitialWait; + + if ( dwInitialWait == 0 && dwPeriod == 0 ) + { + // + // Special case. We are preventing new callbacks + // from being queued. Any existing callbacks in the + // queue will still run. + // + // This effectively disables the timer. It can be + // re-enabled by setting non-zero initial wait or + // period values. + // + + SetThreadpoolTimer( _pTimer, NULL, 0, 0 ); + return; + } + + InitializeRelativeFileTime( &ftInitialWait, dwInitialWait ); + + SetThreadpoolTimer( _pTimer, + &ftInitialWait, + dwPeriod, + 0 ); + } + + VOID + CancelTimer() + { + // + // Disable the timer + // + + SetTimer( 0 ); + + // + // Wait until any callbacks queued prior to disabling + // have completed. + // + + WaitForThreadpoolTimerCallbacks( _pTimer, TRUE ); + } + +private: + + VOID + InitializeRelativeFileTime( + FILETIME * pft, + DWORD dwMilliseconds + ) + { + LARGE_INTEGER li; + + // + // The pftDueTime parameter expects the time to be + // expressed as the number of 100 nanosecond intervals + // times -1. + // + // To convert from milliseconds, we'll multiply by + // -10000 + // + + li.QuadPart = (LONGLONG)dwMilliseconds * -10000; + + pft->dwHighDateTime = li.HighPart; + pft->dwLowDateTime = li.LowPart; + }; + + TP_TIMER * _pTimer; +}; + +class STELAPSED +{ +public: + + STELAPSED() + : _dwInitTime( 0 ), + _dwInitTickCount( 0 ), + _dwPerfCountsPerMillisecond( 0 ), + _fUsingHighResolution( FALSE ) + { + LARGE_INTEGER li; + BOOL fResult; + + _dwInitTickCount = GetTickCount64(); + + fResult = QueryPerformanceFrequency( &li ); + + if ( !fResult ) + { + goto Finished; + } + + _dwPerfCountsPerMillisecond = li.QuadPart / 1000; + + fResult = QueryPerformanceCounter( &li ); + + if ( !fResult ) + { + goto Finished; + } + + _dwInitTime = li.QuadPart / _dwPerfCountsPerMillisecond; + + _fUsingHighResolution = TRUE; + +Finished: + + return; + } + + virtual + ~STELAPSED() + { + } + + LONGLONG + QueryElapsedTime() + { + LARGE_INTEGER li; + + if ( _fUsingHighResolution && QueryPerformanceCounter( &li ) ) + { + DWORD64 dwCurrentTime = li.QuadPart / _dwPerfCountsPerMillisecond; + + if ( dwCurrentTime < _dwInitTime ) + { + // + // It's theoretically possible that QueryPerformanceCounter + // may return slightly different values on different CPUs. + // In this case, we don't want to return an unexpected value + // so we'll return zero. This is acceptable because + // presumably such a case would only happen for a very short + // time window. + // + // It would be possible to prevent this by ensuring processor + // affinity for all calls to QueryPerformanceCounter, but that + // would be undesirable in the general case because it could + // introduce unnecessary context switches and potentially a + // CPU bottleneck. + // + // Note that this issue also applies to callers doing rapid + // calls to this function. If a caller wants to mitigate + // that, they could enforce the affinitization, or they + // could implement a similar sanity check when comparing + // returned values from this function. + // + + return 0; + } + + return dwCurrentTime - _dwInitTime; + } + + return GetTickCount64() - _dwInitTickCount; + } + + BOOL + QueryUsingHighResolution() + { + return _fUsingHighResolution; + } + +private: + + DWORD64 _dwInitTime; + DWORD64 _dwInitTickCount; + DWORD64 _dwPerfCountsPerMillisecond; + BOOL _fUsingHighResolution; +}; + +#endif // _STTIMER_H \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/dbgutil2.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/dbgutil2.h new file mode 100644 index 0000000000..1c4d2d4381 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/dbgutil2.h @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +# ifndef _DBGUTIL_H_ +# define _DBGUTIL_H_ + + +// begin_user_modifiable + +// +// define DEBUG_FLAGS_VAR to assure that DebugFlags will stay private to +// iisutil. This is important in the case when iisutil is linked as static library +// +#define DEBUG_FLAGS_VAR g_dwDebugFlagsIISUtil + +// +// Modify the following flags if necessary +// + +# define DEFAULT_OUTPUT_FLAGS ( DbgOutputKdb ) + + +// end_user_modifiable +// begin_user_unmodifiable + + + +/************************************************************ + * Include Headers + ************************************************************/ + +# include + + +// +// Define the debugging constants +// + +# define DEBUG_ALLOC_CACHE 0x01000000 +# define DEBUG_SCHED 0x02000000 +# define DEBUG_RESOURCE 0x04000000 +# define DEBUG_INET_MONITOR 0x08000000 +# define DEBUG_PIPEDATA 0x10000000 + +// Use the default constants from pudebug.h + +# endif /* _DBGUTIL_H_ */ + +/************************ End of File ***********************/ diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/irtldbg.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/irtldbg.h new file mode 100644 index 0000000000..3c6c48e7b1 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/irtldbg.h @@ -0,0 +1,154 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef __IRTLDBG_H__ +#define __IRTLDBG_H__ + +#ifndef __IRTLMISC_H__ +# include +#endif + +/* Ensure that MessageBoxes can popup */ +# define RUNNING_AS_SERVICE 1 + + +#ifdef _AFX + /* Assure compatiblity with MFC */ + +# define IRTLASSERT(x) ASSERT(x) +# define IRTLVERIFY(x) VERIFY(x) + +#else /* !_AFX */ + +# if DBG || defined(_DEBUG) +# define IRTLDEBUG +# endif + +# if defined(IRTLDEBUG) +# ifndef USE_DEBUG_CRTS + /* IIS (and NT) do not ship msvcrtD.dll, per the VC license, + * so we can't use the assertion code from . Use similar + * macros from instead. */ +# include + + /* workaround for /W4 warnings about 'constant expressions' */ +# define IRTLASSERT(f) \ + ((void) ((f) || (PuDbgAssertFailed(DBG_CONTEXT, #f, ""), 0) )) + +# elif defined(_MSC_VER) && (_MSC_VER >= 1000) + /* Use the new debugging tools in Visual C++ 4.x */ +# include + /* _ASSERTE will give a more meaningful message, but the string takes + * space. Use _ASSERT if this is an issue. */ +# define IRTLASSERT(f) _ASSERTE(f) +# else +# include +# define IRTLASSERT(f) assert(f) +# endif + +# ifdef _PREFAST_ +# undef IRTLASSERT +# define IRTLASSERT(f) ((void)0) +# endif + +# define IRTLVERIFY(f) IRTLASSERT(f) +# define DEBUG_ONLY(f) (f) +# define TRACE IrtlTrace +# define TRACE0(psz) IrtlTrace(_T("%s"), _T(psz)) +# define TRACE1(psz, p1) IrtlTrace(_T(psz), p1) +# define TRACE2(psz, p1, p2) IrtlTrace(_T(psz), p1, p2) +# define TRACE3(psz, p1, p2, p3) IrtlTrace(_T(psz), p1, p2, p3) +# define ASSERT_VALID(pObj) \ + do {IRTLASSERT((pObj) != NULL); (pObj)->AssertValid();} while (0) +# define DUMP(pObj) \ + do {IRTLASSERT((pObj) != NULL); (pObj)->Dump();} while (0) + +# else /* !_DEBUG */ + + /* These macros should all compile away to nothing */ +# define IRTLASSERT(f) ((void)0) +# define IRTLVERIFY(f) ((void)(f)) +# define DEBUG_ONLY(f) ((void)0) +# define TRACE 1 ? (void)0 : IrtlTrace +# define TRACE0(psz) +# define TRACE1(psz, p1) +# define TRACE2(psz, p1, p2) +# define TRACE3(psz, p1, p2, p3) +# define ASSERT_VALID(pObj) ((void)0) +# define DUMP(pObj) ((void)0) + +# endif /* !_DEBUG */ + + +# define ASSERT_POINTER(p, type) \ + IRTLASSERT((p) != NULL) + +#define ASSERT_STRING(s) \ + IRTLASSERT(((s) != NULL)) + +/* Declarations for non-Windows apps */ + +# ifndef _WINDEF_ +typedef void* LPVOID; +typedef const void* LPCVOID; +typedef unsigned int UINT; +typedef int BOOL; +typedef const char* LPCTSTR; +# endif /* _WINDEF_ */ + +# ifndef TRUE +# define FALSE 0 +# define TRUE 1 +# endif + +#endif /* !_AFX */ + + +#ifdef __cplusplus + +// Compile-time (not run-time) assertion. Code will not compile if +// expr is false. Note: there is no non-debug version of this; we +// want this for all builds. The compiler optimizes the code away. +template struct static_checker; +template <> struct static_checker {}; // specialize only for `true' +#define STATIC_ASSERT(expr) static_checker< (expr) >() + +#endif /* !__cplusplus */ + +/* Writes trace messages to debug stream */ +extern +#ifdef __cplusplus +"C" +#endif /* !__cplusplus */ +IRTL_DLLEXP +void __cdecl +IrtlTrace( + LPCTSTR pszFormat, + ...); + + +#ifdef _DEBUG +# define IRTL_DEBUG_INIT() IrtlDebugInit() +# define IRTL_DEBUG_TERM() IrtlDebugTerm() +#else /* !_DEBUG */ +# define IRTL_DEBUG_INIT() ((void)0) +# define IRTL_DEBUG_TERM() ((void)0) +#endif /* !_DEBUG */ + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* should be called from main(), WinMain(), or DllMain() */ +IRTL_DLLEXP void +IrtlDebugInit(); + +IRTL_DLLEXP void +IrtlDebugTerm(); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __IRTLDBG_H__ */ diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/irtlmisc.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/irtlmisc.h new file mode 100644 index 0000000000..02bfa2d065 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/irtlmisc.h @@ -0,0 +1,131 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef __IRTLMISC_H__ +#define __IRTLMISC_H__ + +#include + +//-------------------------------------------------------------------- +// These declarations are needed to export the template classes from +// IisRtl.DLL and import them into other modules. + +// DEBGUDEBUG +/** +#ifndef IRTL_DLLEXP +# ifdef DLL_IMPLEMENTATION +# define IRTL_DLLEXP __declspec(dllexport) +# ifdef IMPLEMENTATION_EXPORT +# define IRTL_EXPIMP +# else +# undef IRTL_EXPIMP +# endif +# elif defined LIB_IMPLEMENTATION +# define IRTL_DLLEXP +# define IRTL_EXPIMP extern +# else +# define IRTL_DLLEXP __declspec(dllimport) +# define IRTL_EXPIMP extern +# endif // !DLL_IMPLEMENTATION +#endif // !IRTL_DLLEXP +*/ + +#define IRTL_DLLEXP +#define IRTL_EXPIMP + + + + + +//-------------------------------------------------------------------- +// Miscellaneous functions + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + + +// Heap routines + +// Private IIS heap +HANDLE +WINAPI +IisHeap(); + +// Allocate dwBytes +LPVOID +WINAPI +IisMalloc( + IN SIZE_T dwBytes); + +// Allocate dwBytes. Memory is zeroed +LPVOID +WINAPI +IisCalloc( + IN SIZE_T dwBytes); + +// Reallocate lpMem to dwBytes +LPVOID +WINAPI +IisReAlloc( + IN LPVOID lpMem, + IN SIZE_T dwBytes); + +// Free lpMem +BOOL +WINAPI +IisFree( + IN LPVOID lpMem); + +// additional IISRTL initialization +BOOL +WINAPI +InitializeIISRTL(); + +// call before unloading IISRTL +void +WINAPI +TerminateIISRTL(); + +// case-insensitive strstr +IRTL_DLLEXP const char* stristr(const char* pszString, const char* pszSubString); + +// how many CPUs on this machine? +inline int NumProcessors() +{ + static int s_nCPUs = 0; + + if (s_nCPUs == 0) + { + SYSTEM_INFO si; + GetSystemInfo(&si); + s_nCPUs = si.dwNumberOfProcessors; + } + return s_nCPUs; +} + + +// how many CPUs on this machine? +inline int ProcessorType() +{ + static int s_nProcessorType = 0; + + if (s_nProcessorType == 0) + { + SYSTEM_INFO si; + GetSystemInfo(&si); + s_nProcessorType = si.dwProcessorType; + } + return s_nProcessorType; +} + + +#ifdef __cplusplus +} +#endif // __cplusplus + +#define HRESULT_FROM_GLE() ( GetLastError() != NO_ERROR ) \ + ? HRESULT_FROM_WIN32( GetLastError() ) \ + : E_FAIL + +#endif // __IRTLMISC_H__ diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/memorylog.hxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/memorylog.hxx new file mode 100644 index 0000000000..effa543259 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/memorylog.hxx @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _MEMORYLOG_HXX_ +#define _MEMORYLOG_HXX_ + +//#include "buffer.hxx" + +class CMemoryLog +{ +public: + CMemoryLog(DWORD dwMaxByteSize); + ~CMemoryLog(); + + // + // Override the new and delete operator to make them + // use LocalAlloc so that CMemoryLog + // can be safely constructed and deleted + // in the DllMain() + // + + VOID * + operator new( + size_t size + ) + { + return LocalAlloc( LPTR, size ); + } + + VOID + operator delete( + VOID * pMemoryLog + ) + { + DBG_ASSERT( pMemoryLog != NULL ); + LocalFree( pMemoryLog ); + } + + // appends to memory log + DWORD Append(LPCSTR pszOutput, + DWORD cchLen + ); +private: + CMemoryLog(); + + // pointer to the beginning of the memory buffer + CHAR *m_pBufferBegin; + // pointer to the byte 1 beyond the end of the last message + CHAR *m_pLastMessageEnd; + // pointer to the end of the memory buffer + CHAR *m_pBufferEnd; + + // Used for storage + BUFFER m_buf; + + // TRUE if storage could be allocated, otherwise FALSE + BOOL m_fValid; + + CRITICAL_SECTION m_cs; + + // to be able to tell if the critsec was initialized successfully + BOOL m_fCritSecInitialized; + +}; + +#endif // _MEMORYLOG_HXX_ + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/precomp.hxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/precomp.hxx new file mode 100644 index 0000000000..d012c7ee29 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/precomp.hxx @@ -0,0 +1,9 @@ +#include +#include "tchar.h" +#include "dbgutil.h" +#include "ntassert.h" +#include "buffer.h" +#include "stringa.h" +#include "stringu.h" +#include "stdlib.h" +#include "stdio.h" diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/pudebug.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/pudebug.h new file mode 100644 index 0000000000..d42153d457 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/include/pudebug.h @@ -0,0 +1,748 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#if !defined(BUILD_PUDEBUG) +// +// if we are not using this header for building the pudebug library +// then better this be used with dbgutil.h +// + # ifndef _DBGUTIL_H_ + // error Please make sure you included dbgutil.h! + // error Do not include pudebug.h directly + #include + # endif // _DBGUTIL_H_ +#endif + +# ifndef _PUDEBUG_H_ +# define _PUDEBUG_H_ + +#ifndef _NO_TRACING_ +# define _NO_TRACING_ +#endif // _NO_TRACING_ + +/************************************************************ + * Include Headers + ************************************************************/ + +# ifdef __cplusplus +extern "C" { +# endif // __cplusplus + +# include + +# ifndef dllexp +# define dllexp __declspec( dllexport) +# endif // dllexp + +#include + +#ifndef IN_OUT +#define IN_OUT __inout +#endif + +/*********************************************************** + * Macros + ************************************************************/ + +enum PRINT_REASONS { + PrintNone = 0x0, // Nothing to be printed + PrintError = 0x1, // An error message + PrintWarning = 0x2, // A warning message + PrintLog = 0x3, // Just logging. Indicates a trace of where ... + PrintMsg = 0x4, // Echo input message + PrintCritical = 0x5, // Print and Exit + PrintAssertion= 0x6 // Printing for an assertion failure + }; + + +enum DEBUG_OUTPUT_FLAGS { + DbgOutputNone = 0x0, // None + DbgOutputKdb = 0x1, // Output to Kernel Debugger + DbgOutputLogFile = 0x2, // Output to LogFile + DbgOutputTruncate = 0x4, // Truncate Log File if necessary + DbgOutputStderr = 0x8, // Send output to std error + DbgOutputBackup = 0x10, // Make backup of debug file ? + DbgOutputMemory = 0x20, // Dump to memory buffer + DbgOutputAll = 0xFFFFFFFF // All the bits set. + }; + + +# define MAX_LABEL_LENGTH ( 100) + + +// The following flags are used internally to track what level of tracing we +// are currently using. Bitmapped for extensibility. +#define DEBUG_FLAG_ODS 0x00000001 +//#define DEBUG_FLAG_INFO 0x00000002 +//#define DEBUG_FLAG_WARN 0x00000004 +//#define DEBUG_FLAG_ERROR 0x00000008 +// The following are used internally to determine whether to log or not based +// on what the current state is +//#define DEBUG_FLAGS_INFO (DEBUG_FLAG_ODS | DEBUG_FLAG_INFO) +//#define DEBUG_FLAGS_WARN (DEBUG_FLAG_ODS | DEBUG_FLAG_INFO | DEBUG_FLAG_WARN) +//#define DEBUG_FLAGS_ERROR (DEBUG_FLAG_ODS | DEBUG_FLAG_INFO | DEBUG_FLAG_WARN | DEBUG_FLAG_ERROR) + +#define DEBUG_FLAGS_ANY (DEBUG_FLAG_INFO | DEBUG_FLAG_WARN | DEBUG_FLAG_ERROR) + +// +// user of DEBUG infrastructure may choose unique variable name for DEBUG_FLAGS +// that's specially useful for cases where DEBUG infrastructure is used within +// static library (static library may prefer to maintain it's own DebugFlags independent +// on the main program it links to +// +#ifndef DEBUG_FLAGS_VAR +#define DEBUG_FLAGS_VAR g_dwDebugFlags +#endif + +extern +#ifdef __cplusplus +"C" +# endif // _cplusplus + DWORD DEBUG_FLAGS_VAR ; // Debugging Flags + +# define DECLARE_DEBUG_VARIABLE() + +# define SET_DEBUG_FLAGS( dwFlags) DEBUG_FLAGS_VAR = dwFlags +# define GET_DEBUG_FLAGS() ( DEBUG_FLAGS_VAR ) + +# define LOAD_DEBUG_FLAGS_FROM_REG(hkey, dwDefault) \ + DEBUG_FLAGS_VAR = PuLoadDebugFlagsFromReg((hkey), (dwDefault)) + +# define LOAD_DEBUG_FLAGS_FROM_REG_STR(pszRegKey, dwDefault) \ + DEBUG_FLAGS_VAR = PuLoadDebugFlagsFromRegStr((pszRegKey), (dwDefault)) + +# define SAVE_DEBUG_FLAGS_IN_REG(hkey, dwDbg) \ + PuSaveDebugFlagsInReg((hkey), (dwDbg)) + +# define DEBUG_IF( arg, s) if ( DEBUG_ ## arg & GET_DEBUG_FLAGS()) { \ + s \ + } else {} + +# define IF_DEBUG( arg) if ( DEBUG_## arg & GET_DEBUG_FLAGS()) + + +/*++ + class DEBUG_PRINTS + + This class is responsible for printing messages to log file / kernel debugger + + Currently the class supports only member functions for char. + ( not unicode-strings). + +--*/ + + +typedef struct _DEBUG_PRINTS { + + CHAR m_rgchLabel[MAX_LABEL_LENGTH]; + CHAR m_rgchLogFilePath[MAX_PATH]; + CHAR m_rgchLogFileName[MAX_PATH]; + HANDLE m_LogFileHandle; + HANDLE m_StdErrHandle; + BOOL m_fInitialized; + BOOL m_fBreakOnAssert; + DWORD m_dwOutputFlags; + VOID *m_pMemoryLog; +} DEBUG_PRINTS, FAR * LPDEBUG_PRINTS; + + +LPDEBUG_PRINTS +PuCreateDebugPrintsObject( + IN const char * pszPrintLabel, + IN DWORD dwOutputFlags); + +// +// frees the debug prints object and closes any file if necessary. +// Returns NULL on success or returns pDebugPrints on failure. +// +LPDEBUG_PRINTS +PuDeleteDebugPrintsObject( + IN_OUT LPDEBUG_PRINTS pDebugPrints); + + +VOID +PuDbgPrint( + IN_OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFilePath, + IN int nLineNum, + IN const char * pszFunctionName, + IN const char * pszFormat, + ...); + // arglist +VOID +PuDbgPrintW( + IN_OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFilePath, + IN int nLineNum, + IN const char * pszFunctionName, + IN const WCHAR * pszFormat, + ...); // arglist + +// PuDbgPrintError is similar to PuDbgPrint() but allows +// one to print error code in friendly manner +VOID +PuDbgPrintError( + IN_OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFilePath, + IN int nLineNum, + IN const char * pszFunctionName, + IN DWORD dwError, + IN const char * pszFormat, + ...); // arglist + +/*++ + PuDbgDump() does not do any formatting of output. + It just dumps the given message onto the debug destinations. +--*/ +VOID +PuDbgDump( + IN_OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFilePath, + IN int nLineNum, + IN const char * pszFunctionName, + IN const char * pszDump + ); + +// +// PuDbgAssertFailed() *must* be __cdecl to properly capture the +// thread context at the time of the failure. +// + +INT +__cdecl +PuDbgAssertFailed( + IN_OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFilePath, + IN int nLineNum, + IN const char * pszFunctionName, + IN const char * pszExpression, + IN const char * pszMessage); + +INT +WINAPI +PuDbgPrintAssertFailed( + IN_OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFilePath, + IN int nLineNum, + IN const char * pszFunctionName, + IN const char * pszExpression, + IN const char * pszMessage); + +VOID +PuDbgCaptureContext ( + OUT PCONTEXT ContextRecord + ); + +VOID +PuDbgPrintCurrentTime( + IN_OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFilePath, + IN int nLineNum, + IN const char * pszFunctionName + ); + +VOID +PuSetDbgOutputFlags( + IN_OUT LPDEBUG_PRINTS pDebugPrints, + IN DWORD dwFlags); + +DWORD +PuGetDbgOutputFlags( + IN const LPDEBUG_PRINTS pDebugPrints); + + +// +// Following functions return Win32 error codes. +// NO_ERROR if success +// + +DWORD +PuOpenDbgPrintFile( + IN_OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFileName, + IN const char * pszPathForFile); + +DWORD +PuReOpenDbgPrintFile( + IN_OUT LPDEBUG_PRINTS pDebugPrints); + +DWORD +PuCloseDbgPrintFile( + IN_OUT LPDEBUG_PRINTS pDebugPrints); + +DWORD +PuOpenDbgMemoryLog( + IN_OUT LPDEBUG_PRINTS pDebugPrints); + +DWORD +PuCloseDbgMemoryLog( + IN_OUT LPDEBUG_PRINTS pDebugPrints); + +DWORD +PuLoadDebugFlagsFromReg(IN HKEY hkey, IN DWORD dwDefault); + +DWORD +PuLoadDebugFlagsFromRegStr(IN LPCSTR pszRegKey, IN DWORD dwDefault); + +DWORD +PuSaveDebugFlagsInReg(IN HKEY hkey, IN DWORD dwDbg); + + +# define PuPrintToKdb( pszOutput) \ + if ( pszOutput != NULL) { \ + OutputDebugString( pszOutput); \ + } else {} + + + +# ifdef __cplusplus +}; +# endif // __cplusplus + +// begin_user_unmodifiable + + + +/*********************************************************** + * Macros + ************************************************************/ + + +extern +#ifdef __cplusplus +"C" +# endif // _cplusplus +DEBUG_PRINTS * g_pDebug; // define a global debug variable + +# if DBG + +// For the CHK build we want ODS enabled. For an explanation of these flags see +// the comment just after the definition of DBG_CONTEXT +# define DECLARE_DEBUG_PRINTS_OBJECT() \ + DEBUG_PRINTS * g_pDebug = NULL; \ + DWORD DEBUG_FLAGS_VAR = DEBUG_FLAG_ERROR; + +#else // !DBG + +# define DECLARE_DEBUG_PRINTS_OBJECT() \ + DEBUG_PRINTS * g_pDebug = NULL; \ + DWORD DEBUG_FLAGS_VAR = 0; + +#endif // !DBG + + +// +// Call the following macro as part of your initialization for program +// planning to use the debugging class. +// +/** DEBUGDEBUG +# define CREATE_DEBUG_PRINT_OBJECT( pszLabel) \ + g_pDebug = PuCreateDebugPrintsObject( pszLabel, DEFAULT_OUTPUT_FLAGS);\ + if ( g_pDebug == NULL) { \ + OutputDebugStringA( "Unable to Create Debug Print Object \n"); \ + } +*/ + +// +// Call the following macro once as part of the termination of program +// which uses the debugging class. +// +# define DELETE_DEBUG_PRINT_OBJECT( ) \ + g_pDebug = PuDeleteDebugPrintsObject( g_pDebug); + + +# define VALID_DEBUG_PRINT_OBJECT() \ + ( ( g_pDebug != NULL) && g_pDebug->m_fInitialized) + + +// +// Use the DBG_CONTEXT without any surrounding braces. +// This is used to pass the values for global DebugPrintObject +// and File/Line information +// +//# define DBG_CONTEXT g_pDebug, __FILE__, __LINE__, __FUNCTION__ + +// The 3 main tracing macros, each one corresponds to a different level of +// tracing + +// The 3 main tracing macros, each one corresponds to a different level of +// tracing +//# define DBGINFO(args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_INFO) { PuDbgPrint args; }} +//# define DBGWARN(args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_WARN) { PuDbgPrint args; }} +//# define DBGERROR(args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_ERROR) { PuDbgPrint args; }} + +# define DBGINFOW(args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_INFO) { PuDbgPrintW args; }} +# define DBGWARNW(args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_WARN) { PuDbgPrintW args; }} +# define DBGERRORW(args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_ERROR) { PuDbgPrintW args; }} + + +// +// DBGPRINTF() is printing function ( much like printf) but always called +// with the DBG_CONTEXT as follows +// DBGPRINTF( ( DBG_CONTEXT, format-string, arguments for format list)); +// +# define DBGPRINTF DBGINFO + +// +// DPERROR() is printing function ( much like printf) but always called +// with the DBG_CONTEXT as follows +// DPERROR( ( DBG_CONTEXT, error, format-string, +// arguments for format list)); +// +# define DPERROR( args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_ERROR) { PuDbgPrintError args; }} + +# if DBG + +# define DBG_CODE(s) s /* echoes code in debugging mode */ + +// The same 3 main tracing macros however in this case the macros are only compiled +// into the CHK build. This is necessary because some tracing info used functions or +// variables which are not compiled into the FRE build. +# define CHKINFO(args) { PuDbgPrint args; } +# define CHKWARN(args) { PuDbgPrint args; } +# define CHKERROR(args) { PuDbgPrint args; } + +# define CHKINFOW(args) { PuDbgPrintW args; } +# define CHKWARNW(args) { PuDbgPrintW args; } +# define CHKERRORW(args) { PuDbgPrintW args; } + + +#ifndef DBG_ASSERT +# ifdef _PREFAST_ +# define DBG_ASSERT(exp) ((void)0) /* Do Nothing */ +# define DBG_ASSERT_MSG(exp, pszMsg) ((void)0) /* Do Nothing */ +# define DBG_REQUIRE( exp) ((void) (exp)) +# else // !_PREFAST_ +# define DBG_ASSERT( exp ) \ + ( (VOID)( ( exp ) || ( DebugBreak(), \ + PuDbgPrintAssertFailed( DBG_CONTEXT, #exp, "" ) ) ) ) + +# define DBG_ASSERT_MSG( exp, pszMsg) \ + ( (VOID)( ( exp ) || ( DebugBreak(), \ + PuDbgPrintAssertFailed( DBG_CONTEXT, #exp, pszMsg ) ) ) ) + +# define DBG_REQUIRE( exp ) \ + DBG_ASSERT( exp ) +# endif // !_PREFAST_ +#endif + + +# define DBG_LOG() PuDbgPrint( DBG_CONTEXT, "\n" ) + +# define DBG_OPEN_LOG_FILE( pszFile, pszPath ) \ + PuOpenDbgPrintFile( g_pDebug, (pszFile), (pszPath) ) + +# define DBG_CLOSE_LOG_FILE( ) \ + PuCloseDbgPrintFile( g_pDebug ) + +# define DBG_OPEN_MEMORY_LOG( ) \ + PuOpenDbgMemoryLog( g_pDebug ) + + +# define DBGDUMP( args ) PuDbgDump args + +# define DBGPRINT_CURRENT_TIME() PuDbgPrintCurrentTime( DBG_CONTEXT ) + +# else // !DBG + +# define DBG_CODE(s) ((void)0) /* Do Nothing */ + +# define CHKINFO(args) ((void)0) /* Do Nothing */ +# define CHKWARN(args) ((void)0) /* Do Nothing */ +# define CHKERROR(args) ((void)0) /* Do Nothing */ + +# define CHKINFOW(args) ((void)0) /* Do Nothing */ +# define CHKWARNW(args) ((void)0) /* Do Nothing */ +# define CHKERRORW(args) ((void)0) /* Do Nothing */ + +#ifndef DBG_ASSERT +# define DBG_ASSERT(exp) ((void)0) /* Do Nothing */ + +# define DBG_ASSERT_MSG(exp, pszMsg) ((void)0) /* Do Nothing */ + +# define DBG_REQUIRE( exp) ((void) (exp)) +#endif // !DBG_ASSERT + +# define DBGDUMP( args) ((void)0) /* Do nothing */ + +# define DBG_LOG() ((void)0) /* Do Nothing */ + +# define DBG_OPEN_LOG_FILE( pszFile, pszPath) ((void)0) /* Do Nothing */ + +# define DBG_OPEN_MEMORY_LOG() ((void)0) /* Do Nothing */ + +# define DBG_CLOSE_LOG_FILE() ((void)0) /* Do Nothing */ + +# define DBGPRINT_CURRENT_TIME() ((void)0) /* Do Nothing */ + +# endif // !DBG + + +// end_user_unmodifiable + +// begin_user_unmodifiable + + +#ifdef ASSERT +# undef ASSERT +#endif + + +# define ASSERT( exp) DBG_ASSERT( exp) + + +// end_user_unmodifiable + +// begin_user_modifiable + +// +// Debugging constants consist of two pieces. +// All constants in the range 0x0 to 0x8000 are reserved +// User extensions may include additional constants (bit flags) +// + +# define DEBUG_API_ENTRY 0x00000001L +# define DEBUG_API_EXIT 0x00000002L +# define DEBUG_INIT_CLEAN 0x00000004L +# define DEBUG_ERROR 0x00000008L + + // End of Reserved Range +# define DEBUG_RESERVED 0x00000FFFL + +// end_user_modifiable + + + +/*********************************************************** + * Platform Type related variables and macros + ************************************************************/ + +// +// Enum for product types +// + +typedef enum _PLATFORM_TYPE { + + PtInvalid = 0, // Invalid + PtNtWorkstation = 1, // NT Workstation + PtNtServer = 2, // NT Server + +} PLATFORM_TYPE; + +// +// IISGetPlatformType is the function used to the platform type +// + +extern +#ifdef __cplusplus +"C" +# endif // _cplusplus +PLATFORM_TYPE +IISGetPlatformType( + VOID + ); + +// +// External Macros +// + +#define InetIsNtServer( _pt ) ((_pt) == PtNtServer) +#define InetIsNtWksta( _pt ) ((_pt) == PtNtWorkstation) +#define InetIsValidPT(_pt) ((_pt) != PtInvalid) + +extern +#ifdef __cplusplus +"C" +# endif // _cplusplus +PLATFORM_TYPE g_PlatformType; + + +// Use the DECLARE_PLATFORM_TYPE macro to declare the platform type +#define DECLARE_PLATFORM_TYPE() \ + PLATFORM_TYPE g_PlatformType = PtInvalid; + +// Use the INITIALIZE_PLATFORM_TYPE to init the platform type +// This should typically go inside the DLLInit or equivalent place. +#define INITIALIZE_PLATFORM_TYPE() \ + g_PlatformType = IISGetPlatformType(); + +// +// Additional Macros to use the Platform Type +// + +#define TsIsNtServer( ) InetIsNtServer(g_PlatformType) +#define TsIsNtWksta( ) InetIsNtWksta(g_PlatformType) +#define IISIsValidPlatform() InetIsValidPT(g_PlatformType) +#define IISPlatformType() (g_PlatformType) + + +/*********************************************************** + * Some utility functions for Critical Sections + ************************************************************/ + +// +// IISSetCriticalSectionSpinCount() provides a thunk for the +// original NT4.0sp3 API SetCriticalSectionSpinCount() for CS with Spin counts +// Users of this function should definitely dynlink with kernel32.dll, +// Otherwise errors will surface to a large extent +// +extern +# ifdef __cplusplus +"C" +# endif // _cplusplus +DWORD +IISSetCriticalSectionSpinCount( + LPCRITICAL_SECTION lpCriticalSection, + DWORD dwSpinCount +); + + +// +// Macro for the calls to SetCriticalSectionSpinCount() +// +# define SET_CRITICAL_SECTION_SPIN_COUNT( lpCS, dwSpins) \ + IISSetCriticalSectionSpinCount( (lpCS), (dwSpins)) + +// +// IIS_DEFAULT_CS_SPIN_COUNT is the default value of spins used by +// Critical sections defined within IIS. +// NYI: We should have to switch the individual values based on experiments! +// Current value is an arbitrary choice +// +# define IIS_DEFAULT_CS_SPIN_COUNT (1000) + +// +// Initializes a critical section and sets its spin count +// to IIS_DEFAULT_CS_SPIN_COUNT. Equivalent to +// InitializeCriticalSectionAndSpinCount(lpCS, IIS_DEFAULT_CS_SPIN_COUNT), +// but provides a safe thunking layer for older systems that don't provide +// this API. +// +extern +# ifdef __cplusplus +"C" +# endif // _cplusplus +BOOL +IISInitializeCriticalSection( + LPCRITICAL_SECTION lpCriticalSection +); + +// +// Macro for the calls to InitializeCriticalSection() +// +# define INITIALIZE_CRITICAL_SECTION(lpCS) IISInitializeCriticalSection(lpCS) + +# endif /* _DEBUG_HXX_ */ + +// +// The following macros allow the automatic naming of certain Win32 objects. +// See IIS\SVCS\IISRTL\WIN32OBJ.C for details on the naming convention. +// +// Set IIS_NAMED_WIN32_OBJECTS to a non-zero value to enable named events, +// semaphores, and mutexes. +// + +#if DBG +#define IIS_NAMED_WIN32_OBJECTS 1 +#else +#define IIS_NAMED_WIN32_OBJECTS 0 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +HANDLE +PuDbgCreateEvent( + __in LPSTR FileName, + IN ULONG LineNumber, + __in LPSTR MemberName, + IN PVOID Address, + IN BOOL ManualReset, + IN BOOL InitialState + ); + +HANDLE +PuDbgCreateSemaphore( + __in LPSTR FileName, + IN ULONG LineNumber, + __in LPSTR MemberName, + IN PVOID Address, + IN LONG InitialCount, + IN LONG MaximumCount + ); + +HANDLE +PuDbgCreateMutex( + __in LPSTR FileName, + IN ULONG LineNumber, + __in LPSTR MemberName, + IN PVOID Address, + IN BOOL InitialOwner + ); + +#ifdef __cplusplus +} // extern "C" +#endif + +#if IIS_NAMED_WIN32_OBJECTS + +#define IIS_CREATE_EVENT( membername, address, manual, state ) \ + PuDbgCreateEvent( \ + (LPSTR)__FILE__, \ + (ULONG)__LINE__, \ + (membername), \ + (PVOID)(address), \ + (manual), \ + (state) \ + ) + +#define IIS_CREATE_SEMAPHORE( membername, address, initial, maximum ) \ + PuDbgCreateSemaphore( \ + (LPSTR)__FILE__, \ + (ULONG)__LINE__, \ + (membername), \ + (PVOID)(address), \ + (initial), \ + (maximum) \ + ) + +#define IIS_CREATE_MUTEX( membername, address, initial ) \ + PuDbgCreateMutex( \ + (LPSTR)__FILE__, \ + (ULONG)__LINE__, \ + (membername), \ + (PVOID)(address), \ + (initial) \ + ) + +#else // !IIS_NAMED_WIN32_OBJECTS + +#define IIS_CREATE_EVENT( membername, address, manual, state ) \ + CreateEventA( \ + NULL, \ + (manual), \ + (state), \ + NULL \ + ) + +#define IIS_CREATE_SEMAPHORE( membername, address, initial, maximum ) \ + CreateSemaphoreA( \ + NULL, \ + (initial), \ + (maximum), \ + NULL \ + ) + +#define IIS_CREATE_MUTEX( membername, address, initial ) \ + CreateMutexA( \ + NULL, \ + (initial), \ + NULL \ + ) + +#endif // IIS_NAMED_WIN32_OBJECTS + + +/************************ End of File ***********************/ + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj new file mode 100644 index 0000000000..257df53c47 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj @@ -0,0 +1,78 @@ + + + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + 15.0 + {A2599642-CBE5-4230-8511-3DC2D81874BE} + Win32Proj + reftrace + + + + StaticLibrary + v141 + + + true + + + + $(ProjectDir)include;$(IIS-Common)Include;$(IncludePath) + + + + true + precomp.hxx + _LIB;%(PreprocessorDefinitions) + + + Windows + + + + + + This project is trying to import a missing file: {0}. + + + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj.filters b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj.filters new file mode 100644 index 0000000000..b77ab9c7c1 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj.filters @@ -0,0 +1,54 @@ + + + + + {aaa5bb99-ba5c-4b8d-9ef9-a406282e05a6} + + + {85a83b74-9536-44d0-a7f7-96e1475f21e9} + + + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + + + include + + + include + + + include + + + include + + + include + + + include + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/irtldbg.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/irtldbg.cpp new file mode 100644 index 0000000000..06ce025bbe --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/irtldbg.cpp @@ -0,0 +1,150 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.hxx" + +#include +#include +#include +#include +#include + +#define IMPLEMENTATION_EXPORT +#include + + +void __cdecl +IrtlTrace( + LPCTSTR ptszFormat, + ...) +{ + TCHAR tszBuff[2048]; + va_list args; + + va_start(args, ptszFormat); + _vsntprintf_s(tszBuff, sizeof(tszBuff) / sizeof(tszBuff[0]), _TRUNCATE, ptszFormat, args); + va_end(args); + + DBGPRINTF(( DBG_CONTEXT, "%ls", tszBuff )); +} + + + +#ifdef IRTLDEBUG + +# if defined(USE_DEBUG_CRTS) && defined(_MSC_VER) && (_MSC_VER >= 1000) + + +# ifdef IRTLDBG_RUNNING_AS_SERVICE + +// The default assertion mechanism set up by Visual C++ 4 will not +// work with Active Server Pages because it's running inside a service +// and there is no desktop to interact with. + +// Note: for this to work properly, #define _WIN32_WINNT 0x400 before +// including or MB_SERVICE_NOTIFICATION won't be #define'd. + +int __cdecl +AspAssertHandler( + int nReportType, + char* pszErrorText, + int* pnReturn) +{ + const char szInfo[] = " (Press ABORT to terminate IIS," + " RETRY to debug this failure," + " or IGNORE to continue.)"; + char* pszMessageTitle = NULL; + int nResult = FALSE; + + *pnReturn = 0; // nothing for _CrtDbgReport to do + + // These flags enable message boxes to show up on the user's console + switch (nReportType) + { + case _CRT_WARN: + // If using MFC's TRACE macro (AfxTrace), the report hook + // (AspAssertHandler) will get called with _CRT_WARN. Ignore. + pszMessageTitle = "Warning"; + *pnReturn = 0; + return FALSE; + + case _CRT_ERROR: + pszMessageTitle = "Fatal Error"; + break; + + case _CRT_ASSERT: + pszMessageTitle = "Assertion Failed"; + break; + } + + char* pszMessageText = + static_cast(malloc(strlen(pszErrorText) + strlen(szInfo) + 1)); + + if (NULL == pszMessageText) + return FALSE; + + strcpy(pszMessageText, pszErrorText); + strcat(pszMessageText, szInfo); + + const int n = MessageBoxA(NULL, pszMessageText, pszMessageTitle, + (MB_SERVICE_NOTIFICATION | MB_TOPMOST + | MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION)); + + if (n == IDABORT) + { + exit(1); + } + else if (n == IDRETRY) + { + *pnReturn = 1; // tell _CrtDbgReport to start the debugger + nResult = TRUE; // tell _CrtDbgReport to run + } + + free(pszMessageText); + + return nResult; +} +# endif // IRTLDBG_RUNNING_AS_SERVICE +# endif // _MSC_VER >= 1000 + + + +void +IrtlDebugInit() +{ +# if defined(USE_DEBUG_CRTS) && defined(_MSC_VER) && (_MSC_VER >= 1000) +# ifdef IRTLDBG_RUNNING_AS_SERVICE + // If we end up in _CrtDbgReport, don't put up a message box + // _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG); + + // Use AspAssertHandler to put up a message box instead + _CrtSetReportHook(AspAssertHandler); +# endif // IRTLDBG_RUNNING_AS_SERVICE + + + // Enable debug heap allocations & check for memory leaks at program exit + // The memory leak check will not be performed if inetinfo.exe is + // run directly under a debugger, only if it is run as a service. + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF + | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)); +# endif // _MSC_VER >= 1000 +} + + + +void +IrtlDebugTerm() +{ +# if defined(USE_DEBUG_CRTS) && defined(_MSC_VER) && (_MSC_VER >= 1000) +# ifdef IRTLDBG_RUNNING_AS_SERVICE + // Turn off AspAssertHandler, so that we don't get numerous message boxes + // if there are memory leaks on shutdown + _CrtSetReportHook(NULL); +# endif // IRTLDBG_RUNNING_AS_SERVICE +# endif // _MSC_VER >= 1000 +} + +#endif //IRTLDEBUG + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/isplat.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/isplat.cxx new file mode 100644 index 0000000000..eb13b3edde --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/isplat.cxx @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.hxx" +#include "pudebug.h" + +#define IMPLEMENTATION_EXPORT + +extern "C" +PLATFORM_TYPE +IISGetPlatformType( + VOID +) +/*++ + + This function consults the registry and determines the platform type + for this machine. + + Arguments: + + None + + Returns: + Platform type + +--*/ +{ + OSVERSIONINFOEX osVersionInfoEx = { 0 }; + DWORDLONG dwlConditionMask = 0; + BOOL fReturn = FALSE; + + osVersionInfoEx.dwOSVersionInfoSize = sizeof( osVersionInfoEx ); + + // + // If we are not workstation (Client) + // that means that we are a server or domain controller (Server) + // + osVersionInfoEx.wProductType = VER_NT_WORKSTATION; + VER_SET_CONDITION( dwlConditionMask, VER_PRODUCT_TYPE, VER_EQUAL ); + + fReturn = VerifyVersionInfo( + &osVersionInfoEx, + VER_PRODUCT_TYPE, + dwlConditionMask ); + + // + // VerifyVersionInfo fails if the return value is zero + // and GetLastError returns an error code other than ERROR_OLD_WIN_VERSION + // + if ( !fReturn && GetLastError() != ERROR_OLD_WIN_VERSION ) + { + DPERROR(( DBG_CONTEXT, + HRESULT_FROM_WIN32 ( GetLastError() ), + "VerifyVersionInfo failed\n" )); + + return PtInvalid; + } + + return ( fReturn ) ? PtNtWorkstation : PtNtServer; +} + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/memorylog.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/memorylog.cxx new file mode 100644 index 0000000000..6f303f94e0 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/memorylog.cxx @@ -0,0 +1,123 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.hxx" +#include "memorylog.hxx" +#include "pudebug.h" + +CMemoryLog::CMemoryLog(DWORD dwMaxByteSize) : + m_fValid(FALSE), + m_fCritSecInitialized(FALSE) +{ + BOOL fRet; + + fRet = m_buf.Resize(dwMaxByteSize); + if (fRet) + { + m_fValid = TRUE; + } + + m_pBufferBegin = (CHAR*) m_buf.QueryPtr(); + m_pLastMessageEnd = (CHAR*) m_buf.QueryPtr(); + m_pBufferEnd = ((CHAR*) m_buf.QueryPtr()) + m_buf.QuerySize(); + + fRet = InitializeCriticalSectionAndSpinCount(&m_cs, + 0x80000000 /* precreate event */ | + IIS_DEFAULT_CS_SPIN_COUNT ); + if (FALSE != fRet) + { + m_fCritSecInitialized = TRUE; + } + +} + +CMemoryLog::~CMemoryLog() +{ + m_pBufferBegin = NULL; + m_pLastMessageEnd = NULL; + m_pBufferEnd = NULL; + m_fValid = FALSE; + + if (m_fCritSecInitialized) + { + DeleteCriticalSection(&m_cs); + m_fCritSecInitialized = FALSE; + } +} + +// +// Appends to end of the circular memory log. +// +DWORD +CMemoryLog::Append(LPCSTR pszOutput, + DWORD cchLen + ) +{ + // make sure internal state can accept this request + if (FALSE == m_fValid || + FALSE == m_fCritSecInitialized ) + { + return ERROR_NOT_ENOUGH_MEMORY; + } + + // make sure that we won't think we need less + // memory than we do. We are going to add 1 to + // this value next, so if it is MAX_UINT then + // we will wrap on the add. Don't allow strings + // that are that long. + if ( (ULONGLONG)cchLen + 1 > MAXDWORD ) + { + return ERROR_ARITHMETIC_OVERFLOW; + } + + // make sure the string length will fit inside the buffer + if ( cchLen + 1 > m_buf.QuerySize()) + { + return ERROR_NOT_ENOUGH_MEMORY; + } + + CHAR * pWhereToWriteMessage = NULL; + + // need to synchronize access to m_pLastMessageEnd + EnterCriticalSection(&m_cs); + + // check if the new message will fit into the remaining space in the buffer + // previous end (+1) + new length + 1 for NULL + if (m_pLastMessageEnd + cchLen + 1 < m_pBufferEnd) + { + // it will fit in remaining space + pWhereToWriteMessage = m_pLastMessageEnd; + } + else + { + // start over at the beginning + pWhereToWriteMessage = (CHAR*)m_buf.QueryPtr(); + + // don't leave extra old goo sitting around in the buffer + ZeroMemory(m_pLastMessageEnd, m_pBufferEnd - m_pLastMessageEnd); + } + + // set end of message to pWhere + length + 1 for NULL + m_pLastMessageEnd = pWhereToWriteMessage + cchLen + 1; + + LeaveCriticalSection(&m_cs); + + // the following memcpy is outside of the criticalsection - + // this introduces a race between leaving the criticalsection and + // looping back through the buffer before we finish writing. + // how likely is this? Not very. + // + // In addition - moving the memcpy inside of the critsec makes the time spent + // quite a bit larger than some simple load/stores that are currently there. + // + // Plus this is a debugging aid - life isn't fair. + + // actually do the copy + memcpy(pWhereToWriteMessage, pszOutput, cchLen); + + // write out a NULL to indicate end of message + *(pWhereToWriteMessage + cchLen) = NULL; + + return NO_ERROR; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/pudebug.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/pudebug.cxx new file mode 100644 index 0000000000..44e42a21b1 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/pudebug.cxx @@ -0,0 +1,1164 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +/************************************************************ + * Include Headers + ************************************************************/ +# include "precomp.hxx" + + +# include +# include +# include +# include +# include + + +# include "pudebug.h" +# include "memorylog.hxx" + + +/************************************************************* + * Global Variables and Default Values + *************************************************************/ + +// +// TRUE if we're in a test process. +// There are a few noisy assertions that fire frequently cause of test code issues. These noisy asserts are masking +// real ones, drastically reducing the value of CHK bits. +// +BOOL g_fTestProcess = FALSE; + +// +// HACK HACK +// suppress shutdown asserts under some hosts +// +BOOL g_fAvoidShutdownAsserts = FALSE; + +# define MAX_PRINTF_OUTPUT ( 10240) + +# define DEFAULT_DEBUG_FLAGS_VALUE ( 0) +# define DEBUG_FLAGS_REGISTRY_LOCATION_A "DebugFlags" +# define DEBUG_BREAK_ENABLED_REGKEYNAME_A "BreakOnAssert" + +/************************************************************* + * Functions + *************************************************************/ + +/********************************************************************++ + +Routine Description: + This function creates a new DEBUG_PRINTS object for the required + program. + +Arguments: + pszPrintLabel pointer to null-terminated string containing + the label for program's debugging output + dwOutputFlags DWORD containing the output flags to be used. + +Returns: + pointer to a new DEBUG_PRINTS object on success. + Returns NULL on failure. +--*********************************************************************/ +LPDEBUG_PRINTS +PuCreateDebugPrintsObject( + IN const char * pszPrintLabel, + IN DWORD dwOutputFlags) +{ + + LPDEBUG_PRINTS pDebugPrints; + + pDebugPrints = (LPDEBUG_PRINTS ) GlobalAlloc( GPTR, sizeof( DEBUG_PRINTS)); + + if ( pDebugPrints != NULL) { + + if ( strlen( pszPrintLabel) < MAX_LABEL_LENGTH) { + + strcpy_s( pDebugPrints->m_rgchLabel, + sizeof( pDebugPrints->m_rgchLabel ) / sizeof( pDebugPrints->m_rgchLabel[0]), + pszPrintLabel); + } else { + strncpy_s( pDebugPrints->m_rgchLabel, + sizeof( pDebugPrints->m_rgchLabel ) / sizeof( pDebugPrints->m_rgchLabel[0]), + pszPrintLabel, + MAX_LABEL_LENGTH - 1); + } + + memset( pDebugPrints->m_rgchLogFilePath, 0, MAX_PATH); + memset( pDebugPrints->m_rgchLogFileName, 0, MAX_PATH); + + pDebugPrints->m_LogFileHandle = INVALID_HANDLE_VALUE; + + pDebugPrints->m_dwOutputFlags = dwOutputFlags; + pDebugPrints->m_StdErrHandle = GetStdHandle( STD_ERROR_HANDLE); + + if ( pDebugPrints->m_StdErrHandle == NULL ) + { + pDebugPrints->m_StdErrHandle = INVALID_HANDLE_VALUE; + } + + pDebugPrints->m_fInitialized = TRUE; + pDebugPrints->m_fBreakOnAssert= TRUE; + pDebugPrints->m_pMemoryLog = NULL; + } + + + return ( pDebugPrints); +} // PuCreateDebugPrintsObject() + + + + +/********************************************************************++ + +Routine Description: + This function cleans up the pDebugPrints object and + frees the allocated memory. + + Arguments: + pDebugPrints poitner to the DEBUG_PRINTS object. + + Returns: + NULL on success. + pDebugPrints() if the deallocation failed. + +--*********************************************************************/ +LPDEBUG_PRINTS +PuDeleteDebugPrintsObject( + IN OUT LPDEBUG_PRINTS pDebugPrints) +{ + if ( pDebugPrints != NULL) { + + PuCloseDbgMemoryLog(pDebugPrints); + DWORD dwError = PuCloseDbgPrintFile( pDebugPrints); + + if ( dwError != NO_ERROR) { + + SetLastError( dwError); + } else { + + // returns NULL on success + pDebugPrints = + (LPDEBUG_PRINTS ) GlobalFree( pDebugPrints); + } + } + + return ( pDebugPrints); + +} // PuDeleteDebugPrintsObject() + + + + +VOID +PuSetDbgOutputFlags( + IN OUT LPDEBUG_PRINTS pDebugPrints, + IN DWORD dwFlags) +{ + + if ( pDebugPrints == NULL) { + + SetLastError( ERROR_INVALID_PARAMETER); + } else { + + pDebugPrints->m_dwOutputFlags = dwFlags; + } + + return; +} // PuSetDbgOutputFlags() + + + +DWORD +PuGetDbgOutputFlags( + IN const LPDEBUG_PRINTS pDebugPrints) +{ + return ( pDebugPrints != NULL) ? pDebugPrints->m_dwOutputFlags : 0; + +} // PuGetDbgOutputFlags() + + +static DWORD +PuOpenDbgFileLocal( + IN OUT LPDEBUG_PRINTS pDebugPrints) +{ + if ( pDebugPrints == NULL) + return ERROR_INVALID_PARAMETER; + + if ( pDebugPrints->m_LogFileHandle != INVALID_HANDLE_VALUE) { + + // + // Silently return as a file handle exists. + // + return ( NO_ERROR); + } + + pDebugPrints->m_LogFileHandle = + CreateFileA( pDebugPrints->m_rgchLogFileName, + GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if ( pDebugPrints->m_LogFileHandle == INVALID_HANDLE_VALUE) { + + CHAR pchBuffer[1024]; + DWORD dwError = GetLastError(); + + sprintf_s( pchBuffer, + sizeof( pchBuffer ) / sizeof( pchBuffer[0] ), + " Critical Error: Unable to Open File %s. Error = %d\n", + pDebugPrints->m_rgchLogFileName, dwError); + OutputDebugStringA( pchBuffer); + + return ( dwError); + } + + return ( NO_ERROR); +} // PuOpenDbgFileLocal() + + + + + +DWORD +PuOpenDbgPrintFile( + IN OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFileName, + IN const char * pszPathForFile) +/********************************************************************++ + + Opens a Debugging log file. This function can be called to set path + and name of the debugging file. + + Arguments: + pszFileName pointer to null-terminated string containing + the name of the file. + + pszPathForFile pointer to null-terminated string containing the + path for the given file. + If NULL, then the old place where dbg files were + stored is used or if none, + default windows directory will be used. + + Returns: + Win32 error codes. NO_ERROR on success. + +--*********************************************************************/ + +{ + if ( pszFileName == NULL || pDebugPrints == NULL) { + + return ( ERROR_INVALID_PARAMETER); + } + + // + // Setup the Path information. if necessary. + // + + if ( pszPathForFile != NULL) { + + // Path is being changed. + + if ( strlen( pszPathForFile) < MAX_PATH) { + + strcpy_s( pDebugPrints->m_rgchLogFilePath, + sizeof( pDebugPrints->m_rgchLogFilePath ) / sizeof( pDebugPrints->m_rgchLogFilePath[0] ), + pszPathForFile); + } else { + + return ( ERROR_INVALID_PARAMETER); + } + } else { + + if ( pDebugPrints->m_rgchLogFilePath[0] == '\0' && // no old path + !GetWindowsDirectoryA( pDebugPrints->m_rgchLogFilePath, MAX_PATH)) { + + // + // Unable to get the windows default directory. Use current dir + // + + strcpy_s( pDebugPrints->m_rgchLogFilePath, + sizeof( pDebugPrints->m_rgchLogFilePath ) / sizeof( pDebugPrints->m_rgchLogFilePath[0] ), + "."); + } + } + + // + // Should need be, we need to create this directory for storing file + // + + + // + // Form the complete Log File name and open the file. + // + if ( (strlen( pszFileName) + strlen( pDebugPrints->m_rgchLogFilePath)) + >= MAX_PATH) { + + return ( ERROR_NOT_ENOUGH_MEMORY); + } + + // form the complete path + strcpy_s( pDebugPrints->m_rgchLogFileName, + sizeof( pDebugPrints->m_rgchLogFileName ) / sizeof( pDebugPrints->m_rgchLogFileName[0] ), + pDebugPrints->m_rgchLogFilePath); + + if ( pDebugPrints->m_rgchLogFileName[ strlen(pDebugPrints->m_rgchLogFileName) - 1] + != '\\') { + // Append a \ if necessary + strcat_s( pDebugPrints->m_rgchLogFileName, + sizeof( pDebugPrints->m_rgchLogFileName ) / sizeof( pDebugPrints->m_rgchLogFileName[0] ), + "\\"); + }; + strcat_s( pDebugPrints->m_rgchLogFileName, + sizeof( pDebugPrints->m_rgchLogFileName ) / sizeof( pDebugPrints->m_rgchLogFileName[0] ), + pszFileName); + + return PuOpenDbgFileLocal( pDebugPrints); + +} // PuOpenDbgPrintFile() + + + + +DWORD +PuReOpenDbgPrintFile( + IN OUT LPDEBUG_PRINTS pDebugPrints) +/********************************************************************++ + + This function closes any open log file and reopens a new copy. + If necessary. It makes a backup copy of the file. + +--*********************************************************************/ + +{ + if ( pDebugPrints == NULL) { + return ( ERROR_INVALID_PARAMETER); + } + + PuCloseDbgPrintFile( pDebugPrints); // close any existing file. + + if ( pDebugPrints->m_dwOutputFlags & DbgOutputBackup) { + + // MakeBkupCopy(); + + OutputDebugStringA( " Error: MakeBkupCopy() Not Yet Implemented\n"); + } + + return PuOpenDbgFileLocal( pDebugPrints); + +} // PuReOpenDbgPrintFile() + + + + +DWORD +PuCloseDbgPrintFile( + IN OUT LPDEBUG_PRINTS pDebugPrints) +{ + DWORD dwError = NO_ERROR; + + if ( pDebugPrints == NULL ) { + dwError = ERROR_INVALID_PARAMETER; + } else { + + if ( pDebugPrints->m_LogFileHandle != INVALID_HANDLE_VALUE) { + + FlushFileBuffers( pDebugPrints->m_LogFileHandle); + + if ( !CloseHandle( pDebugPrints->m_LogFileHandle)) { + + CHAR pchBuffer[1024]; + + dwError = GetLastError(); + + sprintf_s( pchBuffer, + sizeof( pchBuffer ) / sizeof( pchBuffer[0] ), + "CloseDbgPrintFile() : CloseHandle( %p) failed." + " Error = %d\n", + pDebugPrints->m_LogFileHandle, + dwError); + OutputDebugStringA( pchBuffer); + } + + pDebugPrints->m_LogFileHandle = INVALID_HANDLE_VALUE; + } + } + + return ( dwError); +} // DEBUG_PRINTS::CloseDbgPrintFile() + +DWORD +PuOpenDbgMemoryLog(IN OUT LPDEBUG_PRINTS pDebugPrints) +{ + DWORD dwError; + CMemoryLog * pLog = NULL; + + if (NULL == pDebugPrints) + { + dwError = ERROR_INVALID_PARAMETER; + goto done; + } + + if (NULL != pDebugPrints->m_pMemoryLog) + { + dwError = ERROR_SUCCESS; + goto done; + } + + pLog = new CMemoryLog(1024 * 512); // max size of 512 K + if (NULL == pLog) + { + dwError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + + // save away the pointer + pDebugPrints->m_pMemoryLog = pLog; + + // make sure output gets to the log + pDebugPrints->m_dwOutputFlags |= DbgOutputMemory; + + dwError = NO_ERROR; +done: + return dwError; +} + +DWORD +PuCloseDbgMemoryLog(IN OUT LPDEBUG_PRINTS pDebugPrints) +{ + DWORD dwError; + + if (NULL == pDebugPrints) + { + dwError = ERROR_INVALID_PARAMETER; + goto done; + } + if (NULL != pDebugPrints->m_pMemoryLog) + { + CMemoryLog * pLog = (CMemoryLog*) (pDebugPrints->m_pMemoryLog); + delete pLog; + pDebugPrints->m_pMemoryLog = NULL; + } + + dwError = NO_ERROR; +done: + return dwError; +} + +VOID +PupOutputMessage( + IN LPDEBUG_PRINTS pDebugPrints, + IN STRA *straOutput + ) +{ + if ( pDebugPrints != NULL) + { + if ( ( pDebugPrints->m_dwOutputFlags & DbgOutputStderr) && + ( pDebugPrints->m_StdErrHandle != INVALID_HANDLE_VALUE ) ) { + + DWORD nBytesWritten; + + ( VOID) WriteFile( pDebugPrints->m_StdErrHandle, + straOutput->QueryStr(), + straOutput->QueryCCH(), + &nBytesWritten, + NULL); + } + + if ( pDebugPrints->m_dwOutputFlags & DbgOutputLogFile && + pDebugPrints->m_LogFileHandle != INVALID_HANDLE_VALUE) { + + DWORD nBytesWritten; + + // + // Truncation of log files. Not yet implemented. + + ( VOID) WriteFile( pDebugPrints->m_LogFileHandle, + straOutput->QueryStr(), + straOutput->QueryCCH(), + &nBytesWritten, + NULL); + + } + + if ( (pDebugPrints->m_dwOutputFlags & DbgOutputMemory) && + (NULL != pDebugPrints->m_pMemoryLog) ) + { + CMemoryLog* pLog = (CMemoryLog*) (pDebugPrints->m_pMemoryLog); + pLog->Append(straOutput->QueryStr(), straOutput->QueryCCH()); + } + + } + + + if ( pDebugPrints == NULL || + pDebugPrints->m_dwOutputFlags & DbgOutputKdb) + { + OutputDebugStringA( straOutput->QueryStr() ); + } + + return; +} + +void +FormatMsgToBuffer( IN OUT STRA * pSTRAOutput, + IN LPDEBUG_PRINTS pDebugPrints, + IN LPCSTR pszFilePath, + IN DWORD nLineNum, + IN LPCSTR pszFunctionName, + IN LPCSTR pszFormat, + IN va_list * pargsList) +{ + LPCSTR pszFileName = strrchr( pszFilePath, '\\'); + int cchPrologue = 0; + HRESULT hr = S_OK; + DWORD cchOutput = 0; + + // + // Skip the complete path name and retain file name in pszName + // + + if ( pszFileName== NULL) { + + // if skipping \\ yields nothing use whole path. + pszFileName = pszFilePath; + } + else + { + // skip past the '\' + ++pszFileName; + } + + // Format the message header as: tid label!function [file @ line number]:message + cchPrologue = sprintf_s( pSTRAOutput->QueryStr(), + pSTRAOutput->QuerySize(), + "%lu %hs!%hs [%hs @ %d]:", + GetCurrentThreadId(), + pDebugPrints ? pDebugPrints->m_rgchLabel : "??", + pszFunctionName, + pszFileName, + nLineNum); + + // we directly touched the buffer - however, wait to SyncWithBuffer + // until the rest of the operations are done. Do NOT call QueryCCH() it will be WRONG. + + + // Format the incoming message using vsnprintf() so that the overflows are + // captured + + cchOutput = _vsnprintf_s( pSTRAOutput->QueryStr() + cchPrologue, + pSTRAOutput->QuerySize() - cchPrologue, + pSTRAOutput->QuerySize() - cchPrologue - 1, + pszFormat, *pargsList); + + if ( cchOutput == -1 ) + { + // couldn't fit this in the original STRA size. Try a heap allocation. + hr = pSTRAOutput->Resize(MAX_PRINTF_OUTPUT); + if (FAILED(hr)) + { + // Can't allocate, therefore don't give back half done results + pSTRAOutput->Reset(); + return; + } + + cchOutput = _vsnprintf_s( pSTRAOutput->QueryStr() + cchPrologue, + pSTRAOutput->QuerySize() - cchPrologue, + pSTRAOutput->QuerySize() - cchPrologue - 1, + pszFormat, *pargsList); + if (cchOutput == -1) + { + // we need to NULL terminate, as _vsnprintf failed to do that for us. + pSTRAOutput->QueryStr()[pSTRAOutput->QuerySize() - 1] = '\0'; + } + } + + // we directly touched the buffer - therefore: + pSTRAOutput->SyncWithBuffer(); + + return; +} // FormatMsgToBuffer() + + +/********************************************************************++ +Routine Description: + Main function that examines the incoming message and prints out a header + and the message. + +Arguments: + pDebugPrints - pointer to the debug print object + pszFilePaht - pointer to the file from where this function is called + nLineNum - Line number within the file + pszFormat - formatting string to use. + +Returns: + None +--*********************************************************************/ + +VOID +PuDbgPrint( + IN OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFilePath, + IN int nLineNum, + IN const char * pszFunctionName, + IN const char * pszFormat, + ...) +{ + STACK_STRA(straOutput, 256); + va_list argsList; + DWORD dwErr; + + // get a local copy of the error code so that it is not lost + dwErr = GetLastError(); + + va_start( argsList, pszFormat); + FormatMsgToBuffer( &straOutput, + pDebugPrints, + pszFilePath, + nLineNum, + pszFunctionName, + pszFormat, + &argsList); + + va_end( argsList); + + // + // Send the outputs to respective files. + // + PupOutputMessage( pDebugPrints, &straOutput); + + + SetLastError( dwErr ); + + return; +} // PuDbgPrint() + +void +FormatMsgToBufferW( IN OUT STRU * pSTRUOutput, + IN LPDEBUG_PRINTS pDebugPrints, + IN LPCSTR pszFilePath, + IN DWORD nLineNum, + IN LPCSTR pszFunctionName, + IN LPCWSTR pszFormat, + IN va_list * pargsList) +{ + LPCSTR pszFileName = strrchr( pszFilePath, '\\'); + int cchPrologue = 0; + HRESULT hr = S_OK; + DWORD cchOutput = 0; + + // + // Skip the complete path name and retain file name in pszName + // + + if ( pszFileName== NULL) { + + // if skipping \\ yields nothing use whole path. + pszFileName = pszFilePath; + } + else + { + // skip past the '\' + ++pszFileName; + } + + // Format the message header as: tid label!function [file @ line number]:message + cchPrologue = swprintf_s( pSTRUOutput->QueryStr(), + pSTRUOutput->QuerySizeCCH(), + L"%lu %hs!%hs [%hs @ %d]:", + GetCurrentThreadId(), + pDebugPrints ? pDebugPrints->m_rgchLabel : "??", + pszFunctionName, + pszFileName, + nLineNum); + + // we directly touched the buffer - however, wait to SyncWithBuffer + // until the rest of the operations are done. Do NOT call QueryCCH() it will be WRONG. + + // Format the incoming message using vsnprintf() so that the overflows are + // captured + + cchOutput = _vsnwprintf_s( pSTRUOutput->QueryStr() + cchPrologue, + pSTRUOutput->QuerySizeCCH() - cchPrologue, + // DEBUGDEBUG + //pSTRUOutput->QueryBuffer()->QuerySize() / sizeof(WCHAR) - cchPrologue - 1, // this is a count of characters + pSTRUOutput->QuerySizeCCH() - cchPrologue - 1, + pszFormat, *pargsList); + + if ( cchOutput == -1 ) + { + // couldn't fit this in the original STRA size. Try a heap allocation. + hr = pSTRUOutput->Resize(MAX_PRINTF_OUTPUT); + if (FAILED(hr)) + { + // Can't allocate, therefore don't give back half done results + pSTRUOutput->Reset(); + return; + } + + cchOutput = _vsnwprintf_s( pSTRUOutput->QueryStr() + cchPrologue, + pSTRUOutput->QuerySizeCCH() - cchPrologue, + //DEBUGDEBUG + //pSTRUOutput->QueryBuffer()->QuerySize() / sizeof(WCHAR) - cchPrologue - 1, // this is a count of characters + pSTRUOutput->QuerySizeCCH() - cchPrologue - 1, + pszFormat, *pargsList); + if (cchOutput == -1) + { + // we need to NULL terminate, as _vsnprintf failed to do that for us. + //DEBUGDEBUG + pSTRUOutput->QueryStr()[pSTRUOutput->QuerySizeCCH() - 1] = L'\0'; + + } + } + + // we directly touched the buffer - therefore: + pSTRUOutput->SyncWithBuffer(); + + return; +} // FormatMsgToBuffer() + +extern "C" +VOID +PuDbgPrintW( + IN OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFilePath, + IN int nLineNum, + IN const char * pszFunctionName, + IN const WCHAR * pszFormat, + ... +) +{ + STACK_STRU(struOutput, 256); + va_list argsList; + DWORD dwErr; + HRESULT hr; + // get a local copy of the error code so that it is not lost + dwErr = GetLastError(); + + va_start( argsList, pszFormat); + FormatMsgToBufferW( &struOutput, + pDebugPrints, + pszFilePath, + nLineNum, + pszFunctionName, + pszFormat, + &argsList); + + va_end( argsList); + + // + // Send the outputs to respective files. + // + STACK_STRA(straOutput, 256); + hr = straOutput.CopyWTruncate(struOutput.QueryStr(), struOutput.QueryCCH()); + if (FAILED(hr)) + { + goto done; + } + + PupOutputMessage( pDebugPrints, &straOutput); + +done: + + SetLastError( dwErr ); + + return; +} + +/********************************************************************++ +Routine Description: + This function behaves like PuDbgPrint() but also prints out formatted + Error message indicating what failed. + +Arguments: + pDebugPrints - pointer to the debug print object + pszFilePaht - pointer to the file from where this function is called + nLineNum - Line number within the file + dwError - Error code for which the formatted error message should + be printed + pszFormat - formatting string to use. + +Returns: + None +--*********************************************************************/ +VOID +PuDbgPrintError( + IN OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFilePath, + IN int nLineNum, + IN const char * pszFunctionName, + IN DWORD dwError, + IN const char * pszFormat, + ...) // argsList +{ + STACK_STRA(straOutput, 256); + va_list argsList; + DWORD dwErr; + + // get a local copy of the error code so that it is not lost + dwErr = GetLastError(); + + va_start( argsList, pszFormat); + FormatMsgToBuffer( &straOutput, + pDebugPrints, + pszFilePath, + nLineNum, + pszFunctionName, + pszFormat, + &argsList); + + va_end( argsList); + + + // + // obtain the formatted error message for error code + // + + LPSTR lpErrorBuffer = NULL; + DWORD nRet; +#pragma prefast(suppress: __WARNING_ANSI_APICALL,"debug spew is ansi") + nRet = + FormatMessageA((FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM), + NULL, // lpSource + dwError, + LANG_NEUTRAL, + (LPSTR ) &lpErrorBuffer, // pointer to store buffer allocated + 0, // size of buffer + NULL // lpArguments + ); + + if (lpErrorBuffer) + { + CHAR pszErrorOut[64]; // 64 from: (/t=)4 + (Error(=)7 + (%x=)18 (0x + 16hex on 64 bit systems) + (): =)3 == 32 + some more slop + _snprintf_s( pszErrorOut, + sizeof( pszErrorOut ) / sizeof( pszErrorOut[0] ), + sizeof(pszErrorOut) / sizeof(CHAR) - 1, // leave space for NULL. + "\tError(%x): ", + dwError); + pszErrorOut[63] = '\0'; + + // if these appends fail, nothing to be done about it therefore just ignore the return values + straOutput.Append(pszErrorOut); + + straOutput.Append(lpErrorBuffer); + straOutput.Append("\n"); + } + + // + // Send the outputs to respective files. + // + PupOutputMessage( pDebugPrints, &straOutput); + + // free the buffer if any was allocated + if ( lpErrorBuffer != NULL) { + LocalFree (lpErrorBuffer); + } + + SetLastError( dwErr ); + + return; +} // PuDbgPrintError() + + + +VOID +PuDbgDump( + IN OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFilePath, + IN int nLineNum, + IN const char * pszFunctionName, + IN const char * pszDump + ) +{ + UNREFERENCED_PARAMETER( pszFunctionName ); + UNREFERENCED_PARAMETER( nLineNum ); + + LPCSTR pszFileName = strrchr( pszFilePath, '\\'); + DWORD dwErr; + DWORD cbDump; + + + // + // Skip the complete path name and retain file name in pszName + // + + if ( pszFileName== NULL) { + + pszFileName = pszFilePath; + } + + dwErr = GetLastError(); + + // No message header for this dump + cbDump = (DWORD)strlen( pszDump); + + // + // Send the outputs to respective files. + // + + if ( pDebugPrints != NULL) + { + if ( ( pDebugPrints->m_dwOutputFlags & DbgOutputStderr) && + ( pDebugPrints->m_StdErrHandle != INVALID_HANDLE_VALUE ) ) { + + DWORD nBytesWritten; + + ( VOID) WriteFile( pDebugPrints->m_StdErrHandle, + pszDump, + cbDump, + &nBytesWritten, + NULL); + } + + if ( pDebugPrints->m_dwOutputFlags & DbgOutputLogFile && + pDebugPrints->m_LogFileHandle != INVALID_HANDLE_VALUE) { + + DWORD nBytesWritten; + + // + // Truncation of log files. Not yet implemented. + + ( VOID) WriteFile( pDebugPrints->m_LogFileHandle, + pszDump, + cbDump, + &nBytesWritten, + NULL); + + } + + if ( (pDebugPrints->m_dwOutputFlags & DbgOutputMemory) && + (NULL != pDebugPrints->m_pMemoryLog) ) + { + CMemoryLog * pLog = (CMemoryLog*)(pDebugPrints->m_pMemoryLog); + pLog->Append(pszDump, cbDump); + } + } + + if ( pDebugPrints == NULL + || pDebugPrints->m_dwOutputFlags & DbgOutputKdb) + { + OutputDebugStringA( pszDump); + } + + SetLastError( dwErr ); + + return; +} // PuDbgDump() + +// +// N.B. For PuDbgCaptureContext() to work properly, the calling function +// *must* be __cdecl, and must have a "normal" stack frame. So, we decorate +// PuDbgAssertFailed() with the __cdecl modifier and disable the frame pointer +// omission (FPO) optimization. +// + +// DEBUGDEBUG +//#pragma optimize( "y", off ) // disable frame pointer omission (FPO) +#pragma optimize( "", off ) + +INT +__cdecl +PuDbgAssertFailed( + IN OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFilePath, + IN int nLineNum, + IN const char * pszFunctionName, + IN const char * pszExpression, + IN const char * pszMessage) +/********************************************************************++ + This function calls assertion failure and records assertion failure + in log file. + +--*********************************************************************/ + +{ + PuDbgPrintAssertFailed( pDebugPrints, pszFilePath, nLineNum, pszFunctionName, + pszExpression, + pszMessage ); + if ( !g_fAvoidShutdownAsserts ) + { + DebugBreak(); + } + + return 0; +} // PuDbgAssertFailed() + +#pragma optimize( "", on ) // restore frame pointer omission (FPO) + +INT +WINAPI +PuDbgPrintAssertFailed( + IN OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFilePath, + IN int nLineNum, + IN const char * pszFunctionName, + IN const char * pszExpression, + IN const char * pszMessage) +/********************************************************************++ + This function calls assertion failure and records assertion failure + in log file. + +--*********************************************************************/ + +{ + PuDbgPrint( pDebugPrints, pszFilePath, nLineNum, pszFunctionName, + " Assertion (%s) Failed: %s\n", + pszExpression, + pszMessage ); + return 0; +} // PuDbgPrintAssertFailed() + + + +VOID +PuDbgPrintCurrentTime( + IN OUT LPDEBUG_PRINTS pDebugPrints, + IN const char * pszFilePath, + IN int nLineNum, + IN const char * pszFunctionName + ) +/********************************************************************++ + This function generates the current time and prints it out to debugger + for tracing out the path traversed, if need be. + + Arguments: + pszFile pointer to string containing the name of the file + lineNum line number within the file where this function is called. + + Returns: + NO_ERROR always. +--*********************************************************************/ + +{ + PuDbgPrint( pDebugPrints, pszFilePath, nLineNum, pszFunctionName, + " TickCount = %u\n", + GetTickCount() + ); + + return; +} // PrintOutCurrentTime() + + + + +DWORD +PuLoadDebugFlagsFromReg(IN HKEY hkey, IN DWORD dwDefault) +/********************************************************************++ + This function reads the debug flags assumed to be stored in + the location "DebugFlags" under given key. + If there is any error the default value is returned. +--*********************************************************************/ + +{ + DWORD err; + DWORD dwDebug = dwDefault; + DWORD dwBuffer; + DWORD cbBuffer = sizeof(dwBuffer); + DWORD dwType; + + if( hkey != NULL ) + { + err = RegQueryValueExA( hkey, + DEBUG_FLAGS_REGISTRY_LOCATION_A, + NULL, + &dwType, + (LPBYTE)&dwBuffer, + &cbBuffer ); + + if( ( err == NO_ERROR ) && ( dwType == REG_DWORD ) ) + { + dwDebug = dwBuffer; + } + } + + return dwDebug; +} // PuLoadDebugFlagsFromReg() + + + + +DWORD +PuLoadDebugFlagsFromRegStr(IN LPCSTR pszRegKey, IN DWORD dwDefault) +/********************************************************************++ +Description: + This function reads the debug flags assumed to be stored in + the location "DebugFlags" under given key location in registry. + If there is any error the default value is returned. + +Arguments: + pszRegKey - pointer to registry key location from where to read the key from + dwDefault - default values in case the read from registry fails + +Returns: + Newly read value on success + If there is any error the dwDefault is returned. +--*********************************************************************/ + +{ + HKEY hkey = NULL; + + DWORD dwVal = dwDefault; + + DWORD dwError = RegOpenKeyExA(HKEY_LOCAL_MACHINE, + pszRegKey, + 0, + KEY_READ, + &hkey); + if ( dwError == NO_ERROR) { + dwVal = PuLoadDebugFlagsFromReg( hkey, dwDefault); + RegCloseKey( hkey); + hkey = NULL; + } + + return ( dwVal); +} // PuLoadDebugFlagsFromRegStr() + + + + + +DWORD +PuSaveDebugFlagsInReg(IN HKEY hkey, IN DWORD dwDbg) +/********************************************************************++ + Saves the debug flags in registry. On failure returns the error code for + the operation that failed. + +--*********************************************************************/ +{ + DWORD err; + + if( hkey == NULL ) { + + err = ERROR_INVALID_PARAMETER; + } else { + + err = RegSetValueExA(hkey, + DEBUG_FLAGS_REGISTRY_LOCATION_A, + 0, + REG_DWORD, + (LPBYTE)&dwDbg, + sizeof(dwDbg) ); + } + + return (err); +} // PuSaveDebugFlagsInReg() + + +VOID +PuDbgCaptureContext ( + OUT PCONTEXT ContextRecord + ) +{ + // + // This space intentionally left blank. + // + UNREFERENCED_PARAMETER( ContextRecord ); +} // PuDbgCaptureContext + + +/****************************** End of File ******************************/ + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/reftrace.c b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/reftrace.c new file mode 100644 index 0000000000..bfb78aa717 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/reftrace.c @@ -0,0 +1,232 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +//#include +//#include +//#include +#include +#include +#include +#include + + +PTRACE_LOG +CreateRefTraceLog( + IN LONG LogSize, + IN LONG ExtraBytesInHeader + ) +/*++ + +Routine Description: + + Creates a new (empty) ref count trace log buffer. + +Arguments: + + LogSize - The number of entries in the log. + + ExtraBytesInHeader - The number of extra bytes to include in the + log header. This is useful for adding application-specific + data to the log. + +Return Value: + + PTRACE_LOG - Pointer to the newly created log if successful, + NULL otherwise. + +--*/ +{ + + return CreateTraceLog( + LogSize, + ExtraBytesInHeader, + sizeof(REF_TRACE_LOG_ENTRY) + ); + +} // CreateRefTraceLog + + +VOID +DestroyRefTraceLog( + IN PTRACE_LOG Log + ) +/*++ + +Routine Description: + + Destroys a ref count trace log buffer created with CreateRefTraceLog(). + +Arguments: + + Log - The ref count trace log buffer to destroy. + +Return Value: + + None. + +--*/ +{ + + DestroyTraceLog( Log ); + +} // DestroyRefTraceLog + + +// +// N.B. For RtlCaptureBacktrace() to work properly, the calling function +// *must* be __cdecl, and must have a "normal" stack frame. So, we decorate +// WriteRefTraceLog[Ex]() with the __cdecl modifier and disable the frame +// pointer omission (FPO) optimization. +// + +//#pragma optimize( "y", off ) // disable frame pointer omission (FPO) +#pragma optimize( "", off ) // disable frame pointer omission (FPO) + +LONG +__cdecl +WriteRefTraceLog( + IN PTRACE_LOG Log, + IN LONG NewRefCount, + IN CONST VOID * Context + ) +/*++ + +Routine Description: + + Writes a new entry to the specified ref count trace log. The entry + written contains the updated reference count and a stack backtrace + leading up to the current caller. + +Arguments: + + Log - The log to write to. + + NewRefCount - The updated reference count. + + Context - An uninterpreted context to associate with the log entry. + +Return Value: + + Index of entry in log. + +--*/ +{ + + return WriteRefTraceLogEx( + Log, + NewRefCount, + Context, + REF_TRACE_EMPTY_CONTEXT, // suppress use of optional extra contexts + REF_TRACE_EMPTY_CONTEXT, + REF_TRACE_EMPTY_CONTEXT + ); + +} // WriteRefTraceLog + + + + +LONG +__cdecl +WriteRefTraceLogEx( + IN PTRACE_LOG Log, + IN LONG NewRefCount, + IN CONST VOID * Context, + IN CONST VOID * Context1, // optional extra context + IN CONST VOID * Context2, // optional extra context + IN CONST VOID * Context3 // optional extra context + ) +/*++ + +Routine Description: + + Writes a new "extended" entry to the specified ref count trace log. + The entry written contains the updated reference count, stack backtrace + leading up to the current caller and extra context information. + +Arguments: + + Log - The log to write to. + + NewRefCount - The updated reference count. + + Context - An uninterpreted context to associate with the log entry. + Context1 - An uninterpreted context to associate with the log entry. + Context2 - An uninterpreted context to associate with the log entry. + Context3 - An uninterpreted context to associate with the log entry. + + NOTE Context1/2/3 are "optional" in that the caller may suppress + debug display of these values by passing REF_TRACE_EMPTY_CONTEXT + for each of them. + +Return Value: + + Index of entry in log. + +--*/ +{ + + REF_TRACE_LOG_ENTRY entry; + ULONG hash; + DWORD cStackFramesSkipped; + + // + // Initialize the entry. + // + + RtlZeroMemory( + &entry, + sizeof(entry) + ); + + // + // Set log entry members. + // + + entry.NewRefCount = NewRefCount; + entry.Context = Context; + entry.Thread = GetCurrentThreadId(); + entry.Context1 = Context1; + entry.Context2 = Context2; + entry.Context3 = Context3; + + // + // Capture the stack backtrace. Normally, we skip two stack frames: + // one for this routine, and one for RtlCaptureBacktrace() itself. + // For non-Ex callers who come in via WriteRefTraceLog, + // we skip three stack frames. + // + + if ( entry.Context1 == REF_TRACE_EMPTY_CONTEXT + && entry.Context2 == REF_TRACE_EMPTY_CONTEXT + && entry.Context3 == REF_TRACE_EMPTY_CONTEXT + ) { + + cStackFramesSkipped = 2; + + } else { + + cStackFramesSkipped = 1; + + } + + RtlCaptureStackBackTrace( + cStackFramesSkipped, + REF_TRACE_LOG_STACK_DEPTH, + entry.Stack, + &hash + ); + + // + // Write it to the log. + // + + return WriteTraceLog( + Log, + &entry + ); + +} // WriteRefTraceLogEx + +#pragma optimize( "", on ) // restore frame pointer omission (FPO) + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/tracelog.c b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/tracelog.c new file mode 100644 index 0000000000..58eeb4863f --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/tracelog.c @@ -0,0 +1,239 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +//#include +//#include +//#include +#include +#include +#include +#include +#include + + +#define ALLOC_MEM(cb) (PVOID)LocalAlloc( LPTR, (cb) ) +#define FREE_MEM(ptr) (VOID)LocalFree( (HLOCAL)(ptr) ) + + + +PTRACE_LOG +CreateTraceLog( + IN LONG LogSize, + IN LONG ExtraBytesInHeader, + IN LONG EntrySize + ) +/*++ + +Routine Description: + + Creates a new (empty) trace log buffer. + +Arguments: + + LogSize - The number of entries in the log. + + ExtraBytesInHeader - The number of extra bytes to include in the + log header. This is useful for adding application-specific + data to the log. + + EntrySize - The size (in bytes) of each entry. + +Return Value: + + PTRACE_LOG - Pointer to the newly created log if successful, + NULL otherwise. + +--*/ +{ + + ULONG ulTotalSize = 0; + ULONG ulLogSize = 0; + ULONG ulEntrySize = 0; + ULONG ulTmpResult = 0; + ULONG ulExtraBytesInHeader = 0; + PTRACE_LOG log = NULL; + HRESULT hr = S_OK; + + // + // Sanity check the parameters. + // + + //DBG_ASSERT( LogSize > 0 ); + //DBG_ASSERT( EntrySize > 0 ); + //DBG_ASSERT( ExtraBytesInHeader >= 0 ); + //DBG_ASSERT( ( EntrySize & 3 ) == 0 ); + + // + // converting to unsigned long. Since all these values are positive + // so its safe to cast them to their unsigned equivalent directly. + // + ulLogSize = (ULONG) LogSize; + ulEntrySize = (ULONG) EntrySize; + ulExtraBytesInHeader = (ULONG) ExtraBytesInHeader; + + // + // Check if the multiplication operation will overflow a LONG + // ulTotalSize = LogSize * EntrySize; + // + hr = ULongMult( ulLogSize, ulEntrySize, &ulTotalSize ); + if ( FAILED(hr) ) + { + SetLastError( ERROR_ARITHMETIC_OVERFLOW ); + return NULL; + } + + // + // check for overflow in addition operation. + // ulTmpResult = sizeof(TRACE_LOG) + ulExtraBytesInHeader + // + hr = ULongAdd( (ULONG) sizeof(TRACE_LOG), ulExtraBytesInHeader, &ulTmpResult ); + if ( FAILED(hr) ) + { + SetLastError( ERROR_ARITHMETIC_OVERFLOW ); + return NULL; + } + + // + // check for overflow in addition operation. + // ulTotalSize = ulTotalSize + ulTmpResult; + // + hr = ULongAdd( ulTmpResult, ulTotalSize, &ulTotalSize ); + if ( FAILED(hr) ) + { + SetLastError( ERROR_ARITHMETIC_OVERFLOW ); + return NULL; + } + + if ( ulTotalSize > (ULONG) 0x7FFFFFFF ) + { + SetLastError( ERROR_ARITHMETIC_OVERFLOW ); + return NULL; + } + + // + // Allocate & initialize the log structure. + // + + log = (PTRACE_LOG)ALLOC_MEM( ulTotalSize ); + + // + // Initialize it. + // + + if( log != NULL ) { + + RtlZeroMemory( log, ulTotalSize ); + + log->Signature = TRACE_LOG_SIGNATURE; + log->LogSize = LogSize; + log->NextEntry = -1; + log->EntrySize = EntrySize; + log->LogBuffer = (PUCHAR)( log + 1 ) + ExtraBytesInHeader; + } + + return log; + +} // CreateTraceLog + + +VOID +DestroyTraceLog( + IN PTRACE_LOG Log + ) +/*++ + +Routine Description: + + Destroys a trace log buffer created with CreateTraceLog(). + +Arguments: + + Log - The trace log buffer to destroy. + +Return Value: + + None. + +--*/ +{ + if ( Log != NULL ) { + //DBG_ASSERT( Log->Signature == TRACE_LOG_SIGNATURE ); + + Log->Signature = TRACE_LOG_SIGNATURE_X; + FREE_MEM( Log ); + } + +} // DestroyTraceLog + + +LONG +WriteTraceLog( + IN PTRACE_LOG Log, + IN PVOID Entry + ) +/*++ + +Routine Description: + + Writes a new entry to the specified trace log. + +Arguments: + + Log - The log to write to. + + Entry - Pointer to the data to write. This buffer is assumed to be + Log->EntrySize bytes long. + +Return Value: + + Index of entry in log. This is useful for correlating the output + of !inetdbg.ref to a particular point in the output debug stream + +--*/ +{ + + PUCHAR target; + ULONG index; + + //DBG_ASSERT( Log != NULL ); + //DBG_ASSERT( Log->Signature == TRACE_LOG_SIGNATURE ); + //DBG_ASSERT( Entry != NULL ); + + // + // Find the next slot, copy the entry to the slot. + // + + index = ( (ULONG) InterlockedIncrement( &Log->NextEntry ) ) % (ULONG) Log->LogSize; + + //DBG_ASSERT( index < (ULONG) Log->LogSize ); + + target = Log->LogBuffer + ( index * Log->EntrySize ); + + RtlCopyMemory( + target, + Entry, + Log->EntrySize + ); + + return index; +} // WriteTraceLog + + +VOID +ResetTraceLog( + IN PTRACE_LOG Log + ) +{ + + //DBG_ASSERT( Log != NULL ); + //DBG_ASSERT( Log->Signature == TRACE_LOG_SIGNATURE ); + + RtlZeroMemory( + ( Log + 1 ), + Log->LogSize * Log->EntrySize + ); + + Log->NextEntry = -1; + +} // ResetTraceLog + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/win32obj.cxx b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/win32obj.cxx new file mode 100644 index 0000000000..cd6987d860 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/src/win32obj.cxx @@ -0,0 +1,348 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.hxx" +#include "pudebug.h" + +#define MAX_OBJECT_NAME 256 // chars + + +LONG g_PuDbgEventsCreated = 0; +LONG g_PuDbgSemaphoresCreated = 0; +LONG g_PuDbgMutexesCreated = 0; + + + +LPSTR +PuDbgpBuildObjectName( + __in LPSTR ObjectNameBuffer, + IN ULONG ObjectNameBufferCch, + __in LPSTR FileName, + IN ULONG LineNumber, + __in LPSTR MemberName, + IN PVOID Address + ) + +/*++ + +Routine Description: + + Internal routine that builds an appropriate object name based on + the file name, line number, member name, address, and process ID. + +Arguments: + + ObjectNameBuffer - Pointer to the target buffer for the name. + + FileName - The filename of the source creating the object. This + is __FILE__ of the caller. + + LineNumber - The line number within the source. This is __LINE__ + of the caller. + + MemberName - The member/global variable name where the object handle + is to be stored. + + Address - The address of the containing structure/class or of the + global itself. + +Return Value: + + LPSTR - Pointer to ObjectNameBuffer if successful, NULL otherwise. + + N.B. This routine always returns NULL when running under Win9x. + +--*/ + +{ + + PLATFORM_TYPE platformType; + LPSTR fileNamePart; + LPSTR result; + + // + // We have no convenient way to dump objects w/ names from + // Win9x, so we'll only enable this functionality under NT. + // + + // platformType = IISGetPlatformType(); + + // + // By default IIS-Duct-tape will only run on NT platforms. So + // do not worry about getting the platform types yet. + // + platformType = PtNtServer; + result = NULL; + + if( platformType == PtNtServer || + platformType == PtNtWorkstation ) { + + // + // Find the filename part of the incoming source file name. + // + + fileNamePart = strrchr( FileName, '\\' ); + + if( fileNamePart == NULL ) { + fileNamePart = strrchr( FileName, '/' ); + } + + if( fileNamePart == NULL ) { + fileNamePart = strrchr( FileName, ':' ); + } + + if( fileNamePart == NULL ) { + fileNamePart = FileName; + } else { + fileNamePart++; + } + + // + // Ensure we don't overwrite our object name buffer. + // + + if( ( sizeof(":1234567890 :12345678 PID:1234567890") + + strlen( fileNamePart ) + + strlen( MemberName ) ) < MAX_OBJECT_NAME ) { + + sprintf_s( + ObjectNameBuffer, + ObjectNameBufferCch, + "%s:%lu %s:%08p PID:%lu", + fileNamePart, + LineNumber, + MemberName, + Address, + GetCurrentProcessId() + ); + + result = ObjectNameBuffer; + + } + + } + + return result; + +} // PuDbgpBuildObjectName + + +HANDLE +PuDbgCreateEvent( + __in LPSTR FileName, + IN ULONG LineNumber, + __in LPSTR MemberName, + IN PVOID Address, + IN BOOL ManualReset, + IN BOOL InitialState + ) + +/*++ + +Routine Description: + + Creates a new event object. + +Arguments: + + FileName - The filename of the source creating the object. This + is __FILE__ of the caller. + + LineNumber - The line number within the source. This is __LINE__ + of the caller. + + MemberName - The member/global variable name where the object handle + is to be stored. + + Address - The address of the containing structure/class or of the + global itself. + + ManualReset - TRUE to create a manual reset event, FALSE to create + an automatic reset event. + + InitialState - The intitial state of the event object. + +Return Value: + + HANDLE - Handle to the object if successful, NULL otherwise. + +--*/ + +{ + UNREFERENCED_PARAMETER( Address ); + UNREFERENCED_PARAMETER( MemberName ); + UNREFERENCED_PARAMETER( LineNumber ); + UNREFERENCED_PARAMETER( FileName ); + + LPSTR objName = NULL; + HANDLE objHandle; + //CHAR objNameBuffer[MAX_OBJECT_NAME]; + +/* + disable passing names to event creation + Longhorn forces some security checks that + prevent hostable webcore to work on checked builds + (at least ASP requests are failing when + trying to create event) + + objName = PuDbgpBuildObjectName( + objNameBuffer, + FileName, + LineNumber, + MemberName, + Address + ); +*/ + objHandle = CreateEventA( + NULL, // lpEventAttributes + ManualReset, // bManualReset + InitialState, // bInitialState + objName // lpName + ); + + if( objHandle != NULL ) { + InterlockedIncrement( &g_PuDbgEventsCreated ); + } + + return objHandle; + +} // PuDbgCreateEvent + + +HANDLE +PuDbgCreateSemaphore( + __in LPSTR FileName, + IN ULONG LineNumber, + __in LPSTR MemberName, + IN PVOID Address, + IN LONG InitialCount, + IN LONG MaximumCount + ) + +/*++ + +Routine Description: + + Creates a new semaphore object. + +Arguments: + + FileName - The filename of the source creating the object. This + is __FILE__ of the caller. + + LineNumber - The line number within the source. This is __LINE__ + of the caller. + + MemberName - The member/global variable name where the object handle + is to be stored. + + Address - The address of the containing structure/class or of the + global itself. + + InitialCount - The initial count of the semaphore. + + MaximumCount - The maximum count of the semaphore. + +Return Value: + + HANDLE - Handle to the object if successful, NULL otherwise. + +--*/ + +{ + + LPSTR objName; + HANDLE objHandle; + CHAR objNameBuffer[MAX_OBJECT_NAME]; + + objName = PuDbgpBuildObjectName( + objNameBuffer, + sizeof( objNameBuffer) / sizeof( objNameBuffer[0] ), + FileName, + LineNumber, + MemberName, + Address + ); + + objHandle = CreateSemaphoreA( + NULL, // lpSemaphoreAttributes + InitialCount, // lInitialCount + MaximumCount, // lMaximumCount + objName // lpName + ); + + if( objHandle != NULL ) { + InterlockedIncrement( &g_PuDbgSemaphoresCreated ); + } + + return objHandle; + +} // PuDbgCreateSemaphore + + +HANDLE +PuDbgCreateMutex( + __in LPSTR FileName, + IN ULONG LineNumber, + __in LPSTR MemberName, + IN PVOID Address, + IN BOOL InitialOwner + ) + +/*++ + +Routine Description: + + Creates a new mutex object. + +Arguments: + + FileName - The filename of the source creating the object. This + is __FILE__ of the caller. + + LineNumber - The line number within the source. This is __LINE__ + of the caller. + + MemberName - The member/global variable name where the object handle + is to be stored. + + Address - The address of the containing structure/class or of the + global itself. + + InitialOwner - TRUE if the mutex should be created "owned". + +Return Value: + + HANDLE - Handle to the object if successful, NULL otherwise. + +--*/ + +{ + + LPSTR objName; + HANDLE objHandle; + CHAR objNameBuffer[MAX_OBJECT_NAME]; + + objName = PuDbgpBuildObjectName( + objNameBuffer, + sizeof( objNameBuffer) / sizeof( objNameBuffer[0] ), + FileName, + LineNumber, + MemberName, + Address + ); + + objHandle = CreateMutexA( + NULL, // lpMutexAttributes + InitialOwner, // bInitialOwner, + objName // lpName + ); + + if( objHandle != NULL ) { + InterlockedIncrement( &g_PuDbgMutexesCreated ); + } + + return objHandle; + +} // PuDbgCreateMutex + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/version/bldver.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/version/bldver.h new file mode 100644 index 0000000000..63a67d68f4 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/version/bldver.h @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _BLDVER_H_ +#define _BLDVER_H_ + +#define STR_HELPER(x) #x +#define WSTR_HELPER(x) L#x +#define NUM_TO_STR(x) STR_HELPER(x) +#define NUM_TO_WSTR(x) WSTR_HELPER(x) + +// +// Build versions are properties of the build system but can be overwritten below +// +// #define PRODUCT_MAJOR 7 +// #define PRODUCT_MINOR 1 +// #define BUILD_MAJOR 1972 +// #define BUILD_MINOR 0 + +#define PRODUCT_MAJOR_STRING NUM_TO_STR(PRODUCT_MAJOR) +#define PRODUCT_MAJOR_STRING_L NUM_TO_WSTR(PRODUCT_MAJOR) +#define PRODUCT_MAJOR_NUMBER PRODUCT_MAJOR + +#define PRODUCT_MINOR_STRING NUM_TO_STR(PRODUCT_MINOR) +#define PRODUCT_MINOR_STRING_L NUM_TO_WSTR(PRODUCT_MINOR) +#define PRODUCT_MINOR_NUMBER PRODUCT_MINOR + +#define BUILD_MAJOR_STRING NUM_TO_STR(BUILD_MAJOR) +#define BUILD_MAJOR_STRING_L NUM_TO_WSTR(BUILD_MAJOR) +#define BUILD_MAJOR_NUMBER BUILD_MAJOR + +#define BUILD_MINOR_STRING NUM_TO_STR(BUILD_MINOR) +#define BUILD_MINOR_STRING_L NUM_TO_WSTR(BUILD_MINOR) +#define BUILD_MINOR_NUMBER BUILD_MINOR + +#define BUILD_NUMBER BUILD_MAJOR_STRING "." BUILD_MINOR_STRING +#define BUILD_NUM BUILD_MAJOR , BUILD_MINOR +#define PRODUCT_NUMBER PRODUCT_MAJOR_STRING "." PRODUCT_MINOR_STRING +#define PRODUCT_NUM PRODUCT_MAJOR , PRODUCT_MINOR +#define INET_VERSION PRODUCT_MAJOR_STRING "." PRODUCT_MINOR_STRING "." BUILD_MAJOR_STRING "." BUILD_MINOR_STRING +#define INET_VERSION_L PRODUCT_MAJOR_STRING_L L"." PRODUCT_MINOR_STRING_L L"." BUILD_MAJOR_STRING_L L"." BUILD_MINOR_STRING_L +#define INET_VER PRODUCT_MAJOR , PRODUCT_MINOR , BUILD_MAJOR , BUILD_MINOR + +#define BUILD_PRIVATE "Built by IISBLD on IISBLD.\0" + +#undef VER_PRODUCTVERSION +#undef VER_PRODUCTVERSION_STR +#undef VER_PRODUCTMAJORVERSION +#undef VER_PRODUCTMINORVERSION +#undef VER_PRODUCTBUILD +#undef VER_PRODUCTBUILD_QFE +#undef VER_PRODUCTNAME_STR +#undef VER_COMPANYNAME_STR + +#define VER_PRODUCTVERSION PRODUCT_MAJOR,PRODUCT_MINOR,BUILD_MAJOR,BUILD_MINOR +#define VER_PRODUCTVERSION_STR PRODUCT_MAJOR_STRING "." PRODUCT_MINOR_STRING "." BUILD_MAJOR_STRING "." BUILD_MINOR_STRING +#define VER_PRODUCTMAJORVERSION PRODUCT_MAJOR +#define VER_PRODUCTMINORVERSION PRODUCT_MINOR +#define VER_PRODUCTBUILD BUILD_MAJOR +#define VER_PRODUCTBUILD_QFE BUILD_MINOR +#define VER_PRODUCTNAME_STR "Microsoft Web Platform Extensions" +#define VER_COMPANYNAME_STR "Microsoft Corporation" + +#endif diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/version/bldver.rc b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/version/bldver.rc new file mode 100644 index 0000000000..30a96499ec --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/version/bldver.rc @@ -0,0 +1,73 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// BLDVER.RC - Standard version resource for CoreXT applications. + +// Before including this file into your .rc, define the following +// macros for your application (don't forget the \0's): +// #define RC_VERSION_FILE_DESCRIPTION "Test DLL\0" +// #define RC_VERSION_INTERNAL_NAME "Test\0" +// #define RC_VERSION_ORIGINAL_FILE_NAME "Test.DLL\0" + +#include +#include + +VS_VERSION_INFO VERSIONINFO + +FILEVERSION INET_VER +PRODUCTVERSION INET_VER + +FILEFLAGSMASK 0x3fL +#ifdef DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + +// +// Global definitions +// +#ifndef RC_VERSION_COMPANY_NAME + #define RC_VERSION_COMPANY_NAME "Microsoft Corporation\0" +#endif + +#ifndef RC_VERSION_PRODUCT_NAME + #define RC_VERSION_PRODUCT_NAME "Microsoft\256 Web Platform Extensions\0" +#endif + +#ifndef RC_VERSION_LEGAL_COPYRIGHT + #define RC_VERSION_LEGAL_COPYRIGHT "Copyright \251 Microsoft Corporation\0" +#endif + +#ifndef RC_VERSION_LEGAL_TRADEMARKS + #define RC_VERSION_LEGAL_TRADEMARKS "Microsoft\256 is a registered trademark of Microsoft Corporation.\0" +#endif + +FILEOS 0x4L +FILETYPE 0x1L +FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RC_VERSION_COMPANY_NAME + VALUE "FileDescription", RC_VERSION_FILE_DESCRIPTION + VALUE "InternalName", RC_VERSION_INTERNAL_NAME + VALUE "LegalCopyright", RC_VERSION_LEGAL_COPYRIGHT + VALUE "LegalTrademarks", RC_VERSION_LEGAL_TRADEMARKS + VALUE "OriginalFilename", RC_VERSION_ORIGINAL_FILE_NAME + VALUE "ProductName", RC_VERSION_PRODUCT_NAME + VALUE "FileVersion", INET_VERSION + VALUE "ProductVersion", INET_VERSION + VALUE "PrivateBuild", BUILD_PRIVATE +#ifdef OLEREGISTER + VALUE "OLESelfRegister","\0" +#endif + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Setup.sln b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Setup.sln new file mode 100644 index 0000000000..4ec3c19636 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Setup.sln @@ -0,0 +1,41 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26730.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iisca", "iisca\lib\iisca.vcxproj", "{7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CommonLib", "IIS-Common\lib\CommonLib.vcxproj", "{B54A8F61-60DE-4AD9-87CA-D102F230678E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Debug|x64.ActiveCfg = Debug|x64 + {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Debug|x64.Build.0 = Debug|x64 + {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Debug|x86.ActiveCfg = Debug|Win32 + {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Debug|x86.Build.0 = Debug|Win32 + {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Release|x64.ActiveCfg = Release|x64 + {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Release|x64.Build.0 = Release|x64 + {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Release|x86.ActiveCfg = Release|Win32 + {7324770C-0871-4D73-BE3D-5E2F3E9E1B1E}.Release|x86.Build.0 = Release|Win32 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x64.ActiveCfg = Debug|x64 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x64.Build.0 = Debug|x64 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x86.ActiveCfg = Debug|Win32 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Debug|x86.Build.0 = Debug|Win32 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x64.ActiveCfg = Release|x64 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x64.Build.0 = Release|x64 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x86.ActiveCfg = Release|Win32 + {B54A8F61-60DE-4AD9-87CA-D102F230678E}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3DC22D38-F38B-420A-9AD1-77F2512B35FF} + EndGlobalSection +EndGlobal diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/LICENSE b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/LICENSE new file mode 100644 index 0000000000..21071075c2 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/README.md b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/README.md new file mode 100644 index 0000000000..22e594aa6c --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/README.md @@ -0,0 +1,18 @@ +Microsoft IIS Setup +-------------------------------- + +The repository contains setup resources shared by IIS Out-Of-Band (OOB) products. + +### Contributing + +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit https://cla.microsoft.com. + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/appsearch/appsearch.wxi b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/appsearch/appsearch.wxi new file mode 100644 index 0000000000..820cc86f4e --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/appsearch/appsearch.wxi @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/ConfigShared.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/ConfigShared.cpp new file mode 100644 index 0000000000..883a228a33 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/ConfigShared.cpp @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + + +HRESULT +CheckInstallToSharedConfig( + IN MSIHANDLE hInstall, + BOOL * pbShouldInstall + ) +{ + HRESULT hr = S_OK; + STRU strShared; + STRU strWriteToShared; + + *pbShouldInstall = FALSE; + + //Check if config is shared + hr = MsiUtilGetProperty( hInstall, L"IISCONFIGISSHARED", &strShared ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + if( 0 != wcscmp( strShared.QueryStr(), L"1" ) ) + { + //config is not shared, tell caller to schedule executeCA for config + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"IIS Configuration is NOT shared. Setup will schedule the deferred custom action."); + *pbShouldInstall = TRUE; + goto exit; + } + + // + //config is shared lets check IIUSESHAREDCONFIG Property + // + hr = MsiUtilGetProperty( hInstall, L"IIUSESHAREDCONFIG", &strWriteToShared ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + if( 0 == wcscmp( strWriteToShared.QueryStr(), L"1" ) ) + { + //Config is shared but property is set + //tell caller to schedule executeCA for config + // + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"IIS Configuration IS shared. IIUSESHAREDCONFIG property indicated that setup SHOULD schedule the deferred custom action.."); + *pbShouldInstall = TRUE; + } + else + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"IIS Configuration IS shared. IIUSESHAREDCONFIG property indicated that setup should NOT schedule the deferred custom action."); + } + +exit: + return hr; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/ConfigShared.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/ConfigShared.h new file mode 100644 index 0000000000..0ac0ea9852 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/ConfigShared.h @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +HRESULT +CheckInstallToSharedConfig( + IN MSIHANDLE hInstall, + BOOL * pbShouldInstall + ); diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/CustomAction.def b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/CustomAction.def new file mode 100644 index 0000000000..8ba47da929 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/CustomAction.def @@ -0,0 +1,15 @@ +; Copyright (c) Microsoft Corporation. All rights reserved. +; Licensed under the MIT license. + +LIBRARY iisca + +EXPORTS + + ; IIS Common Config custom actions + + IISScheduleInstallCA + IISScheduleUninstallCA + IISExecuteCA + IISBeginTransactionCA + IISRollbackTransactionCA + IISCommitTransactionCA diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/cgi_restrictions.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/cgi_restrictions.cpp new file mode 100644 index 0000000000..b57a5d3037 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/cgi_restrictions.cpp @@ -0,0 +1,271 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +// +// Public functions +// + +HRESULT +RegisterCgiRestriction( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szPath, + IN BOOL fAllowed, + IN OPTIONAL CONST WCHAR * szGroupId, + IN OPTIONAL CONST WCHAR * szDescription + ) +{ + HRESULT hr = NOERROR; + + CComPtr pCgiRestrictionSection; + CComPtr pCgiRestrictionCollection; + CComPtr pNewCgiRestrictionElement; + + BSTR bstrAppHostConfigPath = SysAllocString(szConfigPath); + BSTR bstrCgiRestriction = SysAllocString( L"system.webServer/security/isapiCgiRestriction" ); + BSTR bstrAdd = SysAllocString( L"add" ); + + if( !bstrAppHostConfigPath || + !bstrCgiRestriction || + !bstrAdd ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto exit; + } + + // + // Remove any existing web service first, + // ignore any resulting errors. + // + + hr = UnRegisterCgiRestriction( + pAdminMgr, + szConfigPath, + szPath, + FALSE // do NOT expand environment strings + ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + // press on regardless + } + + hr = UnRegisterCgiRestriction( + pAdminMgr, + szConfigPath, + szPath, + TRUE // DO expand environment strings + ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + // press on regardless + } + + // + // Get the ISAPI CGI Restriction collection + // + + hr = pAdminMgr->GetAdminSection( bstrCgiRestriction, + bstrAppHostConfigPath, + &pCgiRestrictionSection ); + + + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = pCgiRestrictionSection->get_Collection( &pCgiRestrictionCollection ); + + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + // + // Create a new element + // + + hr = pCgiRestrictionCollection->CreateNewElement( bstrAdd, + &pNewCgiRestrictionElement ); + + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = SetElementStringProperty( + pNewCgiRestrictionElement, + L"path", + szPath + ); + + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = SetElementStringProperty( + pNewCgiRestrictionElement, + L"allowed", + fAllowed ? L"true" : L"false" + ); + + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + if( szGroupId && *szGroupId ) + { + hr = SetElementStringProperty( + pNewCgiRestrictionElement, + L"groupId", + szGroupId + ); + + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + } + + if( szDescription && *szDescription ) + { + hr = SetElementStringProperty( + pNewCgiRestrictionElement, + L"description", + szDescription + ); + + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + } + + // + // Add the new element + // + + hr = pCgiRestrictionCollection->AddElement( pNewCgiRestrictionElement ); + + if( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + +exit: + + SysFreeString( bstrAppHostConfigPath ); + SysFreeString( bstrCgiRestriction ); + SysFreeString( bstrAdd ); + + return hr; +} + +HRESULT +UnRegisterCgiRestriction( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szPath, + IN BOOL fExpandPath + ) +{ + HRESULT hr = NOERROR; + + CComPtr pCgiRestrictionSection; + CComPtr pCgiRestrictionCollection; + + BSTR bstrAppHostConfigPath = SysAllocString(szConfigPath); + BSTR bstrCgiRestriction = SysAllocString( L"system.webServer/security/isapiCgiRestriction" ); + + UINT numDeleted; + + STRU expandedPath; + + if( !bstrAppHostConfigPath || + !bstrCgiRestriction ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto exit; + } + + if (fExpandPath) + { + hr = expandedPath.CopyAndExpandEnvironmentStrings(szPath); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + szPath = expandedPath.QueryStr(); + } + + // + // Remove from the ISAPI CGI Restriction collection + // + + hr = pAdminMgr->GetAdminSection( bstrCgiRestriction, + bstrAppHostConfigPath, + &pCgiRestrictionSection ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pCgiRestrictionSection->get_Collection( &pCgiRestrictionCollection ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = DeleteAllElementsFromCollection( pCgiRestrictionCollection, + L"path", + szPath, + FIND_ELEMENT_CASE_INSENSITIVE, + &numDeleted + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if( numDeleted == 0 ) + { + DBGWARN(( DBG_CONTEXT, + "Expected to find %S in ISAPI CGI Restriction collection\n", + szPath )); + } + +exit: + + SysFreeString( bstrAppHostConfigPath ); + SysFreeString( bstrCgiRestriction ); + + return hr; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/cgi_restrictions.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/cgi_restrictions.h new file mode 100644 index 0000000000..68ae838d07 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/cgi_restrictions.h @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + + +#ifndef _CGI_RESTRICTIONS_H_ +#define _CGI_RESTRICTIONS_H_ + + +HRESULT +RegisterCgiRestriction( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szPath, + IN BOOL fAllowed, + IN OPTIONAL CONST WCHAR * szGroupId, + IN OPTIONAL CONST WCHAR * szDescription + ); + + +HRESULT +UnRegisterCgiRestriction( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szPath, + IN BOOL fExpandPath = FALSE + ); + + +#endif + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/config_custom.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/config_custom.cpp new file mode 100644 index 0000000000..8d44a69506 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/config_custom.cpp @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +UINT +__stdcall +CheckForSharedConfigurationCA( + MSIHANDLE hInstall +) +{ + HRESULT hr = S_OK; + UINT status = ERROR_SUCCESS; + BOOL fIsSharedConfig = FALSE; + STRU strWriteToShared; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + hr = GetSharedConfigEnabled( &fIsSharedConfig ); + if ( FAILED( hr ) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Unable to detect whether shared configuration is in use."); + status = LogMsiCustomActionError( hInstall, 30001 ); + goto exit; + } + if ( fIsSharedConfig ) + { + //set config shared property. + //will be used by other CAs via CheckInstallToSharedConfig + hr = MsiSetProperty( hInstall, L"IISCONFIGISSHARED", L"1" ); + if ( FAILED( hr ) ) + { + goto exit; + } + // + //config is shared lets check if user + //set public property IIUSESHAREDCONFIG + // + hr = MsiUtilGetProperty( hInstall, L"IIUSESHAREDCONFIG", &strWriteToShared ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + if( 0 == wcscmp( strWriteToShared.QueryStr(), L"1" ) ) + { + //Config is shared but property is set + //tell caller to schedule executeCA for config + // + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"IIS Configuration IS shared. IIUSESHAREDCONFIG property indicated that setup SHOULD schedule the deferred custom action.."); + } + else + { + // + //public property not set error-out install + // + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Shared Configuration detected."); + status = LogMsiCustomActionError( hInstall, 30002 ); + goto exit; + } + } + else + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"No Shared Configuration detected."); + } + +exit: + + IISLogClose(); + return status; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/config_custom.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/config_custom.h new file mode 100644 index 0000000000..f69b0101c4 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/config_custom.h @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + + +#ifndef _CONFIG_CUSTOM_H_ +#define _CONFIG_CUSTOM_H_ + + +UINT +__stdcall +CheckForSharedConfigurationCA( + MSIHANDLE hInstall +); + +#endif + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/consoleprops.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/consoleprops.cpp new file mode 100644 index 0000000000..ed39ca6af6 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/consoleprops.cpp @@ -0,0 +1,594 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +#define CheckAndGoToExit(hr,sev,msg,prop) if (FAILED(hr)) { DBGERROR_HR(hr); IISLogWrite(sev, msg, prop, hr);goto exit;} +#define CheckAndReturnHr(hr,sev,msg,prop) if (FAILED(hr)) { DBGERROR_HR(hr); IISLogWrite(sev, msg, prop, hr);return hr;} + + +HRESULT +GetConsoleIntProperty( + IN MSIHANDLE hRecord, + IN UINT field, + __inout CA_DATA_WRITER * cadata) +{ + HRESULT hr = S_OK; + + UINT dwValue = 0; + hr = MsiUtilRecordGetInteger( hRecord, + field, + &dwValue ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", field, hr); + return hr; + } + + hr = cadata->Write(dwValue); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error writing custom action data, hr=0x%x", hr); + return hr; + } + + return hr; +} + +HRESULT +GetConsoleProperties( + IN MSIHANDLE hRecord, + __inout CA_DATA_WRITER * cadata) +{ + HRESULT hr = S_OK; + + /*STACK_STRU( strTextColour, 128 ); + STACK_STRU( strBackgroundColour, 128 );*/ + + enum { + CA_CONSOLEPROPS_QUCIKEDIT = 5, + CA_CONSOLEPROPS_INSERTMODE, + CA_CONSOLEPROPS_WINDOWWIDTH, + CA_CONSOLEPROPS_WINDOWHEIGHT, + CA_CONSOLEPROPS_BUFFERWIDTH, + CA_CONSOLEPROPS_BUFFERHEIGHT, + /* CA_CONSOLEPROPS_TEXTCOLOUR, + CA_CONSOLEPROPS_BACKGROUNDCOLOUR*/ + }; + + // GET QuickEdit int + hr = GetConsoleIntProperty( hRecord, + CA_CONSOLEPROPS_QUCIKEDIT, + cadata ); + if ( FAILED(hr) ) { return hr;} + + // GET InsertMode + hr = GetConsoleIntProperty( hRecord, + CA_CONSOLEPROPS_INSERTMODE, + cadata ); + if ( FAILED(hr) ) { return hr;} + + + // GET WindowWidth + hr = GetConsoleIntProperty( hRecord, + CA_CONSOLEPROPS_WINDOWWIDTH, + cadata ); + if ( FAILED(hr) ) { return hr;} + + + // GET WindowHeight + hr = GetConsoleIntProperty( hRecord, + CA_CONSOLEPROPS_WINDOWHEIGHT, + cadata ); + if ( FAILED(hr) ) { return hr;} + + + // GET BufferWidth + hr = GetConsoleIntProperty( hRecord, + CA_CONSOLEPROPS_BUFFERWIDTH, + cadata ); + if ( FAILED(hr) ) { return hr;} + + + // GET BufferHeight + hr = GetConsoleIntProperty( hRecord, + CA_CONSOLEPROPS_BUFFERHEIGHT, + cadata ); + if ( FAILED(hr) ) { return hr;} + + //// Get Text colours + //hr = MsiUtilRecordGetString( hRecord, + // CA_CONSOLEPROPS_TEXTCOLOUR, + // &strTextColour ); + + //CheckAndReturnHr(hr, SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_CONSOLEPROPS_TEXTCOLOUR); + + //hr = cadata->Write( strTextColour.QueryStr(), strTextColour.QueryCCH() ); + //if ( FAILED(hr) ) + //{ + // DBGERROR_HR(hr); + // IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error writing custom action data, hr=0x%x", hr); + // return hr; + //} + + //// Get Background colours + //hr = MsiUtilRecordGetString( hRecord, + // CA_CONSOLEPROPS_BACKGROUNDCOLOUR, + // &strBackgroundColour ); + + //CheckAndReturnHr(hr, SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_CONSOLEPROPS_TEXTCOLOUR); + + //hr = cadata->Write( strBackgroundColour.QueryStr(), strBackgroundColour.QueryCCH() ); + //if ( FAILED(hr) ) + //{ + // DBGERROR_HR(hr); + // IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error writing custom action data, hr=0x%x", hr); + // return hr; + //} + + return hr; +} + +UINT +WINAPI +ScheduleSetConsolePropertiesCA( + IN MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strShortcut, 128 ); + STACK_STRU( strDirectoryId, 256 ); // Directory Identifier + STACK_STRU( strDirectoryName, 256 ); + STACK_STRU( strComponent, 128 ); + STACK_STRU( strShortcutName, 256 ); + STACK_STRU( strData, 256); + + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISShortcutConsoleProperties`.`Shortcut_`, " + L"`Shortcut`.`Component_`, " + L"`Shortcut`.`Name`, " + L"`Directory`.`Directory`, " + L"`IISShortcutConsoleProperties`.`QuickEdit`, " + L"`IISShortcutConsoleProperties`.`InsertMode`, " + L"`IISShortcutConsoleProperties`.`WindowWidth`, " + L"`IISShortcutConsoleProperties`.`WindowHeight`, " + L"`IISShortcutConsoleProperties`.`BufferWidth`, " + L"`IISShortcutConsoleProperties`.`BufferHeight` " + /*L"`IISShortcutConsoleProperties`.`TextColor`, " + L"`IISShortcutConsoleProperties`.`BackgroundColor` "*/ + L"FROM `IISShortcutConsoleProperties`, `Shortcut`, `Directory` " + L"WHERE `IISShortcutConsoleProperties`.`Shortcut_`=`Shortcut`.`Shortcut` " + L"AND `Shortcut`.`Directory_`=`Directory`.`Directory`"; + + + CA_DATA_WRITER cadata; + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + BOOL scheduleDefferedCA = FALSE; + + enum { + CA_CONSOLEPROPS_SHORTCUT = 1, + CA_CONSOLEPROPS_COMPONENT, + CA_CONSOLEPROPS_SHORTCUTNAME, + CA_CONSOLEPROPS_DIRECTORY, + }; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting MSI database, hr=0x%x", hr); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error opening View, hr=0x%x", hr); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error executing view, hr=0x%x", hr); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_CONSOLEPROPS_COMPONENT, + &strComponent ); + CheckAndGoToExit(hr, SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_CONSOLEPROPS_COMPONENT); + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting state for component %s, hr=0x%x", strComponent.QueryStr(), hr); + goto exit; + } + + // Only run if the comonent is installing or reinstalling + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + // Get Shortcut location + { + // GET: directory where shortcut is + // Get the directory id for the shortcut + hr = MsiUtilRecordGetString( hRecord, + CA_CONSOLEPROPS_DIRECTORY, + &strDirectoryId ); + + CheckAndGoToExit(hr, SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_CONSOLEPROPS_DIRECTORY); + + // Get directory path + hr = MsiUtilGetProperty(hInstall, strDirectoryId.QueryStr(), &strDirectoryName ); + + CheckAndGoToExit(hr, SETUP_LOG_SEVERITY_ERROR, L"Error getting value for directory record %s, hr=0x%x", strDirectoryId.QueryStr()); + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Shortcut Directory: '%s'.", + strDirectoryName.QueryStr()); + // ENDGET: directory where shortcut is + + + // GET: Short and Long names of shortcuts + hr = MsiUtilRecordGetString( hRecord, + CA_CONSOLEPROPS_SHORTCUTNAME, + &strShortcutName ); + + CheckAndGoToExit(hr, SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_CONSOLEPROPS_SHORTCUTNAME); + + + // strShortcutName contains the short and long file names of the shortcut + PCWSTR pszPrevious = strShortcutName.QueryStr(); + // Append the shortcut name to the directory and write to cadata + // Write the short and long shortcut paths + for ( DWORD i = 0; i < strShortcutName.QueryCCH() + 1; i++ ) + { + if ( strShortcutName.QueryStr()[ i ] == L'|' || + strShortcutName.QueryStr()[ i ] == L'\0' ) + { + strShortcutName.QueryStr()[ i ] = L'\0'; + + strData.Copy( strDirectoryName ); + strData.Append(L"\\"); + strData.Append(pszPrevious); + strData.Append(L".lnk"); + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Potential shortcut path: %s", + strData.QueryStr()); + + hr = cadata.Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error writing custom action data, hr=0x%x", hr); + goto exit; + } + + pszPrevious = strShortcutName.QueryStr() + i + 1; + + // Get the console properties + hr = GetConsoleProperties(hRecord, &cadata); + if( FAILED(hr)) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting console properties, hr=0x%x", hr); + goto exit; + } + + // Only schedule custom action if needed + scheduleDefferedCA = TRUE; + } + } + // ENDGET: Short and Long names of shortcuts + } + // End OF getting shortcut location + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + } + + if ( scheduleDefferedCA ) + { + hr = MsiUtilScheduleDeferredAction( hInstall, + L"ExecuteSetConsoleProperties", + cadata.QueryData() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error scheduling custom action, hr=0x%x", hr); + goto exit; + } + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Custom action ExecuteSetConsoleProperties scheduled"); + } + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogClose(); + + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_SUCCESS; +} + +void IntializeConsoleProps( + IN NT_CONSOLE_PROPS* pConsoleProps + ) +{ + if (!pConsoleProps) + { + return; + } + + pConsoleProps->dbh.cbSize = sizeof(NT_CONSOLE_PROPS); + pConsoleProps->dbh.dwSignature = NT_CONSOLE_PROPS_SIG; + pConsoleProps->bFullScreen = false; + pConsoleProps->uHistoryBufferSize = 50; + pConsoleProps->uNumberOfHistoryBuffers = 4; + pConsoleProps->uCursorSize = 25; + + pConsoleProps->ColorTable[0] = RGB(0,0,0); + pConsoleProps->ColorTable[1] = RGB(0,0,128); + pConsoleProps->ColorTable[2] = RGB(0,128,0); + pConsoleProps->ColorTable[3] = RGB(0,128,128); + pConsoleProps->ColorTable[4] = RGB(128,0,0); + pConsoleProps->ColorTable[5] = RGB(128,0,128); + pConsoleProps->ColorTable[6] = RGB(128,128,0); + pConsoleProps->ColorTable[7] = RGB(192,192,192); + pConsoleProps->ColorTable[8] = RGB(128,128,128); + pConsoleProps->ColorTable[9] = RGB(0,0,255); + pConsoleProps->ColorTable[10] = RGB(0,255,0); + pConsoleProps->ColorTable[11] = RGB(0,255,255); + pConsoleProps->ColorTable[12] = RGB(255,0,0); + pConsoleProps->ColorTable[13] = RGB(255,0,255); + pConsoleProps->ColorTable[14] = RGB(255,255,0); + pConsoleProps->ColorTable[15] = RGB(255,255,255); + + pConsoleProps->wPopupFillAttribute = ((15 << 4) | 3); +} + + +UINT +WINAPI +ExecuteSetConsolePropertiesCA( + IN MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + + BOOL fCoInit = FALSE; + + WCHAR * szShortcutFile = NULL; + /*WCHAR * szTextColour = NULL; + WCHAR * szBackgroundColour = NULL;*/ + INT dwQuickEdit = 0; + INT dwInsertMode = 0; + INT dwWindowWidth = 120; + INT dwWindowHeight = 50; + INT dwBufferWidth = 120; + INT dwBufferHeight = 3000; + + + CA_DATA_READER cadata; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + // + // Retrieve parameters from ca data + // + + hr = cadata.LoadDeferredCAData( hInstall ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error retrieving custom action data, hr=0x%x", hr); + goto exit; + } + + if ( SUCCEEDED( hr = CoInitialize(NULL) ) ) + { + fCoInit = TRUE; + } + + while ( SUCCEEDED(hr = cadata.Read( &szShortcutFile )) ) + { + hr = cadata.Read( &dwQuickEdit); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata.Read( &dwInsertMode); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata.Read( &dwWindowWidth); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata.Read( &dwWindowHeight); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata.Read( &dwBufferWidth); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata.Read( &dwBufferHeight); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + /*hr = cadata.Read( &szTextColour); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata.Read( &szBackgroundColour); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + }*/ + + // Check to see if file exists + if(GetFileAttributes(szShortcutFile) != 0xFFFFFFFF) + { + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Shortcut %s exists", szShortcutFile); + + // Get shell + CComPtr sppf; + + if (FAILED(hr = sppf.CoCreateInstance(L"lnkfile")) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error get ShellLink com object, hr=0x%x", hr); + goto exit; + } + + // Load shortcut file + if (FAILED(hr = sppf->Load(szShortcutFile, STGM_READWRITE))) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error loading shortcut file %s, hr=0x%x", szShortcutFile, hr); + goto exit; + } + + CComQIPtr spdl(sppf); + if (!spdl) + { + DBGERROR_HR(hr); + goto exit; + } + + NT_CONSOLE_PROPS* pConsoleProps = NULL; + + hr = spdl->CopyDataBlock(NT_CONSOLE_PROPS_SIG, (LPVOID*) &pConsoleProps); + if ( FAILED(hr) || (NULL == pConsoleProps) ) + { + // Create new console properties and set defaults + pConsoleProps = (NT_CONSOLE_PROPS *)malloc(sizeof(NT_CONSOLE_PROPS)); + memset(pConsoleProps,0,sizeof(NT_CONSOLE_PROPS)); + IntializeConsoleProps(pConsoleProps); + } + + pConsoleProps->bQuickEdit = dwQuickEdit > 0; + pConsoleProps->bInsertMode = dwInsertMode > 0; + pConsoleProps->dwWindowSize.X = (short) dwWindowWidth; + pConsoleProps->dwWindowSize.Y = (short) dwWindowHeight; + pConsoleProps->dwScreenBufferSize.X = (short) dwBufferWidth; + pConsoleProps->dwScreenBufferSize.Y = (short) dwBufferHeight; + + pConsoleProps->ColorTable[6] = RGB(238, 237, 240); // text color + pConsoleProps->ColorTable[5] = RGB(1, 36, 86); // backgroud color + pConsoleProps->wFillAttribute = ((5 << 4) | 6 ); + + + spdl->RemoveDataBlock(NT_CONSOLE_PROPS_SIG); + if (FAILED(hr = spdl->AddDataBlock((void *)pConsoleProps))) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error setting NT_CONSOLE_PROPS on shortcut file %s, hr=0x%x", szShortcutFile, hr); + goto exit; + } + + if (FAILED(hr = sppf->Save(NULL, TRUE))) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error saving changes to shortcut, hr=0x%x", hr); + goto exit; + } + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Successfully added properties to shortcut %s", + szShortcutFile); + + } + } + + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + if ( fCoInit ) + { + CoUninitialize(); + } + + IISLogClose(); + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_SUCCESS; +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/consoleprops.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/consoleprops.h new file mode 100644 index 0000000000..11692e14b3 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/consoleprops.h @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +UINT +WINAPI +ScheduleSetConsolePropertiesCA( + IN MSIHANDLE hInstall + ); + +UINT +WINAPI +ExecuteSetConsolePropertiesCA( + IN MSIHANDLE hInstall + ); \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/defaults.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/defaults.cpp new file mode 100644 index 0000000000..51a9831cf7 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/defaults.cpp @@ -0,0 +1,716 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + + +HRESULT +SetElementMetadata( + IAppHostElement * pElement, + CONST WCHAR * szMetaType, + CONST VARIANT * pVarValue + ) +{ + HRESULT hr = NOERROR; + + BSTR bstrMetaType = SysAllocString( szMetaType ); + if( !bstrMetaType ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pElement->SetMetadata( bstrMetaType, + *pVarValue ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + SysFreeString( bstrMetaType ); + + return hr; +} + +HRESULT +ProcessAttributes( + IAppHostElement * pElement, + IXmlReader * pReader + ) +{ + HRESULT hr = NOERROR; + + VARIANT varPropValue; + VariantInit( &varPropValue ); + + CONST WCHAR * pszName; + CONST WCHAR * pszValue; + + for( hr = pReader->MoveToFirstAttribute(); + ; + hr = pReader->MoveToNextAttribute() ) + { + if (hr == S_FALSE) + { + hr = S_OK; + break; + } + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pReader->GetLocalName( &pszName, NULL ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pReader->GetValue( &pszValue, NULL ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = VariantAssign( &varPropValue, pszValue ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = SetElementProperty( pElement, pszName, &varPropValue ); + + if( HRESULT_FROM_WIN32( ERROR_INVALID_INDEX ) == hr ) + { + // + // Possibly this is a metadata attribute not a property + // + + hr = SetElementMetadata( pElement, pszName, &varPropValue ); + } + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + VariantClear( &varPropValue ); + } + +exit: + + VariantClear( &varPropValue ); + + return hr; +} + +HRESULT +ProcessSection( + IAppHostWritableAdminManager * pAdminMgr, + CONST WCHAR * szSectionName, + IXmlReader * pReader, + IAppHostElement * pParent, + BOOL fClearSection + ) +{ + HRESULT hr = NOERROR; + + CComPtr pChildElement; + CComPtr pParentElement = pParent; + + CONST WCHAR * pwszLocalName; + + BSTR bstrName = NULL; + BSTR bstrSectionName = NULL; + BSTR bstrRoot = NULL; + BSTR bstrAddElementName = NULL; + + BOOL isEmpty = FALSE; + + bstrSectionName = SysAllocString( szSectionName ); + bstrRoot = SysAllocString( L"MACHINE/WEBROOT/APPHOST" ); + + if( !bstrSectionName || !bstrRoot ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + XmlNodeType nodeType; + + for (;;) + { + hr = pReader->Read(&nodeType); + + if (hr == S_FALSE) + { + hr = S_OK; + break; + } + + if (FAILED(hr)) + { + break; + } + + if( nodeType == XmlNodeType_Element ) + { + hr = pReader->GetLocalName( &pwszLocalName, NULL ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + SysFreeString( bstrName ); + bstrName = NULL; + + bstrName = SysAllocString( pwszLocalName ); + if( !bstrName ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + isEmpty = pReader->IsEmptyElement(); + + if( !pParent ) + { + // + // This is the entry point to resetting the section. Begin by + // clearing. + // + + hr = pAdminMgr->GetAdminSection( bstrSectionName, + bstrRoot, + &pChildElement ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if (fClearSection) + { + hr = pChildElement->Clear(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // Need to commit change after clear + + hr = pAdminMgr->CommitChanges(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // Need to reload after commit + + pChildElement.Release(); + + hr = pAdminMgr->GetAdminSection( bstrSectionName, + bstrRoot, + &pChildElement ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + } + else + { + // Test the parent of this node for a collection + + CComPtr pCollection; + hr = pParentElement->get_Collection( &pCollection ); + + if ( SUCCEEDED ( hr ) && ( pCollection != NULL ) ) + { + // Get the schema for the collection + CComPtr pCollectionSchema; + hr = pCollection->get_Schema( &pCollectionSchema ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + SysFreeString( bstrAddElementName ); + bstrAddElementName = NULL; + + // Parent element has a collection. Get the addElement token. + pCollectionSchema->get_AddElementNames(&bstrAddElementName); + + if( 0 == wcscmp( pwszLocalName, bstrAddElementName ) ) + { + hr = pCollection->CreateNewElement( bstrName, &pChildElement ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = ProcessAttributes( pChildElement, pReader ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pCollection->AddElement( pChildElement ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + pCollection.Release(); + } + else + { + // Parent has collection, but this isn't an 'addElement' + hr = pParentElement->GetElementByName( bstrName, + &pChildElement ); + if( FAILED(hr) ) + { + DBGERROR(( DBG_CONTEXT, "Failed to get child element %S, %08x\n", bstrName, hr )); + goto exit; + } + } + + pCollectionSchema.Release(); + } + else + { + // Parent is not a collection. + hr = pParentElement->GetElementByName( bstrName, + &pChildElement ); + if( FAILED(hr) ) + { + DBGERROR(( DBG_CONTEXT, "Failed to get child element %S, %08x\n", bstrName, hr )); + goto exit; + } + } + } + + hr = ProcessAttributes( pChildElement, pReader ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if( !isEmpty ) + { + hr = ProcessSection( pAdminMgr, + szSectionName, + pReader, + pChildElement, + fClearSection); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + pChildElement.Release(); + } + else if( nodeType == XmlNodeType_EndElement ) + { + break; + } + } + +exit: + + SysFreeString( bstrAddElementName ); + SysFreeString( bstrName ); + SysFreeString( bstrSectionName ); + SysFreeString( bstrRoot ); + + return hr; +} + +HRESULT +ResetConfigSection( + IN IAppHostWritableAdminManager * pAdminMgr, + IN CONST WCHAR * szSectionName, + IN OUT IStream * pStreamDefaults + ) +{ + HRESULT hr = NOERROR; + + CComPtr pReader; + + + hr = CreateXmlReader(__uuidof(IXmlReader), (void**) &pReader, NULL); + if( FAILED(hr) ) + { + DBGERROR(( DBG_CONTEXT, "Error creating xml reader, error is %08.8lx", hr)); + goto exit; + } + + hr = pReader->SetProperty( XmlReaderProperty_DtdProcessing, + DtdProcessing_Prohibit ); + if( FAILED(hr) ) + { + DBGERROR(( DBG_CONTEXT, "Error setting XmlReaderProperty_DtdProcessing, %08x", hr)); + goto exit; + } + + hr = pReader->SetInput( pStreamDefaults ); + if( FAILED(hr) ) + { + DBGERROR(( DBG_CONTEXT, "Error setting input for reader, %08x", hr)); + goto exit; + } + + hr = ProcessSection( pAdminMgr, + szSectionName, + pReader, + NULL, + TRUE); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return hr; +} + +HRESULT +CreateStreamFromTextResource( + IN HINSTANCE hInstance, + IN CONST WCHAR * szResourceName, + OUT IStream ** ppStream + ) +{ + HRESULT hr = NOERROR; + + HRSRC hResDefaults = NULL; + HGLOBAL hGlobDefaults = NULL; + LPCVOID pDefaults = NULL; + DWORD cbDefaults; + HGLOBAL hDefaultsData = NULL; + LPVOID pDefaultsData = NULL; + + hResDefaults = FindResourceW( g_hinst, + szResourceName, + L"TEXT" ); + if( !hResDefaults ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto exit; + } + + hGlobDefaults = LoadResource( hInstance, hResDefaults ); + if( !hGlobDefaults ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto exit; + } + + pDefaults = LockResource( hGlobDefaults ); + if( !pDefaults ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto exit; + } + + cbDefaults = SizeofResource( g_hinst, hResDefaults ); + if( !cbDefaults ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto exit; + } + + hDefaultsData = GlobalAlloc( GMEM_MOVEABLE, cbDefaults ); + if( !hDefaultsData ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto exit; + } + + pDefaultsData = GlobalLock( hDefaultsData ); + if( !pDefaultsData ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto exit; + } + + #pragma prefast( suppress:26010, "cbDefaults is allocated size for pDefaultsData" ) + CopyMemory( pDefaultsData, pDefaults, cbDefaults ); + + GlobalUnlock( hDefaultsData ); + + hr = CreateStreamOnHGlobal( hDefaultsData, TRUE, ppStream ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hDefaultsData = NULL; + +exit: + + if( hDefaultsData ) + { + GlobalFree( hDefaultsData ); + } + + return hr; +} + + +HRESULT +ResetConfigSectionFromResource( + IN CONST WCHAR * szResourceName, + IN CONST WCHAR * szSectionName + ) +{ + HRESULT hr = NOERROR; + + CComPtr pAdminMgr; + CComPtr pStream; + + hr = CreateStreamFromTextResource( g_hinst, + szResourceName, + &pStream ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( IAppHostWritableAdminManager ), + (VOID **)&pAdminMgr ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = ResetConfigSection( pAdminMgr, + szSectionName, + pStream ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Save + // + + hr = pAdminMgr->CommitChanges(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return ( hr ); +} + +HRESULT +ResetConfigSectionFromFile( + IN CONST WCHAR * szFileName, + IN CONST WCHAR * szSectionName + ) +{ + HRESULT hr = NOERROR; + + CComPtr pAdminMgr; + CComPtr pStream; + + hr = SHCreateStreamOnFileEx( szFileName, + STGM_READ, + FILE_ATTRIBUTE_NORMAL, + FALSE, + NULL, + &pStream); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( IAppHostWritableAdminManager ), + (VOID **)&pAdminMgr ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = ResetConfigSection( pAdminMgr, + szSectionName, + pStream ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Save + // + + hr = pAdminMgr->CommitChanges(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return ( hr ); +} + +HRESULT +AppendConfigSectionFromFile( + IN CONST WCHAR * szFileName, + IN CONST WCHAR * szSectionName + ) +{ + HRESULT hr = NOERROR; + + CComPtr pAdminMgr; + CComPtr pStream; + + hr = SHCreateStreamOnFileEx( szFileName, + STGM_READ, + FILE_ATTRIBUTE_NORMAL, + FALSE, + NULL, + &pStream); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( IAppHostWritableAdminManager ), + (VOID **)&pAdminMgr ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = AppendConfigSection( pAdminMgr, + szSectionName, + pStream ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Save + // + + hr = pAdminMgr->CommitChanges(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return ( hr ); +} + + +HRESULT +AppendConfigSection( + IN IAppHostWritableAdminManager * pAdminMgr, + IN CONST WCHAR * szSectionName, + IN OUT IStream * pStreamDefaults + ) +{ + HRESULT hr = NOERROR; + + CComPtr pReader; + + + hr = CreateXmlReader(__uuidof(IXmlReader), (void**) &pReader, NULL); + if( FAILED(hr) ) + { + DBGERROR(( DBG_CONTEXT, "Error creating xml reader, error is %08.8lx", hr)); + goto exit; + } + + hr = pReader->SetProperty( XmlReaderProperty_DtdProcessing, + DtdProcessing_Prohibit ); + if( FAILED(hr) ) + { + DBGERROR(( DBG_CONTEXT, "Error setting XmlReaderProperty_DtdProcessing, %08x", hr)); + goto exit; + } + + hr = pReader->SetInput( pStreamDefaults ); + if( FAILED(hr) ) + { + DBGERROR(( DBG_CONTEXT, "Error setting input for reader, %08x", hr)); + goto exit; + } + + hr = ProcessSection( pAdminMgr, + szSectionName, + pReader, + NULL, + FALSE); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return hr; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/defaults.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/defaults.h new file mode 100644 index 0000000000..491938dfc9 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/defaults.h @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _DEFAULTS_H_ +#define _DEFAULTS_H_ + + +// +// Helper routines for setting-up default module config. +// + +HRESULT +CreateStreamFromTextResource( + IN HINSTANCE hInstance, + IN CONST WCHAR * szResourceName, + OUT IStream ** ppStream + ); + +HRESULT +ResetConfigSection( + IN IAppHostWritableAdminManager * pAdminMgr, + IN CONST WCHAR * szSectionName, + IN OUT IStream * pStreamDefaults + ); + +HRESULT +ResetConfigSectionFromResource( + IN CONST WCHAR * szResourceName, + IN CONST WCHAR * szSectionName + ); + +HRESULT +ResetConfigSectionFromFile( + IN CONST WCHAR * szFileName, + IN CONST WCHAR * szSectionName + ); + +HRESULT +AppendConfigSectionFromFile( + IN CONST WCHAR * szFileName, + IN CONST WCHAR * szSectionName + ); + +HRESULT +AppendConfigSection( + IN IAppHostWritableAdminManager * pAdminMgr, + IN CONST WCHAR * szSectionName, + IN OUT IStream * pStreamDefaults + ); + +#endif + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/elevatedsc.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/elevatedsc.cpp new file mode 100644 index 0000000000..bc9abda798 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/elevatedsc.cpp @@ -0,0 +1,346 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +UINT +WINAPI +ScheduleMakeShortcutElevatedCA( + IN MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strShortcut, 128 ); + STACK_STRU( strDirectoryId, 256 ); // Directory Identifier + STACK_STRU( strDirectoryName, 256 ); + STACK_STRU( strComponent, 128 ); + STACK_STRU( strShortcutName, 256 ); + STACK_STRU( strData, 256); + + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISElevatedShortcut`.`Shortcut_`, " + L"`Shortcut`.`Component_`, " + L"`Shortcut`.`Name`, " + L"`Directory`.`Directory` " + L"FROM `IISElevatedShortcut`, `Shortcut`, `Directory` " + L"WHERE `IISElevatedShortcut`.`Shortcut_`=`Shortcut`.`Shortcut` " + L"AND `Shortcut`.`Directory_`=`Directory`.`Directory`"; + + + CA_DATA_WRITER cadata; + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + BOOL scheduleDefferedCA = FALSE; + + enum { + CA_ELEVATESC_SHORTCUT = 1, + CA_ELEVATESC_COMPONENT, + CA_ELEVATESC_SHORTCUTNAME, + CA_ELEVATESC_DIRECTORY, + }; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting MSI database, hr=0x%x", hr); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error opening View, hr=0x%x", hr); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error executing view, hr=0x%x", hr); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_ELEVATESC_COMPONENT, + &strComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_ELEVATESC_COMPONENT, hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting state for component %s, hr=0x%x", strComponent.QueryStr(), hr); + goto exit; + } + + // Only run if the comonent is installing or reinstalling + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + // GET: directory where shortcut is + // Get the directory id for the shortcut + hr = MsiUtilRecordGetString( hRecord, + CA_ELEVATESC_DIRECTORY, + &strDirectoryId ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_ELEVATESC_DIRECTORY, hr); + goto exit; + } + + // Get directory path + hr = MsiUtilGetProperty(hInstall, strDirectoryId.QueryStr(), &strDirectoryName ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting value for directory record %s, hr=0x%x", strDirectoryId.QueryStr(), hr); + goto exit; + } + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Shortcut Directory: '%s'.", + strDirectoryName.QueryStr()); + // ENDGET: directory where shortcut is + + + // GET: Short and Long names of shortcuts + hr = MsiUtilRecordGetString( hRecord, + CA_ELEVATESC_SHORTCUTNAME, + &strShortcutName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_ELEVATESC_SHORTCUTNAME, hr); + goto exit; + } + + // strShortcutName contains the short and long file names of the shortcut + + PCWSTR pszPrevious = strShortcutName.QueryStr(); + // Append the shortcut name to the directory and write to cadata + // Write the short and long shortcut paths + for ( DWORD i = 0; i < strShortcutName.QueryCCH() + 1; i++ ) + { + if ( strShortcutName.QueryStr()[ i ] == L'|' || + strShortcutName.QueryStr()[ i ] == L'\0' ) + { + strShortcutName.QueryStr()[ i ] = L'\0'; + + strData.Copy( strDirectoryName ); + strData.Append(L"\\"); + strData.Append(pszPrevious); + strData.Append(L".lnk"); + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Potential shortcut path: %s", + strData.QueryStr()); + + hr = cadata.Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error writing custom action data, hr=0x%x", hr); + goto exit; + } + + pszPrevious = strShortcutName.QueryStr() + i + 1; + + // Only schedule custom action if needed + scheduleDefferedCA = TRUE; + } + } + + // ENDGET: Short and Long names of shortcuts + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + } + + if ( scheduleDefferedCA ) + { + hr = MsiUtilScheduleDeferredAction( hInstall, + L"ExecuteMakeShortcutElevated", + cadata.QueryData() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error scheduling custom action, hr=0x%x", hr); + goto exit; + } + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Custom action ExecuteMakeShortcutElevated scheduled"); + } + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogClose(); + + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_SUCCESS; +} + +UINT +WINAPI +ExecuteMakeShortcutElevatedCA( + IN MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + + BOOL fCoInit = FALSE; + + WCHAR * szShortcutFile = NULL; + + CA_DATA_READER cadata; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + // + // Retrieve parameters from ca data + // + + hr = cadata.LoadDeferredCAData( hInstall ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error retrieving custom action data, hr=0x%x", hr); + goto exit; + } + + if ( SUCCEEDED( hr = CoInitialize(NULL) ) ) + { + fCoInit = TRUE; + } + + while ( SUCCEEDED(hr = cadata.Read( &szShortcutFile )) ) + { + if(GetFileAttributes(szShortcutFile) != 0xFFFFFFFF) + { + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Shortcut %s exists", szShortcutFile); + + // Get shell + CComPtr sppf; + + if (FAILED(hr = sppf.CoCreateInstance(L"lnkfile")) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error get ShellLink com object, hr=0x%x", hr); + goto exit; + } + + // Load shortcut file + if (FAILED(hr = sppf->Load(szShortcutFile, STGM_READWRITE))) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error loading shortcut file %s, hr=0x%x", szShortcutFile, hr); + goto exit; + } + + CComQIPtr spdl(sppf); + if (!spdl) + { + DBGERROR_HR(hr); + goto exit; + } + + DWORD dwFlags; + if (FAILED(hr = spdl->GetFlags(&dwFlags))) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting shortcut flags, hr=0x%x", hr); + goto exit; + } + + // Add "run as ..." flag + dwFlags |= SLDF_RUNAS_USER; + if (FAILED(hr = spdl->SetFlags(dwFlags))) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error setting SLDF_RUNAS_USER flag, hr=0x%x", hr); + goto exit; + } + + // Save file. + if (FAILED(hr = sppf->Save(NULL, TRUE))) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error saving changes to shortcut, hr=0x%x", hr); + goto exit; + } + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Successfully added SLDF_RUNAS_USER flag to shortcut %s", + szShortcutFile); + + } + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + if ( fCoInit ) + { + CoUninitialize(); + } + + IISLogClose(); + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_SUCCESS; +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/elevatedsc.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/elevatedsc.h new file mode 100644 index 0000000000..c5f5428510 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/elevatedsc.h @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +UINT +WINAPI +ScheduleMakeShortcutElevatedCA( + IN MSIHANDLE hInstall + ); + +UINT +WINAPI +ExecuteMakeShortcutElevatedCA( + IN MSIHANDLE hInstall + ); \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/handlers.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/handlers.cpp new file mode 100644 index 0000000000..1e824ae72e --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/handlers.cpp @@ -0,0 +1,472 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +// +// Local function declarations +// + +// +// Public functions +// + +HRESULT +RegisterHandler( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN ULONG Index, + IN CONST WCHAR * szName, + IN CONST WCHAR * szPath, + IN CONST WCHAR * szVerbs, + IN OPTIONAL CONST WCHAR * szType, + IN OPTIONAL CONST WCHAR * szModules, + IN OPTIONAL CONST WCHAR * szScriptProcessor, + IN OPTIONAL CONST WCHAR * szResourceType, + IN OPTIONAL CONST WCHAR * szRequiredAccess, + IN OPTIONAL CONST WCHAR * szPreCondition + ) +{ + HRESULT hr; + CComPtr pHandlersCollection; + CComPtr pNewElement; + UINT numDeleted; + BSTR bstrAdd; + + bstrAdd = SysAllocString(L"add"); + + if (bstrAdd == NULL) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = GetHandlersCollection( + pAdminMgr, + szConfigPath, + &pHandlersCollection + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Just in case... delete if it's already there. + // + + hr = DeleteAllElementsFromCollection( + pHandlersCollection, + L"name", + szName, + FIND_ELEMENT_CASE_SENSITIVE, + &numDeleted + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if (Index == HANDLER_INDEX_BEFORE_STATICFILE) + { + // + // If the StaticFile handler is installed (and it probably is) + // then install just before it. + // + + hr = FindHandlerByName( + pAdminMgr, + szConfigPath, + HANDLER_STATICFILE_NAME, + &Index + ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + if (hr == S_FALSE) + { + // + // Not found. Install at end of list. + // + + Index = HANDLER_INDEX_LAST; + } + } + + // + // If the caller wants this to be the last handler, then + // chase down the current entry count. + // + + if (Index == HANDLER_INDEX_LAST) + { + hr = pHandlersCollection->get_Count(&Index); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + hr = pHandlersCollection->CreateNewElement(bstrAdd, &pNewElement); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Required properties. + // + + hr = SetElementStringProperty( + pNewElement, + L"name", + szName + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = SetElementStringProperty( + pNewElement, + L"path", + szPath + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = SetElementStringProperty( + pNewElement, + L"verb", + szVerbs + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Optional properties. + // + + if (szType != NULL && szType[0] != L'\0') + { + hr = SetElementStringProperty( + pNewElement, + L"type", + szType + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if (szModules != NULL && szModules[0] != L'\0') + { + hr = SetElementStringProperty( + pNewElement, + L"modules", + szModules + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if (szScriptProcessor != NULL && szScriptProcessor[0] != L'\0') + { + hr = SetElementStringProperty( + pNewElement, + L"scriptProcessor", + szScriptProcessor + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if (szResourceType != NULL && szResourceType[0] != L'\0') + { + hr = SetElementStringProperty( + pNewElement, + L"resourceType", + szResourceType + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if (szRequiredAccess != NULL && szRequiredAccess[0] != L'\0') + { + hr = SetElementStringProperty( + pNewElement, + L"requireAccess", + szRequiredAccess + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if (szPreCondition != NULL && szPreCondition[0] != L'\0') + { + hr = SetElementStringProperty( + pNewElement, + L"preCondition", + szPreCondition + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + hr = pHandlersCollection->AddElement(pNewElement, Index); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + SysFreeString(bstrAdd); + return hr; +} + +HRESULT +UnRegisterHandler( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szName + ) +{ + HRESULT hr; + CComPtr pHandlersCollection; + CComPtr pLocationCollection; + CComPtr pLocation; + CComPtr pElement; + ENUM_INDEX locationIndex; + BOOL found; + UINT numDeleted; + + // + // Enum the tags, look for any sections, + // and if found, remove the specified handler from each. + // + + hr = GetLocationCollection( + pAdminMgr, + szConfigPath, + &pLocationCollection + ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + for (hr = FindFirstLocation(pLocationCollection, &locationIndex, &pLocation) ; + SUCCEEDED(hr) ; + hr = FindNextLocation(pLocationCollection, &locationIndex, &pLocation)) + { + if (hr == S_FALSE) + { + hr = S_OK; + break; + } + + hr = GetSectionFromLocation( + pLocation, + L"system.webServer/handlers", + &pElement, + &found + ); + + if (SUCCEEDED(hr)) + { + if (found) + { + hr = pElement->get_Collection(&pHandlersCollection); + + if (SUCCEEDED(hr)) + { + hr = DeleteAllElementsFromCollection( + pHandlersCollection, + L"name", + szName, + FIND_ELEMENT_CASE_SENSITIVE, + &numDeleted + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + } + + pHandlersCollection.Release(); + } + else + { + DBGERROR_HR(hr); + } + + pElement.Release(); + } + } + else + { + DBGERROR_HR(hr); + } + + pLocation.Release(); + } + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return hr; +} + +HRESULT +FindHandlerByName( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szName, + OUT ULONG * pIndex + ) +{ + HRESULT hr; + CComPtr pHandlersCollection; + + *pIndex = 0; + + hr = GetHandlersCollection( + pAdminMgr, + szConfigPath, + &pHandlersCollection + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = FindElementInCollection( + pHandlersCollection, + L"name", + szName, + FIND_ELEMENT_CASE_SENSITIVE, + pIndex + ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return hr; +} + +HRESULT +GetHandlersCollection( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + OUT IAppHostElementCollection ** pHandlersCollection + ) +{ + HRESULT hr; + CComPtr pHandlersElement; + BSTR bstrConfigPath; + BSTR bstrHandlersSectionName; + + bstrConfigPath = SysAllocString(szConfigPath); + bstrHandlersSectionName = SysAllocString(L"system.webServer/handlers"); + *pHandlersCollection = NULL; + + if (bstrConfigPath == NULL || bstrHandlersSectionName == NULL) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + // + // Chase down the handlers collection. + // + + hr = pAdminMgr->GetAdminSection( bstrHandlersSectionName, + bstrConfigPath, + &pHandlersElement ); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pHandlersElement->get_Collection(pHandlersCollection); + + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + SysFreeString(bstrHandlersSectionName); + SysFreeString(bstrConfigPath); + return hr; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/handlers.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/handlers.h new file mode 100644 index 0000000000..3024acf8fd --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/handlers.h @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _HANDLERS_H_ +#define _HANDLERS_H_ + + +#define HANDLER_INDEX_FIRST 0 +#define HANDLER_INDEX_LAST ((ULONG)(-1L)) +#define HANDLER_INDEX_BEFORE_STATICFILE ((ULONG)(-2L)) + +#define HANDLER_STATICFILE_NAME L"StaticFile" + +HRESULT +RegisterHandler( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN ULONG Index, + IN CONST WCHAR * szName, + IN CONST WCHAR * szPath, + IN CONST WCHAR * szVerbs, + IN OPTIONAL CONST WCHAR * szType, + IN OPTIONAL CONST WCHAR * szModules, + IN OPTIONAL CONST WCHAR * szScriptProcessor, + IN OPTIONAL CONST WCHAR * szResourceType, + IN OPTIONAL CONST WCHAR * szRequiredAccess, + IN OPTIONAL CONST WCHAR * szPreCondition = NULL + ); + +HRESULT +UnRegisterHandler( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szName + ); + +HRESULT +FindHandlerByName( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + IN CONST WCHAR * szName, + OUT ULONG * pIndex + ); + +HRESULT +GetHandlersCollection( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + OUT IAppHostElementCollection ** pHandlersCollection + ); + + +#endif + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/hotfix.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/hotfix.cpp new file mode 100644 index 0000000000..a800948b13 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/hotfix.cpp @@ -0,0 +1,766 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" +#include "wuerror.h" + +#define REBOOT_REQUIRED_REGKEY L"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce" +#define REBOOT_REGVALUE L"IIS Extensions Reboot Required" + +HRESULT ExecuteCommandLine( + IN PCWSTR szCommandLine, + IN DWORD dwTimeout, + __out LPDWORD pExitCode + + ) +{ + HRESULT hr = NOERROR; + UINT status = 0; + PROCESS_INFORMATION oProcInfo = {0}; + STARTUPINFOW oStartInfo = {0}; + DWORD dwExitCode = ERROR_SUCCESS; + STACK_STRU( strModifiableCommandLine, MAX_PATH); + + oStartInfo.cb = sizeof ( STARTUPINFOW ); + oProcInfo.hThread = INVALID_HANDLE_VALUE; + oProcInfo.hProcess = INVALID_HANDLE_VALUE; + + _ASSERTE ( szCommandLine ); + _ASSERTE ( pExitCode ); + + hr = strModifiableCommandLine.Copy ( szCommandLine ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error copying command line, hr=0x%x", hr); + goto exit; + } + + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Launching process with command line %s", strModifiableCommandLine.QueryStr()); + + status = CreateProcessW(NULL, + strModifiableCommandLine.QueryStr(), // command line + NULL, // security info + NULL, // thread info + TRUE, // inherit handles + GetPriorityClass(GetCurrentProcess()), // creation flags + NULL, // environment + NULL, // cur dir + &oStartInfo, + &oProcInfo); + + if ( 0 == status ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error creating process, hr=0x%x", hr); + goto exit; + } + + status = WaitForSingleObject( oProcInfo.hProcess, dwTimeout ); + if ( status == WAIT_FAILED ) + { + IISLogWrite(SETUP_LOG_SEVERITY_WARNING, L"Process wait failed, hr=0x%x", HRESULT_FROM_WIN32 ( GetLastError() ) ); + // but we can still continue + } + + status = GetExitCodeProcess ( oProcInfo.hProcess, &dwExitCode ); + if ( 0 == status ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting exit code for process, hr=0x%x", hr); + goto exit; + } + + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Process returned with exit code %d", dwExitCode); + *pExitCode = dwExitCode; + +exit: + if ( INVALID_HANDLE_VALUE != oProcInfo.hThread ) + { + CloseHandle ( oProcInfo.hThread ); + oProcInfo.hThread = INVALID_HANDLE_VALUE; + } + + if ( INVALID_HANDLE_VALUE != oProcInfo.hProcess ) + { + CloseHandle ( oProcInfo.hProcess ); + oProcInfo.hProcess = INVALID_HANDLE_VALUE; + } + + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error in function %s, hr=0x%x", UNITEXT(__FUNCTION__), hr); + } + + return hr; +} + + +HRESULT +InstallWindowsHotfixQuietly( + IN PCWSTR szHotFixPath, + __out BOOL * pbRebootRequired +) +{ + HRESULT hr = NOERROR; + UINT status = 0; + STACK_STRU( strCommandLine, MAX_PATH); + DWORD cch = 0; + DWORD exitCode = 0; + + _ASSERTE(szHotFixPath); + _ASSERTE(pbRebootRequired); + + *pbRebootRequired = FALSE; + cch = strCommandLine.QuerySizeCCH(); + + status = GetSystemDirectoryW(strCommandLine.QueryStr(), cch); + if ( status > cch) + { + cch = status; + hr = strCommandLine.Resize( ++cch ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error resizing buffer, hr=0x%x", hr); + goto exit; + } + + status = GetSystemDirectoryW(strCommandLine.QueryStr(), cch); + } + + if ( 0 == status ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting system folder path, hr=0x%x", hr); + goto exit; + } + + strCommandLine.SyncWithBuffer(); + + hr = strCommandLine.Append(L"\\wusa.exe /quiet /norestart \""); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error apppending wusa, hr=0x%x", hr); + goto exit; + } + + hr = strCommandLine.Append(szHotFixPath); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error apppending hotfixpath, hr=0x%x", hr); + goto exit; + } + + hr = strCommandLine.Append(L"\""); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error apppending end quote, hr=0x%x", hr); + goto exit; + } + + hr = ExecuteCommandLine ( strCommandLine.QueryStr(), INFINITE, &exitCode); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error running the hotfix installer, hr=0x%x", hr); + goto exit; + } + + // + // handle return codes based on WinSE team info regarding WUSA.exe + // + switch ( exitCode ) + { + case ERROR_SUCCESS: + // install succeeded, continue. + hr = S_OK; + break; + case ERROR_SUCCESS_REBOOT_INITIATED: + case ERROR_SUCCESS_REBOOT_REQUIRED: + case WU_S_REBOOT_REQUIRED: + *pbRebootRequired = TRUE; + hr = S_OK; + break; + case WU_S_ALREADY_INSTALLED: + // WUSA.exe can return the above codes if this DWORD registry value is set: + // HKLM\Software\Microsoft\Windows\CurrentVersion\WUSA\ExtendedReturnCode + hr = S_OK; + break; + case S_FALSE: + // WUSA.exe returns this when the MSU is already installed, or when its not applicable, continue. + hr = S_OK; + break; + + // + // need cases to handle new WU_S_ALREADY_INSTALLED and WU_E_NOT_APPLICABLE error codes + // + + default: + // the installation failed, abort + hr = HRESULT_FROM_WIN32 ( ERROR_INSTALL_FAILURE ); + goto exit; + } + +exit: + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error in function %s, hr=0x%x", UNITEXT(__FUNCTION__), hr); + } + + return hr; +} +UINT +__stdcall +ExecuteCleanUpWindowsHotfixCA( + IN MSIHANDLE hInstall +) +{ + HRESULT hr = NOERROR; + UINT status = 0; + CA_DATA_READER cadata; + WCHAR * szHotFixName = NULL; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + hr = cadata.LoadDeferredCAData( hInstall ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error retrieving custom action data, hr=0x%x", hr); + goto exit; + } + + while ( SUCCEEDED(hr = cadata.Read( &szHotFixName )) ) + { + status = 0; + status = DeleteFileW( szHotFixName ); + + if( FAILED(status) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error deleting hotfix temp file '%s', hr=0x%x", szHotFixName, hr); + //eat this error and try and delete other temp files + hr = NOERROR; + } + else + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Success deleting hotfix temp file '%s'", szHotFixName ); + } + } + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error in function %s, hr=0x%x", UNITEXT(__FUNCTION__), hr); + } + + IISLogClose(); + //do not fail commit or rollback transaction for this + return ERROR_SUCCESS; +} + +UINT +__stdcall +ScheduleInstallWindowsHotfixCA( + IN MSIHANDLE hInstall +) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + OSVERSIONINFOEXW osVersionInfo = {0}; + + PMSIHANDLE hDatabase; + PMSIHANDLE hView; + PMSIHANDLE hRecord; + BOOL bDeferredRequired = FALSE; + + CA_DATA_WRITER cadata; + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISWindowsHotfix`.`Name`, " + L"`IISWindowsHotfix`.`OSMajorVersion`, " + L"`IISWindowsHotfix`.`OSMinorVersion`, " + L"`IISWindowsHotfix`.`SPMajorVersion`, " + L"`IISWindowsHotfix`.`Condition`, " + L"`Binary`.`Data` " + L"FROM `IISWindowsHotfix`, `Binary` " + L"WHERE `IISWindowsHotfix`.`BinaryName_`=`Binary`.`Name`"; + + enum { CA_HOTFIX_NAME = 1, + CA_HOTFIX_OSMAJORVERSION, + CA_HOTFIX_OSMINORVERSION, + CA_HOTFIX_SPMAJORVERSION, + CA_HOTFIX_CONDITION, + CA_HOTFIX_BINARYDATA + }; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + osVersionInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFOEXW ); +#pragma warning( push ) +#pragma warning( disable : 4996) + status = GetVersionEx( (LPOSVERSIONINFOW) &osVersionInfo ); +#pragma warning( pop ) + + if ( !status ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting Windows version, hr=0x%x", hr); + DBGERROR_HR(hr); + goto exit; + } + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting MSI database, hr=0x%x", hr); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error opening View, hr=0x%x", hr); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error executing view, hr=0x%x", hr); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + UINT dwTargetOSMajorVersion = 0; + UINT dwTargetOSMinorVersion = 0; + UINT dwTargetSPMajorVersion = 0; + STACK_STRU( strHotFixName, 128 ); + BOOL isApplicable = TRUE; // Applicable by default + + hr = MsiUtilRecordGetString( hRecord, + CA_HOTFIX_NAME, + &strHotFixName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting column %d from record, hr=0x%x", CA_HOTFIX_NAME, hr); + goto exit; + } + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Checking applicability of Hotfix '%s'.", + strHotFixName.QueryStr()); + + hr = MsiUtilRecordGetInteger( hRecord, + CA_HOTFIX_OSMAJORVERSION, + &dwTargetOSMajorVersion); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"No OS Major Version available.", CA_HOTFIX_OSMAJORVERSION, hr); + // This column may be NULL + hr = S_FALSE; + } + + hr = MsiUtilRecordGetInteger( hRecord, + CA_HOTFIX_OSMINORVERSION, + &dwTargetOSMinorVersion); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"No OS Minor Version available."); + // This column may be NULL + hr = S_FALSE; + } + + hr = MsiUtilRecordGetInteger( hRecord, + CA_HOTFIX_SPMAJORVERSION, + &dwTargetSPMajorVersion); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"No OS SP Major Version available."); + // This column may be NULL + hr = S_FALSE; + } + + if ( hr == S_FALSE ) + { + // No OS Version information available + hr = S_OK; + } + else + { + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"OS Version: Actual '%d.%d'. Hotfix Target '%d.%d'.", + osVersionInfo.dwMajorVersion, + osVersionInfo.dwMinorVersion, + dwTargetOSMajorVersion, + dwTargetOSMinorVersion); + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"OS Service Pack Level: Actual '%d'. Hotfix Target '%d'.", + osVersionInfo.wServicePackMajor, + dwTargetSPMajorVersion); + + if ( osVersionInfo.dwMajorVersion != dwTargetOSMajorVersion || + osVersionInfo.dwMinorVersion != dwTargetOSMinorVersion) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"OS Version Mismatch! Will not apply the hotfix."); + isApplicable = FALSE; + } + else if(osVersionInfo.wServicePackMajor != dwTargetSPMajorVersion) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"OS SP Level Mismatch! Will not apply the hotfix."); + isApplicable = FALSE; + } + else + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"OS Versions match! Will try to apply the hotfix."); + isApplicable = TRUE; + } + } + + if ( isApplicable ) + { + STACK_STRU( strCondition, 128 ); + MSICONDITION Condition; + + hr = MsiUtilRecordGetString( hRecord, + CA_HOTFIX_CONDITION, + &strCondition ); + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"Error gettting column %d from record, hr=0x%x", + CA_HOTFIX_CONDITION, + hr); + goto exit; + } + + Condition = MsiEvaluateCondition( hInstall, strCondition.QueryStr() ); + + switch( Condition ) + { + case MSICONDITION_ERROR: + hr = E_UNEXPECTED; + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"Cannot evaluate hotfix install condition \"%s\", hr=0x%x", + strCondition.QueryStr(), + hr ); + goto exit; + + case MSICONDITION_FALSE: + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Condition evaluation returned false! Will not apply the hotfix."); + isApplicable = FALSE; + break; + + case MSICONDITION_TRUE: + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Condition evaluation returned true! Will try to apply the hotfix."); + isApplicable = TRUE; + break; + + case MSICONDITION_NONE: + + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"No condition available to evaluate."); + + break; + } + } + + if ( isApplicable ) + { + //apply the hotfix + STACK_STRU( hotFixFilePath, MAX_PATH * 2 ); + + hr = GenerateTempFileName ( strHotFixName.QueryStr(), + L"msu", + &hotFixFilePath); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error generating temp file name for the hotfix, hr=0x%x", hr); + goto exit; + } + + hr = MsiUtilRecordReadStreamIntoFile ( hRecord, + CA_HOTFIX_BINARYDATA, + hotFixFilePath.QueryStr()); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error streaming binary data into file, hr=0x%x", hr); + goto exit; + } + else + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Streamed hotfix '%s' into file '%s'.", strHotFixName.QueryStr(), hotFixFilePath.QueryStr()); + } + + bDeferredRequired = TRUE; + hr = cadata.Write( hotFixFilePath.QueryStr(), hotFixFilePath.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error writing custom action data, hr=0x%x", hr); + goto exit; + } + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + if( bDeferredRequired ) + { + //schedule CA to install the msu files + hr = MsiUtilScheduleDeferredAction( hInstall, + L"ExecuteInstallWindowsHotfix", + cadata.QueryData() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error scheduling custom action ExecuteInstallWindowsHotfix, hr=0x%x", hr); + goto exit; + } + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Custom action ExecuteInstallWindowsHotfix scheduled"); + + + //schedule CA to delete the msu files if rollback transaction initiated + hr = MsiUtilScheduleDeferredAction( hInstall, + L"RollbackCleanUpWindowsHotfix", + cadata.QueryData() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error scheduling custom action RollbackCleanUpWindowsHotfix, hr=0x%x", hr); + goto exit; + } + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Custom action RollbackCleanUpWindowsHotfix scheduled"); + + //schedule CA to delete the msu files if commit transaction initiated + hr = MsiUtilScheduleDeferredAction( hInstall, + L"CommitCleanUpWindowsHotfix", + cadata.QueryData() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error scheduling custom action CommitCleanUpWindowsHotfix, hr=0x%x", hr); + goto exit; + } + + IISLogWrite ( SETUP_LOG_SEVERITY_INFORMATION, + L"Custom action CommitCleanUpWindowsHotfix scheduled"); + + } + +exit: + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error in function %s, hr=0x%x", UNITEXT(__FUNCTION__), hr); + } + + IISLogClose(); + + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; +} + + +UINT +__stdcall +ExecuteInstallWindowsHotfixCA( + IN MSIHANDLE hInstall +) +{ + HRESULT hr = NOERROR; + CA_DATA_READER cadata; + WCHAR * szHotFixName = NULL; + BOOL rebootRequired = FALSE; + HKEY regKey = NULL; + LONG status = ERROR_SUCCESS; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + hr = cadata.LoadDeferredCAData( hInstall ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error retrieving custom action data, hr=0x%x", hr); + goto exit; + } + + while ( SUCCEEDED(hr = cadata.Read( &szHotFixName )) ) + { + BOOL requiresReboot = FALSE; + hr = InstallWindowsHotfixQuietly ( szHotFixName , &requiresReboot ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error installing hotfix '%s', hr=0x%x", szHotFixName, hr); + goto exit; + } + if ( requiresReboot ) + { + rebootRequired = TRUE; + } + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + + if ( rebootRequired ) + { + status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + REBOOT_REQUIRED_REGKEY, + 0, + KEY_SET_VALUE, + ®Key); + if(status != ERROR_SUCCESS) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error opening the reboot registry key, hr=0x%x", hr); + goto exit; + } + + status = RegSetValueEx(regKey, + REBOOT_REGVALUE, + 0, + REG_SZ, + (PBYTE)L"", + 4); + if(status != ERROR_SUCCESS) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error creating the reboot registry value, hr=0x%x", hr); + goto exit; + } + + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Created a registry key to signal reboot is required"); + } + +exit: + if(regKey != NULL) + { + RegCloseKey(regKey); + regKey = NULL; + } + + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error in function %s, hr=0x%x", UNITEXT(__FUNCTION__), hr); + } + + IISLogClose(); + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; +} + +UINT +__stdcall +ScheduleRebootIfRequiredCA( + IN MSIHANDLE hInstall +) +{ + HRESULT hr = NOERROR; + HKEY regKey = NULL; + LONG status = ERROR_SUCCESS; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + REBOOT_REQUIRED_REGKEY, + 0, + KEY_QUERY_VALUE, + ®Key); + if(status != ERROR_SUCCESS) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error opening the reboot registry key, hr=0x%x", hr); + goto exit; + } + + status = RegQueryValueEx(regKey, + REBOOT_REGVALUE, + 0, + NULL, + NULL, + NULL); + switch(status) + { + case ERROR_SUCCESS: + status = MsiSetMode(hInstall, + MSIRUNMODE_REBOOTATEND, + TRUE); + if( status != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error setting reboot required for the installation, hr=0x%x", hr); + goto exit; + } + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Signalled the installer to reboot at the end of the installation."); + break; + + case ERROR_FILE_NOT_FOUND: + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"No reboot is required by the IIS custom actions."); + hr = S_OK; + break; + + default: + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting the IIS registry key reboot value, hr=0x%x", hr); + goto exit; + } + +exit: + if(regKey != NULL) + { + RegCloseKey(regKey); + regKey = NULL; + } + + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error in function %s, hr=0x%x", UNITEXT(__FUNCTION__), hr); + } + + IISLogClose(); + + //dont report an error here. the install has completed so its too late to report a failure + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_SUCCESS; + +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/httpapi.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/httpapi.cpp new file mode 100644 index 0000000000..c3b5d059ba --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/httpapi.cpp @@ -0,0 +1,518 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + + +HRESULT GetSidStringForAccount( + const WCHAR * szAccount, + __inout STRU * pstr + ) +{ + HRESULT hr = NOERROR; + BOOL success = TRUE; + DWORD sidSize = 0; + DWORD domainSize = 0; + PSID psid = NULL; + SID_NAME_USE sidKind; + LPWSTR pszSid = NULL; + LPWSTR pszDomain = NULL; + + LookupAccountNameW(NULL, + szAccount, + NULL, + &sidSize, + NULL, + &domainSize, + &sidKind); + + _ASSERT ( sidSize > 0 ); + + psid = new BYTE[sidSize]; + if( psid == NULL ) + { + hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY ); + DBGERROR_HR(hr); + goto exit; + } + + pszDomain = new WCHAR[domainSize]; + if( pszDomain == NULL ) + { + hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY ); + DBGERROR_HR(hr); + goto exit; + } + + success = LookupAccountNameW(NULL, + szAccount, + psid, + &sidSize, + pszDomain, + &domainSize, + &sidKind); + if( !success ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto exit; + } + + success = ConvertSidToStringSidW( psid, &pszSid ); + if( !success ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto exit; + } + + _ASSERT(pszSid); + + hr = pstr->Copy(pszSid); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error in function %s, hr=0x%x", UNITEXT(__FUNCTION__), hr); + } + + if (pszSid) + { + LocalFree( pszSid ); + pszSid = NULL; + } + + delete [] psid; + psid = NULL; + delete [] pszDomain; + pszDomain = NULL; + + return hr; +} + +UINT +WINAPI +ScheduleHttpListenerCA( + IN MSIHANDLE hInstall, + IN const WCHAR * pszCAName, + IIS_HTTP_LISTENER_CA_TYPE caType + ) +{ + HRESULT hr = S_OK; + UINT status = ERROR_SUCCESS; + BOOL scheduleDefferedCA = FALSE; + + PMSIHANDLE hDatabase; + PMSIHANDLE hView; + PMSIHANDLE hRecord; + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISHttpListener`.`Name`, " + L"`IISHttpListener`.`Component_`, " + L"`IISHttpListener`.`Account`, " + L"`IISHttpListener`.`Prefix` " + L"FROM `IISHttpListener`"; + + enum { CA_HTTP_NAME = 1, + CA_HTTP_COMPONENT, + CA_HTTP_ACCOUNT, + CA_HTTP_PREFIX}; + + CA_DATA_WRITER cadata; + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + STACK_STRU( strName, 128 ); + STACK_STRU( strComponent, 128 ); + STACK_STRU( strAccount, 128 ); + STACK_STRU( strPrefix, 128 ); + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + BOOL scheduleThisComponent = FALSE; + + hr = MsiUtilRecordGetString( hRecord, + CA_HTTP_NAME, + &strName ); + if ( FAILED( hr ) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_HTTP_COMPONENT, + &strComponent ); + if ( FAILED( hr ) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if (MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + if (caType == IIS_HTTP_LISTENER_CA_INSTALL) + { + scheduleThisComponent = TRUE; + scheduleDefferedCA = TRUE; + } + } + else if (MsiUtilIsUnInstalling( installStateCurrent, installStateAction)) + { + if (caType == IIS_HTTP_LISTENER_CA_UNINSTALL) + { + scheduleThisComponent = TRUE; + scheduleDefferedCA = TRUE; + } + + } + + if (scheduleThisComponent) + { + hr = MsiUtilRecordGetString( hRecord, + CA_HTTP_ACCOUNT, + &strAccount ); + if ( FAILED( hr ) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_HTTP_PREFIX, + &strPrefix ); + if ( FAILED( hr ) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata.Write( strName.QueryStr(), strName.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilFormatString( hInstall, &strAccount); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata.Write( strAccount.QueryStr(), strAccount.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilFormatString( hInstall, &strPrefix); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata.Write( strPrefix.QueryStr(), strPrefix.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + } + + if ( scheduleDefferedCA ) + { + hr = MsiUtilScheduleDeferredAction( hInstall, + pszCAName, + cadata.QueryData() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + +exit: + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error in function %s, hr=0x%x", UNITEXT(__FUNCTION__), hr); + } + + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; +} + +UINT +__stdcall +ExecuteHttpListenerCA( + IN MSIHANDLE hInstall, + IIS_HTTP_LISTENER_CA_TYPE caType + ) +{ + HRESULT hr = NOERROR; + ULONG status = NO_ERROR; + BOOL bHttpInitialized = FALSE; + CA_DATA_READER cadata; + WCHAR * szName = NULL; + WCHAR * szAccount = NULL; + WCHAR * szPrefix = NULL; + HTTPAPI_VERSION httpVersion1 = HTTPAPI_VERSION_1; + + hr = cadata.LoadDeferredCAData( hInstall ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + status = HttpInitialize( httpVersion1, HTTP_INITIALIZE_CONFIG, NULL ); + if ( status != NO_ERROR ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error calling HttpInitialize, hr=0x%x", hr); + goto exit; + } + bHttpInitialized = TRUE; + + while ( SUCCEEDED(hr = cadata.Read( &szName)) ) + { + const WCHAR * securityDescriptorFormat = L"D:(A;;GX;;;%s)"; + HTTP_SERVICE_CONFIG_URLACL_SET inputConfigInfo; + STACK_STRU( strSid, 128 ); + STACK_STRU( strSecurityString, 128 ); + + hr = cadata.Read( &szAccount); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata.Read( &szPrefix); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = GetSidStringForAccount(szAccount, &strSid); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = strSecurityString.SafeSnwprintf(securityDescriptorFormat, strSid.QueryStr()); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + inputConfigInfo.KeyDesc.pUrlPrefix = szPrefix; + inputConfigInfo.ParamDesc.pStringSecurityDescriptor = strSecurityString.QueryStr(); + + status = HttpDeleteServiceConfiguration(NULL, + HttpServiceConfigUrlAclInfo, + &inputConfigInfo, + sizeof(inputConfigInfo), + NULL); + + if (status == E_INVALIDARG) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error calling Http API. Please make sure that the URL and Account information specified is correct."); + } + + if ( (status != NO_ERROR) && (status != ERROR_FILE_NOT_FOUND) ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error calling HttpDeleteServiceConfiguration for account '%s', prefix '%s', securityDescriptor '%s', hr=0x%x", + szAccount, + szPrefix, + strSecurityString.QueryStr(), + hr); + goto exit; + } + + if ( caType == IIS_HTTP_LISTENER_CA_INSTALL) + { + status = HttpSetServiceConfiguration(NULL, + HttpServiceConfigUrlAclInfo, + &inputConfigInfo, + sizeof(inputConfigInfo), + NULL); + if (status == E_INVALIDARG) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error calling Http API. Please make sure that the URL and Account information specified is correct."); + } + if ( status != NO_ERROR ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error calling HttpSetServiceConfiguration for account '%s', prefix '%s', securityDescriptor '%s', hr=0x%x", + szAccount, + szPrefix, + strSecurityString.QueryStr(), + hr); + goto exit; + } + } + } + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + if (bHttpInitialized) + { + HttpTerminate ( HTTP_INITIALIZE_CONFIG , NULL); + } + + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error in function %s, hr=0x%x", UNITEXT(__FUNCTION__), hr); + } + + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; +} + + //for(inputConfigInfo.dwToken = 0; /* condition inside */ ; inputConfigInfo.dwToken++) + //{ + // HTTP_SERVICE_CONFIG_URLACL_SET * pOutputConfigInfo = NULL; + // ULONG outputConfigInfoSize = 0; + + // while (status == ERROR_INSUFFICIENT_BUFFER) + // { + // delete pOutputConfigInfo; + // pOutputConfigInfo = NULL; + // pOutputConfigInfo = new BYTE[outputConfigInfoSize]; + // if (pOutputConfigInfo == NULL) + // { + // hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY ); + // DBGERROR_HR(hr); + // goto exit; + // } + + // status = HttpQueryServiceConfiguration ( NULL, + // HttpServiceConfigUrlAclInfo, + // &inputConfigInfo, + // sizeof(inputConfigInfo), + // pOutputConfigInfo, + // outputConfigInfoSize, + // &outputConfigInfoSize, + // NULL); + // } //end while + + // _ASSERT (status != ERROR_INSUFFICIENT_BUFFER) + // + // if (status == NO_ERROR) + // { + // //lookup output info + + // } + // else if (status == ERROR_NO_MORE_ITEMS) + // { + // //we're done + // break; + // } + // else + // { + // hr = HRESULT_FROM_WIN32( status ); + // DBGERROR_HR(hr); + // IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error calling HttpQueryServiceConfiguration, hr=0x%x", hr); + // goto exit; + // } + //} //end for + +UINT +WINAPI +ScheduleInstallHttpListenerCA( + IN MSIHANDLE hInstall + ) +{ + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + UINT retVal = ScheduleHttpListenerCA(hInstall, L"ExecuteInstallHttpListener", IIS_HTTP_LISTENER_CA_INSTALL); + IISLogClose(); + return retVal; +} + +UINT +WINAPI +ScheduleUnInstallHttpListenerCA( + IN MSIHANDLE hInstall + ) +{ + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + UINT retVal = ScheduleHttpListenerCA(hInstall, L"ExecuteUnInstallHttpListener", IIS_HTTP_LISTENER_CA_UNINSTALL); + IISLogClose(); + return retVal; +} +UINT +__stdcall +ExecuteInstallHttpListenerCA( + IN MSIHANDLE hInstall + ) +{ + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + UINT retVal = ExecuteHttpListenerCA(hInstall, IIS_HTTP_LISTENER_CA_INSTALL); + IISLogClose(); + return retVal; +} + +UINT +__stdcall +ExecuteUnInstallHttpListenerCA( + IN MSIHANDLE hInstall + ) +{ + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + UINT retVal = ExecuteHttpListenerCA(hInstall, IIS_HTTP_LISTENER_CA_UNINSTALL); + IISLogClose(); + return retVal; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/httpapi.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/httpapi.h new file mode 100644 index 0000000000..1783e4ddf8 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/httpapi.h @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + + +enum IIS_HTTP_LISTENER_CA_TYPE +{ + IIS_HTTP_LISTENER_CA_INSTALL, + IIS_HTTP_LISTENER_CA_UNINSTALL +}; + +HRESULT GetSidStringForAccount( + const WCHAR * szAccount, + __inout STRU * pstr + ); + +UINT +WINAPI +ScheduleHttpListenerCA( + IN MSIHANDLE hInstall, + IN const WCHAR * pszCAName, + IIS_HTTP_LISTENER_CA_TYPE caType + ); + +UINT +__stdcall +ExecuteHttpListenerCA( + IN MSIHANDLE hInstall, + IIS_HTTP_LISTENER_CA_TYPE caType + ); + +UINT +WINAPI +ScheduleInstallHttpListenerCA( + IN MSIHANDLE hInstall + ); + +UINT +__stdcall +ExecuteInstallHttpListenerCA( + IN MSIHANDLE hInstall + ); + +UINT +WINAPI +ScheduleUnInstallHttpListenerCA( + IN MSIHANDLE hInstall + ); + +UINT +__stdcall +ExecuteUnInstallHttpListenerCA( + IN MSIHANDLE hInstall + ); \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.cpp new file mode 100644 index 0000000000..06631ce964 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.cpp @@ -0,0 +1,4302 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +#define ROOT_CONFIG_PATH L"MACHINE/WEBROOT/APPHOST" + +#define MAX_NAME 256 +#define _UNITEXT(quote) L##quote +#define UNITEXT(quote) _UNITEXT(quote) + +HRESULT +GetFullTypeFromAssemblyTable( + IN MSIHANDLE hDatabase, + IN CONST WCHAR * szComponent, + IN CONST WCHAR * szTypeName, + IN OUT STRU * pstrFullType + ); + +BOOL IsSectionInAdminConfig( + IN CONST WCHAR * szIsInAdminConfig + ) +{ + if( 0 == _wcsicmp(szIsInAdminConfig, L"yes") ) + { + return TRUE; + } + else + { + return FALSE; + } +} + +HRESULT +ScheduleInstallModuleCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + // + // If the module being installed includes the optional TypeName, + // then the we'll test the component to insure that the module + // is a .Net module. If so, then we will not install the module + // in and we'll include the TypeName and strong + // name info when we install in the . + // + + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + STACK_STRU( strTemp, 128 ); + STACK_STRU( strComponent, 128 ); + STACK_STRU( strTypeName, 128 ); + STACK_STRU( strFullType, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISGlobalModule`.`Name`, " + L"`IISGlobalModule`.`File_`, " + L"`IISGlobalModule`.`PreCondition`, " + L"`File`.`Component_`, " + L"`IISGlobalModule`.`TypeName` " + L"FROM `IISGlobalModule`, `File` " + L"WHERE `File`.`File`=`IISGlobalModule`.`File_`"; + + enum { CA_MODULE_NAME = 1, + CA_MODULE_IMAGE, + CA_MODULE_PRECONDITION, + CA_MODULE_COMPONENT, + CA_MODULE_TYPENAME }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + // does table exists + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISGlobalModule"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_MODULE_COMPONENT, + &strComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + + cadata->Write( IIS_INSTALL_MODULE ); + + // Get the module name + hr = MsiUtilRecordGetString( hRecord, + CA_MODULE_NAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // CA_MODULE_IMAGE is the name of the File element, need to + // resolve it to the full path by formatting it as [#ModuleDll] + // + + hr = MsiUtilRecordGetString( hRecord, + CA_MODULE_IMAGE, + &strTemp ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = strData.SafeSnwprintf( L"[#%s]", strTemp.QueryStr() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilFormatString( hInstall, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_MODULE_PRECONDITION, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Get the type name (optional) + // If the type name is present, then this is a .Net and does not have + // to be registered in the + // + hr = MsiUtilRecordGetString( hRecord, + CA_MODULE_TYPENAME, + &strTypeName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( strTypeName.QueryCCH() > 0 ) + { + // TypeName is present. Get the assembly info + hr = GetFullTypeFromAssemblyTable( hDatabase, + strComponent.QueryStr(), + strTypeName.QueryStr(), + &strFullType ); + + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + else + { + strFullType.Reset(); + } + + hr = cadata->Write( strFullType.QueryStr(), strFullType.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + + +HRESULT +ScheduleUnInstallModuleCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISGlobalModule`.`Name`, " + L"`File`.`Component_`, " + L"`IISGlobalModule`.`TypeName` " + L"FROM `IISGlobalModule`, `File` " + L"WHERE `File`.`File`=`IISGlobalModule`.`File_`"; + + enum { CA_MODULE_NAME = 1, + CA_MODULE_COMPONENT, + CA_MODULE_TYPENAME }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + //Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISGlobalModule"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_MODULE_COMPONENT, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strData.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsUnInstalling( installStateCurrent, installStateAction ) ) + { + + cadata->Write( IIS_UNINSTALL_MODULE ); + + + hr = MsiUtilRecordGetString( hRecord, + CA_MODULE_NAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_MODULE_TYPENAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + + +HRESULT +ExecuteInstallModuleCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szName = NULL; + WCHAR * szImage = NULL; + WCHAR * szPreCondition = NULL; + WCHAR * szType = NULL; + + + hr = cadata->Read( &szName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szImage ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szPreCondition ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szType ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Install the module + // + + hr = InstallModule( szName, + szImage, + szPreCondition, + szType ); + + if ( hr == HRESULT_FROM_WIN32( ERROR_ALREADY_EXISTS ) ) + { + // + // We'll quietly accept a module already exists. + // This will happen if a component has multiple features + // that each have a module. + // If a feature is omitted on the initial install, + // and added later using Change, the features that + // were initially installed will show up in the + // ScheduleInstallModuleCA with install + // INSTALLSTATE_UNKNOWN, which will trigger a reinstall. + // Reinstall will result in ERROR_ALREADY_EXISTS. + // + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, + L"Module: '%s' already installed.", + szName); + + hr = S_OK; + } + + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + + +HRESULT +ExecuteUnInstallModuleCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szName = NULL; + WCHAR * szType = NULL; + + + + hr = cadata->Read( &szName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szType ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = UnInstallModule( szName, szType ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + + +HRESULT +ScheduleRegisterSectionSchemaCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISConfigSections`.`Name`, " + L"`IISConfigSections`.`File_`, " + L"`IISConfigSections`.`OverrideModeDefault`, " + L"`IISConfigSections`.`AllowDefinition`, " + L"`IISConfigSections`.`Type`, " + L"`IISConfigSections`.`InAdminConfig`, " + L"`File`.`Component_` " + L"FROM `IISConfigSections`, `File` " + L"WHERE `File`.`File`=`IISConfigSections`.`File_`"; + + enum + { + CA_SECTION_NAME = 1, + CA_SCHEMA_FILE, + CA_SECTION_OVERRIDEMODE, + CA_SECTION_ALLOWDEF, + CA_SECTION_TYPE, + CA_SECTION_INADMINCONFIG, + CA_SCHEMA_COMPONENT + }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + //Does table exists + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISConfigSections"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_SCHEMA_COMPONENT, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strData.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + + cadata->Write( IIS_INSTALL_SECTIONSCHEMA ); + + hr = MsiUtilRecordGetString( hRecord, + CA_SECTION_NAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_SECTION_OVERRIDEMODE, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_SECTION_ALLOWDEF, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_SECTION_TYPE, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_SECTION_INADMINCONFIG, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; +} + + +HRESULT +ScheduleUnRegisterSectionSchemaCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISConfigSections`.`Name`, " + L"`IISConfigSections`.`InAdminConfig`, " + L"`File`.`Component_` " + L"FROM `IISConfigSections`, `File` " + L"WHERE `File`.`File`=`IISConfigSections`.`File_`"; + + enum { + CA_SECTION_NAME = 1, + CA_SECTION_INADMINCONFIG, + CA_SCHEMA_COMPONENT }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + //Does table exists + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISConfigSections"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_SCHEMA_COMPONENT, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strData.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsUnInstalling( installStateCurrent, installStateAction ) ) + { + cadata->Write( IIS_UNINSTALL_SECTIONSCHEMA ); + + hr = MsiUtilRecordGetString( hRecord, + CA_SECTION_NAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_SECTION_INADMINCONFIG, + &strData ); + + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + + +HRESULT +ExecuteRegisterSectionSchemaCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szSectionName = NULL; + WCHAR * szOverrideMode = NULL; + WCHAR * szAllowDefinition = NULL; + WCHAR * szType = NULL; + WCHAR * szIsInAdminConfig = NULL; + + + // + // Retrieve parameters from ca data + // + hr = cadata->Read( &szSectionName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szOverrideMode ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szAllowDefinition ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szType ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szIsInAdminConfig ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Register the section + // + + hr = RegisterSectionSchema( IsSectionInAdminConfig(szIsInAdminConfig), + szSectionName, + szOverrideMode, + szAllowDefinition, + szType ); + + if ( hr == HRESULT_FROM_WIN32( ERROR_ALREADY_EXISTS ) ) + { + // + // We'll quietly accept a section name already exists. + // This will happen if a package has multiple features + // that each have a section. + // If a feature is omitted on the initial install, + // and added later using Change, the features that + // were initially installed will show up in the + // ScheduleRegisterSectionSchemaCA with install + // INSTALLSTATE_UNKNOWN, which will trigger a reinstall. + // Reinstall will result in ERROR_ALREADY_EXISTS. + // + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, + L"Section name: '%s' already exists.", + szSectionName); + + hr = S_OK; + } + + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; +} + + +HRESULT +ExecuteUnRegisterSectionSchemaCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szSectionName = NULL; + WCHAR * szIsInAdminConfig = NULL; + + + hr = cadata->Read( &szSectionName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szIsInAdminConfig ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = UnRegisterSectionSchema( IsSectionInAdminConfig(szIsInAdminConfig), + szSectionName ); + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"Failed to unregister section schema for section: '%s', hr=0x%x .", + szSectionName, + hr ); + DBGERROR_HR(hr); + + // + // We need to keep going because this is an uninstall action + // and should be resilient to missing elements. + // + hr = S_OK; + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; +} + +HRESULT +CanonicalizeAssemblyVersion( + STRU & strValue +) +{ + // + // Converts 7.1.2.000 to 7.1.2.0 + // + + HRESULT hr = S_OK; + LPCWSTR psz = wcschr( strValue.QueryStr(), L'.' ); + DWORD dwDotCount = 0; + + // + // Find the 3rd '.' + // + while ( psz != NULL ) + { + dwDotCount++; + LPCWSTR psz2 = wcschr( psz + 1, L'.' ); + if ( psz2 == NULL ) + { + break; + } + psz = psz2; + } + + if ( dwDotCount == 3 && psz != NULL ) + { + // + // Convert "000" to integer and then back to string. + // + + psz ++; + DWORD dw = _wtoi( psz ); + STACK_STRU( strTemp, 16 ); + + hr = strTemp.SafeSnwprintf( L"%u", dw ); + if ( SUCCEEDED( hr ) ) + { + ptrdiff_t diff = psz - strValue.QueryStr(); + + _ASSERTE( diff >= 0 ); + + hr = strValue.SetLen( (DWORD) diff ); + if ( FAILED( hr ) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = strValue.Append(strTemp); + if ( FAILED( hr ) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + } + +exit: + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + +HRESULT +GetFullTypeFromAssemblyTable( + IN MSIHANDLE hDatabase, + IN CONST WCHAR * szComponent, + IN CONST WCHAR * szTypeName, + IN OUT STRU * pstrFullType + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + BOOL fRecordFound = FALSE; + BOOL fVersion = FALSE; + + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strQuery, 128 ); + STACK_STRU( strPropName, 64 ); + STACK_STRU( strPropValueName, 64 ); + STACK_STRU( strPropVersion, 64 ); + STACK_STRU( strPropCulture, 64 ); + STACK_STRU( strPropKeyToken, 64 ); + + CONST WCHAR * szQueryTemplate = + L"SELECT `Name`, `Value` " + L"FROM `MsiAssemblyName` " + L"WHERE `Component_`='%s'"; + + CONST WCHAR * szFullTypeTempl = L"%s, %s, Version=%s, Culture=%s, PublicKeyToken=%s"; + // szTypeName, name, version, culture, publicKeyToken + + enum { CA_ASSEMBLY_PROP_NAME = 1, CA_ASSEMBLY_PROP_VALUE }; + + hr = strQuery.SafeSnwprintf( szQueryTemplate, szComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, strQuery.QueryStr(), &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + STRU * pstr; + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + fRecordFound = TRUE; + hr = MsiUtilRecordGetString( hRecord, + CA_ASSEMBLY_PROP_NAME, + &strPropName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + pstr = NULL; + + if ( 0 == wcscmp( strPropName.QueryStr(), L"name" ) ) + { + pstr = &strPropValueName; + } + else if ( 0 == wcscmp( strPropName.QueryStr(), L"version" ) ) + { + fVersion = TRUE; + pstr = &strPropVersion; + } + else if ( 0 == wcscmp( strPropName.QueryStr(), L"culture" ) ) + { + pstr = &strPropCulture; + } + else if ( 0 == wcscmp( strPropName.QueryStr(), L"publicKeyToken" ) ) + { + pstr = &strPropKeyToken; + } + + if ( pstr ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_ASSEMBLY_PROP_VALUE, + pstr ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( fVersion ) + { + hr = CanonicalizeAssemblyVersion( *pstr ); + if ( FAILED( hr ) ) + { + DBGERROR_HR(hr); + goto exit; + } + fVersion = FALSE; + } + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + hr = pstrFullType->SafeSnwprintf( szFullTypeTempl, + szTypeName, + strPropValueName.QueryStr(), + strPropVersion.QueryStr(), + strPropCulture.QueryStr(), + strPropKeyToken.QueryStr() + ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + _ASSERTE( fRecordFound ); + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + + +HRESULT +ScheduleRegisterUIModuleCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strComponent, 128 ); + STACK_STRU( strAssemblyInfoComponent, 128 ); + STACK_STRU( strData, 128 ); + STACK_STRU( strFullType, 128 ); + + const STRU * pstrComponentName = NULL; + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISUIModule`.`Name`, " + L"`IISUIModule`.`TypeName`, " + L"`IISUIModule`.`Component_` ," + L"`IISUIModule`.`AssemblyInfoComponent_` ," + L"`IISUIModule`.`RegisterInModulesSection` ," + L"`IISUIModule`.`PrependToList` " + L"FROM `IISUIModule` "; + + enum { + CA_UIMODULE_NAME = 1, + CA_UIMODULE_TYPE, + CA_UIMODULE_COMPONENT, + CA_UIMODULE_ASSEMBLYINFOCOMPONENT, + CA_UIMODULE_REGISTER, + CA_UIMODULE_PREPEND + }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + //Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISUIModule"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_UIMODULE_COMPONENT, + &strComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + + cadata->Write( IIS_INSTALL_UIMODULE ); + + hr = MsiUtilRecordGetString( hRecord, + CA_UIMODULE_NAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_UIMODULE_ASSEMBLYINFOCOMPONENT, + &strAssemblyInfoComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // use the AssemblyInfoComponent_ to get the module assembly information + // fall back to using the component if the value is null. + if ( strAssemblyInfoComponent.QueryCCH() > 0 ) + { + pstrComponentName = &strAssemblyInfoComponent; + } + else + { + pstrComponentName = &strComponent; + } + _ASSERTE( pstrComponentName != NULL ); + + hr = MsiUtilRecordGetString( hRecord, + CA_UIMODULE_TYPE, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = GetFullTypeFromAssemblyTable( hDatabase, + pstrComponentName->QueryStr(), + strData.QueryStr(), + &strFullType ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strFullType.QueryStr(), strFullType.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_UIMODULE_REGISTER, + &strData ); + if (FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_UIMODULE_PREPEND, + &strData ); + if (FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; +} + + +HRESULT +ScheduleUnRegisterUIModuleCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strComponent, 128 ); + STACK_STRU( strAssemblyInfoComponent, 128 ); + STACK_STRU( strData, 128 ); + STACK_STRU( strFullType, 128 ); + + const STRU * pstrComponentName = NULL; + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISUIModule`.`Name`, " + L"`IISUIModule`.`TypeName`, " + L"`IISUIModule`.`Component_` ," + L"`IISUIModule`.`AssemblyInfoComponent_` " + L"FROM `IISUIModule` "; + + enum { + CA_UIMODULE_NAME = 1, + CA_UIMODULE_TYPE, + CA_UIMODULE_COMPONENT, + CA_UIMODULE_ASSEMBLYINFOCOMPONENT, + }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + //Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISUIModule"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_UIMODULE_COMPONENT, + &strComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsUnInstalling( installStateCurrent, installStateAction ) ) + { + + cadata->Write( IIS_UNINSTALL_UIMODULE ); + + hr = MsiUtilRecordGetString( hRecord, + CA_UIMODULE_NAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordGetString( hRecord, + CA_UIMODULE_ASSEMBLYINFOCOMPONENT, + &strAssemblyInfoComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // use the AssemblyInfoComponent_ to get the module assembly information + // fall back to using the component if the value is null. + if ( strAssemblyInfoComponent.QueryCCH() > 0 ) + { + pstrComponentName = &strAssemblyInfoComponent; + } + else + { + pstrComponentName = &strComponent; + } + _ASSERTE( pstrComponentName != NULL ); + + hr = MsiUtilRecordGetString( hRecord, + CA_UIMODULE_TYPE, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = GetFullTypeFromAssemblyTable( hDatabase, + pstrComponentName->QueryStr(), + strData.QueryStr(), + &strFullType ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strFullType.QueryStr(), strFullType.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; +} + + +HRESULT +ExecuteRegisterUIModuleCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szUIModuleName = NULL; + WCHAR * szUIModuleTypeInfo = NULL; + WCHAR * szUIModuleRegister = NULL; + WCHAR * szUIModulePrepend = NULL; + + hr = cadata->Read( &szUIModuleName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szUIModuleTypeInfo ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szUIModuleRegister ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szUIModulePrepend ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Register the section + // + + hr = RegisterUIModule( szUIModuleName, + szUIModuleTypeInfo, + szUIModuleRegister, + szUIModulePrepend ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + + +HRESULT +ExecuteUnRegisterUIModuleCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szUIModuleName = NULL; + WCHAR * szUIModuleTypeInfo = NULL; + + hr = cadata->Read( &szUIModuleName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szUIModuleTypeInfo ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = UnRegisterUIModule( szUIModuleName, szUIModuleTypeInfo ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + +HRESULT +ScheduleRegisterTraceAreaCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + STACK_STRU( strComponent, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISTraceArea`.`Component_`, " + L"`IISTraceArea`.`ProviderName`, " + L"`IISTraceArea`.`ProviderGuid`, " + L"`IISTraceArea`.`AreaName`, " + L"`IISTraceArea`.`AreaValue` " + L"FROM `IISTraceArea` "; + + enum { CA_COMPONENT = 1, + CA_PROVIDER_NAME, + CA_PROVIDER_GUID, + CA_AREA_NAME, + CA_AREA_VALUE }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + //Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISTraceArea"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_COMPONENT, + &strComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + cadata->Write( IIS_INSTALL_TRACEAREA ); + + // Get the values + for ( DWORD Index = CA_PROVIDER_NAME; Index <= CA_AREA_VALUE; Index++ ) + { + hr = MsiUtilRecordGetString( hRecord, + Index, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + + +HRESULT +ExecuteRegisterTraceAreaCA( + IN CA_DATA_READER * cadata +) +{ + HRESULT hr = NOERROR; + + WCHAR * szTraceProviderName = NULL; + WCHAR * szTraceProviderGuid = NULL; + WCHAR * szAreaName = NULL; + WCHAR * szAreaValue = NULL; + + + hr = cadata->Read( &szTraceProviderName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szTraceProviderGuid ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szAreaName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szAreaValue ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Register the section + // + hr = RegisterTraceArea( szTraceProviderName, + szTraceProviderGuid, + szAreaName, + szAreaValue ); + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"Failed to register trace area (Provider: '%s'; " + L"Guid: '%s'; AreaName: '%s'; AreaValue: '%s') hr=0x%x", + szTraceProviderName, + szTraceProviderGuid, + szAreaName, + szAreaValue, + hr ); + DBGERROR_HR(hr); + goto exit; + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_SUCCESS; +} + +/// The error messages are from setstrings.wxl. +/// The integer parameter is used to to get the string. +UINT +LogMsiCustomActionError( + IN MSIHANDLE hInstall, + UINT messageId + ) +{ + PMSIHANDLE pLogger = MsiCreateRecord(1); + if ( pLogger == NULL ) + { + return ERROR_INSTALL_FAILURE; + } + + MsiRecordSetInteger( pLogger, 1, messageId ); + MsiProcessMessage( hInstall, INSTALLMESSAGE_ERROR, pLogger ); + + if ( pLogger != NULL ) + { + MsiCloseHandle( pLogger ); + pLogger = NULL; + } + + return ERROR_INSTALL_FAILURE; +} + + +HRESULT +ScheduleRegisterMofFileCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISTraceArea`.`BinaryName_`, " + L"`Binary`.`Data`, " + L"`IISTraceArea`.`Component_` " + L"FROM `IISTraceArea`, `Binary` " + L"WHERE `Binary`.`Name`=`IISTraceArea`.`BinaryName_`"; + + enum { CA_BINARY_NAME = 1, + CA_FILE_DATA, + CA_MOF_COMPONENT }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + + // + //Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISTraceArea"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_MOF_COMPONENT, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strData.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + + cadata->Write( IIS_INSTALL_MOFFILE ); + + STACK_STRU( strBinaryName, 128 ); + STACK_STRU( strMofFilePath, MAX_PATH ); + + hr = MsiUtilRecordGetString( hRecord, + CA_BINARY_NAME, + &strBinaryName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = GenerateTempFileName( strBinaryName.QueryStr(), + L"mof", + &strMofFilePath); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = MsiUtilRecordReadStreamIntoFile( hRecord, + CA_FILE_DATA, + strMofFilePath.QueryStr()); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strMofFilePath.QueryStr(), strMofFilePath.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + } + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + +HRESULT +ExecuteRegisterMofFileCA( + IN CA_DATA_READER * cadata +) +{ + HRESULT hr = NOERROR; + + WCHAR * szMofFileName = NULL; + + hr = cadata->Read( &szMofFileName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + // Register the section + // + hr = RegisterMofFile( szMofFileName ); + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"Failed to register MOF file (File name: '%s') hr=0x%x", + szMofFileName, + hr ); + DBGERROR_HR(hr); + + // + // Continue setup, this is not a fatal error. + // + hr = S_OK; + + goto exit; + } + else + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, + L"MOF file '%s' registered.", + szMofFileName ); + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return (SUCCEEDED(hr)) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; +} + +HRESULT +ScheduleInstallHandlerCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + STACK_STRU( strComponent, 128 ); + + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISGlobalHandler`.`Name`, " + L"`IISGlobalHandler`.`Component_`, " + L"`IISGlobalHandler`.`Path`, " + L"`IISGlobalHandler`.`Verb`, " + L"`IISGlobalHandler`.`Type`, " + L"`IISGlobalHandler`.`Index`, " + L"`IISGlobalHandler`.`Modules`, " + L"`IISGlobalHandler`.`ScriptProcessor`, " + L"`IISGlobalHandler`.`ResourceType`, " + L"`IISGlobalHandler`.`RequiredAccess`, " + L"`IISGlobalHandler`.`PreCondition` " + L"FROM `IISGlobalHandler` "; + + enum { CA_HANDLER_NAME = 1, + CA_HANDLER_COMPONENT, + CA_HANDLER_PATH, + CA_HANDLER_VERB, + CA_HANDLER_TYPE, + CA_HANDLER_INDEX, + CA_HANDLER_MODULES, + CA_HANDLER_SCRIPTPROCESSOR, + CA_HANDLER_RESOURCETYPE, + CA_HANDLER_REQUIREDACCESS, + CA_HANDLER_PRECONDITION + }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + + // + //Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISGlobalHandler"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_COMPONENT, + &strComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + + cadata->Write( IIS_INSTALL_HANDLER ); + + // Get the Handler name + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_NAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Get handler Path + // + + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_PATH, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + //Get handler Verb + // + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_VERB, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + // Get handler Type + // + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_TYPE, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + // Get handler Index + // + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_INDEX, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + // Get handler Modules + // + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_MODULES, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + // Get handler Script Processor + // + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_SCRIPTPROCESSOR, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + // Get handler ResourceType + // + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_RESOURCETYPE, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + // Get handler RequiredAccess + // + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_REQUIREDACCESS, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + // Get handler PreCondition + // + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_PRECONDITION, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + + +HRESULT +ScheduleUnInstallHandlerCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISGlobalHandler`.`Name`, " + L"`IISGlobalHandler`.`Component_` " + L"FROM `IISGlobalHandler` "; + + enum { CA_HANDLER_NAME = 1, + CA_HANDLER_COMPONENT + }; + + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + //Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISGlobalHandler"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_COMPONENT, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strData.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsUnInstalling( installStateCurrent, installStateAction ) ) + { + + cadata->Write( IIS_UNINSTALL_HANDLER ); + + hr = MsiUtilRecordGetString( hRecord, + CA_HANDLER_NAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; +} + + +HRESULT +ExecuteInstallHandlerCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szName = NULL; + WCHAR * szPath = NULL; + WCHAR * szVerb = NULL; + WCHAR * szType = NULL; + WCHAR * szIndex = NULL; + WCHAR * szModules = NULL; + WCHAR * szScriptProcessor = NULL; + WCHAR * szResourceType = NULL; + WCHAR * szRequiredAccess = NULL; + WCHAR * szPreCondition = NULL; + + ULONG ulIndex = HANDLER_INDEX_FIRST; + + CComPtr pAdminMgr; + + + hr = CoCreateInstance(__uuidof(AppHostWritableAdminManager), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IAppHostWritableAdminManager), + (VOID **)&pAdminMgr); + if (FAILED(hr)) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"CoCreateInstance failed 0x%08x", hr); + DBGERROR_HR(hr); + goto exit; + } + + + hr = cadata->Read( &szName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szPath ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szVerb ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szType ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szIndex ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + if( 0 == _wcsicmp( szIndex, L"FIRST" ) ) + { + ulIndex = HANDLER_INDEX_FIRST; + } + else if ( 0 == _wcsicmp( szIndex, L"LAST" ) ) + { + ulIndex = HANDLER_INDEX_FIRST; + } + else if ( 0 == _wcsicmp( szIndex, L"BEFORE_STATICFILE" ) ) + { + ulIndex = HANDLER_INDEX_BEFORE_STATICFILE; + } + + hr = cadata->Read( &szModules ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szScriptProcessor ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szResourceType ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szRequiredAccess ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Read( &szPreCondition ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Install the Handler + // + hr = RegisterHandler( pAdminMgr, + ROOT_CONFIG_PATH, + ulIndex, + szName, + szPath, + szVerb, + szType, + szModules, + szScriptProcessor, + szResourceType, + szRequiredAccess, + szPreCondition + ); + + if ( hr == HRESULT_FROM_WIN32( ERROR_ALREADY_EXISTS ) ) + { + // + // We'll quietly accept a handler already exists. + // + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, + L"Handler: '%s' already installed.", + szName); + + hr = S_OK; + } + + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + + // + // Update config + // + hr = pAdminMgr->CommitChanges(); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; +} + + +HRESULT +ExecuteUnInstallHandlerCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szName = NULL; + + CComPtr pAdminMgr; + + + hr = CoCreateInstance(__uuidof(AppHostWritableAdminManager), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IAppHostWritableAdminManager), + (VOID **)&pAdminMgr); + if (FAILED(hr)) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"CoCreateInstance failed 0x%08x", hr); + DBGERROR_HR(hr); + goto exit; + } + + + hr = cadata->Read( &szName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = UnRegisterHandler( pAdminMgr, ROOT_CONFIG_PATH, szName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + + // + // Update config + // + hr = pAdminMgr->CommitChanges(); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; +} + +HRESULT +ScheduleInstallSectionDefaultsCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + STACK_STRU( strComponent, 128 ); + STACK_STRU( strName, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISConfigSectionDefaults`.`Name`, " + L"`IISConfigSectionDefaults`.`SectionName`, " + L"`IISConfigSectionDefaults`.`Component_`, " + L"`Binary`.`Data` " + L"FROM `IISConfigSectionDefaults`, `Binary` " + L"WHERE `IISConfigSectionDefaults`.`BinaryName_`=`Binary`.`Name`"; + + + enum { CA_DEFAULTS_NAME = 1, + CA_DEFAULTS_SECTIONNAME, + CA_DEFAULTS_COMPONENT, + CA_DEFAULTS_BINARYDATA + }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + //Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISConfigSectionDefaults"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_DEFAULTS_COMPONENT, + &strComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + + cadata->Write( IIS_INSTALL_DEFAULTS ); + + // Get the record name + hr = MsiUtilRecordGetString( hRecord, + CA_DEFAULTS_NAME, + &strName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // Get the Section name + hr = MsiUtilRecordGetString( hRecord, + CA_DEFAULTS_SECTIONNAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Get File from binary, write to temp file + // + STACK_STRU( strFilePath, MAX_PATH * 2 ); + + hr = GenerateTempFileName ( strName.QueryStr(), + L"def", + &strFilePath); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error generating temp file name for the hotfix, hr=0x%x", hr); + goto exit; + } + + hr = MsiUtilRecordReadStreamIntoFile ( hRecord, + CA_DEFAULTS_BINARYDATA, + strFilePath.QueryStr()); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error streaming binary data into file, hr=0x%x", hr); + goto exit; + } + + hr = cadata->Write( strFilePath.QueryStr(), strFilePath.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error writing custom action data, hr=0x%x", hr); + goto exit; + } + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; + +} +HRESULT +ExecuteInstallSectionDefaultsCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szSectionName = NULL; + WCHAR * szTempFileName = NULL; + + CComPtr pAdminMgr; + + + hr = CoCreateInstance(__uuidof(AppHostWritableAdminManager), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IAppHostWritableAdminManager), + (VOID **)&pAdminMgr); + if (FAILED(hr)) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"CoCreateInstance failed 0x%08x", hr); + DBGERROR_HR(hr); + goto exit; + } + + + hr = cadata->Read( &szSectionName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szTempFileName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Set Section Defaults from temp file created during schedule + // + hr = ResetConfigSectionFromFile( szTempFileName, szSectionName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + // delete temp file. No error checking. + // + ::DeleteFileW( szTempFileName ); + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + + // + // Update config + // + hr = pAdminMgr->CommitChanges(); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; + +} + +HRESULT +ScheduleInstallSectionAdditionsCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + STACK_STRU( strComponent, 128 ); + STACK_STRU( strName, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISConfigSectionAdditions`.`Name`, " + L"`IISConfigSectionAdditions`.`SectionName`, " + L"`IISConfigSectionAdditions`.`Component_`, " + L"`Binary`.`Data` " + L"FROM `IISConfigSectionAdditions`, `Binary` " + L"WHERE `IISConfigSectionAdditions`.`BinaryName_`=`Binary`.`Name`"; + + + enum { CA_SECTION_ADDITION_NAME = 1, + CA_SECTION_ADDITION_SECTIONNAME, + CA_SECTION_ADDITION_COMPONENT, + CA_SECTION_ADDITION_BINARYDATA + }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + + // + // Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISConfigSectionAdditions"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_SECTION_ADDITION_COMPONENT, + &strComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + + cadata->Write( IIS_INSTALL_SECTION_ADDITIONS); + + // Get the record name + hr = MsiUtilRecordGetString( hRecord, + CA_SECTION_ADDITION_NAME, + &strName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // Get the Section name + hr = MsiUtilRecordGetString( hRecord, + CA_SECTION_ADDITION_SECTIONNAME, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Get File from binary, write to temp file + // + STACK_STRU( strFilePath, MAX_PATH * 2 ); + + hr = GenerateTempFileName ( strName.QueryStr(), + L"def", + &strFilePath); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error generating temp file name for the hotfix, hr=0x%x", hr); + goto exit; + } + + hr = MsiUtilRecordReadStreamIntoFile ( hRecord, + CA_SECTION_ADDITION_BINARYDATA, + strFilePath.QueryStr()); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error streaming binary data into file, hr=0x%x", hr); + goto exit; + } + + hr = cadata->Write( strFilePath.QueryStr(), strFilePath.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error writing custom action data, hr=0x%x", hr); + goto exit; + } + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; + +} +HRESULT +ExecuteInstallSectionAdditionsCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szSectionName = NULL; + WCHAR * szTempFileName = NULL; + + CComPtr pAdminMgr; + + + hr = CoCreateInstance(__uuidof(AppHostWritableAdminManager), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IAppHostWritableAdminManager), + (VOID **)&pAdminMgr); + if (FAILED(hr)) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"CoCreateInstance failed 0x%08x", hr); + DBGERROR_HR(hr); + goto exit; + } + + + hr = cadata->Read( &szSectionName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szTempFileName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Set Section Defaults from temp file created during schedule + // + hr = AppendConfigSectionFromFile( szTempFileName, szSectionName ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // + // delete temp file. No error checking. + // + ::DeleteFileW( szTempFileName ); + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + + // + // Update config + // + hr = pAdminMgr->CommitChanges(); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; + +} + +HRESULT +ScheduleInstallCgiRestrictionsCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + STACK_STRU( strComponent, 128 ); + STACK_STRU( strName, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISCgiRestriction`.`Name`, " + L"`IISCgiRestriction`.`Component_`, " + L"`IISCgiRestriction`.`Path`, " + L"`IISCgiRestriction`.`Allowed`, " + L"`IISCgiRestriction`.`GroupId`, " + L"`IISCgiRestriction`.`Description` " + L"FROM `IISCgiRestriction` "; + + enum { CA_CGI_NAME = 1, + CA_CGI_COMPONENT, + CA_CGI_PATH, + CA_CGI_ALLOWED, + CA_CGI_GROUPID, + CA_CGI_DESC + }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + //Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISCgiRestriction"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + cadata->Write( IIS_INSTALL_CGIRESTRICTIONS ); + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_CGI_COMPONENT, + &strComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsInstalling( installStateCurrent, installStateAction ) || + MsiUtilIsReInstalling( installStateCurrent, installStateAction ) ) + { + + // Get the Path + hr = MsiUtilRecordGetString( hRecord, + CA_CGI_PATH, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // Get the Allowed + hr = MsiUtilRecordGetString( hRecord, + CA_CGI_ALLOWED, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // Get the GroupId + hr = MsiUtilRecordGetString( hRecord, + CA_CGI_GROUPID, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + // Get the Description + hr = MsiUtilRecordGetString( hRecord, + CA_CGI_DESC, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; + +} + +HRESULT +ScheduleUnInstallCgiRestrictionsCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ) +{ + + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + MSIHANDLE hDatabase = NULL; + MSIHANDLE hView = NULL; + MSIHANDLE hRecord = NULL; + + STACK_STRU( strData, 128 ); + STACK_STRU( strComponent, 128 ); + STACK_STRU( strName, 128 ); + + CONST WCHAR * szQuery = + L"SELECT " + L"`IISCgiRestriction`.`Name`, " + L"`IISCgiRestriction`.`Component_`, " + L"`IISCgiRestriction`.`Path`, " + L"FROM `IISCgiRestriction` "; + + enum { CA_CGI_NAME = 1, + CA_CGI_COMPONENT, + CA_CGI_PATH, + CA_CGI_ALLOWED, + CA_CGI_GROUPID, + CA_CGI_DESC + }; + + INSTALLSTATE installStateCurrent; + INSTALLSTATE installStateAction; + + hDatabase = MsiGetActiveDatabase( hInstall ); + if ( !hDatabase ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + // + //Does table exist + // + UINT er = ERROR_SUCCESS; + er = ::MsiDatabaseIsTablePersistentW(hDatabase, L"IISCgiRestriction"); + if (MSICONDITION_TRUE != er) + { + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' Table not found, exiting", + UNITEXT(__FUNCTION__) + ); + goto exit; + } + + + cadata->Write( IIS_UNINSTALL_CGIRESTRICTIONS ); + + status = MsiDatabaseOpenViewW( hDatabase, szQuery, &hView ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiViewExecute( hView, NULL ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto exit; + } + + while ( ERROR_SUCCESS == MsiViewFetch( hView, &hRecord ) ) + { + hr = MsiUtilRecordGetString( hRecord, + CA_CGI_COMPONENT, + &strComponent ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetComponentStateW( hInstall, + strComponent.QueryStr(), + &installStateCurrent, + &installStateAction ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + if ( MsiUtilIsUnInstalling( installStateCurrent, installStateAction ) ) + { + + // Get the Path + hr = MsiUtilRecordGetString( hRecord, + CA_CGI_PATH, + &strData ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Write( strData.QueryStr(), strData.QueryCCH() ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + } + + +exit: + + if ( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + if ( hView ) + { + MsiCloseHandle( hView ); + hView = NULL; + } + + if ( hDatabase ) + { + MsiCloseHandle( hDatabase ); + hDatabase = NULL; + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + + return hr; + +} + + +HRESULT +ExecuteInstallCgiRestrictionsCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szPath = NULL; + WCHAR * szAllowed = NULL; + WCHAR * szGroupId = NULL; + WCHAR * szDescription = NULL; + BOOL fAllowed = FALSE; + + CComPtr pAdminMgr; + + + hr = CoCreateInstance(__uuidof(AppHostWritableAdminManager), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IAppHostWritableAdminManager), + (VOID **)&pAdminMgr); + if (FAILED(hr)) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"CoCreateInstance failed 0x%08x", hr); + DBGERROR_HR(hr); + goto exit; + } + + + while ( SUCCEEDED(hr = cadata->Read( &szPath )) ) + { + + hr = cadata->Read( &szAllowed ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szGroupId ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + hr = cadata->Read( &szDescription ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( 0 == wcscmp( szAllowed, L"true" ) ) + { + fAllowed = TRUE; + } + else if ( 0 == wcscmp( szAllowed, L"false" ) ) + { + fAllowed = FALSE; + } + + hr = RegisterCgiRestriction( + pAdminMgr, + ROOT_CONFIG_PATH, + szPath, + fAllowed, + szGroupId, + szDescription + ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + + // + // Update config + // + hr = pAdminMgr->CommitChanges(); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; + +} + + +HRESULT +ExecuteUnInstallCgiRestrictionsCA( + IN CA_DATA_READER * cadata + ) +{ + HRESULT hr = NOERROR; + + WCHAR * szPath = NULL; + + CComPtr pAdminMgr; + + + hr = CoCreateInstance(__uuidof(AppHostWritableAdminManager), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IAppHostWritableAdminManager), + (VOID **)&pAdminMgr); + if (FAILED(hr)) + { + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, + L"CoCreateInstance failed 0x%08x", hr); + DBGERROR_HR(hr); + goto exit; + } + + + while ( SUCCEEDED(hr = cadata->Read( &szPath )) ) + { + hr = UnRegisterCgiRestriction( + pAdminMgr, + ROOT_CONFIG_PATH, + szPath, + FALSE + ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + hr = S_OK; + } + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + + // + // Update config + // + hr = pAdminMgr->CommitChanges(); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + return hr; +} + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.h new file mode 100644 index 0000000000..40f7097845 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.h @@ -0,0 +1,255 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#define _UNITEXT(quote) L##quote +#define UNITEXT(quote) _UNITEXT(quote) + + +// IIS Custom action Types +enum IIS_COSTOM_ACTION_TYPE +{ + IIS_INSTALL_MODULE = 1, + IIS_UNINSTALL_MODULE, + IIS_INSTALL_UIMODULE, + IIS_UNINSTALL_UIMODULE, + IIS_INSTALL_HANDLER, + IIS_UNINSTALL_HANDLER, + IIS_INSTALL_SECTIONSCHEMA, + IIS_UNINSTALL_SECTIONSCHEMA, + IIS_INSTALL_TRACEAREA, + IIS_INSTALL_MOFFILE, + IIS_INSTALL_DEFAULTS, + IIS_INSTALL_SECTION_ADDITIONS, + IIS_INSTALL_CGIRESTRICTIONS, + IIS_UNINSTALL_CGIRESTRICTIONS, + IIS_INSTALL_, + IIS_UNINSTALL_, + IIS_END +}; + + +HRESULT +InstallModule( + IN CONST WCHAR * szName, + IN CONST WCHAR * szImage, + IN OPTIONAL CONST WCHAR * szPreCondition, + IN OPTIONAL CONST WCHAR * szTYpe + ); + + +HRESULT +UnInstallModule( + IN CONST WCHAR * szName, + IN OPTIONAL CONST WCHAR * szPreCondition + ); + +HRESULT +RegisterSectionSchema( + IN CONST BOOL isSectionInAdminSchema, + IN CONST WCHAR * szSectionName, + IN CONST WCHAR * szOverideModeDefault, + IN OPTIONAL CONST WCHAR * szAllowDefinition, + IN OPTIONAL CONST WCHAR * szType + ); + +HRESULT +UnRegisterSectionSchema( + IN CONST BOOL isSectionInAdminSchema, + IN CONST WCHAR * szSectionName + ); + +HRESULT +RegisterUIModule( + IN CONST WCHAR * szModuleName, + IN CONST WCHAR * szModuleTypeInfo, + IN OPTIONAL CONST WCHAR * szRegisterInModulesSection, + IN OPTIONAL CONST WCHAR * szPrependToList + ); + +HRESULT +UnRegisterUIModule( + IN CONST WCHAR * szModuleName, + IN CONST WCHAR * szModuleTypeInfo + ); + +UINT +WINAPI +CheckForAdminSIDCA( + MSIHANDLE hInstall + ); + +UINT +LogMsiCustomActionError( + IN MSIHANDLE hInstall, + UINT messageId + ); + +HRESULT +InitAdminMgrForAdminConfig( + IN IAppHostWritableAdminManager * pAdminMgr, + IN CONST WCHAR * szCommitPath +); + +HRESULT +RegisterMofFile( + IN PWSTR pszFileName +); + +HRESULT +ScheduleInstallModuleCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + +HRESULT +ScheduleUnInstallModuleCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + +HRESULT +ExecuteInstallModuleCA( + IN CA_DATA_READER * cadata +); + +HRESULT +ExecuteUnInstallModuleCA( + IN CA_DATA_READER * cadata +); + + +HRESULT +ExecuteUnRegisterUIModuleCA( + IN CA_DATA_READER * cadata +); + + +HRESULT +ScheduleRegisterUIModuleCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); +HRESULT +ExecuteRegisterUIModuleCA( + IN CA_DATA_READER * cadata +); + +HRESULT +ScheduleUnRegisterUIModuleCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + + +HRESULT +ScheduleInstallHandlerCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ); + +HRESULT +ScheduleUnInstallHandlerCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata + ); + +HRESULT +ExecuteInstallHandlerCA( + IN CA_DATA_READER * cadata + ); + +HRESULT +ExecuteUnInstallHandlerCA( + IN CA_DATA_READER * cadata + ); + +HRESULT +ExecuteUnRegisterSectionSchemaCA( + IN CA_DATA_READER * cadata +); + + +HRESULT +ScheduleRegisterSectionSchemaCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + +HRESULT +ExecuteRegisterSectionSchemaCA( + IN CA_DATA_READER * cadata +); + +HRESULT +ScheduleUnRegisterSectionSchemaCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + +HRESULT +ScheduleRegisterTraceAreaCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + +HRESULT +ExecuteRegisterTraceAreaCA( + IN CA_DATA_READER * cadata +); + +HRESULT +ScheduleRegisterMofFileCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + +HRESULT +ExecuteRegisterMofFileCA( + IN CA_DATA_READER * cadata +); + +HRESULT +ScheduleInstallSectionDefaultsCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + +HRESULT +ExecuteInstallSectionDefaultsCA( + IN CA_DATA_READER * cadata +); + +HRESULT +ScheduleInstallSectionAdditionsCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + +HRESULT +ExecuteInstallSectionAdditionsCA( + IN CA_DATA_READER * cadata +); + +HRESULT +ScheduleInstallCgiRestrictionsCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + +HRESULT +ScheduleUnInstallCgiRestrictionsCA( + IN MSIHANDLE hInstall, + IN CA_DATA_WRITER * cadata +); + +HRESULT +ExecuteInstallCgiRestrictionsCA( + IN CA_DATA_READER * cadata +); + +HRESULT +ExecuteUnInstallCgiRestrictionsCA( + IN CA_DATA_READER * cadata +); diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.vcxproj b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.vcxproj new file mode 100644 index 0000000000..aced7ff216 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.vcxproj @@ -0,0 +1,131 @@ + + + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {b54a8f61-60de-4ad9-87ca-d102f230678e} + + + + {7324770c-0871-4d73-be3d-5e2f3e9e1b1e} + Win32Proj + iisca + + + + StaticLibrary + Unicode + v141 + + + + $(IIS-Common)version;$(IIS-Common)Include;$(AdditionalIncludeDirectories) + Create + precomp.h + $(IntDir)precomp.pch + + + + $(WIX)sdk\$(WixPlatformToolset)\inc;$(AdditionalIncludeDirectories) + Level4 + + + nothrownew.obj;httpapi.lib;shlwapi.lib;ahadmin.lib;xmllite.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;%(AdditionalDependencies) + CustomAction.def + Windows + + + + + _DEBUG;_WINDOWS;_USRDLL;CUSTOMACTIONTEST_EXPORTS;%(PreprocessorDefinitions) + + + + + MaxSpeed + + + true + + + + + $(VC_ReferencesPath_x86);$(WindowsSDK_LibraryPath)\$(PlatformTarget);$(WIX)sdk\$(WixPlatformToolset)\lib\x86;%(AdditionalLibraryDirectories) + MachineX86 + + + + + $(VC_ReferencesPath_x64);$(WindowsSDK_LibraryPath)\$(PlatformTarget);$(WIX)sdk\$(WixPlatformToolset)\lib\x64;%(AdditionalLibraryDirectories) + Machinex64 + + + + + + This project is trying to import a missing file: {0}. + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iiscaexp.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iiscaexp.cpp new file mode 100644 index 0000000000..e407497402 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iiscaexp.cpp @@ -0,0 +1,791 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + + + +#define IIS_CONFIG_BACKUP_EXT L"IISOOBBACK" + + +typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); + +LPFN_ISWOW64PROCESS fnIsWow64Process; + +BOOL IsWow64() +{ + BOOL bIsWow64 = FALSE; + + //IsWow64Process is not available on all supported versions of Windows. + //Use GetModuleHandle to get a handle to the DLL that contains the function + //and GetProcAddress to get a pointer to the function if available. + + fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress( + GetModuleHandle(TEXT("kernel32")),"IsWow64Process"); + + if(NULL != fnIsWow64Process) + { + if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64)) + { + //handle error + } + } + return bIsWow64; +} + +/******************************************************************** +IISScheduleInstall CA - CUSTOM ACTION ENTRY POINT for reading IIS custom +table settings into CA Data + +********************************************************************/ +UINT +WINAPI +IISScheduleInstallCA( + IN MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + CA_DATA_WRITER cadata; + BOOL bWriteToShared = FALSE; + BOOL fCoInit = FALSE; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + if ( SUCCEEDED( CoInitializeEx( NULL, COINIT_MULTITHREADED ) ) ) + { + fCoInit = TRUE; + } + + // + //See if we are going to update shared config + // + hr = CheckInstallToSharedConfig( hInstall, &bWriteToShared ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + if ( !bWriteToShared ) + { + //do not update config for this module + //ExecuteCA will not be scheduled. + } + // + // Schedule transactions + // + hr = MsiUtilScheduleDeferredAction( hInstall, + L"IISBeginTransactionCA", + cadata.QueryData() ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = MsiUtilScheduleDeferredAction( hInstall, + L"IISRollbackTransactionCA", + cadata.QueryData() ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = MsiUtilScheduleDeferredAction( hInstall, + L"IISCommitTransactionCA", + cadata.QueryData() ); + if ( FAILED(hr) ) + { + goto exit; + } + if( bWriteToShared ) + { + // + // Do the Config Install actions + // + hr = ScheduleInstallModuleCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleRegisterUIModuleCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleInstallHandlerCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleRegisterSectionSchemaCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleRegisterTraceAreaCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleInstallSectionDefaultsCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleInstallSectionAdditionsCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleInstallCgiRestrictionsCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + } + + // + // Do the Non-Config Install actions + // + hr = ScheduleRegisterMofFileCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + + + // + // Schedule deferred execute CA + // + + hr = MsiUtilScheduleDeferredAction( hInstall, + L"IISExecuteCA", + cadata.QueryData() ); + if ( FAILED(hr) ) + { + goto exit; + } + + hr = NOERROR; + + +exit: + if ( fCoInit ) + { + CoUninitialize(); + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + IISLogClose(); + + return hr; +} +/******************************************************************** +IISScheduleUninstall CA - CUSTOM ACTION ENTRY POINT for reading IIS custom +table settings into CA Data + +********************************************************************/ +UINT +WINAPI +IISScheduleUninstallCA( + IN MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + CA_DATA_WRITER cadata; + BOOL bWriteToShared = FALSE; + BOOL fCoInit = FALSE; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + if ( SUCCEEDED( CoInitializeEx( NULL, COINIT_MULTITHREADED ) ) ) + { + fCoInit = TRUE; + } + + // + //See if we are going to update shared config + // + hr = CheckInstallToSharedConfig( hInstall, &bWriteToShared ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + if ( !bWriteToShared ) + { + //do not update config for this module + //ExecuteCA will not be scheduled. + } + + if( bWriteToShared ) + { + // + // Do the Config Uninstall actions + // + hr = ScheduleUnInstallModuleCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleUnRegisterUIModuleCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleUnInstallHandlerCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleUnRegisterSectionSchemaCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + hr = ScheduleUnInstallCgiRestrictionsCA( hInstall, &cadata ); + if ( FAILED(hr) ) + { + goto exit; + } + } + // + // Do the Non-Config Uninstall actions + // + + + // + // Schedule deferred execute CA + // + + hr = MsiUtilScheduleDeferredAction( hInstall, + L"IISExecuteCA", + cadata.QueryData() ); + if ( FAILED(hr) ) + { + goto exit; + } + + hr = NOERROR; + + +exit: + if ( fCoInit ) + { + CoUninitialize(); + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + IISLogClose(); + + // + // Don't fail while uninstalling. + // + return NOERROR; +} +/******************************************************************** +IISExecuteCA - CUSTOM ACTION ENTRY POINT for writing IIS custom +table settings to iis config + +********************************************************************/ +UINT +WINAPI +IISExecuteCA( + IN MSIHANDLE hInstall + ) +{ + HRESULT hr = NOERROR; + CA_DATA_READER cadata; + INT icaType = 0; + BOOL fCoInit = FALSE; + + IISLogInitialize(hInstall, UNITEXT(__FUNCTION__)); + + if ( SUCCEEDED( CoInitializeEx( NULL, COINIT_MULTITHREADED ) ) ) + { + fCoInit = TRUE; + } + // + // Retrieve parameters from ca data + // + + hr = cadata.LoadDeferredCAData( hInstall ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + while ( SUCCEEDED(hr = cadata.Read( &icaType )) ) + { + switch (icaType ) + { + case IIS_INSTALL_MODULE: + { + hr = ExecuteInstallModuleCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_UNINSTALL_MODULE: + { + hr = ExecuteUnInstallModuleCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_INSTALL_UIMODULE: + { + hr = ExecuteRegisterUIModuleCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_UNINSTALL_UIMODULE: + { + hr = ExecuteUnRegisterUIModuleCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_INSTALL_HANDLER: + { + hr = ExecuteInstallHandlerCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_UNINSTALL_HANDLER: + { + hr = ExecuteUnInstallHandlerCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_INSTALL_SECTIONSCHEMA: + { + hr = ExecuteRegisterSectionSchemaCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_UNINSTALL_SECTIONSCHEMA: + { + hr = ExecuteUnRegisterSectionSchemaCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_INSTALL_TRACEAREA: + { + hr = ExecuteRegisterTraceAreaCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_INSTALL_MOFFILE: + { + hr = ExecuteRegisterMofFileCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_INSTALL_DEFAULTS: + { + hr = ExecuteInstallSectionDefaultsCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_INSTALL_SECTION_ADDITIONS: + { + hr = ExecuteInstallSectionAdditionsCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_INSTALL_CGIRESTRICTIONS: + { + hr = ExecuteInstallCgiRestrictionsCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + case IIS_UNINSTALL_CGIRESTRICTIONS: + { + hr = ExecuteInstallCgiRestrictionsCA( &cadata ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + break; + } + default: + { + //unknown execute CA action type + hr = E_UNEXPECTED; + goto exit; + } + } + } + + if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ) + { + hr = S_OK; + } + +exit: + + if ( fCoInit ) + { + CoUninitialize(); + } + + IISLogWrite( + SETUP_LOG_SEVERITY_INFORMATION, + L"CA '%s' completed with return code hr=0x%x", + UNITEXT(__FUNCTION__), + hr ); + + IISLogClose(); + + return hr; +} + +/******************************************************************** + BeginTransaction - CUSTOM ACTION ENTRY POINT for backing up + config + + Input: deferred CustomActionData - BackupName +********************************************************************/ +UINT +WINAPI +IISBeginTransactionCA( + IN MSIHANDLE + ) + +{ + HRESULT hr = S_OK; + STACK_STRU( wzConfigSource, MAX_PATH ); + STACK_STRU( wzConfigCopy, MAX_PATH ); + DWORD dwSize = 0; + + if( IsWow64() ) + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\Sysnative\\inetsrv\\config\\applicationHost.config", + wzConfigSource.QueryStr(), + MAX_PATH + ); + } + else + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\applicationHost.config", + wzConfigSource.QueryStr(), + MAX_PATH + ); + } + if ( dwSize == 0 ) + { + //ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings"); + goto exit; + } + wzConfigSource.SyncWithBuffer(); + hr = wzConfigCopy.Copy( wzConfigSource ); + + //add ca action as extension + + hr = wzConfigCopy.Append( L"."); + + hr = wzConfigCopy.Append( IIS_CONFIG_BACKUP_EXT); + + if ( !::CopyFileW(wzConfigSource.QueryStr(), wzConfigCopy.QueryStr(), FALSE) ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + //ExitOnFailure2(hr, "Failed to copy config backup %S -> %S", wzConfigSource, wzConfigCopy); + } + + if( IsWow64() ) + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\Sysnative\\inetsrv\\config\\administration.config", + wzConfigSource.QueryStr(), + MAX_PATH + ); + } + else + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\administration.config", + wzConfigSource.QueryStr(), + MAX_PATH + ); + } + + if ( dwSize == 0 ) + { + //ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings"); + goto exit; + } + wzConfigSource.SyncWithBuffer(); + hr = wzConfigCopy.Copy( wzConfigSource ); + + //add ca action as extension + + hr = wzConfigCopy.Append( L"."); + + hr = wzConfigCopy.Append( IIS_CONFIG_BACKUP_EXT); + + if ( !::CopyFileW(wzConfigSource.QueryStr(), wzConfigCopy.QueryStr(), FALSE) ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + //ExitOnFailure2(hr, "Failed to copy config backup %S -> %S", wzConfigSource, wzConfigCopy); + } + + +exit: + + return S_OK; + +} + + +/******************************************************************** + RollbackTransaction - CUSTOM ACTION ENTRY POINT for unbacking up + config + + Input: deferred CustomActionData - BackupName +********************************************************************/ +UINT +WINAPI +IISRollbackTransactionCA( + IN MSIHANDLE + ) +{ + + HRESULT hr = S_OK; + STACK_STRU( wzConfigSource, MAX_PATH ); + STACK_STRU( wzConfigCopy, MAX_PATH ); + DWORD dwSize = 0; + + + if( IsWow64() ) + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\Sysnative\\inetsrv\\config\\applicationHost.config", + wzConfigSource.QueryStr(), + MAX_PATH + ); + } + else + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\applicationHost.config", + wzConfigSource.QueryStr(), + MAX_PATH + ); + } + if ( dwSize == 0 ) + { + //ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings"); + goto exit; + } + wzConfigSource.SyncWithBuffer(); + hr = wzConfigCopy.Copy( wzConfigSource ); + + //add ca action as extension + + hr = wzConfigCopy.Append( L"." ); + + hr = wzConfigCopy.Append( IIS_CONFIG_BACKUP_EXT ); + + //rollback copy is reverse of start transaction + if( !::CopyFileW( wzConfigCopy.QueryStr(), wzConfigSource.QueryStr(), FALSE) ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + //ExitOnFailure(hr, "failed to restore config backup"); + } + + if ( !::DeleteFileW( wzConfigCopy.QueryStr() ) ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + //ExitOnFailure(hr, "failed to delete config backup"); + } + + if( IsWow64() ) + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\Sysnative\\inetsrv\\config\\administration.config", + wzConfigSource.QueryStr(), + MAX_PATH + ); + } + else + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\administration.config", + wzConfigSource.QueryStr(), + MAX_PATH + ); + } + if ( dwSize == 0 ) + { + //ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings"); + goto exit; + } + wzConfigSource.SyncWithBuffer(); + hr = wzConfigCopy.Copy( wzConfigSource ); + + //add ca action as extension + + hr = wzConfigCopy.Append( L"." ); + + hr = wzConfigCopy.Append( IIS_CONFIG_BACKUP_EXT ); + + //rollback copy is reverse of start transaction + if( !::CopyFileW( wzConfigCopy.QueryStr(), wzConfigSource.QueryStr(), FALSE) ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + //ExitOnFailure(hr, "failed to restore config backup"); + } + + if ( !::DeleteFileW( wzConfigCopy.QueryStr() ) ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + //ExitOnFailure(hr, "failed to delete config backup"); + } + + +exit: + + return S_OK; + +} +/******************************************************************** + CommitTransaction - CUSTOM ACTION ENTRY POINT for unbacking up + config + + Input: deferred CustomActionData - BackupName +********************************************************************/ +UINT +WINAPI +IISCommitTransactionCA( + IN MSIHANDLE + ) +{ + HRESULT hr = S_OK; + STACK_STRU( wzConfigCopy, MAX_PATH ); + DWORD dwSize = 0; + + + + // Config AdminMgr changes already committed, just + // delete backup config file. + + if( IsWow64() ) + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\Sysnative\\inetsrv\\config\\applicationHost.config", + wzConfigCopy.QueryStr(), + MAX_PATH + ); + } + else + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\applicationHost.config", + wzConfigCopy.QueryStr(), + MAX_PATH + ); + } + if ( dwSize == 0 ) + { + //ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings"); + goto exit; + } + wzConfigCopy.SyncWithBuffer(); + + hr = wzConfigCopy.Append( L"." ); + + hr = wzConfigCopy.Append( IIS_CONFIG_BACKUP_EXT); + + if( !::DeleteFileW(wzConfigCopy.QueryStr() ) ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + //ExitOnFailure(hr, "failed to delete config backup"); + } + + if( IsWow64() ) + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\Sysnative\\inetsrv\\config\\administration.config", + wzConfigCopy.QueryStr(), + MAX_PATH + ); + } + else + { + dwSize = ExpandEnvironmentStringsW(L"%windir%\\system32\\inetsrv\\config\\administration.config", + wzConfigCopy.QueryStr(), + MAX_PATH + ); + } + if ( dwSize == 0 ) + { + //ExitWithLastError(hr, "failed to get ExpandEnvironmentStrings"); + goto exit; + } + wzConfigCopy.SyncWithBuffer(); + + hr = wzConfigCopy.Append( L"." ); + + hr = wzConfigCopy.Append( IIS_CONFIG_BACKUP_EXT); + + if( !::DeleteFileW(wzConfigCopy.QueryStr() ) ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + //ExitOnFailure(hr, "failed to delete config backup"); + } + + +exit: + + return S_OK; + +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iiscaexp.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iiscaexp.h new file mode 100644 index 0000000000..184df8aff8 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iiscaexp.h @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +UINT +WINAPI +IISScheduleInstallCA( + IN MSIHANDLE hInstall + ); + +UINT +WINAPI +IISScheduleUninstallCA( + IN MSIHANDLE hInstall + ); + +UINT +WINAPI +IISExecuteCA( + IN MSIHANDLE hInstall + ); + +UINT +WINAPI +IISBeginTransactionCA( + IN MSIHANDLE hInstall + ); + +UINT +WINAPI +IISRollbackTransactionCA( + IN MSIHANDLE hInstall + ); + +UINT +WINAPI +IISCommitTransactionCA( + IN MSIHANDLE hInstall + ); + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/modules.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/modules.cpp new file mode 100644 index 0000000000..341306461d --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/modules.cpp @@ -0,0 +1,655 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +// +// Local function declarations +// + +HRESULT +AddModuleToGlobalModules( + IN IAppHostWritableAdminManager * pAdminMgr, + IN CONST WCHAR * szName, + IN CONST WCHAR * szImage, + IN OPTIONAL CONST WCHAR * szPreCondition + ); + +HRESULT +AddModuleToRootModules( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szName, + IN CONST WCHAR * szPreCondition, + IN OPTIONAL CONST WCHAR * szType + ); + +HRESULT +DeleteModuleFromRootModules( + IAppHostAdminManager * pAdminMgr, + CONST WCHAR * szName, + BOOL * pfDeleted + ); + +// +// Public functions +// + +HRESULT +InstallModule( + IN CONST WCHAR * szName, + IN CONST WCHAR * szImage, + IN OPTIONAL CONST WCHAR * szPreCondition, + IN OPTIONAL CONST WCHAR * szType + ) +{ + HRESULT hr = NOERROR; + + CComPtr pAdminMgr; + + hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( IAppHostWritableAdminManager ), + (VOID **)&pAdminMgr ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // If the type is present, this is a .Net module and + // should not be added to the globalModules + if ( ( szType == NULL ) || ( *szType == L'\0' ) ) + { + STRU strFinalImage; + WCHAR ProgFiles[64]; + WCHAR SysRoot[64]; + WCHAR SysDrive[16]; + PCWSTR szSubstFrom = NULL; + PCWSTR szSubstTo = NULL; + + if (GetEnvironmentVariable(L"ProgramFiles", + ProgFiles, + _countof(ProgFiles)) > _countof(ProgFiles) || + GetEnvironmentVariable(L"SystemRoot", + SysRoot, + _countof(SysRoot)) > _countof(SysRoot) || + GetEnvironmentVariable(L"SystemDrive", + SysDrive, + _countof(SysDrive)) > _countof(SysDrive)) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + + if (_wcsnicmp(szImage, ProgFiles, wcslen(ProgFiles)) == 0) + { + szSubstFrom = ProgFiles; + szSubstTo = L"%ProgramFiles%"; + } + else if (_wcsnicmp(szImage, SysRoot, wcslen(SysRoot)) == 0) + { + szSubstFrom = SysRoot; + szSubstTo = L"%SystemRoot%"; + } + else if (_wcsnicmp(szImage, SysDrive, wcslen(SysDrive)) == 0) + { + szSubstFrom = SysDrive; + szSubstTo = L"%SystemDrive%"; + } + + if (szSubstFrom != NULL) + { + if (FAILED(hr = strFinalImage.Copy(szSubstTo)) || + FAILED(hr = strFinalImage.Append(szImage + wcslen(szSubstFrom)))) + { + goto exit; + } + szImage = strFinalImage.QueryStr(); + } + + hr = AddModuleToGlobalModules( pAdminMgr, + szName, + szImage, + szPreCondition ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + hr = AddModuleToRootModules( pAdminMgr, + szName, + szPreCondition, + szType ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->CommitChanges(); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return hr; +} + +HRESULT +UnInstallModule( + IN CONST WCHAR * szName, + IN OPTIONAL CONST WCHAR * szType + ) +{ + HRESULT hr = NOERROR; + + CComPtr pAdminMgr; + CComPtr pGlobalModulesSection; + CComPtr pGlobalModulesCollection; + + BSTR bstrAppHostConfigPath = SysAllocString( L"MACHINE/WEBROOT/APPHOST" ); + BSTR bstrGlobalModules = SysAllocString( L"system.webServer/globalModules" ); + + BOOL fChanged = FALSE; + BOOL fDeleted = FALSE; + UINT numDeleted; + + if ( !bstrAppHostConfigPath || + !bstrGlobalModules ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto exit; + } + + hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( IAppHostWritableAdminManager ), + (VOID **)&pAdminMgr ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Remove from root modules + // + + hr = DeleteModuleFromRootModules( pAdminMgr, + szName, + &fDeleted ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( !fDeleted ) + { + DBGWARN(( DBG_CONTEXT, + "Expected to find %S in root modules collection\n" , + szName )); + } + + fChanged = fDeleted; + + if ( ( szType == NULL ) || ( *szType == L'\0' ) ) + { + // + // Remove from globalModules + // + + hr = pAdminMgr->GetAdminSection( bstrGlobalModules, + bstrAppHostConfigPath, + &pGlobalModulesSection ); + + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pGlobalModulesSection->get_Collection( &pGlobalModulesCollection ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + + hr = DeleteAllElementsFromCollection( pGlobalModulesCollection, + L"name", + szName, + FIND_ELEMENT_CASE_SENSITIVE, + &numDeleted ); + + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( numDeleted == 0 ) + { + DBGWARN(( DBG_CONTEXT, + "Expected to find %S in globalModules list.\n", + szName )); + } + else + { + fChanged = TRUE; + } + } + + if ( fChanged ) + { + hr = pAdminMgr->CommitChanges(); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + +exit: + + SysFreeString( bstrAppHostConfigPath ); + SysFreeString( bstrGlobalModules ); + + return hr; +} + +// +// Local functions +// + +HRESULT +AddModuleToGlobalModules( + IN IAppHostWritableAdminManager * pAdminMgr, + IN CONST WCHAR * szName, + IN CONST WCHAR * szImage, + IN OPTIONAL CONST WCHAR * szPreCondition + ) +{ + HRESULT hr = NOERROR; + + CComPtr pGlobalModulesSection; + CComPtr pGlobalModulesCollection; + CComPtr pNewGlobalModuleElement; + + VARIANT varPropValue; + VariantInit( &varPropValue ); + + BSTR bstrAppHostConfigPath = SysAllocString( L"MACHINE/WEBROOT/APPHOST" ); + BSTR bstrGlobalModules = SysAllocString( L"system.webServer/globalModules" ); + BSTR bstrAdd = SysAllocString( L"add" ); + + if ( !bstrAppHostConfigPath || + !bstrGlobalModules || + !bstrAdd ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto exit; + } + + // + // Get the global modules collection + // + + hr = pAdminMgr->GetAdminSection( bstrGlobalModules, + bstrAppHostConfigPath, + &pGlobalModulesSection ); + + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = pGlobalModulesSection->get_Collection( &pGlobalModulesCollection ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + // + // Create a new module element + // + + hr = pGlobalModulesCollection->CreateNewElement( bstrAdd, + &pNewGlobalModuleElement ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = VariantAssign( &varPropValue, szName ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = SetElementProperty( pNewGlobalModuleElement, + L"name", + &varPropValue ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = VariantAssign( &varPropValue, szImage ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = SetElementProperty( pNewGlobalModuleElement, + L"image", + &varPropValue ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + if ( szPreCondition && *szPreCondition ) + { + hr = VariantAssign( &varPropValue, szPreCondition ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = SetElementProperty( pNewGlobalModuleElement, + L"preCondition", + &varPropValue ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + } + + // + // Add the new element + // + + hr = pGlobalModulesCollection->AddElement( pNewGlobalModuleElement ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + +exit: + + VariantClear( &varPropValue ); + + SysFreeString( bstrAppHostConfigPath ); + SysFreeString( bstrGlobalModules ); + SysFreeString( bstrAdd ); + + return hr; +} + +HRESULT +AddModuleToRootModules( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szName, + IN CONST WCHAR * szPreCondition, + IN OPTIONAL CONST WCHAR * szType + ) +{ + HRESULT hr = NOERROR; + + BOOL found = FALSE; + + CComPtr pLocation; + CComPtr pModulesSection; + CComPtr pModuleCollection; + CComPtr pNewModuleElement; + + VARIANT varPropValue; + VariantInit( &varPropValue ); + + BSTR bstrAdd = SysAllocString( L"add" ); + + if ( !bstrAdd ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = GetLocationFromFile( pAdminMgr, + L"MACHINE/WEBROOT/APPHOST", + L"", + &pLocation, + &found ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( !found ) + { + hr = HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ); + DBGERROR(( DBG_CONTEXT, + "Failed to find root location path\n" )); + goto exit; + } + + hr = GetSectionFromLocation( pLocation, + L"system.webServer/modules", + &pModulesSection, + &found ); + + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( !found ) + { + hr = HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ); + DBGERROR(( DBG_CONTEXT, + "Failed to find modules section\n" )); + goto exit; + } + + // + // Create a new module element + // + + hr = pModulesSection->get_Collection( &pModuleCollection ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pModuleCollection->CreateNewElement( bstrAdd, + &pNewModuleElement ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = VariantAssign( &varPropValue, szName ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = SetElementProperty( pNewModuleElement, + L"name", + &varPropValue ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + if ( szPreCondition && *szPreCondition ) + { + hr = VariantAssign( &varPropValue, szPreCondition ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = SetElementProperty( pNewModuleElement, + L"preCondition", + &varPropValue ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + } + + if ( szType && *szType ) + { + hr = VariantAssign( &varPropValue, szType ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + + hr = SetElementProperty( pNewModuleElement, + L"type", + &varPropValue ); + if ( FAILED(hr) ) + { + DBGERROR_HR( hr ); + goto exit; + } + } + + hr = pModuleCollection->AddElement( pNewModuleElement, + -1 ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + SysFreeString( bstrAdd ); + VariantClear( &varPropValue ); + + return hr; +} + +HRESULT +DeleteModuleFromRootModules( + IAppHostAdminManager * pAdminMgr, + CONST WCHAR * szName, + BOOL * pfDeleted + ) +{ + HRESULT hr = NOERROR; + + CComPtr pLocation; + CComPtr pModulesSection; + CComPtr pModulesCollection; + + UINT numDeleted; + BOOL found = FALSE; + + *pfDeleted = FALSE; + + hr = GetLocationFromFile( pAdminMgr, + L"MACHINE/WEBROOT/APPHOST", + L"", + &pLocation, + &found ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( !found ) + { + DBGWARN(( DBG_CONTEXT, + "Failed to find root location path\n" )); + goto exit; + } + + hr = GetSectionFromLocation( pLocation, + L"system.webServer/modules", + &pModulesSection, + &found ); + + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( !found ) + { + DBGWARN(( DBG_CONTEXT, + "Failed to find modules section in root\n" )); + goto exit; + } + + hr = pModulesSection->get_Collection( &pModulesCollection ); + + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = DeleteAllElementsFromCollection( pModulesCollection, + L"name", + szName, + FIND_ELEMENT_CASE_SENSITIVE, + &numDeleted ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( numDeleted == 0 ) + { + DBGWARN(( DBG_CONTEXT, + "Failed to find %S in root modules\n", + szName )); + } + else + { + *pfDeleted = TRUE; + } + +exit: + + return hr; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/mof.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/mof.cpp new file mode 100644 index 0000000000..2f13ab1dfc --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/mof.cpp @@ -0,0 +1,82 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" +#include + +HRESULT +RegisterMofFile( + __in PWSTR pszFileName +) +{ + HRESULT hr = S_OK; + WBEM_COMPILE_STATUS_INFO CompileStatusInfo; + CComPtr pCompiler; + + hr = CoCreateInstance( _uuidof(MofCompiler), + 0, + CLSCTX_INPROC_SERVER, + _uuidof(IMofCompiler), + (LPVOID *) &pCompiler); + if ( FAILED( hr ) ) + { + // + // Register the COM object if is not registered. + // + WCHAR * pszDllPath = new WCHAR[ MAX_PATH ]; + if ( pszDllPath != NULL ) + { + if ( GetSystemDirectory( pszDllPath, MAX_PATH ) != 0 ) + { + HRESULT (STDAPICALLTYPE *pfDllRegisterServer)(VOID); + + (VOID) StringCchCat( pszDllPath, MAX_PATH, L"\\wbem\\mofd.dll" ); + + HINSTANCE hLib = LoadLibraryEx( pszDllPath, + NULL, + LOAD_WITH_ALTERED_SEARCH_PATH ); + if ( hLib != NULL ) + { + pfDllRegisterServer = (HRESULT (STDAPICALLTYPE *)(VOID))GetProcAddress(hLib, "DllRegisterServer"); + if ( pfDllRegisterServer != NULL ) + { + pfDllRegisterServer(); + hr = CoCreateInstance( _uuidof(MofCompiler), + 0, + CLSCTX_INPROC_SERVER, + _uuidof(IMofCompiler), + (LPVOID *) &pCompiler); + } + FreeLibrary( hLib ); + } + } + delete [] pszDllPath; + } + if ( FAILED( hr ) ) + { + goto Finished; + } + } + + hr = pCompiler->CompileFile( pszFileName, + NULL, // namespace + NULL, // username + NULL, // authoroty + NULL, // password + 0, // option flags + 0, // class flags + 0, // instance + &CompileStatusInfo ); + if ( hr != S_OK ) + { + // + // Means failure. + // + goto Finished; + } + +Finished: + + return hr; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/msiutil.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/msiutil.cpp new file mode 100644 index 0000000000..2a9b65ab37 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/msiutil.cpp @@ -0,0 +1,581 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +HRESULT +MsiUtilGetProperty( + IN MSIHANDLE hInstall, + __in PCWSTR szName, + __inout STRU * pstrProperty + ) +{ + HRESULT hr = NOERROR; + DWORD cch = 0; + WCHAR dummy = L'\0'; + DWORD status; + + pstrProperty->Reset(); + + // + // Get the length. + // + + status = MsiGetPropertyW( hInstall, + szName, + &dummy, + &cch ); + + if( status != ERROR_MORE_DATA ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + // + // Return is count of characters w/o NULL + // + + cch++; + + hr = pstrProperty->Resize( cch ); + if( FAILED( hr ) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiGetPropertyW( hInstall, + szName, + pstrProperty->QueryStr(), + &cch ); + + if( status != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + pstrProperty->SyncWithBuffer(); + +exit: + + return hr; +} + + +HRESULT +MsiUtilScheduleDeferredAction( + IN MSIHANDLE hInstall, + __in PCWSTR szAction, + __in PCWSTR szData + ) +{ + HRESULT hr = NOERROR; + UINT status; + + status = MsiSetPropertyW( hInstall, + szAction, + szData ); + if( status != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + status = MsiDoActionW( hInstall, + szAction ); + + if( status != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32(status ); + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return hr; +} + +HRESULT +MsiUtilRecordGetInteger( + IN MSIHANDLE hRecord, + IN UINT field, + __inout UINT * pInt + ) +{ + HRESULT hr = NOERROR; + UINT tempValue = 0; + + _ASSERTE(pInt); + + tempValue = MsiRecordGetInteger(hRecord, field); + + if( MSI_NULL_INTEGER == tempValue ) + { + hr = E_UNEXPECTED; + DBGERROR(( DBG_CONTEXT, "Non-integer value encountered in Integer field, %08x\n", hr )); + goto exit; + } + + *pInt = tempValue; + +exit: + return hr; +} + +HRESULT +MsiUtilRecordGetString( + IN MSIHANDLE hRecord, + IN UINT field, + __inout STRU * pstr + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + + DWORD cch = pstr->QuerySizeCCH(); + + status = MsiRecordGetStringW( hRecord, + field, + pstr->QueryStr(), + &cch ); + + if( ERROR_MORE_DATA == status ) + { + hr = pstr->Resize( ++cch ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiRecordGetStringW( hRecord, + field, + pstr->QueryStr(), + &cch ); + } + + if( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + hr = pstr->SetLen( cch ); + if( FAILED(hr) ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return hr; +} + +HRESULT +MsiUtilRecordReadStreamIntoFile( + IN MSIHANDLE hRecord, + IN UINT field, + IN PCWSTR szFileName + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + HANDLE hOutputFile = INVALID_HANDLE_VALUE; + + _ASSERTE(szFileName); + + hOutputFile = CreateFileW( szFileName, + GENERIC_WRITE, + 0, + NULL, + CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, + NULL); + if ( INVALID_HANDLE_VALUE == hOutputFile ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + goto exit; + } + + do + { + DWORD bytesWritten = 0; + BOOL fRet = FALSE; + CHAR szBuffer[4096]; + DWORD cbBuf = sizeof(szBuffer); + + status = MsiRecordReadStream(hRecord, field, szBuffer, &cbBuf); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + else if ( 0 == cbBuf ) + { + //we've reached the end of the stream + break; + } + + fRet = WriteFile(hOutputFile, szBuffer, cbBuf, &bytesWritten, NULL); + if( !fRet ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + } while (1); + + +exit: + + if( INVALID_HANDLE_VALUE != hOutputFile) + { + CloseHandle( hOutputFile ); + hOutputFile = INVALID_HANDLE_VALUE; + } + + return hr; +} + +HRESULT +MsiUtilFormatString( + IN MSIHANDLE hInstall, + __inout STRU * pstrData + ) +{ + HRESULT hr = NOERROR; + UINT status = ERROR_SUCCESS; + MSIHANDLE hRecord = NULL; + + hRecord = MsiCreateRecord( 1 ); + if( !hRecord ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto exit; + } + + status = MsiRecordSetStringW( hRecord, + 0, + pstrData->QueryStr() ); + if( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + DWORD cch = pstrData->QuerySizeCCH(); + + status = MsiFormatRecordW( hInstall, + hRecord, + pstrData->QueryStr(), + &cch ); + if( ERROR_MORE_DATA == status ) + { + hr = pstrData->Resize( ++cch ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + status = MsiFormatRecordW( hInstall, + hRecord, + pstrData->QueryStr(), + &cch ); + } + + if( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32(status); + DBGERROR_HR(hr); + goto exit; + } + + hr = pstrData->SetLen( cch ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + if( hRecord ) + { + MsiCloseHandle( hRecord ); + hRecord = NULL; + } + + return hr; +} + +WCHAR CA_DATA_DELIM[] = { '^', 0 }; + +// +// BUGBUG - Prefix will barf on this +// Can I really trust this data hasn't been tampered with? +// +WCHAR * +CA_DATA_READER::ExtractString() +{ + if( !_current || *_current == 0 ) + { + return NULL; + } + + // + // String format is: + // (len - delim - data - delim) (xN) \0 + // "3^cat^4^fish^\0" + // + + // + // extract length of data + // + + WCHAR * psz = wcsstr( _current, CA_DATA_DELIM ); + + _ASSERTE( psz ); + if( psz ) + { + *psz = 0; + INT cch = wcstol( _current, NULL, 0 ); + + // + // advance to data + // + + psz++; + + // + // terminate and advance to next block + // + + _current = psz + cch; + *_current = 0; + + _current++; + } + + return psz; +} + +HRESULT +CA_DATA_WRITER::WriteInternal( + CONST WCHAR * sz, + INT n +) +{ + HRESULT hr = NOERROR; + + // + // Write out the data length + // + + WCHAR buffer[20]; + StringCchPrintfW( buffer, sizeof(buffer)/sizeof(buffer[0]), L"%d", n ); + + hr = _data.Append( buffer ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = _data.Append( CA_DATA_DELIM ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Write out the data + // + + hr = _data.Append( sz ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = _data.Append( CA_DATA_DELIM ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + return hr; +} + + + +BOOL +MsiUtilIsInstalling( + INSTALLSTATE isInstalled, + INSTALLSTATE isAction + ) +{ + return (INSTALLSTATE_LOCAL == isAction || + INSTALLSTATE_SOURCE == isAction || + (INSTALLSTATE_DEFAULT == isAction && + (INSTALLSTATE_LOCAL == isInstalled || + INSTALLSTATE_SOURCE == isInstalled))); +} + + +BOOL +MsiUtilIsReInstalling( + INSTALLSTATE isInstalled, + INSTALLSTATE isAction + ) +{ + return ((INSTALLSTATE_LOCAL == isAction || + INSTALLSTATE_SOURCE == isAction || + INSTALLSTATE_DEFAULT == isAction || + INSTALLSTATE_UNKNOWN == isAction) && + (INSTALLSTATE_LOCAL == isInstalled || + INSTALLSTATE_SOURCE == isInstalled)); +} + + +BOOL +MsiUtilIsUnInstalling( + INSTALLSTATE isInstalled, + INSTALLSTATE isAction + ) +{ + return ((INSTALLSTATE_ABSENT == isAction || + INSTALLSTATE_REMOVED == isAction) && + (INSTALLSTATE_LOCAL == isInstalled || + INSTALLSTATE_SOURCE == isInstalled)); +} + +HRESULT +GenerateTempFileName( + __in PCWSTR szPrefix, + __in PCWSTR szExtension, + __inout STRU * pstr +) +{ + HRESULT hr = NOERROR; + UINT status = 0; + STACK_STRU( guidName, 128 ); + GUID guid = {0}; + DWORD cch = 0; + + _ASSERTE(szPrefix); + _ASSERTE(szExtension); + _ASSERTE(pstr); + + cch = pstr->QuerySizeCCH(); + + status = GetTempPathW(cch, pstr->QueryStr()); + if ( status > cch) + { + cch = status; + hr = pstr->Resize( ++cch ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error resizing buffer, hr=0x%x", hr); + goto exit; + } + + status = GetTempPathW(cch, pstr->QueryStr()); + } + + if ( 0 == status ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting temp path, hr=0x%x", hr); + goto exit; + } + + pstr->SyncWithBuffer(); + + hr = pstr->Append(L"\\"); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error apppending \\, hr=0x%x", hr); + goto exit; + } + + hr = pstr->Append(szPrefix); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error appending file prefix, hr=0x%x", hr); + goto exit; + } + + cch = guidName.QuerySizeCCH(); + hr = CoCreateGuid ( &guid ); + if ( FAILED (hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error generating the GUID, hr=0x%x", hr); + goto exit; + } + + if ( !StringFromGUID2( guid, guidName.QueryStr(), cch ) ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error getting string from GUID, hr=0x%x", hr); + goto exit; + } + + guidName.SyncWithBuffer(); + + hr = pstr->Append(guidName.QueryStr()); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error appending GUID, hr=0x%x", hr); + goto exit; + } + + hr = pstr->Append(L"."); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error appending ., hr=0x%x", hr); + goto exit; + } + + hr = pstr->Append(szExtension); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + IISLogWrite(SETUP_LOG_SEVERITY_ERROR, L"Error appending extension, hr=0x%x", hr); + goto exit; + } + +exit: + if ( FAILED(hr) ) + { + IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Error in function %s, hr=0x%x", UNITEXT(__FUNCTION__), hr); + } + return hr; +} \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/msiutil.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/msiutil.h new file mode 100644 index 0000000000..e7c770c534 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/msiutil.h @@ -0,0 +1,192 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +HRESULT +MsiUtilGetProperty( + IN MSIHANDLE hInstall, + __in PCWSTR szName, + __inout STRU * pstrProperty + ); + +HRESULT +MsiUtilScheduleDeferredAction( + IN MSIHANDLE hInstall, + __in PCWSTR szAction, + __in PCWSTR szData + ); + +HRESULT +MsiUtilRecordGetInteger( + IN MSIHANDLE hRecord, + IN UINT field, + __inout UINT * pInt + ); + +HRESULT +MsiUtilRecordGetString( + IN MSIHANDLE hRecord, + IN UINT field, + __inout STRU * pstr + ); + +HRESULT +MsiUtilRecordReadStreamIntoFile( + IN MSIHANDLE hRecord, + IN UINT field, + IN PCWSTR szFileName + ); + +HRESULT +MsiUtilFormatString( + IN MSIHANDLE hInstall, + __inout STRU * pstrData + ); + +class CA_DATA_WRITER +{ +public: + + CA_DATA_WRITER() + { + } + + HRESULT + Write( + CONST WCHAR * sz + ) + { + return WriteInternal( sz, (INT)wcslen(sz) ); + } + + HRESULT + Write( + CONST WCHAR * sz, + INT cch + ) + { + return WriteInternal( sz, cch ); + } + + HRESULT + Write( + INT n + ) + { + HRESULT hr; + + WCHAR buffer[20]; + hr = StringCchPrintfW( buffer, + sizeof(buffer)/sizeof(buffer[0]), + L"%d", + n ); + if( FAILED(hr) ) + { + return hr; + } + + return WriteInternal( buffer, (INT)wcslen(buffer) ); + } + + CONST WCHAR * + QueryData() const + { + return _data.QueryStr(); + } + +protected: + + HRESULT + WriteInternal( + CONST WCHAR * sz, + INT n + ); + + STRU _data; +}; + +class CA_DATA_READER +{ +public: + + CA_DATA_READER() : + _current( NULL ) + { + } + + ~CA_DATA_READER() + { + } + + HRESULT + LoadDeferredCAData( + MSIHANDLE hInstall + ) + { + HRESULT hr = MsiUtilGetProperty( hInstall, L"CustomActionData", &_strCustomActionData ); + _current = _strCustomActionData.QueryStr(); + return hr; + } + + HRESULT + Read( + __deref_out_z WCHAR ** psz + ) + { + *psz = ExtractString(); + if( !*psz ) + { + return HRESULT_FROM_WIN32( ERROR_NO_MORE_ITEMS ); + } + return S_OK; + } + + HRESULT + Read( + INT * pi + ) + { + CONST WCHAR * sz = ExtractString(); + if( !sz ) + { + return HRESULT_FROM_WIN32( ERROR_NO_MORE_ITEMS ); + } + *pi = wcstol( sz, NULL, 10 ); + return S_OK; + } + +private: + + WCHAR * + ExtractString(); + + STRU _strCustomActionData; + WCHAR * _current; +}; + + +BOOL +MsiUtilIsReInstalling( + INSTALLSTATE isInstalled, + INSTALLSTATE isAction + ); + +BOOL +MsiUtilIsInstalling( + INSTALLSTATE isInstalled, + INSTALLSTATE isAction + ); + +BOOL +MsiUtilIsUnInstalling( + INSTALLSTATE isInstalled, + INSTALLSTATE isAction + ); + +HRESULT +GenerateTempFileName( + __in PCWSTR szPrefix, + __in PCWSTR szExtension, + __inout STRU * pstr +); \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/packages.config b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/packages.config new file mode 100644 index 0000000000..21d9344493 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/packages.config @@ -0,0 +1,4 @@ + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/precomp.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/precomp.h new file mode 100644 index 0000000000..5f32044523 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/precomp.h @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +// Don't throw exceptions for CComVariant failures. +// Check for VT_ERROR instead. +#define _ATL_NO_VARIANT_THROW +#define WIN32_LEAN_AND_MEAN + +#include +#include +#include +#include +#pragma warning( disable:4127 ) +#include +#include "dbgutil.h" +#include +#define IRTL_DLLEXP +#include +#include +#include +#include +#include +#include +#include + +// +// Security APIs. +// +#include +#include +#include +#include + + +#include "ahutil.h" +#include "msiutil.h" +#include "defaults.h" +#include "cgi_restrictions.h" +#include "handlers.h" +#include "tracing.h" +#include "config_custom.h" +#include "setup_log.h" +#include "httpapi.h" +#include "secutils.h" +#include "ConfigShared.h" +#include "iisca.h" +#include "iiscaexp.h" +extern HINSTANCE g_hinst; + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/schema.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/schema.cpp new file mode 100644 index 0000000000..fe39b356f0 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/schema.cpp @@ -0,0 +1,741 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +HRESULT +GetChildSectionGroup( + IN IAppHostSectionGroup * pParentSectionGroup, + IN CONST WCHAR * szChildGroupName, + OUT IAppHostSectionGroup ** ppChildSectionGroup + ) +{ + HRESULT hr = NOERROR; + + CComPtr pChildSectionGroup; + + VARIANT varChildGroupName; + VariantInit( &varChildGroupName ); + + *ppChildSectionGroup = NULL; + + hr = VariantAssign( &varChildGroupName, + szChildGroupName ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pParentSectionGroup->get_Item( varChildGroupName, + &pChildSectionGroup ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + *ppChildSectionGroup = pChildSectionGroup.Detach(); + +exit: + + VariantClear( &varChildGroupName ); + + return hr; +} + +HRESULT +GetRootSectionGroup( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szConfigPath, + OUT IAppHostSectionGroup ** ppRootSectionGroup + ) +{ + HRESULT hr = NOERROR; + + CComPtr pRootSectionGroup; + CComPtr pConfigMgr; + CComPtr pConfigFile; + + BSTR bstrConfigPath = NULL; + + *ppRootSectionGroup = NULL; + + bstrConfigPath = SysAllocString( szConfigPath ); + + if( !bstrConfigPath ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->get_ConfigManager( &pConfigMgr ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pConfigMgr->GetConfigFile( bstrConfigPath, + &pConfigFile ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pConfigFile->get_RootSectionGroup( &pRootSectionGroup ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + *ppRootSectionGroup = pRootSectionGroup.Detach(); + +exit: + + SysFreeString( bstrConfigPath ); + + return hr; +} + +HRESULT +InitializeAdminManager( + IN CONST BOOL isSectionInAdminSchema, + IN IAppHostWritableAdminManager * pAdminMgr, + OUT CONST WCHAR ** pszCommitPath +) +{ + HRESULT hr = NOERROR; + CONST WCHAR * szAdminCommitPath = L"MACHINE/WEBROOT"; + CONST WCHAR * szAppHostCommitPath = L"MACHINE/WEBROOT/APPHOST"; + + CONST WCHAR * szCommitPath = NULL; + + *pszCommitPath = NULL; + + if(isSectionInAdminSchema) + { + szCommitPath = szAdminCommitPath; + hr = InitAdminMgrForAdminConfig( pAdminMgr, + szCommitPath ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + else + { + szCommitPath = szAppHostCommitPath; + } + + *pszCommitPath = szCommitPath; + +exit: + return hr; +} + +HRESULT +RegisterSectionSchema( + IN CONST BOOL isSectionInAdminSchema, + IN CONST WCHAR * szSectionName, + IN CONST WCHAR * szOverrideModeDefault, + IN OPTIONAL CONST WCHAR * szAllowDefinition, + IN OPTIONAL CONST WCHAR * szType + ) +{ + HRESULT hr = NOERROR; + + CComPtr pAdminMgr; + CComPtr pRootSectionGroup; + CComPtr pParentSectionGroup; + CComPtr pChildSectionGroup; + CComPtr pSections; + CComPtr pNewSection; + + + BSTR bstrSectionGroupName = NULL; + BSTR bstrSectionName = NULL; + BSTR bstrOverrideModeDefault = NULL; + BSTR bstrAllowDefinition = NULL; + BSTR bstrType = NULL; + + CONST WCHAR * szCommitPath = NULL; + + WCHAR * szSectionNameCopy = _wcsdup( szSectionName ); + if( !szSectionNameCopy ) + { + hr = E_OUTOFMEMORY; + goto exit; + } + szSectionName = NULL; + + // + // szSectionNameCopy is the full name of the section. The last + // segment szShortName will be registered as the name of the + // section and the other segments are section groups + // + // eg. "system.webServer/foo/bar/mysection" + // + + WCHAR * szShortName = wcsrchr( szSectionNameCopy, L'/' ); + if( szShortName == NULL ) + { + szShortName = szSectionNameCopy; + } + else + { + *szShortName++ = L'\0'; + } + + hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( IAppHostWritableAdminManager ), + (VOID **)&pAdminMgr ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = InitializeAdminManager( isSectionInAdminSchema, + pAdminMgr, + &szCommitPath); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = GetRootSectionGroup( pAdminMgr, + szCommitPath, + &pRootSectionGroup); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // For each section group referenced in szSectionNameCopy retrieve or + // create it. + // + + WCHAR * pszGroupName = szSectionNameCopy; + WCHAR * pszNext = NULL; + + pParentSectionGroup = pRootSectionGroup; + + if (szShortName == szSectionNameCopy) + { + goto SkipAddingGroups; + } + + while( pszGroupName ) + { + pszNext = wcschr( pszGroupName, L'/' ); + if( pszNext ) + { + *pszNext++ = 0; + } + + hr = GetChildSectionGroup( pParentSectionGroup, + pszGroupName, + &pChildSectionGroup ); + + if( hr == HRESULT_FROM_WIN32( ERROR_INVALID_INDEX ) ) + { + // + // Create the group if it does not exist + // + bstrSectionGroupName = SysAllocString( pszGroupName ); + if( !bstrSectionGroupName ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pParentSectionGroup->AddSectionGroup( bstrSectionGroupName, + &pChildSectionGroup ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + else if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + pParentSectionGroup = pChildSectionGroup; + pChildSectionGroup.Release(); + + SysFreeString( bstrSectionGroupName ); + bstrSectionGroupName = NULL; + + pszGroupName = pszNext; + } + + SkipAddingGroups: + // + // Add the new section + // + + hr = pParentSectionGroup->get_Sections( &pSections ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + bstrSectionName = SysAllocString( szShortName ); + if( !bstrSectionName ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pSections->AddSection( bstrSectionName, + &pNewSection ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + bstrOverrideModeDefault = SysAllocString( szOverrideModeDefault ); + if( !bstrOverrideModeDefault ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pNewSection->put_OverrideModeDefault( bstrOverrideModeDefault ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if( szAllowDefinition && *szAllowDefinition ) + { + bstrAllowDefinition = SysAllocString( szAllowDefinition ); + if( !bstrAllowDefinition ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pNewSection->put_AllowDefinition( bstrAllowDefinition ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if( szType && *szType ) + { + bstrType = SysAllocString( szType ); + if( !bstrType ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pNewSection->put_Type( bstrType ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + // + // Persist changes + // + + hr = pAdminMgr->CommitChanges(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + SysFreeString( bstrSectionGroupName ); + SysFreeString( bstrSectionName ); + SysFreeString( bstrOverrideModeDefault ); + SysFreeString( bstrType ); + SysFreeString( bstrAllowDefinition ); + + free( szSectionNameCopy ); + + return hr; +} + +HRESULT +RemoveSectionDefinition( + IN IAppHostSectionGroup * pParentSection, + __in_z WCHAR * szSectionPath, + __in_z WCHAR * szSectionName + ) +{ + HRESULT hr = NOERROR; + + CComPtr pChildSectionGroup; + CComPtr pSections; + + WCHAR * pszNextPath = NULL; + + VARIANT varIndex; + VariantInit( &varIndex ); + + // + // If there are no more path segments, remove the section + // + + if( !szSectionPath ) + { + hr = pParentSection->get_Sections( &pSections ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = VariantAssign( &varIndex, szSectionName ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pSections->DeleteSection( varIndex ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // End recursion + goto exit; + } + + // + // We have more path segments, so move to the next segment + // and call RemoveSectionDefinition recursively + // + + pszNextPath = wcschr( szSectionPath, L'/' ); + if( pszNextPath ) + { + *pszNextPath++ = 0; + } + + hr = GetChildSectionGroup( pParentSection, + szSectionPath, + &pChildSectionGroup ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = RemoveSectionDefinition( pChildSectionGroup, + pszNextPath, + szSectionName ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // The section has been removed, check to see if the + // child section group is empty and clean up if it is. + // + + ULONG childCount = 0; + hr = pChildSectionGroup->get_Count( &childCount ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if( childCount == 0 ) + { + hr = pChildSectionGroup->get_Sections( &pSections ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pSections->get_Count( &childCount ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if( childCount == 0 ) + { + hr = VariantAssign( &varIndex, szSectionPath ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pParentSection->DeleteSectionGroup( varIndex ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + } + } + +exit: + + VariantClear( &varIndex ); + + return hr; +} + +HRESULT +RemoveSectionData( + IN IAppHostAdminManager * pAdminMgr, + IN CONST WCHAR * szSectionName, + IN CONST WCHAR * szConfigPath + ) +{ + HRESULT hr = NOERROR; + + CComPtr pSectionElement; + CComPtr pConfigMgr; + CComPtr pConfigFile; + CComPtr pLocations; + CComPtr pLocation; + + BSTR bstrSectionName = SysAllocString( szSectionName ); + BSTR bstrPath = SysAllocString( szConfigPath ); + + VARIANT varSectionName; + VariantInit( &varSectionName ); + + if( !bstrSectionName || + !bstrPath ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = VariantAssign( &varSectionName, szSectionName ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->GetAdminSection( bstrSectionName, + bstrPath, + &pSectionElement ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pSectionElement->Clear(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Go through the location tags and delete the section + // + + hr = pAdminMgr->get_ConfigManager( &pConfigMgr ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pConfigMgr->GetConfigFile( bstrPath, + &pConfigFile ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pConfigFile->get_Locations( &pLocations ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + DWORD count; + VARIANT varIndex; + VariantInit( &varIndex ); + + hr = pLocations->get_Count( &count ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + for( DWORD i = 0; i < count; i++ ) + { + varIndex.vt = VT_UI4; + varIndex.ulVal = i; + + hr = pLocations->get_Item( varIndex, &pLocation ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pLocation->DeleteConfigSection( varSectionName ); + if( HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) == hr ) + { + hr = S_OK; + } + else if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + pLocation.Release(); + } + +exit: + + SysFreeString( bstrSectionName ); + SysFreeString( bstrPath ); + + return hr; +} + +HRESULT +UnRegisterSectionSchema( + IN CONST BOOL isSectionInAdminSchema, + IN CONST WCHAR * szSectionName + ) +{ + HRESULT hr = NOERROR; + + CComPtr pAdminMgr; + CComPtr pRootSectionGroup; + + CONST WCHAR * szCommitPath = NULL; + + WCHAR * szSectionNameCopy = _wcsdup( szSectionName ); + if( !szSectionNameCopy ) + { + hr = E_OUTOFMEMORY; + goto exit; + } + + // + // szSectionNameCopy is the full name of the section. The last + // segment szShortName will be registered as the name of the + // section and the other segments are section groups + // + // eg. "system.webServer/foo/bar/mysection" + // + + WCHAR * szShortName = wcsrchr( szSectionNameCopy, L'/' ); + if( szShortName == NULL ) + { + szShortName = szSectionNameCopy; + } + else + { + *szShortName++ = 0; + } + + hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( IAppHostWritableAdminManager ), + (VOID **)&pAdminMgr ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = InitializeAdminManager( isSectionInAdminSchema, + pAdminMgr, + &szCommitPath); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = RemoveSectionData( pAdminMgr, + szSectionName, + szCommitPath); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = GetRootSectionGroup( pAdminMgr, + szCommitPath, + &pRootSectionGroup ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = RemoveSectionDefinition( pRootSectionGroup, + (szShortName == szSectionNameCopy) ? NULL : szSectionNameCopy, + szShortName ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->CommitChanges(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + free( szSectionNameCopy ); + + return hr; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/secutils.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/secutils.cpp new file mode 100644 index 0000000000..8806cd667e --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/secutils.cpp @@ -0,0 +1,1125 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +#ifndef NT_SUCCESS +#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) +#endif + +#ifndef STATUS_SOME_NOT_MAPPED +// +// MessageId: STATUS_SOME_NOT_MAPPED +// +// MessageText: +// +// Some of the information to be translated has not been translated. +// +#define STATUS_SOME_NOT_MAPPED ((NTSTATUS)0x00000107L) +#endif + +#ifndef STATUS_NONE_MAPPED +#define STATUS_NONE_MAPPED ((NTSTATUS)0xc0000073L) +#endif + + +HRESULT +IsVistaOrGreater( + __out BOOL & fIsVistaOrGreater +) +/*++ + +Routine Description: + + Return TRUE if we are running in a Server SKU, + otherwise return FALSE. + +Arguments: + + pfIsServer - The return value. + +Return Value: + + BOOL + +--*/ +{ + HRESULT hr = S_OK; + OSVERSIONINFOEX osVersionInfoEx = { 0 }; + DWORDLONG dwlConditionMask = 0; + BOOL fReturn = FALSE; + + fIsVistaOrGreater = FALSE; + osVersionInfoEx.dwOSVersionInfoSize = sizeof( osVersionInfoEx ); + osVersionInfoEx.dwMajorVersion = 6; + + VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL ); + + fReturn = VerifyVersionInfo( + &osVersionInfoEx, + VER_MAJORVERSION, + dwlConditionMask ); + + // + // If the function fails, the return value is zero + // and GetLastError returns an error code other than ERROR_OLD_WIN_VERSION + // + if ( fReturn == FALSE && GetLastError() != ERROR_OLD_WIN_VERSION ) + { + hr = HRESULT_FROM_WIN32 ( GetLastError() ); + DBGERROR_HR( hr ); + goto Finished; + } + + fIsVistaOrGreater = ( fReturn ); + +Finished: + + return hr; + +} + +HRESULT +CreateDirectory( + __in LPCWSTR pszFileName +) +{ + HRESULT hr = S_OK; + DWORD dwFileAttributes = 0; + + dwFileAttributes = GetFileAttributes( pszFileName ); + if ( dwFileAttributes == INVALID_FILE_ATTRIBUTES ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + + if ( hr == HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) || + hr == HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) ) + { + hr = S_OK; + + // + // Create the folder. + // + if ( !CreateDirectory( pszFileName, NULL ) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR( hr ); + goto Finished; + } + } + else + { + DBGERROR_HR( hr ); + } + } + +Finished: + + return hr; +} + +HRESULT +AddExplicitAccessToFileDacl( + __in LPWSTR pszFilePath, + DWORD cExplicitAccess, + EXPLICIT_ACCESS rgExplicitAccess[] +) +/*++ + +Routine Description: + + Add EXPLICIT_ACCESS entries to a file DACL + +Arguments: + + pszFilePath - The path to the file where the DACL will be modified + cExplicitAccess - The count of EXPLICIT_ACCESS entires to add + rgExplicitAccess - The EXPLICIT_ACCESS entries + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + DWORD dwError = ERROR_SUCCESS; + PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL; + PACL pOldFileDacl = NULL; + PACL pNewFileDacl = NULL; + + if ( pszFilePath == NULL || + cExplicitAccess == 0 || + rgExplicitAccess == NULL ) + { + hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); + goto Finished; + } + + // + // Get the current file DACL + // + dwError = GetNamedSecurityInfo( pszFilePath, + SE_FILE_OBJECT, + DACL_SECURITY_INFORMATION, + NULL, // ppsidOwner + NULL, // ppsidGroup + &pOldFileDacl, + NULL, // ppSacl + &pSecurityDescriptor ); + if ( dwError != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32( dwError ); + goto Finished; + } + + // + // Create a new DACL with the EXPLICIT_ACCESS entries + // + + dwError = SetEntriesInAcl( cExplicitAccess, + rgExplicitAccess, + pOldFileDacl, + &pNewFileDacl ); + if ( dwError != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32( dwError ); + goto Finished; + } + + // + // Write the new DACL + // + + dwError = SetNamedSecurityInfo( pszFilePath, + SE_FILE_OBJECT, + DACL_SECURITY_INFORMATION, + NULL, // psidOwner + NULL, // psidGroup + pNewFileDacl, + NULL ); // pSacl + if ( dwError != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32( dwError ); + goto Finished; + } + +Finished: + + if ( pNewFileDacl != NULL ) + { + LocalFree( pNewFileDacl ); + pNewFileDacl = NULL; + } + + if ( pSecurityDescriptor != NULL ) + { + LocalFree( pSecurityDescriptor ); + pSecurityDescriptor = NULL; + } + + return hr; +} + +HRESULT +GrantFileAccessToIisIusrs( + __in LPWSTR pszFilePath, + DWORD dwAccessMask, + DWORD dwInheritance +) +/*++ + +Routine Description: + + This method gives the IIS_IUSRS group access to a specified file + path. In the case that this is executed on a domain controller, + this method will grant access explicitly to Local Service and + Network Service instead. + +Arguments: + + pszFilePath - The path where access is granted + dwAccessMask - Desired access to grant + dwInhertiance - Inheritance for access mask + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + DWORD cExplicitAccess = 1; + PSID pSidUserAccount = NULL; + DWORD cbUserAccount = 0; + EXPLICIT_ACCESS rgExplicitAccess[ 1 ]; + + if ( pszFilePath == NULL ) + { + hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); + goto Finished; + } + + // Zero out the struct + ZeroMemory( &(rgExplicitAccess[0]), sizeof( EXPLICIT_ACCESS ) ); + + // Get the SID for IIS_IUSRS + if ( CreateWellKnownSid( WinBuiltinIUsersSid, + NULL, // DomainSid + pSidUserAccount, + &cbUserAccount ) ) + { + // + // We are expecing a FALSE return value since we + // are obtaining required buffer sizes. + // + hr = HRESULT_FROM_WIN32( ERROR_INVALID_DATA ); + goto Finished; + } + + hr = HRESULT_FROM_WIN32( GetLastError() ); + if ( hr != HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) ) + { + goto Finished; + } + hr = S_OK; + + pSidUserAccount = (PSID) LocalAlloc( LPTR, cbUserAccount ); + if ( pSidUserAccount == NULL ) + { + hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY ); + goto Finished; + } + + if ( !CreateWellKnownSid( WinBuiltinIUsersSid, + NULL, // DomainSid + pSidUserAccount, + &cbUserAccount ) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Finished; + } + + // Build TRUSTEE with the IIS_IUSRS SID + BuildTrusteeWithSid( &(rgExplicitAccess[0].Trustee), pSidUserAccount ); + rgExplicitAccess[0].grfAccessPermissions = dwAccessMask; + rgExplicitAccess[0].grfAccessMode = GRANT_ACCESS; + rgExplicitAccess[0].grfInheritance = dwInheritance; + + // Add access to file DACL + hr = AddExplicitAccessToFileDacl( pszFilePath, + cExplicitAccess, + rgExplicitAccess ); + if ( FAILED( hr ) ) + { + goto Finished; + } + +Finished: + + return hr; +} + +HRESULT +GetStringSddlFromFile( + __in LPWSTR pszFileName, + __out STRU & strFileSddl, + __in BOOL fCreateIfDoesNotExist +) +/*++ + +Routine Description: + + Returns the DACL in the format SDDL for the + specified file or directory. + +Arguments: + + pszFileName - The file or directory path from to get the DACL. + strFileSddl - The file's security descriptor as string. + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + DWORD dwResult = ERROR_SUCCESS; + PACL pFileObjectAcl = NULL; + PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL; + LPWSTR pszSddl = NULL; + ULONG cchSddlLen = 0; + + if ( fCreateIfDoesNotExist ) + { + hr = CreateDirectory( pszFileName ); + if ( FAILED( hr ) ) + { + DBGERROR_HR( hr ); + goto Finished; + } + } + + dwResult = GetNamedSecurityInfo( + pszFileName, + SE_FILE_OBJECT, + DACL_SECURITY_INFORMATION, + NULL, + NULL, + &pFileObjectAcl, + NULL, + &pSecurityDescriptor ); + if ( dwResult != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32( dwResult ); + DBGERROR_HR( hr ); + goto Finished; + } + + if ( ! ConvertSecurityDescriptorToStringSecurityDescriptor( + pSecurityDescriptor, + SDDL_REVISION_1, + DACL_SECURITY_INFORMATION, + &pszSddl, + &cchSddlLen ) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR( hr ); + goto Finished; + } + + hr = strFileSddl.Copy( pszSddl ); + if ( FAILED( hr ) ) + { + goto Finished; + } + +Finished: + + if ( pSecurityDescriptor != NULL ) + { + LocalFree( pSecurityDescriptor ); + pSecurityDescriptor = NULL; + } + + if ( pszSddl != NULL ) + { + LocalFree( pszSddl ); + pszSddl = NULL; + } + + return hr; +} + +VOID +FreeStringSids( + __in DWORD cStringSids, + __in_bcount(cStringSids) LPWSTR rgszStringSids[] +) +/*++ + +Routine Description: + + Frees the memory allocated by ConvertAccountNamesToStringSids. + +Arguments: + + cStringSids - The number of string in the array rgszStringSids. + rgszStringSids - An array of SIDs represented as string. + +Return Value: + + HRESULT + +--*/ +{ + if ( rgszStringSids == NULL ) + { + return; + } + + for ( DWORD dwIndex = 0; dwIndex < cStringSids; dwIndex ++ ) + { + LocalFree( rgszStringSids [ dwIndex ] ); + } + + LocalFree ( rgszStringSids ); +} + +HRESULT +ConvertAccountNamesToStringSids ( + __in DWORD dwNameCount, + __in_ecount(dwNameCount) LPWSTR rgszNames[], + __deref_out_ecount(*pcStringSids) LPWSTR** StringSids, + __out DWORD* pcStringSids +) +/*++ + +Routine Description: + + Converts a list of local users or groups to string SIDs. + The StringSids array must be freed via the FreeStringSids function + +Arguments: + + dwNameCount - Number of names to convert. + + rgszNames - Array of pointers to Domain\Member strings + + StringSids - Returns a pointer to an array of pointers to String SIDs. + The array should be freed via FreeStringSids. + + pcStringSids - The number of String SIDs translated. + +Return Value: + + HRESULT + +--*/ +{ + HRESULT hr = S_OK; + NTSTATUS ntStatus = ERROR_SUCCESS; + LSA_HANDLE hPolicy = NULL; + LSA_OBJECT_ATTRIBUTES ObjectAttributes = {0}; + PUNICODE_STRING pUnicodeNames = NULL; + PLSA_REFERENCED_DOMAIN_LIST pReferencedDomainList = NULL; + PLSA_TRANSLATED_SID2 pTranslatedSid = NULL; + SIZE_T cchLength = 0; + LPWSTR * rgszStringSids = NULL; + DWORD cStringSids = 0; + DWORD dwStringIndex = 0; + + HMODULE hModule = NULL; + + typedef NTSTATUS + (NTAPI * PFN_LSALOOKUPNAMES2) ( + __in LSA_HANDLE PolicyHandle, + __in ULONG Flags, // Reserved + __in ULONG Count, + __in PLSA_UNICODE_STRING Names, + __out PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains, + __out PLSA_TRANSLATED_SID2 *Sids + ); + + PFN_LSALOOKUPNAMES2 pfn = NULL; + + hModule = LoadLibrary( L"Advapi32.dll" ); + if ( hModule == NULL ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR( hr ); + goto Finished; + } + + pfn = ( PFN_LSALOOKUPNAMES2 ) GetProcAddress( hModule, "LsaLookupNames2" ); + if ( pfn == NULL ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR( hr ); + if ( hr == HRESULT_FROM_WIN32( ERROR_PROC_NOT_FOUND ) ) + { + // + // This must be an OS before Windows 2003. + // + hr = S_OK; + } + goto Finished; + } + + // + // Open the local LSA database + // + ntStatus = LsaOpenPolicy( NULL, // Open the local policy + &ObjectAttributes, + POLICY_LOOKUP_NAMES, + &hPolicy ) ; + + if ( !NT_SUCCESS( ntStatus ) ) + { + hr = HRESULT_FROM_NT( ntStatus ); + DBGERROR_HR( hr ); + goto Finished; + } + + // + // Convert the names to unicode strings + // + pUnicodeNames = (PUNICODE_STRING) LocalAlloc( + LMEM_FIXED, + sizeof(UNICODE_STRING) * dwNameCount ); + + if ( pUnicodeNames == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto Finished; + } + + for ( DWORD dwIndex = 0; dwIndex < dwNameCount; dwIndex++ ) + { + cchLength = wcslen( rgszNames[dwIndex] ) * sizeof( *rgszNames[dwIndex] ); + if ( ( cchLength + sizeof( UNICODE_NULL ) ) > USHRT_MAX ) + { + hr = HRESULT_FROM_WIN32 ( ERROR_ARITHMETIC_OVERFLOW ); + goto Finished; + } + + pUnicodeNames[dwIndex].Buffer = rgszNames[dwIndex]; + pUnicodeNames[dwIndex].Length = ( USHORT ) cchLength; + pUnicodeNames[dwIndex].MaximumLength = ( USHORT ) ( cchLength + sizeof( UNICODE_NULL ) ); + } + + // + // Convert the names to sids + // + ntStatus = (*pfn) ( hPolicy, + 0, // Flags + dwNameCount, + pUnicodeNames, + &pReferencedDomainList, + &pTranslatedSid ); + + if ( !NT_SUCCESS( ntStatus ) ) + { + hr = HRESULT_FROM_WIN32( ntStatus ); + DBGERROR_HR( hr ); + goto Finished; + } + + // + // Some of the names could not be translated. + // This is an informational-level return value. + // + if ( ntStatus == STATUS_SOME_NOT_MAPPED ) + { + hr = HRESULT_FROM_WIN32( ntStatus ); + DBGERROR_HR( hr ); + hr = S_OK; + } + + // + // Count the number of SIDs retrieved + // + for ( DWORD dwIndex = 0; dwIndex < dwNameCount; dwIndex++ ) + { + if ( pTranslatedSid[dwIndex].Sid != NULL ) + { + cStringSids ++; + } + } + + // + // Allocate the SID list to return + // + rgszStringSids = (LPWSTR *) LocalAlloc( + LMEM_FIXED, + sizeof( LPWSTR ) * cStringSids ); + + if ( rgszStringSids == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR( hr ); + goto Finished; + } + + // + // Construct a string SID for each name + // + dwStringIndex = 0; + for ( DWORD dwIndex = 0; dwIndex < dwNameCount; dwIndex++ ) + { + if ( pTranslatedSid[dwIndex].Sid != NULL ) + { + if ( ! ConvertSidToStringSid( + pTranslatedSid [dwIndex].Sid, + &rgszStringSids [dwStringIndex] ) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR( hr ); + goto Finished; + } + dwStringIndex ++; + } + } + +Finished: + + if ( pUnicodeNames != NULL ) + { + LocalFree( pUnicodeNames ); + pUnicodeNames = NULL; + } + + if ( pReferencedDomainList != NULL ) + { + LsaFreeMemory( pReferencedDomainList ); + pReferencedDomainList = NULL; + } + + if ( pTranslatedSid != NULL ) + { + LsaFreeMemory( pTranslatedSid ); + pTranslatedSid = NULL; + } + + if ( hPolicy != NULL ) + { + LsaClose( hPolicy ); + hPolicy = NULL; + } + + // + // If the translation wasn't successful, + // free any partial translation. + // + + if ( FAILED( hr ) ) + { + if ( rgszStringSids != NULL ) + { + FreeStringSids( cStringSids, rgszStringSids ); + rgszStringSids = NULL; + } + } + + // + // Assign the output parameters + // + (*StringSids) = rgszStringSids; + (*pcStringSids) = cStringSids; + + if ( hModule != NULL ) + { + FreeLibrary( hModule ); + hModule = NULL; + } + + return hr; +} + +HRESULT +SetFileSddl( + __in LPCWSTR pszSddl, + __in LPWSTR pszPath +) +{ + HRESULT hr = S_OK; + SECURITY_ATTRIBUTES sa = { 0 }; + DWORD status = 0; + BOOL fIsVistaOrGreater = FALSE; + + sa.nLength = sizeof( sa ); + sa.bInheritHandle = FALSE; + if ( ! ConvertStringSecurityDescriptorToSecurityDescriptor( + pszSddl, + SDDL_REVISION_1, + &sa.lpSecurityDescriptor, + NULL)) + { + hr = HRESULT_FROM_WIN32 ( GetLastError() ); + DBGERROR_HR( hr ); + goto Finished; + } + + hr = IsVistaOrGreater ( fIsVistaOrGreater ); + if ( FAILED(hr) ) + { + fIsVistaOrGreater = FALSE; + hr = S_OK; + } + + if ( fIsVistaOrGreater ) + { + status = SetNamedSecurityInfo( pszPath, + SE_FILE_OBJECT, + DACL_SECURITY_INFORMATION, + NULL, + NULL, + (PACL) sa.lpSecurityDescriptor, + NULL ); + if ( status != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32 (status ); + DBGERROR_HR( hr ); + goto Finished; + } + } + else + { + if ( ! SetFileSecurity( pszPath, + DACL_SECURITY_INFORMATION, + (PSECURITY_DESCRIPTOR) sa.lpSecurityDescriptor ) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR( hr ); + goto Finished; + } + } + + +Finished: + + if ( sa.lpSecurityDescriptor != NULL ) + { + LocalFree( sa.lpSecurityDescriptor ); + sa.lpSecurityDescriptor = NULL; + } + + return hr; +} + +HRESULT +GetIISWPGSid( + __out STRU & strIISWPGSid +) +{ + HRESULT hr = S_OK; + LPWSTR* ppszStringSids = NULL; + DWORD cStringSids = 0; + + LPWSTR rgszIisAccountsToResolve [] = { L"IIS_WPG" }; + + hr = ConvertAccountNamesToStringSids( _countof( rgszIisAccountsToResolve ), + rgszIisAccountsToResolve, + &ppszStringSids, + &cStringSids ); + if ( FAILED( hr ) ) + { + DBGERROR_HR( hr ); + goto Finished; + } + + if ( cStringSids < 1 ) + { + hr = E_INVALIDARG; + goto Finished; + } + + hr = strIISWPGSid.Copy( ppszStringSids[0] ); + if ( FAILED( hr ) ) + { + goto Finished; + } + +Finished: + + if ( ppszStringSids != NULL ) + { + FreeStringSids( cStringSids, ppszStringSids ); + ppszStringSids = NULL; + } + + return hr; +} + +ULONG +GetRealAclSize( + __in PACL Acl + ) +/*++ + +Routine Description: + + Walks the sids in an ACL to determine it's minimum size + +Arguments: + + Acl - Acl to scan + +Return Value: + + Byte count + +--*/ +{ + PACE_HEADER Ace = FirstAce( Acl ); + int i = 0; + while (i < Acl->AceCount ) { + i++; + Ace = NextAce( Ace ); + } + + return (ULONG) ((PBYTE) Ace - (PBYTE) Acl); + +} + +HRESULT +MakeAutoInheritFromParent( + __in LPWSTR pszPath +) +{ + HRESULT hr = S_OK; + DWORD dwError; + PACL Acl; + PACE_HEADER Ace; + PSECURITY_DESCRIPTOR pSecurityDescriptor; + SECURITY_INFORMATION SecurityInfo = DACL_SECURITY_INFORMATION; + + // + // Get the current file DACL + // + dwError = GetNamedSecurityInfo( pszPath, + SE_FILE_OBJECT, + SecurityInfo, + NULL, + NULL, + &Acl, + NULL, + &pSecurityDescriptor ); + if ( dwError != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32( dwError ); + DBGERROR_HR( hr ); + goto Finished; + } + + // + // Remove all the ACEs + // + Ace = FirstAce( Acl ); + int i = 0; + while ( i < Acl->AceCount ) + { + // + // The Ace was not inherited + // + if( (Ace->AceFlags & INHERITED_ACE) == 0 ) + { + if (!DeleteAce( Acl, i )) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR( hr ); + goto Finished; + } + } + else + { + i++; + Ace = NextAce( Ace ); + } + } + Acl->AclSize = (WORD) GetRealAclSize( Acl ); + + // + // Auto-inherit + // + SecurityInfo |= UNPROTECTED_DACL_SECURITY_INFORMATION; + + dwError = SetNamedSecurityInfo( pszPath, + SE_FILE_OBJECT, + SecurityInfo, + NULL, + NULL, + Acl, + NULL ); + if ( dwError != ERROR_SUCCESS ) + { + hr = HRESULT_FROM_WIN32( dwError ); + DBGERROR_HR( hr ); + goto Finished; + } + +Finished: + + if ( pSecurityDescriptor != NULL ) + { + LocalFree( pSecurityDescriptor ); + pSecurityDescriptor = NULL; + } + + return hr; +} + +HRESULT +GrantIISWPGReadWritePermissions( + __in LPWSTR pszPath +) +{ + HRESULT hr = S_OK; + STACK_STRU( strAces, 128 ); + STACK_STRU( strFileSddl, 128 ); + STACK_STRU( strFileSddlTemp, 128 ); + STACK_STRU( strIISWPGSid, 32 ); + + hr = GetStringSddlFromFile( pszPath, + strFileSddlTemp ); + if ( FAILED( hr ) ) + { + DBGERROR_HR( hr ); + goto Finished; + } + + hr = GetIISWPGSid( strIISWPGSid ); + if ( FAILED( hr ) ) + { + DBGERROR_HR( hr ); + if ( hr == STATUS_NONE_MAPPED ) + { + // + // No maps found. + // + hr = S_OK; + } + goto Finished; + } + + // + // Add Read/Write permissions. + // + hr = strAces.Copy( L"(A;OICI;0x12019f;;;" ); + if ( FAILED( hr ) ) + { + goto Finished; + } + + hr = strAces.Append( strIISWPGSid ); + if ( FAILED( hr ) ) + { + goto Finished; + } + + hr = strAces.Append( L")", 1 ); + if ( FAILED( hr ) ) + { + goto Finished; + } + + // + // Insert the ACE before any other ACE. + // + + // + // Search for the first ACE '(' + // + LPCWSTR psz = wcschr( strFileSddlTemp.QueryStr(), SDDL_ACE_BEGINC ); + + // + // Copy the first part before the first '(' + // + hr = strFileSddl.Append( strFileSddlTemp.QueryStr(), + (DWORD)(psz - strFileSddlTemp.QueryStr()) ); + if ( FAILED( hr ) ) + { + DBGERROR_HR( hr ); + goto Finished; + } + + // + // Copy the new ACE + // + hr = strFileSddl.Append( strAces ); + if ( FAILED( hr ) ) + { + DBGERROR_HR( hr ); + goto Finished; + } + + // + // Copy the other ACEs. + // + hr = strFileSddl.Append( psz ); + if ( FAILED( hr ) ) + { + DBGERROR_HR( hr ); + goto Finished; + } + + hr = SetFileSddl( strFileSddl.QueryStr(), + pszPath ); + if ( FAILED( hr ) ) + { + DBGERROR_HR( hr ); + goto Finished; + } + +Finished: + + return hr; +} + +HRESULT +SetupAclsWow64( + LPCWSTR pwszPath +) +{ + HRESULT hr = S_OK; + HMODULE hModule = NULL; + STACK_STRU( strPath, MAX_PATH ); + + typedef UINT + (WINAPI *PFN_GETSYSTEMWOW64DIRECTORY) + ( + __out LPTSTR lpBuffer, + __in UINT uSize + ); + + PFN_GETSYSTEMWOW64DIRECTORY pfn; + + hModule = LoadLibrary( L"kernel32.dll" ); + if ( hModule == NULL ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR( hr ); + goto Finished; + } + pfn = ( PFN_GETSYSTEMWOW64DIRECTORY ) GetProcAddress( hModule, "GetSystemWow64DirectoryW" ); + if ( pfn == NULL ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + DBGERROR_HR( hr ); + if ( hr == HRESULT_FROM_WIN32( ERROR_PROC_NOT_FOUND ) ) + { + // + // This must be an OS before Windows 2003. + // + hr = S_OK; + } + goto Finished; + } + + if ( ! (*pfn)( strPath.QueryStr(), + strPath.QuerySizeCCH() ) ) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + if ( hr == HRESULT_FROM_WIN32( ERROR_CALL_NOT_IMPLEMENTED ) ) + { + // + // This is not Win64. + // + hr = S_OK; + } + else + { + DBGERROR_HR( hr ); + } + goto Finished; + } + strPath.SyncWithBuffer(); + + if (pwszPath != NULL) + { + hr = strPath.Append( pwszPath ); + if ( FAILED( hr ) ) + { + goto Finished; + } + } + + hr = MakeAutoInheritFromParent( strPath.QueryStr() ); + if ( FAILED( hr ) ) + { + DBGERROR_HR( hr ); + goto Finished; + } + +Finished: + + if ( hModule != NULL ) + { + FreeLibrary( hModule ); + hModule = NULL; + } + + return hr; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/secutils.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/secutils.h new file mode 100644 index 0000000000..416ffd369c --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/secutils.h @@ -0,0 +1,98 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +HRESULT +IsVistaOrGreater( + __out BOOL & fIsVistaOrGreater +); + +HRESULT +CreateDirectory( + __in LPCWSTR pszFileName +); + +HRESULT +AddExplicitAccessToFileDacl( + __in LPWSTR pszFilePath, + DWORD cExplicitAccess, + EXPLICIT_ACCESS rgExplicitAccess[] +); + +HRESULT +GrantFileAccessToIisIusrs( + __in LPWSTR pszFilePath, + DWORD dwAccessMask, + DWORD dwInheritance +); + +HRESULT +GetStringSddlFromFile( + __in LPWSTR pszFileName, + __out STRU & strFileSddl, + __in BOOL fCreateIfDoesNotExist = TRUE +); + +VOID +FreeStringSids( + __in DWORD cStringSids, + __in_bcount(cStringSids) LPWSTR rgszStringSids[] +); + +HRESULT +ConvertAccountNamesToStringSids ( + __in DWORD dwNameCount, + __in_ecount(dwNameCount) LPWSTR rgszNames[], + __deref_out_ecount(*pcStringSids) LPWSTR** StringSids, + __out DWORD* pcStringSids +); + +HRESULT +SetFileSddl( + __in LPCWSTR pszSddl, + __in LPWSTR pszPath +); + +HRESULT +GetIISWPGSid( + __out STRU & strIISWPGSid +); + +inline PACE_HEADER +FirstAce( __in PACL Acl ) +{ + return (PACE_HEADER)(((PBYTE)Acl) + sizeof( ACL )); +} + +inline PACE_HEADER +NextAce( __in PACE_HEADER Ace ) +{ + return (PACE_HEADER)(((PBYTE)Ace) + Ace->AceSize ); +} + +inline PSID +SidFromAce( __in PACE_HEADER Ace ) +{ + return (PSID)&((PACCESS_ALLOWED_ACE)Ace)->SidStart; +} + +ULONG +GetRealAclSize( + __in PACL Acl +); + + +HRESULT +MakeAutoInheritFromParent( + __in LPWSTR pszPath +); + +HRESULT +GrantIISWPGReadWritePermissions( + __in LPWSTR pszPath +); + +HRESULT +SetupAclsWow64( + LPCWSTR pwszPath +); + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/setup_log.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/setup_log.cpp new file mode 100644 index 0000000000..86a8857096 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/setup_log.cpp @@ -0,0 +1,423 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" +#include "ntassert.h" +// +// SETUP_LOG class, used only by MsiLogXXX functions not used directly by CA code +// +class SETUP_LOG +{ + +public: + + SETUP_LOG( + VOID + ) + { + _severityThreshold = SETUP_LOG_SEVERITY_INFORMATION; + } + + ~SETUP_LOG( + VOID + ) + { + } + + VOID + Initialize( + IN MSIHANDLE hInstall, + IN LPCWSTR pszCAName + ); + + VOID + Close( + VOID + ); + + VOID + Write( + IN CONST SETUP_LOG_SEVERITY setupLogSeverity, + IN LPCWSTR pszLogMessageFormat + ); + +private: + + MSIHANDLE _hInstall; + SETUP_LOG_SEVERITY _severityThreshold; + STRU _strSCANamePrefix; + +private: + HRESULT + WriteMSIMessage( + IN STRU * pstrLogMessage + ); + + HRESULT + SETUP_LOG::FmtCAName( + IN STRU * pstrFmtCAName + ); +}; + + +VOID +SETUP_LOG::Initialize( + IN MSIHANDLE hInstall, + IN LPCWSTR pszCAName + ) +/*++ + +Routine Description: + + Initialization. Opens handle to the log file and writes a message. + +Return Value: + + HRESULT + +--*/ +{ + STACK_STRU ( strMsiRegKey, 64 ); + STACK_STRU ( strStartLogMessage, MAX_PATH ); + STACK_STRU ( strMsiLoggingValue, 32 ); + DWORD dwBufLen = strMsiRegKey.QuerySizeCCH(); + DWORD status = ERROR_SUCCESS; + HKEY hKey = NULL; + + //for checking logging level + WORD i; + + // + //Set MSI handle & CA name + // + + _hInstall = hInstall; + + // + //Prefix message with CAname + // + _strSCANamePrefix.Copy( L"IISCA " ); + _strSCANamePrefix.Append( pszCAName ); + _strSCANamePrefix.Append( L" : " ); + + // + //test MsiLogging property MSI 4.0+ + // + + (VOID) MsiUtilGetProperty( hInstall, L"MsiLogging", &strMsiLoggingValue ); + + if( !strMsiLoggingValue.IsEmpty() ) + { + WCHAR * szValueBuf = strMsiLoggingValue.QueryStr(); + if( wcschr( szValueBuf, L'v' ) || wcschr( szValueBuf, L'V' ) ) + { + _severityThreshold = SETUP_LOG_SEVERITY_DEBUG ; + } + } + + if ( _severityThreshold != SETUP_LOG_SEVERITY_DEBUG ) + { + // + // Last chance - check Logging Registry Key/value + // + + status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Policies\\Microsoft\\Windows\\Installer", + 0, + KEY_QUERY_VALUE, + &hKey ); + + if ( status == ERROR_SUCCESS ) + { + status = RegQueryValueEx( hKey, + L"Logging", + NULL, + NULL, + (LPBYTE) strMsiRegKey.QueryStr(), + &dwBufLen); + + strMsiRegKey.SyncWithBuffer( ); + } + + if ( !( status != ERROR_SUCCESS ) || ( dwBufLen > strMsiRegKey.QuerySizeCCH() ) ) + { + // + //Have Logging key Value.. we will log something + // + // Check logging flags for verbosity 'v' + // + for ( i = 0; i < strMsiRegKey.QueryCCH() ; i++ ) + { + if ( strMsiRegKey.QueryStr()[ i ] == L'V' || strMsiRegKey.QueryStr()[ i ] == L'v' ) + { + _severityThreshold = SETUP_LOG_SEVERITY_DEBUG ; + break; + } + } + } + } + + // + // write the start message, prifix message with CAname + // + strStartLogMessage.Append( _strSCANamePrefix.QueryStr() ); + + strStartLogMessage.Append( L"Begin CA Setup" ); + + // + // write the message + // + + WriteMSIMessage( &strStartLogMessage ); + + + if ( hKey != NULL ) + { + RegCloseKey( hKey ); + hKey = NULL; + } + + return; +} + +VOID +SETUP_LOG::Close( + VOID + ) + +{ + STACK_STRU ( strEndLogMessage, MAX_PATH ); + + strEndLogMessage.Append( _strSCANamePrefix.QueryStr() ); + strEndLogMessage.Append( L"End CA Setup" ); + + // + // write the message + // + + WriteMSIMessage( &strEndLogMessage); + + return; +} + +VOID +SETUP_LOG::Write( + IN SETUP_LOG_SEVERITY setupLogSeverity, + IN LPCWSTR pszLogMessage + ) +/*++ + +Routine Description: + + Write a formatted message to the log file. Note that the message + will not be written to the log file if the severity is below that + of the current threshold. + +Arguments: + + setupLogSeverity - Severity of the message + pszLogMessageFormat - Format of the log message + +--*/ +{ + STACK_STRU ( struLogMessage, MAX_PATH ); + + DBG_ASSERT( pszLogMessage); + + if ( pszLogMessage == NULL ) + { + goto Exit; + } + + // + // If this message does not have high enough severity, we are done. + // + if ( setupLogSeverity < _severityThreshold ) + { + goto Exit; + } + + // + //Prefix message with CAname + // + + struLogMessage.Append( _strSCANamePrefix.QueryStr() ); + + // + // Prefix the high severity messages so we can easily spot errors. + // + + if ( setupLogSeverity == SETUP_LOG_SEVERITY_WARNING ) + { + struLogMessage.Append( L"< WARNING! > " ); + } + else if ( setupLogSeverity == SETUP_LOG_SEVERITY_ERROR ) + { + struLogMessage.Append( L"< !!ERROR!! > " ); + } + + struLogMessage.Append( pszLogMessage ); + + // + // Write to the log file + // + + WriteMSIMessage( &struLogMessage ); + +Exit: + + return; +} + +HRESULT +SETUP_LOG::WriteMSIMessage( + STRU * pstrLogMessage + ) + +{ + HRESULT hr = S_OK; + PMSIHANDLE msiRow; + UINT status = 0; + // + // get an MSI record + // + + //consider passing a parameterized string here + msiRow = MsiCreateRecord( 1 ); + if ( msiRow == NULL ) + { + hr = E_UNEXPECTED; + DBGERROR_HR(hr); + goto Exit; + } + + // + // put message in msi record + // + + status = MsiRecordSetStringW( msiRow, 1, (LPCWSTR)pstrLogMessage->QueryStr() ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto Exit; + } + + // + // send message to MSI log file + // + + status = MsiProcessMessage( _hInstall, INSTALLMESSAGE_INFO, msiRow ); + if ( ERROR_SUCCESS != status ) + { + hr = HRESULT_FROM_WIN32( status ); + DBGERROR_HR(hr); + goto Exit; + } + +Exit: + + return hr; +} + +// +//Use static global instance of SETUP_LOG class +// +static SETUP_LOG * g_pSetupLog = NULL; + +// +//MSI Log safe functions, used directly by CA code +// +VOID +IISLogInitialize( + IN MSIHANDLE hInstall, + IN LPCWSTR pszCAName + ) +{ + HRESULT hr = S_OK; + + //debug assert that it is always null. becaues previous custom action should have cleaned it up + DBG_ASSERT( g_pSetupLog == NULL ); + + if ( g_pSetupLog == NULL ) + { + g_pSetupLog = new SETUP_LOG(); + if ( g_pSetupLog == NULL ) + { + hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY ); + DBGERROR_HR(hr); + goto Exit; + } + } + + // + // init + // + + g_pSetupLog->Initialize( hInstall, pszCAName ); + +Exit: + return; +} + + +VOID +IISLogClose( + VOID + ) +{ + if ( !g_pSetupLog ) + { + goto Exit; + } + + // + // do the call + // + + g_pSetupLog->Close(); + + // + //Done with SETUP_LOG instance + // + + delete g_pSetupLog; + g_pSetupLog = NULL; + +Exit: + + return ; +} + + +VOID +IISLogWrite( + IN SETUP_LOG_SEVERITY setupLogSeverity, + IN LPCWSTR pszLogMessageFormat, + ... + ) +{ + va_list argsList; + va_start ( argsList, pszLogMessageFormat ); + + STACK_STRU ( struLogMessage, 128 ); + //debug assert that it is not null + DBG_ASSERT( g_pSetupLog ); + + if ( !g_pSetupLog ) + { + goto Exit; + } + + // + // Form struLogMessage so that we can write a single string + // + + struLogMessage.SafeVsnwprintf( pszLogMessageFormat, argsList ); + + g_pSetupLog->Write( setupLogSeverity, struLogMessage.QueryStr() ); + +Exit: + va_end ( argsList ); + return; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/setup_log.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/setup_log.h new file mode 100644 index 0000000000..848fe4d0a3 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/setup_log.h @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#ifndef _SETUP_LOG_H_ +#define _SETUP_LOG_H_ + + +// +// Severity levels for setup log information. This is arranged in the +// order of increasing severity. +// +enum SETUP_LOG_SEVERITY +{ + SETUP_LOG_SEVERITY_DEBUG, + SETUP_LOG_SEVERITY_INFORMATION, + SETUP_LOG_SEVERITY_WARNING, + SETUP_LOG_SEVERITY_ERROR +}; + +//consider using an IIS prefix for Msi* methods - they conflict with MSI apis + +// +// Initalize logging once at begining of CA +// + +VOID +IISLogInitialize( + IN MSIHANDLE hInstall, + IN LPCWSTR pszCAName + ); + +// +// Close logging at end / exit of CA +// + +VOID +IISLogClose( + VOID + ); + +// +// Writes a message to msi log file +// +VOID +IISLogWrite( + IN SETUP_LOG_SEVERITY setupLogSeverity, + IN LPCWSTR pszLogMessageFormat, + ... + ); + +#endif + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/tracing.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/tracing.cpp new file mode 100644 index 0000000000..a7e051b92e --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/tracing.cpp @@ -0,0 +1,343 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +HRESULT +RegisterTraceArea( + IN CONST WCHAR * szTraceProviderName, + IN CONST WCHAR * szTraceProviderGuid, + IN CONST WCHAR * szAreaName, + IN CONST WCHAR * szAreaValue +) +{ + HRESULT hr = NOERROR; + CComPtr pAdminMgr; + CComPtr pTraceProviderSection; + CComPtr pTraceProvidersCollection; + CComPtr pTraceProvider; + CComPtr pAreasElement; + CComPtr pAreasCollection; + CComPtr pAreaElement; + + BSTR bstrAppHostConfigPath = SysAllocString( L"MACHINE/WEBROOT/APPHOST" ); + BSTR bstrTracingSection = SysAllocString( L"system.webServer/tracing/traceProviderDefinitions" ); + BSTR bstrAreas = SysAllocString( L"areas" ); + + NAME_VALUE_PAIR ProviderProperties[] = + { + { L"name", CComVariant( szTraceProviderName )}, + { L"guid", CComVariant( szTraceProviderGuid )} + }; + + NAME_VALUE_PAIR AreaProperties[] = + { + { L"name", CComVariant( szAreaName )}, + { L"value", CComVariant( szAreaValue )} + }; + + if ( bstrAppHostConfigPath == NULL || + bstrTracingSection == NULL || + bstrAreas == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( IAppHostWritableAdminManager ), + (VOID **)&pAdminMgr ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->GetAdminSection( bstrTracingSection, + bstrAppHostConfigPath, + &pTraceProviderSection ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pTraceProviderSection->get_Collection( &pTraceProvidersCollection ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = GetElementFromCollection( pTraceProvidersCollection, + L"name", + szTraceProviderName, + &pTraceProvider ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Create the trace provider if it doesn't exist. + // + if ( hr == S_FALSE ) + { + hr = AddElementToCollection( pTraceProvidersCollection, + L"add", + ProviderProperties, + _countof( ProviderProperties ), + &pTraceProvider ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + hr = pTraceProvider->GetElementByName( bstrAreas, + &pAreasElement ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pAreasElement->get_Collection( &pAreasCollection ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = GetElementFromCollection( pAreasCollection, + L"name", + szAreaName, + &pAreaElement ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + // + // Add the trace area if it doesn't exist. + // + if ( hr != S_FALSE ) + { + hr = S_OK; + goto exit; + } + + hr = AddElementToCollection( pAreasCollection, + L"add", + AreaProperties, + _countof( AreaProperties ), + NULL ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->CommitChanges(); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + SysFreeString( bstrAppHostConfigPath ); + SysFreeString( bstrTracingSection ); + SysFreeString( bstrAreas ); + + return hr; +} + +HRESULT +AddElementToCollection( + IN IAppHostElementCollection * pCollection, + IN CONST WCHAR * pElementName, + IN NAME_VALUE_PAIR rgProperties[], + IN DWORD cProperties, + OUT IAppHostElement ** ppElement +) +{ + HRESULT hr = NOERROR; + CComPtr pElement; + CComPtr pProperty; + + BSTR bstrName = NULL; + BSTR bstrElementName = SysAllocString( pElementName ); + + if ( bstrElementName == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pCollection->CreateNewElement( bstrElementName, + &pElement ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + for ( DWORD Index = 0; Index < cProperties; Index ++ ) + { + bstrName = SysAllocString( rgProperties[Index].Name ); + if ( bstrName == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pElement->GetPropertyByName( bstrName, + &pProperty ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( rgProperties[Index].Value.vt == VT_ERROR ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pProperty->put_Value( rgProperties[Index].Value ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + SysFreeString( bstrName ); + pProperty.Detach()->Release(); + } + + hr = pCollection->AddElement( pElement ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if ( ppElement != NULL ) + { + *ppElement = pElement.Detach(); + } + +exit: + + SysFreeString( bstrElementName ); + SysFreeString( bstrName ); + + return hr; +} + +HRESULT +GetElementFromCollection( + IN IAppHostElementCollection * pCollection, + IN CONST WCHAR * szIndex, + IN CONST WCHAR * szExpectedPropertyValue, + OUT IAppHostElement ** ppElement, + OUT DWORD * pIndex +) +{ + HRESULT hr = NOERROR; + DWORD dwElementCount = 0; + CComPtr pElement; + CComPtr pProperty; + + BSTR bstrPropertyName = SysAllocString( szIndex ); + + if ( bstrPropertyName == NULL ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pCollection->get_Count( &dwElementCount ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + for ( DWORD Index = 0; Index < dwElementCount; Index ++ ) + { + CComVariant value; + + hr = pCollection->get_Item( CComVariant( Index ), + &pElement ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pElement->GetPropertyByName( bstrPropertyName, + &pProperty ); + if ( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pProperty->get_Value( &value ); + if ( value.vt == VT_ERROR ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + if ( value.vt != VT_BSTR ) + { + hr = HRESULT_FROM_WIN32( ERROR_INVALID_DATA ); + DBGERROR_HR(hr); + goto exit; + } + + if ( _wcsicmp( value.bstrVal, szExpectedPropertyValue ) == 0 ) + { + // + // Element found. + // + *ppElement = pElement.Detach(); + if ( pIndex != NULL ) + { + *pIndex = Index; + } + hr = S_OK; + goto exit; + } + + pProperty.Detach()->Release(); + pElement.Detach()->Release(); + } + + // + // Element not found. + // + hr = S_FALSE; + +exit: + + SysFreeString( bstrPropertyName ); + + return hr; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/tracing.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/tracing.h new file mode 100644 index 0000000000..087e8ded74 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/tracing.h @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +HRESULT +RegisterTraceArea( + IN CONST WCHAR * szTraceProviderName, + IN CONST WCHAR * szTraceProviderGuid, + IN CONST WCHAR * szAreaName, + IN CONST WCHAR * szAreaValue +); + +HRESULT +GetElementFromCollection( + IN IAppHostElementCollection * pCollection, + IN CONST WCHAR * szPropertyName, + IN CONST WCHAR * szExpectedPropertyValue, + OUT IAppHostElement ** ppElement, + OUT DWORD * pIndex = NULL +); + +struct NAME_VALUE_PAIR +{ + LPCWSTR Name; + CComVariant Value; +}; + +HRESULT +AddElementToCollection( + IN IAppHostElementCollection * pCollection, + IN CONST WCHAR * pElementName, + IN NAME_VALUE_PAIR rgProperties[], + IN DWORD cProperties, + OUT IAppHostElement ** ppElement +); diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/uimodule.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/uimodule.cpp new file mode 100644 index 0000000000..76adb89ca6 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/uimodule.cpp @@ -0,0 +1,637 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#include "precomp.h" + +class ADMINISTRATION_CONFIG_PATH_MAPPER : public IAppHostPathMapper +{ + +public: + + ADMINISTRATION_CONFIG_PATH_MAPPER( + VOID + ) : _cRefs( 1 ) + { + } + + ~ADMINISTRATION_CONFIG_PATH_MAPPER( + VOID + ) + { + } + + HRESULT + Initialize() + { + // TODO this could be more reliable. + HRESULT hr = NOERROR; + DWORD cch; + + cch = ExpandEnvironmentStringsW( + L"%windir%\\system32\\inetsrv\\config\\administration.config", + _strMappedPath.QueryStr(), + _strMappedPath.QuerySizeCCH() + ); + if( !cch ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + goto exit; + } + + if( cch > _strMappedPath.QuerySizeCCH() ) + { + hr = _strMappedPath.Resize( cch ); + if( FAILED(hr) ) + { + goto exit; + } + + cch = ExpandEnvironmentStringsW( + L"%windir%\\system32\\inetsrv\\config\\administration.config", + _strMappedPath.QueryStr(), + _strMappedPath.QuerySizeCCH() + ); + if( !cch || + cch > _strMappedPath.QuerySizeCCH() ) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + goto exit; + } + } + + _strMappedPath.SyncWithBuffer(); + + exit: + + return hr; + + } + + ULONG + STDMETHODCALLTYPE + AddRef( + VOID + ) + { + return InterlockedIncrement( &_cRefs ); + } + + ULONG + STDMETHODCALLTYPE + Release( + VOID + ) + { + ULONG ulRet = 0; + + ulRet = InterlockedDecrement( &_cRefs ); + + if ( ulRet == 0 ) + { + delete this; + } + return ulRet; + } + + HRESULT + STDMETHODCALLTYPE + QueryInterface( + REFIID riid, + void ** ppObject + ) + { + if ( riid == __uuidof(IUnknown) || + riid == __uuidof(IAppHostPathMapper) ) + { + AddRef(); + *ppObject = (IAppHostPathMapper*) this; + return S_OK; + } + else + { + *ppObject = NULL; + return E_NOINTERFACE; + } + } + + HRESULT + STDMETHODCALLTYPE + MapPath( + BSTR bstrConfigPath, + BSTR bstrMappedPhysicalPath, + BSTR * pbstrNewPhysicalPath + ) + { + BSTR bstrNewPhysicalPath = NULL; + + if ( wcscmp( bstrConfigPath, L"MACHINE/WEBROOT" ) == 0 ) + { + bstrNewPhysicalPath = SysAllocString( _strMappedPath.QueryStr() ); + } + else + { + bstrNewPhysicalPath = SysAllocString( bstrMappedPhysicalPath ); + } + + if ( bstrNewPhysicalPath == NULL ) + { + return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY ); + } + + *pbstrNewPhysicalPath = bstrNewPhysicalPath; + return S_OK; + } + +private: + + LONG _cRefs; + STRU _strMappedPath; +}; + +HRESULT +InitAdminMgrForAdminConfig( + IN IAppHostWritableAdminManager * pAdminMgr, + IN CONST WCHAR * szCommitPath + ) +{ + HRESULT hr = NOERROR; + + VARIANT varPathMapper; + VariantInit( &varPathMapper ); + + BSTR bstrPathMapperName = SysAllocString( L"pathMapper" ); + BSTR bstrCommitPath = SysAllocString( szCommitPath ); + + ADMINISTRATION_CONFIG_PATH_MAPPER * pPathMapper = NULL; + + if( !bstrPathMapperName || !bstrCommitPath) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->put_CommitPath( bstrCommitPath ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + pPathMapper = new ADMINISTRATION_CONFIG_PATH_MAPPER(); + if( !pPathMapper ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = pPathMapper->Initialize(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + varPathMapper.vt = VT_UNKNOWN; + varPathMapper.punkVal = pPathMapper; + pPathMapper = NULL; + + hr = pAdminMgr->SetMetadata( bstrPathMapperName, varPathMapper ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + SysFreeString( bstrPathMapperName ); + SysFreeString( bstrCommitPath ); + + VariantClear( &varPathMapper ); + + if( pPathMapper ) + { + pPathMapper->Release(); + pPathMapper = NULL; + } + + return hr; +} + + +HRESULT +RegisterUIModule( + IN CONST WCHAR * szModuleName, + IN CONST WCHAR * szModuleTypeInfo, + IN OPTIONAL CONST WCHAR * szRegisterInModulesSection, + IN OPTIONAL CONST WCHAR * szPrependToList + ) +{ + HRESULT hr = NOERROR; + + CComPtr pAdminMgr; + CComPtr pProvidersSection; + CComPtr pProvidersCollection; + CComPtr pNewModuleElement; + CComPtr pModulesSection; + CComPtr pModulesCollection; + CComPtr pModulesCollectionElement; + + VARIANT varValue; + VariantInit( &varValue ); + DWORD dwIndex; + BOOL fAddElement = FALSE; + INT cIndex; + + BSTR bstrCommitPath = SysAllocString( L"MACHINE/WEBROOT" ); + BSTR bstrModuleProvidersName = SysAllocString( L"moduleProviders" ); + BSTR bstrAdd = SysAllocString( L"add" ); + BSTR bstrModulesSectionName = SysAllocString( L"modules" ); + + if( !bstrCommitPath || + !bstrModuleProvidersName || + !bstrAdd || + !bstrModulesSectionName ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( IAppHostWritableAdminManager ), + (VOID **)&pAdminMgr ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = InitAdminMgrForAdminConfig( pAdminMgr, + bstrCommitPath ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->GetAdminSection( bstrModuleProvidersName, + bstrCommitPath, + &pProvidersSection ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pProvidersSection->get_Collection( &pProvidersCollection ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = FindElementInCollection( + pProvidersCollection, + L"name", + szModuleName, + FIND_ELEMENT_CASE_SENSITIVE, + &dwIndex); + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + if (hr == S_OK) + { + VARIANT vtIndex; + vtIndex.vt = VT_UI4; + vtIndex.ulVal = dwIndex; + + hr = pProvidersCollection->get_Item( + vtIndex, + &pNewModuleElement); + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + } + else + { + hr = pProvidersCollection->CreateNewElement( bstrAdd, + &pNewModuleElement ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + fAddElement = TRUE; + } + + hr = VariantAssign( &varValue, szModuleName ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = SetElementProperty( pNewModuleElement, + L"name", + &varValue ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = VariantAssign( &varValue, szModuleTypeInfo ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = SetElementProperty( pNewModuleElement, + L"type", + &varValue ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if (fAddElement) + { + cIndex = -1; + if (szPrependToList && *szPrependToList) + { + cIndex = 0; + } + + hr = pProvidersCollection->AddElement( pNewModuleElement, + cIndex ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + if( szRegisterInModulesSection && *szRegisterInModulesSection ) + { + // register global section + hr = pAdminMgr->GetAdminSection( bstrModulesSectionName, + bstrCommitPath, + &pModulesSection ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pModulesSection->get_Collection( &pModulesCollection ); + + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pModulesCollection->CreateNewElement( bstrAdd, + &pModulesCollectionElement ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = VariantAssign( &varValue, szModuleName ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = SetElementProperty( pModulesCollectionElement, + L"name", + &varValue ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + cIndex = -1; + if (szPrependToList && *szPrependToList) + { + cIndex = 0; + } + + hr = pModulesCollection->AddElement( pModulesCollectionElement, + cIndex ); + if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) + { + hr = S_OK; + } + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + + hr = pAdminMgr->CommitChanges(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + +exit: + + SysFreeString( bstrCommitPath ); + SysFreeString( bstrModuleProvidersName ); + SysFreeString( bstrAdd ); + SysFreeString( bstrModulesSectionName ); + + VariantClear( &varValue ); + + return hr; +} + +HRESULT +UnRegisterUIModule( + IN CONST WCHAR * szModuleName, + IN CONST WCHAR * szModuleTypeInfo + ) +{ + HRESULT hr = NOERROR; + + CComPtr pAdminMgr; + CComPtr pProvidersSection; + CComPtr pProvidersCollection; + CComPtr pProviderElement; + CComPtr pModulesSection; + CComPtr pModulesCollection; + + BSTR bstrCommitPath = SysAllocString( L"MACHINE/WEBROOT" ); + BSTR bstrModuleProvidersName = SysAllocString( L"moduleProviders" ); + BSTR bstrModulesSectionName = SysAllocString( L"modules" ); + BSTR bstrType = NULL; + DWORD dwIndex; + + if( !bstrCommitPath || + !bstrModuleProvidersName || + !bstrModulesSectionName ) + { + hr = E_OUTOFMEMORY; + DBGERROR_HR(hr); + goto exit; + } + + hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof( IAppHostWritableAdminManager ), + (VOID **)&pAdminMgr ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = InitAdminMgrForAdminConfig( pAdminMgr, bstrCommitPath ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pAdminMgr->GetAdminSection( bstrModuleProvidersName, + bstrCommitPath, + &pProvidersSection ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pProvidersSection->get_Collection( &pProvidersCollection ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + BOOL fProvidersDeleted = FALSE; + + hr = FindElementInCollection( + pProvidersCollection, + L"name", + szModuleName, + FIND_ELEMENT_CASE_SENSITIVE, + &dwIndex); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + if (hr == S_OK) + { + VARIANT vtIndex; + vtIndex.vt = VT_UI4; + vtIndex.ulVal = dwIndex; + + hr = pProvidersCollection->get_Item( + vtIndex, + &pProviderElement); + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = GetElementStringProperty( + pProviderElement, + L"type", + &bstrType); + if (FAILED(hr)) + { + DBGERROR_HR(hr); + goto exit; + } + + if (wcscmp(bstrType, szModuleTypeInfo) == 0) + { + hr = pProvidersCollection->DeleteElement(vtIndex); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + fProvidersDeleted = TRUE; + } + else + { + goto exit; + } + } + + // now remove from global section if present + hr = pAdminMgr->GetAdminSection( bstrModulesSectionName, + bstrCommitPath, + &pModulesSection ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + hr = pModulesSection->get_Collection( &pModulesCollection ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + BOOL fModulesDeleted = FALSE; + hr = DeleteElementFromCollection( pModulesCollection, + L"name", + szModuleName, + FIND_ELEMENT_CASE_SENSITIVE, + &fModulesDeleted ); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + + if( fProvidersDeleted || fModulesDeleted ) + { + hr = pAdminMgr->CommitChanges(); + if( FAILED(hr) ) + { + DBGERROR_HR(hr); + goto exit; + } + } + +exit: + + SysFreeString( bstrCommitPath ); + SysFreeString( bstrModuleProvidersName ); + SysFreeString( bstrModulesSectionName ); + SysFreeString( bstrType ); + + return hr; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/wuerror.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/wuerror.h new file mode 100644 index 0000000000..a735af0cf7 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/wuerror.h @@ -0,0 +1,2456 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +/*************************************************************************** +* * +* wuerror.mc -- error code definitions for Windows Update. * +* * +***************************************************************************/ +#ifndef _WUERROR_ +#define _WUERROR_ + +#if defined (_MSC_VER) && (_MSC_VER >= 1020) && !defined(__midl) +#pragma once +#endif + +#ifdef RC_INVOKED +#define _HRESULT_TYPEDEF_(_sc) _sc +#else // RC_INVOKED +#define _HRESULT_TYPEDEF_(_sc) ((HRESULT)_sc) +#endif // RC_INVOKED + + +/////////////////////////////////////////////////////////////////////////////// +// Windows Update Success Codes +/////////////////////////////////////////////////////////////////////////////// +// +// Values are 32 bit values laid out as follows: +// +// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +---+-+-+-----------------------+-------------------------------+ +// |Sev|C|R| Facility | Code | +// +---+-+-+-----------------------+-------------------------------+ +// +// where +// +// Sev - is the severity code +// +// 00 - Success +// 01 - Informational +// 10 - Warning +// 11 - Error +// +// C - is the Customer code flag +// +// R - is a reserved bit +// +// Facility - is the facility code +// +// Code - is the facility's status code +// +// +// Define the facility codes +// + + +// +// Define the severity codes +// + + +// +// MessageId: WU_S_SERVICE_STOP +// +// MessageText: +// +// Windows Update Agent was stopped successfully. +// +#define WU_S_SERVICE_STOP _HRESULT_TYPEDEF_(0x00240001L) + +// +// MessageId: WU_S_SELFUPDATE +// +// MessageText: +// +// Windows Update Agent updated itself. +// +#define WU_S_SELFUPDATE _HRESULT_TYPEDEF_(0x00240002L) + +// +// MessageId: WU_S_UPDATE_ERROR +// +// MessageText: +// +// Operation completed successfully but there were errors applying the updates. +// +#define WU_S_UPDATE_ERROR _HRESULT_TYPEDEF_(0x00240003L) + +// +// MessageId: WU_S_MARKED_FOR_DISCONNECT +// +// MessageText: +// +// A callback was marked to be disconnected later because the request to disconnect the operation came while a callback was executing. +// +#define WU_S_MARKED_FOR_DISCONNECT _HRESULT_TYPEDEF_(0x00240004L) + +// +// MessageId: WU_S_REBOOT_REQUIRED +// +// MessageText: +// +// The system must be restarted to complete installation of the update. +// +#define WU_S_REBOOT_REQUIRED _HRESULT_TYPEDEF_(0x00240005L) + +// +// MessageId: WU_S_ALREADY_INSTALLED +// +// MessageText: +// +// The update to be installed is already installed on the system. +// +#define WU_S_ALREADY_INSTALLED _HRESULT_TYPEDEF_(0x00240006L) + +// +// MessageId: WU_S_ALREADY_UNINSTALLED +// +// MessageText: +// +// The update to be removed is not installed on the system. +// +#define WU_S_ALREADY_UNINSTALLED _HRESULT_TYPEDEF_(0x00240007L) + +// +// MessageId: WU_S_ALREADY_DOWNLOADED +// +// MessageText: +// +// The update to be downloaded has already been downloaded. +// +#define WU_S_ALREADY_DOWNLOADED _HRESULT_TYPEDEF_(0x00240008L) + +/////////////////////////////////////////////////////////////////////////////// +// Windows Update Error Codes +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_NO_SERVICE +// +// MessageText: +// +// Windows Update Agent was unable to provide the service. +// +#define WU_E_NO_SERVICE _HRESULT_TYPEDEF_(0x80240001L) + +// +// MessageId: WU_E_MAX_CAPACITY_REACHED +// +// MessageText: +// +// The maximum capacity of the service was exceeded. +// +#define WU_E_MAX_CAPACITY_REACHED _HRESULT_TYPEDEF_(0x80240002L) + +// +// MessageId: WU_E_UNKNOWN_ID +// +// MessageText: +// +// An ID cannot be found. +// +#define WU_E_UNKNOWN_ID _HRESULT_TYPEDEF_(0x80240003L) + +// +// MessageId: WU_E_NOT_INITIALIZED +// +// MessageText: +// +// The object could not be initialized. +// +#define WU_E_NOT_INITIALIZED _HRESULT_TYPEDEF_(0x80240004L) + +// +// MessageId: WU_E_RANGEOVERLAP +// +// MessageText: +// +// The update handler requested a byte range overlapping a previously requested range. +// +#define WU_E_RANGEOVERLAP _HRESULT_TYPEDEF_(0x80240005L) + +// +// MessageId: WU_E_TOOMANYRANGES +// +// MessageText: +// +// The requested number of byte ranges exceeds the maximum number (2^31 - 1). +// +#define WU_E_TOOMANYRANGES _HRESULT_TYPEDEF_(0x80240006L) + +// +// MessageId: WU_E_INVALIDINDEX +// +// MessageText: +// +// The index to a collection was invalid. +// +#define WU_E_INVALIDINDEX _HRESULT_TYPEDEF_(0x80240007L) + +// +// MessageId: WU_E_ITEMNOTFOUND +// +// MessageText: +// +// The key for the item queried could not be found. +// +#define WU_E_ITEMNOTFOUND _HRESULT_TYPEDEF_(0x80240008L) + +// +// MessageId: WU_E_OPERATIONINPROGRESS +// +// MessageText: +// +// Another conflicting operation was in progress. Some operations such as installation cannot be performed twice simultaneously. +// +#define WU_E_OPERATIONINPROGRESS _HRESULT_TYPEDEF_(0x80240009L) + +// +// MessageId: WU_E_COULDNOTCANCEL +// +// MessageText: +// +// Cancellation of the operation was not allowed. +// +#define WU_E_COULDNOTCANCEL _HRESULT_TYPEDEF_(0x8024000AL) + +// +// MessageId: WU_E_CALL_CANCELLED +// +// MessageText: +// +// Operation was cancelled. +// +#define WU_E_CALL_CANCELLED _HRESULT_TYPEDEF_(0x8024000BL) + +// +// MessageId: WU_E_NOOP +// +// MessageText: +// +// No operation was required. +// +#define WU_E_NOOP _HRESULT_TYPEDEF_(0x8024000CL) + +// +// MessageId: WU_E_XML_MISSINGDATA +// +// MessageText: +// +// Windows Update Agent could not find required information in the update's XML data. +// +#define WU_E_XML_MISSINGDATA _HRESULT_TYPEDEF_(0x8024000DL) + +// +// MessageId: WU_E_XML_INVALID +// +// MessageText: +// +// Windows Update Agent found invalid information in the update's XML data. +// +#define WU_E_XML_INVALID _HRESULT_TYPEDEF_(0x8024000EL) + +// +// MessageId: WU_E_CYCLE_DETECTED +// +// MessageText: +// +// Circular update relationships were detected in the metadata. +// +#define WU_E_CYCLE_DETECTED _HRESULT_TYPEDEF_(0x8024000FL) + +// +// MessageId: WU_E_TOO_DEEP_RELATION +// +// MessageText: +// +// Update relationships too deep to evaluate were evaluated. +// +#define WU_E_TOO_DEEP_RELATION _HRESULT_TYPEDEF_(0x80240010L) + +// +// MessageId: WU_E_INVALID_RELATIONSHIP +// +// MessageText: +// +// An invalid update relationship was detected. +// +#define WU_E_INVALID_RELATIONSHIP _HRESULT_TYPEDEF_(0x80240011L) + +// +// MessageId: WU_E_REG_VALUE_INVALID +// +// MessageText: +// +// An invalid registry value was read. +// +#define WU_E_REG_VALUE_INVALID _HRESULT_TYPEDEF_(0x80240012L) + +// +// MessageId: WU_E_DUPLICATE_ITEM +// +// MessageText: +// +// Operation tried to add a duplicate item to a list. +// +#define WU_E_DUPLICATE_ITEM _HRESULT_TYPEDEF_(0x80240013L) + +// +// MessageId: WU_E_INSTALL_NOT_ALLOWED +// +// MessageText: +// +// Operation tried to install while another installation was in progress or the system was pending a mandatory restart. +// +#define WU_E_INSTALL_NOT_ALLOWED _HRESULT_TYPEDEF_(0x80240016L) + +// +// MessageId: WU_E_NOT_APPLICABLE +// +// MessageText: +// +// Operation was not performed because there are no applicable updates. +// +#define WU_E_NOT_APPLICABLE _HRESULT_TYPEDEF_(0x80240017L) + +// +// MessageId: WU_E_NO_USERTOKEN +// +// MessageText: +// +// Operation failed because a required user token is missing. +// +#define WU_E_NO_USERTOKEN _HRESULT_TYPEDEF_(0x80240018L) + +// +// MessageId: WU_E_EXCLUSIVE_INSTALL_CONFLICT +// +// MessageText: +// +// An exclusive update cannot be installed with other updates at the same time. +// +#define WU_E_EXCLUSIVE_INSTALL_CONFLICT _HRESULT_TYPEDEF_(0x80240019L) + +// +// MessageId: WU_E_POLICY_NOT_SET +// +// MessageText: +// +// A policy value was not set. +// +#define WU_E_POLICY_NOT_SET _HRESULT_TYPEDEF_(0x8024001AL) + +// +// MessageId: WU_E_SELFUPDATE_IN_PROGRESS +// +// MessageText: +// +// The operation could not be performed because the Windows Update Agent is self-updating. +// +#define WU_E_SELFUPDATE_IN_PROGRESS _HRESULT_TYPEDEF_(0x8024001BL) + +// +// MessageId: WU_E_INVALID_UPDATE +// +// MessageText: +// +// An update contains invalid metadata. +// +#define WU_E_INVALID_UPDATE _HRESULT_TYPEDEF_(0x8024001DL) + +// +// MessageId: WU_E_SERVICE_STOP +// +// MessageText: +// +// Operation did not complete because the service or system was being shut down. +// +#define WU_E_SERVICE_STOP _HRESULT_TYPEDEF_(0x8024001EL) + +// +// MessageId: WU_E_NO_CONNECTION +// +// MessageText: +// +// Operation did not complete because the network connection was unavailable. +// +#define WU_E_NO_CONNECTION _HRESULT_TYPEDEF_(0x8024001FL) + +// +// MessageId: WU_E_NO_INTERACTIVE_USER +// +// MessageText: +// +// Operation did not complete because there is no logged-on interactive user. +// +#define WU_E_NO_INTERACTIVE_USER _HRESULT_TYPEDEF_(0x80240020L) + +// +// MessageId: WU_E_TIME_OUT +// +// MessageText: +// +// Operation did not complete because it timed out. +// +#define WU_E_TIME_OUT _HRESULT_TYPEDEF_(0x80240021L) + +// +// MessageId: WU_E_ALL_UPDATES_FAILED +// +// MessageText: +// +// Operation failed for all the updates. +// +#define WU_E_ALL_UPDATES_FAILED _HRESULT_TYPEDEF_(0x80240022L) + +// +// MessageId: WU_E_EULAS_DECLINED +// +// MessageText: +// +// The license terms for all updates were declined. +// +#define WU_E_EULAS_DECLINED _HRESULT_TYPEDEF_(0x80240023L) + +// +// MessageId: WU_E_NO_UPDATE +// +// MessageText: +// +// There are no updates. +// +#define WU_E_NO_UPDATE _HRESULT_TYPEDEF_(0x80240024L) + +// +// MessageId: WU_E_USER_ACCESS_DISABLED +// +// MessageText: +// +// Group Policy settings prevented access to Windows Update. +// +#define WU_E_USER_ACCESS_DISABLED _HRESULT_TYPEDEF_(0x80240025L) + +// +// MessageId: WU_E_INVALID_UPDATE_TYPE +// +// MessageText: +// +// The type of update is invalid. +// +#define WU_E_INVALID_UPDATE_TYPE _HRESULT_TYPEDEF_(0x80240026L) + +// +// MessageId: WU_E_URL_TOO_LONG +// +// MessageText: +// +// The URL exceeded the maximum length. +// +#define WU_E_URL_TOO_LONG _HRESULT_TYPEDEF_(0x80240027L) + +// +// MessageId: WU_E_UNINSTALL_NOT_ALLOWED +// +// MessageText: +// +// The update could not be uninstalled because the request did not originate from a WSUS server. +// +#define WU_E_UNINSTALL_NOT_ALLOWED _HRESULT_TYPEDEF_(0x80240028L) + +// +// MessageId: WU_E_INVALID_PRODUCT_LICENSE +// +// MessageText: +// +// Search may have missed some updates before there is an unlicensed application on the system. +// +#define WU_E_INVALID_PRODUCT_LICENSE _HRESULT_TYPEDEF_(0x80240029L) + +// +// MessageId: WU_E_MISSING_HANDLER +// +// MessageText: +// +// A component required to detect applicable updates was missing. +// +#define WU_E_MISSING_HANDLER _HRESULT_TYPEDEF_(0x8024002AL) + +// +// MessageId: WU_E_LEGACYSERVER +// +// MessageText: +// +// An operation did not complete because it requires a newer version of server. +// +#define WU_E_LEGACYSERVER _HRESULT_TYPEDEF_(0x8024002BL) + +// +// MessageId: WU_E_BIN_SOURCE_ABSENT +// +// MessageText: +// +// A delta-compressed update could not be installed because it required the source. +// +#define WU_E_BIN_SOURCE_ABSENT _HRESULT_TYPEDEF_(0x8024002CL) + +// +// MessageId: WU_E_SOURCE_ABSENT +// +// MessageText: +// +// A full-file update could not be installed because it required the source. +// +#define WU_E_SOURCE_ABSENT _HRESULT_TYPEDEF_(0x8024002DL) + +// +// MessageId: WU_E_WU_DISABLED +// +// MessageText: +// +// Access to an unmanaged server is not allowed. +// +#define WU_E_WU_DISABLED _HRESULT_TYPEDEF_(0x8024002EL) + +// +// MessageId: WU_E_CALL_CANCELLED_BY_POLICY +// +// MessageText: +// +// Operation did not complete because the DisableWindowsUpdateAccess policy was set. +// +#define WU_E_CALL_CANCELLED_BY_POLICY _HRESULT_TYPEDEF_(0x8024002FL) + +// +// MessageId: WU_E_INVALID_PROXY_SERVER +// +// MessageText: +// +// The format of the proxy list was invalid. +// +#define WU_E_INVALID_PROXY_SERVER _HRESULT_TYPEDEF_(0x80240030L) + +// +// MessageId: WU_E_INVALID_FILE +// +// MessageText: +// +// The file is in the wrong format. +// +#define WU_E_INVALID_FILE _HRESULT_TYPEDEF_(0x80240031L) + +// +// MessageId: WU_E_INVALID_CRITERIA +// +// MessageText: +// +// The search criteria string was invalid. +// +#define WU_E_INVALID_CRITERIA _HRESULT_TYPEDEF_(0x80240032L) + +// +// MessageId: WU_E_EULA_UNAVAILABLE +// +// MessageText: +// +// License terms could not be downloaded. +// +#define WU_E_EULA_UNAVAILABLE _HRESULT_TYPEDEF_(0x80240033L) + +// +// MessageId: WU_E_DOWNLOAD_FAILED +// +// MessageText: +// +// Update failed to download. +// +#define WU_E_DOWNLOAD_FAILED _HRESULT_TYPEDEF_(0x80240034L) + +// +// MessageId: WU_E_UPDATE_NOT_PROCESSED +// +// MessageText: +// +// The update was not processed. +// +#define WU_E_UPDATE_NOT_PROCESSED _HRESULT_TYPEDEF_(0x80240035L) + +// +// MessageId: WU_E_INVALID_OPERATION +// +// MessageText: +// +// The object's current state did not allow the operation. +// +#define WU_E_INVALID_OPERATION _HRESULT_TYPEDEF_(0x80240036L) + +// +// MessageId: WU_E_NOT_SUPPORTED +// +// MessageText: +// +// The functionality for the operation is not supported. +// +#define WU_E_NOT_SUPPORTED _HRESULT_TYPEDEF_(0x80240037L) + +// +// MessageId: WU_E_WINHTTP_INVALID_FILE +// +// MessageText: +// +// The downloaded file has an unexpected content type. +// +#define WU_E_WINHTTP_INVALID_FILE _HRESULT_TYPEDEF_(0x80240038L) + +// +// MessageId: WU_E_TOO_MANY_RESYNC +// +// MessageText: +// +// Agent is asked by server to resync too many times. +// +#define WU_E_TOO_MANY_RESYNC _HRESULT_TYPEDEF_(0x80240039L) + +// +// MessageId: WU_E_NO_SERVER_CORE_SUPPORT +// +// MessageText: +// +// WUA API method does not run on Server Core installation. +// +#define WU_E_NO_SERVER_CORE_SUPPORT _HRESULT_TYPEDEF_(0x80240040L) + +// +// MessageId: WU_E_SYSPREP_IN_PROGRESS +// +// MessageText: +// +// Service is not available while sysprep is running. +// +#define WU_E_SYSPREP_IN_PROGRESS _HRESULT_TYPEDEF_(0x80240041L) + +// +// MessageId: WU_E_UNKNOWN_SERVICE +// +// MessageText: +// +// The update service is no longer registered with AU. +// +#define WU_E_UNKNOWN_SERVICE _HRESULT_TYPEDEF_(0x80240042L) + +// +// MessageId: WU_E_NO_UI_SUPPORT +// +// MessageText: +// +// There is no support for WUA UI. +// +#define WU_E_NO_UI_SUPPORT _HRESULT_TYPEDEF_(0x80240043L) + +// +// MessageId: WU_E_UNEXPECTED +// +// MessageText: +// +// An operation failed due to reasons not covered by another error code. +// +#define WU_E_UNEXPECTED _HRESULT_TYPEDEF_(0x80240FFFL) + +/////////////////////////////////////////////////////////////////////////////// +// Windows Installer minor errors +// +// The following errors are used to indicate that part of a search failed for +// MSI problems. Another part of the search may successfully return updates. +// All MSI minor codes should share the same error code range so that the caller +// tell that they are related to Windows Installer. +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_MSI_WRONG_VERSION +// +// MessageText: +// +// Search may have missed some updates because the Windows Installer is less than version 3.1. +// +#define WU_E_MSI_WRONG_VERSION _HRESULT_TYPEDEF_(0x80241001L) + +// +// MessageId: WU_E_MSI_NOT_CONFIGURED +// +// MessageText: +// +// Search may have missed some updates because the Windows Installer is not configured. +// +#define WU_E_MSI_NOT_CONFIGURED _HRESULT_TYPEDEF_(0x80241002L) + +// +// MessageId: WU_E_MSP_DISABLED +// +// MessageText: +// +// Search may have missed some updates because policy has disabled Windows Installer patching. +// +#define WU_E_MSP_DISABLED _HRESULT_TYPEDEF_(0x80241003L) + +// +// MessageId: WU_E_MSI_WRONG_APP_CONTEXT +// +// MessageText: +// +// An update could not be applied because the application is installed per-user. +// +#define WU_E_MSI_WRONG_APP_CONTEXT _HRESULT_TYPEDEF_(0x80241004L) + +// +// MessageId: WU_E_MSP_UNEXPECTED +// +// MessageText: +// +// Search may have missed some updates because there was a failure of the Windows Installer. +// +#define WU_E_MSP_UNEXPECTED _HRESULT_TYPEDEF_(0x80241FFFL) + +/////////////////////////////////////////////////////////////////////////////// +// Protocol Talker errors +// +// The following map to SOAPCLIENT_ERRORs from atlsoap.h. These errors +// are obtained from calling GetClientError() on the CClientWebService +// object. +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_PT_SOAPCLIENT_BASE +// +// MessageText: +// +// WU_E_PT_SOAPCLIENT_* error codes map to the SOAPCLIENT_ERROR enum of the ATL Server Library. +// +#define WU_E_PT_SOAPCLIENT_BASE _HRESULT_TYPEDEF_(0x80244000L) + +// +// MessageId: WU_E_PT_SOAPCLIENT_INITIALIZE +// +// MessageText: +// +// Same as SOAPCLIENT_INITIALIZE_ERROR - initialization of the SOAP client failed, possibly because of an MSXML installation failure. +// +#define WU_E_PT_SOAPCLIENT_INITIALIZE _HRESULT_TYPEDEF_(0x80244001L) + +// +// MessageId: WU_E_PT_SOAPCLIENT_OUTOFMEMORY +// +// MessageText: +// +// Same as SOAPCLIENT_OUTOFMEMORY - SOAP client failed because it ran out of memory. +// +#define WU_E_PT_SOAPCLIENT_OUTOFMEMORY _HRESULT_TYPEDEF_(0x80244002L) + +// +// MessageId: WU_E_PT_SOAPCLIENT_GENERATE +// +// MessageText: +// +// Same as SOAPCLIENT_GENERATE_ERROR - SOAP client failed to generate the request. +// +#define WU_E_PT_SOAPCLIENT_GENERATE _HRESULT_TYPEDEF_(0x80244003L) + +// +// MessageId: WU_E_PT_SOAPCLIENT_CONNECT +// +// MessageText: +// +// Same as SOAPCLIENT_CONNECT_ERROR - SOAP client failed to connect to the server. +// +#define WU_E_PT_SOAPCLIENT_CONNECT _HRESULT_TYPEDEF_(0x80244004L) + +// +// MessageId: WU_E_PT_SOAPCLIENT_SEND +// +// MessageText: +// +// Same as SOAPCLIENT_SEND_ERROR - SOAP client failed to send a message for reasons of WU_E_WINHTTP_* error codes. +// +#define WU_E_PT_SOAPCLIENT_SEND _HRESULT_TYPEDEF_(0x80244005L) + +// +// MessageId: WU_E_PT_SOAPCLIENT_SERVER +// +// MessageText: +// +// Same as SOAPCLIENT_SERVER_ERROR - SOAP client failed because there was a server error. +// +#define WU_E_PT_SOAPCLIENT_SERVER _HRESULT_TYPEDEF_(0x80244006L) + +// +// MessageId: WU_E_PT_SOAPCLIENT_SOAPFAULT +// +// MessageText: +// +// Same as SOAPCLIENT_SOAPFAULT - SOAP client failed because there was a SOAP fault for reasons of WU_E_PT_SOAP_* error codes. +// +#define WU_E_PT_SOAPCLIENT_SOAPFAULT _HRESULT_TYPEDEF_(0x80244007L) + +// +// MessageId: WU_E_PT_SOAPCLIENT_PARSEFAULT +// +// MessageText: +// +// Same as SOAPCLIENT_PARSEFAULT_ERROR - SOAP client failed to parse a SOAP fault. +// +#define WU_E_PT_SOAPCLIENT_PARSEFAULT _HRESULT_TYPEDEF_(0x80244008L) + +// +// MessageId: WU_E_PT_SOAPCLIENT_READ +// +// MessageText: +// +// Same as SOAPCLIENT_READ_ERROR - SOAP client failed while reading the response from the server. +// +#define WU_E_PT_SOAPCLIENT_READ _HRESULT_TYPEDEF_(0x80244009L) + +// +// MessageId: WU_E_PT_SOAPCLIENT_PARSE +// +// MessageText: +// +// Same as SOAPCLIENT_PARSE_ERROR - SOAP client failed to parse the response from the server. +// +#define WU_E_PT_SOAPCLIENT_PARSE _HRESULT_TYPEDEF_(0x8024400AL) + +// The following map to SOAP_ERROR_CODEs from atlsoap.h. These errors +// are obtained from the m_fault.m_soapErrCode member on the +// CClientWebService object when GetClientError() returned +// SOAPCLIENT_SOAPFAULT. +// +// MessageId: WU_E_PT_SOAP_VERSION +// +// MessageText: +// +// Same as SOAP_E_VERSION_MISMATCH - SOAP client found an unrecognizable namespace for the SOAP envelope. +// +#define WU_E_PT_SOAP_VERSION _HRESULT_TYPEDEF_(0x8024400BL) + +// +// MessageId: WU_E_PT_SOAP_MUST_UNDERSTAND +// +// MessageText: +// +// Same as SOAP_E_MUST_UNDERSTAND - SOAP client was unable to understand a header. +// +#define WU_E_PT_SOAP_MUST_UNDERSTAND _HRESULT_TYPEDEF_(0x8024400CL) + +// +// MessageId: WU_E_PT_SOAP_CLIENT +// +// MessageText: +// +// Same as SOAP_E_CLIENT - SOAP client found the message was malformed; fix before resending. +// +#define WU_E_PT_SOAP_CLIENT _HRESULT_TYPEDEF_(0x8024400DL) + +// +// MessageId: WU_E_PT_SOAP_SERVER +// +// MessageText: +// +// Same as SOAP_E_SERVER - The SOAP message could not be processed due to a server error; resend later. +// +#define WU_E_PT_SOAP_SERVER _HRESULT_TYPEDEF_(0x8024400EL) + +// +// MessageId: WU_E_PT_WMI_ERROR +// +// MessageText: +// +// There was an unspecified Windows Management Instrumentation (WMI) error. +// +#define WU_E_PT_WMI_ERROR _HRESULT_TYPEDEF_(0x8024400FL) + +// +// MessageId: WU_E_PT_EXCEEDED_MAX_SERVER_TRIPS +// +// MessageText: +// +// The number of round trips to the server exceeded the maximum limit. +// +#define WU_E_PT_EXCEEDED_MAX_SERVER_TRIPS _HRESULT_TYPEDEF_(0x80244010L) + +// +// MessageId: WU_E_PT_SUS_SERVER_NOT_SET +// +// MessageText: +// +// WUServer policy value is missing in the registry. +// +#define WU_E_PT_SUS_SERVER_NOT_SET _HRESULT_TYPEDEF_(0x80244011L) + +// +// MessageId: WU_E_PT_DOUBLE_INITIALIZATION +// +// MessageText: +// +// Initialization failed because the object was already initialized. +// +#define WU_E_PT_DOUBLE_INITIALIZATION _HRESULT_TYPEDEF_(0x80244012L) + +// +// MessageId: WU_E_PT_INVALID_COMPUTER_NAME +// +// MessageText: +// +// The computer name could not be determined. +// +#define WU_E_PT_INVALID_COMPUTER_NAME _HRESULT_TYPEDEF_(0x80244013L) + +// +// MessageId: WU_E_PT_REFRESH_CACHE_REQUIRED +// +// MessageText: +// +// The reply from the server indicates that the server was changed or the cookie was invalid; refresh the state of the internal cache and retry. +// +#define WU_E_PT_REFRESH_CACHE_REQUIRED _HRESULT_TYPEDEF_(0x80244015L) + +// +// MessageId: WU_E_PT_HTTP_STATUS_BAD_REQUEST +// +// MessageText: +// +// Same as HTTP status 400 - the server could not process the request due to invalid syntax. +// +#define WU_E_PT_HTTP_STATUS_BAD_REQUEST _HRESULT_TYPEDEF_(0x80244016L) + +// +// MessageId: WU_E_PT_HTTP_STATUS_DENIED +// +// MessageText: +// +// Same as HTTP status 401 - the requested resource requires user authentication. +// +#define WU_E_PT_HTTP_STATUS_DENIED _HRESULT_TYPEDEF_(0x80244017L) + +// +// MessageId: WU_E_PT_HTTP_STATUS_FORBIDDEN +// +// MessageText: +// +// Same as HTTP status 403 - server understood the request, but declined to fulfill it. +// +#define WU_E_PT_HTTP_STATUS_FORBIDDEN _HRESULT_TYPEDEF_(0x80244018L) + +// +// MessageId: WU_E_PT_HTTP_STATUS_NOT_FOUND +// +// MessageText: +// +// Same as HTTP status 404 - the server cannot find the requested URI (Uniform Resource Identifier). +// +// +#define WU_E_PT_HTTP_STATUS_NOT_FOUND _HRESULT_TYPEDEF_(0x80244019L) + +// +// MessageId: WU_E_PT_HTTP_STATUS_BAD_METHOD +// +// MessageText: +// +// Same as HTTP status 405 - the HTTP method is not allowed. +// +#define WU_E_PT_HTTP_STATUS_BAD_METHOD _HRESULT_TYPEDEF_(0x8024401AL) + +// +// MessageId: WU_E_PT_HTTP_STATUS_PROXY_AUTH_REQ +// +// MessageText: +// +// Same as HTTP status 407 - proxy authentication is required. +// +#define WU_E_PT_HTTP_STATUS_PROXY_AUTH_REQ _HRESULT_TYPEDEF_(0x8024401BL) + +// +// MessageId: WU_E_PT_HTTP_STATUS_REQUEST_TIMEOUT +// +// MessageText: +// +// Same as HTTP status 408 - the server timed out waiting for the request. +// +#define WU_E_PT_HTTP_STATUS_REQUEST_TIMEOUT _HRESULT_TYPEDEF_(0x8024401CL) + +// +// MessageId: WU_E_PT_HTTP_STATUS_CONFLICT +// +// MessageText: +// +// Same as HTTP status 409 - the request was not completed due to a conflict with the current state of the resource. +// +#define WU_E_PT_HTTP_STATUS_CONFLICT _HRESULT_TYPEDEF_(0x8024401DL) + +// +// MessageId: WU_E_PT_HTTP_STATUS_GONE +// +// MessageText: +// +// Same as HTTP status 410 - requested resource is no longer available at the server. +// +#define WU_E_PT_HTTP_STATUS_GONE _HRESULT_TYPEDEF_(0x8024401EL) + +// +// MessageId: WU_E_PT_HTTP_STATUS_SERVER_ERROR +// +// MessageText: +// +// Same as HTTP status 500 - an error internal to the server prevented fulfilling the request. +// +#define WU_E_PT_HTTP_STATUS_SERVER_ERROR _HRESULT_TYPEDEF_(0x8024401FL) + +// +// MessageId: WU_E_PT_HTTP_STATUS_NOT_SUPPORTED +// +// MessageText: +// +// Same as HTTP status 500 - server does not support the functionality required to fulfill the request. +// +#define WU_E_PT_HTTP_STATUS_NOT_SUPPORTED _HRESULT_TYPEDEF_(0x80244020L) + +// +// MessageId: WU_E_PT_HTTP_STATUS_BAD_GATEWAY +// +// MessageText: +// +// Same as HTTP status 502 - the server, while acting as a gateway or proxy, received an invalid response from the upstream server it accessed in attempting to fulfill the request. +// +#define WU_E_PT_HTTP_STATUS_BAD_GATEWAY _HRESULT_TYPEDEF_(0x80244021L) + +// +// MessageId: WU_E_PT_HTTP_STATUS_SERVICE_UNAVAIL +// +// MessageText: +// +// Same as HTTP status 503 - the service is temporarily overloaded. +// +#define WU_E_PT_HTTP_STATUS_SERVICE_UNAVAIL _HRESULT_TYPEDEF_(0x80244022L) + +// +// MessageId: WU_E_PT_HTTP_STATUS_GATEWAY_TIMEOUT +// +// MessageText: +// +// Same as HTTP status 503 - the request was timed out waiting for a gateway. +// +#define WU_E_PT_HTTP_STATUS_GATEWAY_TIMEOUT _HRESULT_TYPEDEF_(0x80244023L) + +// +// MessageId: WU_E_PT_HTTP_STATUS_VERSION_NOT_SUP +// +// MessageText: +// +// Same as HTTP status 505 - the server does not support the HTTP protocol version used for the request. +// +#define WU_E_PT_HTTP_STATUS_VERSION_NOT_SUP _HRESULT_TYPEDEF_(0x80244024L) + +// +// MessageId: WU_E_PT_FILE_LOCATIONS_CHANGED +// +// MessageText: +// +// Operation failed due to a changed file location; refresh internal state and resend. +// +#define WU_E_PT_FILE_LOCATIONS_CHANGED _HRESULT_TYPEDEF_(0x80244025L) + +// +// MessageId: WU_E_PT_REGISTRATION_NOT_SUPPORTED +// +// MessageText: +// +// Operation failed because Windows Update Agent does not support registration with a non-WSUS server. +// +#define WU_E_PT_REGISTRATION_NOT_SUPPORTED _HRESULT_TYPEDEF_(0x80244026L) + +// +// MessageId: WU_E_PT_NO_AUTH_PLUGINS_REQUESTED +// +// MessageText: +// +// The server returned an empty authentication information list. +// +#define WU_E_PT_NO_AUTH_PLUGINS_REQUESTED _HRESULT_TYPEDEF_(0x80244027L) + +// +// MessageId: WU_E_PT_NO_AUTH_COOKIES_CREATED +// +// MessageText: +// +// Windows Update Agent was unable to create any valid authentication cookies. +// +#define WU_E_PT_NO_AUTH_COOKIES_CREATED _HRESULT_TYPEDEF_(0x80244028L) + +// +// MessageId: WU_E_PT_INVALID_CONFIG_PROP +// +// MessageText: +// +// A configuration property value was wrong. +// +#define WU_E_PT_INVALID_CONFIG_PROP _HRESULT_TYPEDEF_(0x80244029L) + +// +// MessageId: WU_E_PT_CONFIG_PROP_MISSING +// +// MessageText: +// +// A configuration property value was missing. +// +#define WU_E_PT_CONFIG_PROP_MISSING _HRESULT_TYPEDEF_(0x8024402AL) + +// +// MessageId: WU_E_PT_HTTP_STATUS_NOT_MAPPED +// +// MessageText: +// +// The HTTP request could not be completed and the reason did not correspond to any of the WU_E_PT_HTTP_* error codes. +// +#define WU_E_PT_HTTP_STATUS_NOT_MAPPED _HRESULT_TYPEDEF_(0x8024402BL) + +// +// MessageId: WU_E_PT_WINHTTP_NAME_NOT_RESOLVED +// +// MessageText: +// +// Same as ERROR_WINHTTP_NAME_NOT_RESOLVED - the proxy server or target server name cannot be resolved. +// +#define WU_E_PT_WINHTTP_NAME_NOT_RESOLVED _HRESULT_TYPEDEF_(0x8024402CL) + +// +// MessageId: WU_E_PT_SAME_REDIR_ID +// +// MessageText: +// +// Windows Update Agent failed to download a redirector cabinet file with a new redirectorId value from the server during the recovery. +// +#define WU_E_PT_SAME_REDIR_ID _HRESULT_TYPEDEF_(0x8024502DL) + +// +// MessageId: WU_E_PT_NO_MANAGED_RECOVER +// +// MessageText: +// +// A redirector recovery action did not complete because the server is managed. +// +#define WU_E_PT_NO_MANAGED_RECOVER _HRESULT_TYPEDEF_(0x8024502EL) + +// +// MessageId: WU_E_PT_ECP_SUCCEEDED_WITH_ERRORS +// +// MessageText: +// +// External cab file processing completed with some errors. +// +#define WU_E_PT_ECP_SUCCEEDED_WITH_ERRORS _HRESULT_TYPEDEF_(0x8024402FL) + +// +// MessageId: WU_E_PT_ECP_INIT_FAILED +// +// MessageText: +// +// The external cab processor initialization did not complete. +// +#define WU_E_PT_ECP_INIT_FAILED _HRESULT_TYPEDEF_(0x80244030L) + +// +// MessageId: WU_E_PT_ECP_INVALID_FILE_FORMAT +// +// MessageText: +// +// The format of a metadata file was invalid. +// +#define WU_E_PT_ECP_INVALID_FILE_FORMAT _HRESULT_TYPEDEF_(0x80244031L) + +// +// MessageId: WU_E_PT_ECP_INVALID_METADATA +// +// MessageText: +// +// External cab processor found invalid metadata. +// +#define WU_E_PT_ECP_INVALID_METADATA _HRESULT_TYPEDEF_(0x80244032L) + +// +// MessageId: WU_E_PT_ECP_FAILURE_TO_EXTRACT_DIGEST +// +// MessageText: +// +// The file digest could not be extracted from an external cab file. +// +#define WU_E_PT_ECP_FAILURE_TO_EXTRACT_DIGEST _HRESULT_TYPEDEF_(0x80244033L) + +// +// MessageId: WU_E_PT_ECP_FAILURE_TO_DECOMPRESS_CAB_FILE +// +// MessageText: +// +// An external cab file could not be decompressed. +// +#define WU_E_PT_ECP_FAILURE_TO_DECOMPRESS_CAB_FILE _HRESULT_TYPEDEF_(0x80244034L) + +// +// MessageId: WU_E_PT_ECP_FILE_LOCATION_ERROR +// +// MessageText: +// +// External cab processor was unable to get file locations. +// +#define WU_E_PT_ECP_FILE_LOCATION_ERROR _HRESULT_TYPEDEF_(0x80244035L) + +// +// MessageId: WU_E_PT_UNEXPECTED +// +// MessageText: +// +// A communication error not covered by another WU_E_PT_* error code. +// +#define WU_E_PT_UNEXPECTED _HRESULT_TYPEDEF_(0x80244FFFL) + +/////////////////////////////////////////////////////////////////////////////// +// Redirector errors +// +// The following errors are generated by the components that download and +// parse the wuredir.cab +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_REDIRECTOR_LOAD_XML +// +// MessageText: +// +// The redirector XML document could not be loaded into the DOM class. +// +#define WU_E_REDIRECTOR_LOAD_XML _HRESULT_TYPEDEF_(0x80245001L) + +// +// MessageId: WU_E_REDIRECTOR_S_FALSE +// +// MessageText: +// +// The redirector XML document is missing some required information. +// +#define WU_E_REDIRECTOR_S_FALSE _HRESULT_TYPEDEF_(0x80245002L) + +// +// MessageId: WU_E_REDIRECTOR_ID_SMALLER +// +// MessageText: +// +// The redirectorId in the downloaded redirector cab is less than in the cached cab. +// +#define WU_E_REDIRECTOR_ID_SMALLER _HRESULT_TYPEDEF_(0x80245003L) + +// +// MessageId: WU_E_REDIRECTOR_UNEXPECTED +// +// MessageText: +// +// The redirector failed for reasons not covered by another WU_E_REDIRECTOR_* error code. +// +#define WU_E_REDIRECTOR_UNEXPECTED _HRESULT_TYPEDEF_(0x80245FFFL) + +/////////////////////////////////////////////////////////////////////////////// +// driver util errors +// +// The device PnP enumerated device was pruned from the SystemSpec because +// one of the hardware or compatible IDs matched an installed printer driver. +// This is not considered a fatal error and the device is simply skipped. +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_DRV_PRUNED +// +// MessageText: +// +// A driver was skipped. +// +#define WU_E_DRV_PRUNED _HRESULT_TYPEDEF_(0x8024C001L) + +// +// MessageId: WU_E_DRV_NOPROP_OR_LEGACY +// +// MessageText: +// +// A property for the driver could not be found. It may not conform with required specifications. +// +#define WU_E_DRV_NOPROP_OR_LEGACY _HRESULT_TYPEDEF_(0x8024C002L) + +// +// MessageId: WU_E_DRV_REG_MISMATCH +// +// MessageText: +// +// The registry type read for the driver does not match the expected type. +// +#define WU_E_DRV_REG_MISMATCH _HRESULT_TYPEDEF_(0x8024C003L) + +// +// MessageId: WU_E_DRV_NO_METADATA +// +// MessageText: +// +// The driver update is missing metadata. +// +#define WU_E_DRV_NO_METADATA _HRESULT_TYPEDEF_(0x8024C004L) + +// +// MessageId: WU_E_DRV_MISSING_ATTRIBUTE +// +// MessageText: +// +// The driver update is missing a required attribute. +// +#define WU_E_DRV_MISSING_ATTRIBUTE _HRESULT_TYPEDEF_(0x8024C005L) + +// +// MessageId: WU_E_DRV_SYNC_FAILED +// +// MessageText: +// +// Driver synchronization failed. +// +#define WU_E_DRV_SYNC_FAILED _HRESULT_TYPEDEF_(0x8024C006L) + +// +// MessageId: WU_E_DRV_NO_PRINTER_CONTENT +// +// MessageText: +// +// Information required for the synchronization of applicable printers is missing. +// +#define WU_E_DRV_NO_PRINTER_CONTENT _HRESULT_TYPEDEF_(0x8024C007L) + +// +// MessageId: WU_E_DRV_UNEXPECTED +// +// MessageText: +// +// A driver error not covered by another WU_E_DRV_* code. +// +#define WU_E_DRV_UNEXPECTED _HRESULT_TYPEDEF_(0x8024CFFFL) + +////////////////////////////////////////////////////////////////////////////// +// data store errors +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_DS_SHUTDOWN +// +// MessageText: +// +// An operation failed because Windows Update Agent is shutting down. +// +#define WU_E_DS_SHUTDOWN _HRESULT_TYPEDEF_(0x80248000L) + +// +// MessageId: WU_E_DS_INUSE +// +// MessageText: +// +// An operation failed because the data store was in use. +// +#define WU_E_DS_INUSE _HRESULT_TYPEDEF_(0x80248001L) + +// +// MessageId: WU_E_DS_INVALID +// +// MessageText: +// +// The current and expected states of the data store do not match. +// +#define WU_E_DS_INVALID _HRESULT_TYPEDEF_(0x80248002L) + +// +// MessageId: WU_E_DS_TABLEMISSING +// +// MessageText: +// +// The data store is missing a table. +// +#define WU_E_DS_TABLEMISSING _HRESULT_TYPEDEF_(0x80248003L) + +// +// MessageId: WU_E_DS_TABLEINCORRECT +// +// MessageText: +// +// The data store contains a table with unexpected columns. +// +#define WU_E_DS_TABLEINCORRECT _HRESULT_TYPEDEF_(0x80248004L) + +// +// MessageId: WU_E_DS_INVALIDTABLENAME +// +// MessageText: +// +// A table could not be opened because the table is not in the data store. +// +#define WU_E_DS_INVALIDTABLENAME _HRESULT_TYPEDEF_(0x80248005L) + +// +// MessageId: WU_E_DS_BADVERSION +// +// MessageText: +// +// The current and expected versions of the data store do not match. +// +#define WU_E_DS_BADVERSION _HRESULT_TYPEDEF_(0x80248006L) + +// +// MessageId: WU_E_DS_NODATA +// +// MessageText: +// +// The information requested is not in the data store. +// +#define WU_E_DS_NODATA _HRESULT_TYPEDEF_(0x80248007L) + +// +// MessageId: WU_E_DS_MISSINGDATA +// +// MessageText: +// +// The data store is missing required information or has a NULL in a table column that requires a non-null value. +// +#define WU_E_DS_MISSINGDATA _HRESULT_TYPEDEF_(0x80248008L) + +// +// MessageId: WU_E_DS_MISSINGREF +// +// MessageText: +// +// The data store is missing required information or has a reference to missing license terms, file, localized property or linked row. +// +#define WU_E_DS_MISSINGREF _HRESULT_TYPEDEF_(0x80248009L) + +// +// MessageId: WU_E_DS_UNKNOWNHANDLER +// +// MessageText: +// +// The update was not processed because its update handler could not be recognized. +// +#define WU_E_DS_UNKNOWNHANDLER _HRESULT_TYPEDEF_(0x8024800AL) + +// +// MessageId: WU_E_DS_CANTDELETE +// +// MessageText: +// +// The update was not deleted because it is still referenced by one or more services. +// +#define WU_E_DS_CANTDELETE _HRESULT_TYPEDEF_(0x8024800BL) + +// +// MessageId: WU_E_DS_LOCKTIMEOUTEXPIRED +// +// MessageText: +// +// The data store section could not be locked within the allotted time. +// +#define WU_E_DS_LOCKTIMEOUTEXPIRED _HRESULT_TYPEDEF_(0x8024800CL) + +// +// MessageId: WU_E_DS_NOCATEGORIES +// +// MessageText: +// +// The category was not added because it contains no parent categories and is not a top-level category itself. +// +#define WU_E_DS_NOCATEGORIES _HRESULT_TYPEDEF_(0x8024800DL) + +// +// MessageId: WU_E_DS_ROWEXISTS +// +// MessageText: +// +// The row was not added because an existing row has the same primary key. +// +#define WU_E_DS_ROWEXISTS _HRESULT_TYPEDEF_(0x8024800EL) + +// +// MessageId: WU_E_DS_STOREFILELOCKED +// +// MessageText: +// +// The data store could not be initialized because it was locked by another process. +// +#define WU_E_DS_STOREFILELOCKED _HRESULT_TYPEDEF_(0x8024800FL) + +// +// MessageId: WU_E_DS_CANNOTREGISTER +// +// MessageText: +// +// The data store is not allowed to be registered with COM in the current process. +// +#define WU_E_DS_CANNOTREGISTER _HRESULT_TYPEDEF_(0x80248010L) + +// +// MessageId: WU_E_DS_UNABLETOSTART +// +// MessageText: +// +// Could not create a data store object in another process. +// +#define WU_E_DS_UNABLETOSTART _HRESULT_TYPEDEF_(0x80248011L) + +// +// MessageId: WU_E_DS_DUPLICATEUPDATEID +// +// MessageText: +// +// The server sent the same update to the client with two different revision IDs. +// +#define WU_E_DS_DUPLICATEUPDATEID _HRESULT_TYPEDEF_(0x80248013L) + +// +// MessageId: WU_E_DS_UNKNOWNSERVICE +// +// MessageText: +// +// An operation did not complete because the service is not in the data store. +// +#define WU_E_DS_UNKNOWNSERVICE _HRESULT_TYPEDEF_(0x80248014L) + +// +// MessageId: WU_E_DS_SERVICEEXPIRED +// +// MessageText: +// +// An operation did not complete because the registration of the service has expired. +// +#define WU_E_DS_SERVICEEXPIRED _HRESULT_TYPEDEF_(0x80248015L) + +// +// MessageId: WU_E_DS_DECLINENOTALLOWED +// +// MessageText: +// +// A request to hide an update was declined because it is a mandatory update or because it was deployed with a deadline. +// +#define WU_E_DS_DECLINENOTALLOWED _HRESULT_TYPEDEF_(0x80248016L) + +// +// MessageId: WU_E_DS_TABLESESSIONMISMATCH +// +// MessageText: +// +// A table was not closed because it is not associated with the session. +// +#define WU_E_DS_TABLESESSIONMISMATCH _HRESULT_TYPEDEF_(0x80248017L) + +// +// MessageId: WU_E_DS_SESSIONLOCKMISMATCH +// +// MessageText: +// +// A table was not closed because it is not associated with the session. +// +#define WU_E_DS_SESSIONLOCKMISMATCH _HRESULT_TYPEDEF_(0x80248018L) + +// +// MessageId: WU_E_DS_NEEDWINDOWSSERVICE +// +// MessageText: +// +// A request to remove the Windows Update service or to unregister it with Automatic Updates was declined because it is a built-in service and/or Automatic Updates cannot fall back to another service. +// +#define WU_E_DS_NEEDWINDOWSSERVICE _HRESULT_TYPEDEF_(0x80248019L) + +// +// MessageId: WU_E_DS_INVALIDOPERATION +// +// MessageText: +// +// A request was declined because the operation is not allowed. +// +#define WU_E_DS_INVALIDOPERATION _HRESULT_TYPEDEF_(0x8024801AL) + +// +// MessageId: WU_E_DS_SCHEMAMISMATCH +// +// MessageText: +// +// The schema of the current data store and the schema of a table in a backup XML document do not match. +// +#define WU_E_DS_SCHEMAMISMATCH _HRESULT_TYPEDEF_(0x8024801BL) + +// +// MessageId: WU_E_DS_RESETREQUIRED +// +// MessageText: +// +// The data store requires a session reset; release the session and retry with a new session. +// +#define WU_E_DS_RESETREQUIRED _HRESULT_TYPEDEF_(0x8024801CL) + +// +// MessageId: WU_E_DS_IMPERSONATED +// +// MessageText: +// +// A data store operation did not complete because it was requested with an impersonated identity. +// +#define WU_E_DS_IMPERSONATED _HRESULT_TYPEDEF_(0x8024801DL) + +// +// MessageId: WU_E_DS_UNEXPECTED +// +// MessageText: +// +// A data store error not covered by another WU_E_DS_* code. +// +#define WU_E_DS_UNEXPECTED _HRESULT_TYPEDEF_(0x80248FFFL) + +///////////////////////////////////////////////////////////////////////////// +//Inventory Errors +///////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_INVENTORY_PARSEFAILED +// +// MessageText: +// +// Parsing of the rule file failed. +// +#define WU_E_INVENTORY_PARSEFAILED _HRESULT_TYPEDEF_(0x80249001L) + +// +// MessageId: WU_E_INVENTORY_GET_INVENTORY_TYPE_FAILED +// +// MessageText: +// +// Failed to get the requested inventory type from the server. +// +#define WU_E_INVENTORY_GET_INVENTORY_TYPE_FAILED _HRESULT_TYPEDEF_(0x80249002L) + +// +// MessageId: WU_E_INVENTORY_RESULT_UPLOAD_FAILED +// +// MessageText: +// +// Failed to upload inventory result to the server. +// +#define WU_E_INVENTORY_RESULT_UPLOAD_FAILED _HRESULT_TYPEDEF_(0x80249003L) + +// +// MessageId: WU_E_INVENTORY_UNEXPECTED +// +// MessageText: +// +// There was an inventory error not covered by another error code. +// +#define WU_E_INVENTORY_UNEXPECTED _HRESULT_TYPEDEF_(0x80249004L) + +// +// MessageId: WU_E_INVENTORY_WMI_ERROR +// +// MessageText: +// +// A WMI error occurred when enumerating the instances for a particular class. +// +#define WU_E_INVENTORY_WMI_ERROR _HRESULT_TYPEDEF_(0x80249005L) + +///////////////////////////////////////////////////////////////////////////// +//AU Errors +///////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_AU_NOSERVICE +// +// MessageText: +// +// Automatic Updates was unable to service incoming requests. +// +#define WU_E_AU_NOSERVICE _HRESULT_TYPEDEF_(0x8024A000L) + +// +// MessageId: WU_E_AU_NONLEGACYSERVER +// +// MessageText: +// +// The old version of the Automatic Updates client has stopped because the WSUS server has been upgraded. +// +#define WU_E_AU_NONLEGACYSERVER _HRESULT_TYPEDEF_(0x8024A002L) + +// +// MessageId: WU_E_AU_LEGACYCLIENTDISABLED +// +// MessageText: +// +// The old version of the Automatic Updates client was disabled. +// +#define WU_E_AU_LEGACYCLIENTDISABLED _HRESULT_TYPEDEF_(0x8024A003L) + +// +// MessageId: WU_E_AU_PAUSED +// +// MessageText: +// +// Automatic Updates was unable to process incoming requests because it was paused. +// +#define WU_E_AU_PAUSED _HRESULT_TYPEDEF_(0x8024A004L) + +// +// MessageId: WU_E_AU_NO_REGISTERED_SERVICE +// +// MessageText: +// +// No unmanaged service is registered with AU. +// +#define WU_E_AU_NO_REGISTERED_SERVICE _HRESULT_TYPEDEF_(0x8024A005L) + +// +// MessageId: WU_E_AU_UNEXPECTED +// +// MessageText: +// +// An Automatic Updates error not covered by another WU_E_AU * code. +// +#define WU_E_AU_UNEXPECTED _HRESULT_TYPEDEF_(0x8024AFFFL) + +////////////////////////////////////////////////////////////////////////////// +// update handler errors +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_UH_REMOTEUNAVAILABLE +// +// MessageText: +// +// A request for a remote update handler could not be completed because no remote process is available. +// +#define WU_E_UH_REMOTEUNAVAILABLE _HRESULT_TYPEDEF_(0x80242000L) + +// +// MessageId: WU_E_UH_LOCALONLY +// +// MessageText: +// +// A request for a remote update handler could not be completed because the handler is local only. +// +#define WU_E_UH_LOCALONLY _HRESULT_TYPEDEF_(0x80242001L) + +// +// MessageId: WU_E_UH_UNKNOWNHANDLER +// +// MessageText: +// +// A request for an update handler could not be completed because the handler could not be recognized. +// +#define WU_E_UH_UNKNOWNHANDLER _HRESULT_TYPEDEF_(0x80242002L) + +// +// MessageId: WU_E_UH_REMOTEALREADYACTIVE +// +// MessageText: +// +// A remote update handler could not be created because one already exists. +// +#define WU_E_UH_REMOTEALREADYACTIVE _HRESULT_TYPEDEF_(0x80242003L) + +// +// MessageId: WU_E_UH_DOESNOTSUPPORTACTION +// +// MessageText: +// +// A request for the handler to install (uninstall) an update could not be completed because the update does not support install (uninstall). +// +#define WU_E_UH_DOESNOTSUPPORTACTION _HRESULT_TYPEDEF_(0x80242004L) + +// +// MessageId: WU_E_UH_WRONGHANDLER +// +// MessageText: +// +// An operation did not complete because the wrong handler was specified. +// +#define WU_E_UH_WRONGHANDLER _HRESULT_TYPEDEF_(0x80242005L) + +// +// MessageId: WU_E_UH_INVALIDMETADATA +// +// MessageText: +// +// A handler operation could not be completed because the update contains invalid metadata. +// +#define WU_E_UH_INVALIDMETADATA _HRESULT_TYPEDEF_(0x80242006L) + +// +// MessageId: WU_E_UH_INSTALLERHUNG +// +// MessageText: +// +// An operation could not be completed because the installer exceeded the time limit. +// +#define WU_E_UH_INSTALLERHUNG _HRESULT_TYPEDEF_(0x80242007L) + +// +// MessageId: WU_E_UH_OPERATIONCANCELLED +// +// MessageText: +// +// An operation being done by the update handler was cancelled. +// +#define WU_E_UH_OPERATIONCANCELLED _HRESULT_TYPEDEF_(0x80242008L) + +// +// MessageId: WU_E_UH_BADHANDLERXML +// +// MessageText: +// +// An operation could not be completed because the handler-specific metadata is invalid. +// +#define WU_E_UH_BADHANDLERXML _HRESULT_TYPEDEF_(0x80242009L) + +// +// MessageId: WU_E_UH_CANREQUIREINPUT +// +// MessageText: +// +// A request to the handler to install an update could not be completed because the update requires user input. +// +#define WU_E_UH_CANREQUIREINPUT _HRESULT_TYPEDEF_(0x8024200AL) + +// +// MessageId: WU_E_UH_INSTALLERFAILURE +// +// MessageText: +// +// The installer failed to install (uninstall) one or more updates. +// +#define WU_E_UH_INSTALLERFAILURE _HRESULT_TYPEDEF_(0x8024200BL) + +// +// MessageId: WU_E_UH_FALLBACKTOSELFCONTAINED +// +// MessageText: +// +// The update handler should download self-contained content rather than delta-compressed content for the update. +// +#define WU_E_UH_FALLBACKTOSELFCONTAINED _HRESULT_TYPEDEF_(0x8024200CL) + +// +// MessageId: WU_E_UH_NEEDANOTHERDOWNLOAD +// +// MessageText: +// +// The update handler did not install the update because it needs to be downloaded again. +// +#define WU_E_UH_NEEDANOTHERDOWNLOAD _HRESULT_TYPEDEF_(0x8024200DL) + +// +// MessageId: WU_E_UH_NOTIFYFAILURE +// +// MessageText: +// +// The update handler failed to send notification of the status of the install (uninstall) operation. +// +#define WU_E_UH_NOTIFYFAILURE _HRESULT_TYPEDEF_(0x8024200EL) + +// +// MessageId: WU_E_UH_INCONSISTENT_FILE_NAMES +// +// MessageText: +// +// The file names contained in the update metadata and in the update package are inconsistent. +// +#define WU_E_UH_INCONSISTENT_FILE_NAMES _HRESULT_TYPEDEF_(0x8024200FL) + +// +// MessageId: WU_E_UH_FALLBACKERROR +// +// MessageText: +// +// The update handler failed to fall back to the self-contained content. +// +#define WU_E_UH_FALLBACKERROR _HRESULT_TYPEDEF_(0x80242010L) + +// +// MessageId: WU_E_UH_TOOMANYDOWNLOADREQUESTS +// +// MessageText: +// +// The update handler has exceeded the maximum number of download requests. +// +#define WU_E_UH_TOOMANYDOWNLOADREQUESTS _HRESULT_TYPEDEF_(0x80242011L) + +// +// MessageId: WU_E_UH_UNEXPECTEDCBSRESPONSE +// +// MessageText: +// +// The update handler has received an unexpected response from CBS. +// +#define WU_E_UH_UNEXPECTEDCBSRESPONSE _HRESULT_TYPEDEF_(0x80242012L) + +// +// MessageId: WU_E_UH_BADCBSPACKAGEID +// +// MessageText: +// +// The update metadata contains an invalid CBS package identifier. +// +#define WU_E_UH_BADCBSPACKAGEID _HRESULT_TYPEDEF_(0x80242013L) + +// +// MessageId: WU_E_UH_POSTREBOOTSTILLPENDING +// +// MessageText: +// +// The post-reboot operation for the update is still in progress. +// +#define WU_E_UH_POSTREBOOTSTILLPENDING _HRESULT_TYPEDEF_(0x80242014L) + +// +// MessageId: WU_E_UH_POSTREBOOTRESULTUNKNOWN +// +// MessageText: +// +// The result of the post-reboot operation for the update could not be determined. +// +#define WU_E_UH_POSTREBOOTRESULTUNKNOWN _HRESULT_TYPEDEF_(0x80242015L) + +// +// MessageId: WU_E_UH_POSTREBOOTUNEXPECTEDSTATE +// +// MessageText: +// +// The state of the update after its post-reboot operation has completed is unexpected. +// +#define WU_E_UH_POSTREBOOTUNEXPECTEDSTATE _HRESULT_TYPEDEF_(0x80242016L) + +// +// MessageId: WU_E_UH_NEW_SERVICING_STACK_REQUIRED +// +// MessageText: +// +// The OS servicing stack must be updated before this update is downloaded or installed. +// +#define WU_E_UH_NEW_SERVICING_STACK_REQUIRED _HRESULT_TYPEDEF_(0x80242017L) + +// +// MessageId: WU_E_UH_UNEXPECTED +// +// MessageText: +// +// An update handler error not covered by another WU_E_UH_* code. +// +#define WU_E_UH_UNEXPECTED _HRESULT_TYPEDEF_(0x80242FFFL) + +////////////////////////////////////////////////////////////////////////////// +// download manager errors +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_DM_URLNOTAVAILABLE +// +// MessageText: +// +// A download manager operation could not be completed because the requested file does not have a URL. +// +#define WU_E_DM_URLNOTAVAILABLE _HRESULT_TYPEDEF_(0x80246001L) + +// +// MessageId: WU_E_DM_INCORRECTFILEHASH +// +// MessageText: +// +// A download manager operation could not be completed because the file digest was not recognized. +// +#define WU_E_DM_INCORRECTFILEHASH _HRESULT_TYPEDEF_(0x80246002L) + +// +// MessageId: WU_E_DM_UNKNOWNALGORITHM +// +// MessageText: +// +// A download manager operation could not be completed because the file metadata requested an unrecognized hash algorithm. +// +#define WU_E_DM_UNKNOWNALGORITHM _HRESULT_TYPEDEF_(0x80246003L) + +// +// MessageId: WU_E_DM_NEEDDOWNLOADREQUEST +// +// MessageText: +// +// An operation could not be completed because a download request is required from the download handler. +// +#define WU_E_DM_NEEDDOWNLOADREQUEST _HRESULT_TYPEDEF_(0x80246004L) + +// +// MessageId: WU_E_DM_NONETWORK +// +// MessageText: +// +// A download manager operation could not be completed because the network connection was unavailable. +// +#define WU_E_DM_NONETWORK _HRESULT_TYPEDEF_(0x80246005L) + +// +// MessageId: WU_E_DM_WRONGBITSVERSION +// +// MessageText: +// +// A download manager operation could not be completed because the version of Background Intelligent Transfer Service (BITS) is incompatible. +// +#define WU_E_DM_WRONGBITSVERSION _HRESULT_TYPEDEF_(0x80246006L) + +// +// MessageId: WU_E_DM_NOTDOWNLOADED +// +// MessageText: +// +// The update has not been downloaded. +// +#define WU_E_DM_NOTDOWNLOADED _HRESULT_TYPEDEF_(0x80246007L) + +// +// MessageId: WU_E_DM_FAILTOCONNECTTOBITS +// +// MessageText: +// +// A download manager operation failed because the download manager was unable to connect the Background Intelligent Transfer Service (BITS). +// +#define WU_E_DM_FAILTOCONNECTTOBITS _HRESULT_TYPEDEF_(0x80246008L) + +// +// MessageId: WU_E_DM_BITSTRANSFERERROR +// +// MessageText: +// +// A download manager operation failed because there was an unspecified Background Intelligent Transfer Service (BITS) transfer error. +// +#define WU_E_DM_BITSTRANSFERERROR _HRESULT_TYPEDEF_(0x80246009L) + +// +// MessageId: WU_E_DM_DOWNLOADLOCATIONCHANGED +// +// MessageText: +// +// A download must be restarted because the location of the source of the download has changed. +// +#define WU_E_DM_DOWNLOADLOCATIONCHANGED _HRESULT_TYPEDEF_(0x8024600AL) + +// +// MessageId: WU_E_DM_CONTENTCHANGED +// +// MessageText: +// +// A download must be restarted because the update content changed in a new revision. +// +#define WU_E_DM_CONTENTCHANGED _HRESULT_TYPEDEF_(0x8024600BL) + +// +// MessageId: WU_E_DM_UNEXPECTED +// +// MessageText: +// +// There was a download manager error not covered by another WU_E_DM_* error code. +// +#define WU_E_DM_UNEXPECTED _HRESULT_TYPEDEF_(0x80246FFFL) + +////////////////////////////////////////////////////////////////////////////// +// Setup/SelfUpdate errors +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_SETUP_INVALID_INFDATA +// +// MessageText: +// +// Windows Update Agent could not be updated because an INF file contains invalid information. +// +#define WU_E_SETUP_INVALID_INFDATA _HRESULT_TYPEDEF_(0x8024D001L) + +// +// MessageId: WU_E_SETUP_INVALID_IDENTDATA +// +// MessageText: +// +// Windows Update Agent could not be updated because the wuident.cab file contains invalid information. +// +#define WU_E_SETUP_INVALID_IDENTDATA _HRESULT_TYPEDEF_(0x8024D002L) + +// +// MessageId: WU_E_SETUP_ALREADY_INITIALIZED +// +// MessageText: +// +// Windows Update Agent could not be updated because of an internal error that caused setup initialization to be performed twice. +// +#define WU_E_SETUP_ALREADY_INITIALIZED _HRESULT_TYPEDEF_(0x8024D003L) + +// +// MessageId: WU_E_SETUP_NOT_INITIALIZED +// +// MessageText: +// +// Windows Update Agent could not be updated because setup initialization never completed successfully. +// +#define WU_E_SETUP_NOT_INITIALIZED _HRESULT_TYPEDEF_(0x8024D004L) + +// +// MessageId: WU_E_SETUP_SOURCE_VERSION_MISMATCH +// +// MessageText: +// +// Windows Update Agent could not be updated because the versions specified in the INF do not match the actual source file versions. +// +#define WU_E_SETUP_SOURCE_VERSION_MISMATCH _HRESULT_TYPEDEF_(0x8024D005L) + +// +// MessageId: WU_E_SETUP_TARGET_VERSION_GREATER +// +// MessageText: +// +// Windows Update Agent could not be updated because a WUA file on the target system is newer than the corresponding source file. +// +#define WU_E_SETUP_TARGET_VERSION_GREATER _HRESULT_TYPEDEF_(0x8024D006L) + +// +// MessageId: WU_E_SETUP_REGISTRATION_FAILED +// +// MessageText: +// +// Windows Update Agent could not be updated because regsvr32.exe returned an error. +// +#define WU_E_SETUP_REGISTRATION_FAILED _HRESULT_TYPEDEF_(0x8024D007L) + +// +// MessageId: WU_E_SELFUPDATE_SKIP_ON_FAILURE +// +// MessageText: +// +// An update to the Windows Update Agent was skipped because previous attempts to update have failed. +// +#define WU_E_SELFUPDATE_SKIP_ON_FAILURE _HRESULT_TYPEDEF_(0x8024D008L) + +// +// MessageId: WU_E_SETUP_SKIP_UPDATE +// +// MessageText: +// +// An update to the Windows Update Agent was skipped due to a directive in the wuident.cab file. +// +#define WU_E_SETUP_SKIP_UPDATE _HRESULT_TYPEDEF_(0x8024D009L) + +// +// MessageId: WU_E_SETUP_UNSUPPORTED_CONFIGURATION +// +// MessageText: +// +// Windows Update Agent could not be updated because the current system configuration is not supported. +// +#define WU_E_SETUP_UNSUPPORTED_CONFIGURATION _HRESULT_TYPEDEF_(0x8024D00AL) + +// +// MessageId: WU_E_SETUP_BLOCKED_CONFIGURATION +// +// MessageText: +// +// Windows Update Agent could not be updated because the system is configured to block the update. +// +#define WU_E_SETUP_BLOCKED_CONFIGURATION _HRESULT_TYPEDEF_(0x8024D00BL) + +// +// MessageId: WU_E_SETUP_REBOOT_TO_FIX +// +// MessageText: +// +// Windows Update Agent could not be updated because a restart of the system is required. +// +#define WU_E_SETUP_REBOOT_TO_FIX _HRESULT_TYPEDEF_(0x8024D00CL) + +// +// MessageId: WU_E_SETUP_ALREADYRUNNING +// +// MessageText: +// +// Windows Update Agent setup is already running. +// +#define WU_E_SETUP_ALREADYRUNNING _HRESULT_TYPEDEF_(0x8024D00DL) + +// +// MessageId: WU_E_SETUP_REBOOTREQUIRED +// +// MessageText: +// +// Windows Update Agent setup package requires a reboot to complete installation. +// +#define WU_E_SETUP_REBOOTREQUIRED _HRESULT_TYPEDEF_(0x8024D00EL) + +// +// MessageId: WU_E_SETUP_HANDLER_EXEC_FAILURE +// +// MessageText: +// +// Windows Update Agent could not be updated because the setup handler failed during execution. +// +#define WU_E_SETUP_HANDLER_EXEC_FAILURE _HRESULT_TYPEDEF_(0x8024D00FL) + +// +// MessageId: WU_E_SETUP_INVALID_REGISTRY_DATA +// +// MessageText: +// +// Windows Update Agent could not be updated because the registry contains invalid information. +// +#define WU_E_SETUP_INVALID_REGISTRY_DATA _HRESULT_TYPEDEF_(0x8024D010L) + +// +// MessageId: WU_E_SELFUPDATE_REQUIRED +// +// MessageText: +// +// Windows Update Agent must be updated before search can continue. +// +#define WU_E_SELFUPDATE_REQUIRED _HRESULT_TYPEDEF_(0x8024D011L) + +// +// MessageId: WU_E_SELFUPDATE_REQUIRED_ADMIN +// +// MessageText: +// +// Windows Update Agent must be updated before search can continue. An administrator is required to perform the operation. +// +#define WU_E_SELFUPDATE_REQUIRED_ADMIN _HRESULT_TYPEDEF_(0x8024D012L) + +// +// MessageId: WU_E_SETUP_WRONG_SERVER_VERSION +// +// MessageText: +// +// Windows Update Agent could not be updated because the server does not contain update information for this version. +// +#define WU_E_SETUP_WRONG_SERVER_VERSION _HRESULT_TYPEDEF_(0x8024D013L) + +// +// MessageId: WU_E_SETUP_UNEXPECTED +// +// MessageText: +// +// Windows Update Agent could not be updated because of an error not covered by another WU_E_SETUP_* error code. +// +#define WU_E_SETUP_UNEXPECTED _HRESULT_TYPEDEF_(0x8024DFFFL) + +////////////////////////////////////////////////////////////////////////////// +// expression evaluator errors +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_EE_UNKNOWN_EXPRESSION +// +// MessageText: +// +// An expression evaluator operation could not be completed because an expression was unrecognized. +// +#define WU_E_EE_UNKNOWN_EXPRESSION _HRESULT_TYPEDEF_(0x8024E001L) + +// +// MessageId: WU_E_EE_INVALID_EXPRESSION +// +// MessageText: +// +// An expression evaluator operation could not be completed because an expression was invalid. +// +#define WU_E_EE_INVALID_EXPRESSION _HRESULT_TYPEDEF_(0x8024E002L) + +// +// MessageId: WU_E_EE_MISSING_METADATA +// +// MessageText: +// +// An expression evaluator operation could not be completed because an expression contains an incorrect number of metadata nodes. +// +#define WU_E_EE_MISSING_METADATA _HRESULT_TYPEDEF_(0x8024E003L) + +// +// MessageId: WU_E_EE_INVALID_VERSION +// +// MessageText: +// +// An expression evaluator operation could not be completed because the version of the serialized expression data is invalid. +// +#define WU_E_EE_INVALID_VERSION _HRESULT_TYPEDEF_(0x8024E004L) + +// +// MessageId: WU_E_EE_NOT_INITIALIZED +// +// MessageText: +// +// The expression evaluator could not be initialized. +// +#define WU_E_EE_NOT_INITIALIZED _HRESULT_TYPEDEF_(0x8024E005L) + +// +// MessageId: WU_E_EE_INVALID_ATTRIBUTEDATA +// +// MessageText: +// +// An expression evaluator operation could not be completed because there was an invalid attribute. +// +#define WU_E_EE_INVALID_ATTRIBUTEDATA _HRESULT_TYPEDEF_(0x8024E006L) + +// +// MessageId: WU_E_EE_CLUSTER_ERROR +// +// MessageText: +// +// An expression evaluator operation could not be completed because the cluster state of the computer could not be determined. +// +#define WU_E_EE_CLUSTER_ERROR _HRESULT_TYPEDEF_(0x8024E007L) + +// +// MessageId: WU_E_EE_UNEXPECTED +// +// MessageText: +// +// There was an expression evaluator error not covered by another WU_E_EE_* error code. +// +#define WU_E_EE_UNEXPECTED _HRESULT_TYPEDEF_(0x8024EFFFL) + +////////////////////////////////////////////////////////////////////////////// +// UI errors +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_INSTALLATION_RESULTS_UNKNOWN_VERSION +// +// MessageText: +// +// The results of download and installation could not be read from the registry due to an unrecognized data format version. +// +#define WU_E_INSTALLATION_RESULTS_UNKNOWN_VERSION _HRESULT_TYPEDEF_(0x80243001L) + +// +// MessageId: WU_E_INSTALLATION_RESULTS_INVALID_DATA +// +// MessageText: +// +// The results of download and installation could not be read from the registry due to an invalid data format. +// +#define WU_E_INSTALLATION_RESULTS_INVALID_DATA _HRESULT_TYPEDEF_(0x80243002L) + +// +// MessageId: WU_E_INSTALLATION_RESULTS_NOT_FOUND +// +// MessageText: +// +// The results of download and installation are not available; the operation may have failed to start. +// +#define WU_E_INSTALLATION_RESULTS_NOT_FOUND _HRESULT_TYPEDEF_(0x80243003L) + +// +// MessageId: WU_E_TRAYICON_FAILURE +// +// MessageText: +// +// A failure occurred when trying to create an icon in the taskbar notification area. +// +#define WU_E_TRAYICON_FAILURE _HRESULT_TYPEDEF_(0x80243004L) + +// +// MessageId: WU_E_NON_UI_MODE +// +// MessageText: +// +// Unable to show UI when in non-UI mode; WU client UI modules may not be installed. +// +#define WU_E_NON_UI_MODE _HRESULT_TYPEDEF_(0x80243FFDL) + +// +// MessageId: WU_E_WUCLTUI_UNSUPPORTED_VERSION +// +// MessageText: +// +// Unsupported version of WU client UI exported functions. +// +#define WU_E_WUCLTUI_UNSUPPORTED_VERSION _HRESULT_TYPEDEF_(0x80243FFEL) + +// +// MessageId: WU_E_AUCLIENT_UNEXPECTED +// +// MessageText: +// +// There was a user interface error not covered by another WU_E_AUCLIENT_* error code. +// +#define WU_E_AUCLIENT_UNEXPECTED _HRESULT_TYPEDEF_(0x80243FFFL) + +////////////////////////////////////////////////////////////////////////////// +// reporter errors +/////////////////////////////////////////////////////////////////////////////// +// +// MessageId: WU_E_REPORTER_EVENTCACHECORRUPT +// +// MessageText: +// +// The event cache file was defective. +// +#define WU_E_REPORTER_EVENTCACHECORRUPT _HRESULT_TYPEDEF_(0x8024F001L) + +// +// MessageId: WU_E_REPORTER_EVENTNAMESPACEPARSEFAILED +// +// MessageText: +// +// The XML in the event namespace descriptor could not be parsed. +// +#define WU_E_REPORTER_EVENTNAMESPACEPARSEFAILED _HRESULT_TYPEDEF_(0x8024F002L) + +// +// MessageId: WU_E_INVALID_EVENT +// +// MessageText: +// +// The XML in the event namespace descriptor could not be parsed. +// +#define WU_E_INVALID_EVENT _HRESULT_TYPEDEF_(0x8024F003L) + +// +// MessageId: WU_E_SERVER_BUSY +// +// MessageText: +// +// The server rejected an event because the server was too busy. +// +#define WU_E_SERVER_BUSY _HRESULT_TYPEDEF_(0x8024F004L) + +// +// MessageId: WU_E_REPORTER_UNEXPECTED +// +// MessageText: +// +// There was a reporter error not covered by another error code. +// +#define WU_E_REPORTER_UNEXPECTED _HRESULT_TYPEDEF_(0x8024FFFFL) + +// +// MessageId: WU_E_OL_INVALID_SCANFILE +// +// MessageText: +// +// An operation could not be completed because the scan package was invalid. +// +#define WU_E_OL_INVALID_SCANFILE _HRESULT_TYPEDEF_(0x80247001L) + +// +// MessageId: WU_E_OL_NEWCLIENT_REQUIRED +// +// MessageText: +// +// An operation could not be completed because the scan package requires a greater version of the Windows Update Agent. +// +#define WU_E_OL_NEWCLIENT_REQUIRED _HRESULT_TYPEDEF_(0x80247002L) + +// +// MessageId: WU_E_OL_UNEXPECTED +// +// MessageText: +// +// Search using the scan package failed. +// +#define WU_E_OL_UNEXPECTED _HRESULT_TYPEDEF_(0x80247FFFL) + +#endif //_WUERROR_ diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix/iisca.wxs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix/iisca.wxs new file mode 100644 index 0000000000..5bf076f74d --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix/iisca.wxs @@ -0,0 +1,209 @@ + + + + + + + + + + + + + + + + + + + NOT SKIPINSTALLCA AND NOT( REMOVE="ALL" ) + NOT SKIPUNINSTALLCA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NOT SKIPINSTALLWINDOWSHOTFIX + NOT SKIPREBOOTIFREQUIRED + + + + + + + + + + + + + + + + + NOT SKIPMAKESHORTCUTELEVATED + + + + + + + + + + + + + + + + + + + + + + + NOT SKIPSETCONSOLEPROPERTIES + + + + + + + + + + + + + + + + + + + + + + + + NOT SKIPINSTALLHTTPLISTENER + NOT SKIPUNINSTALLHTTPLISTENER + + + + + + + + + + + Installed And PATCH + Installed And PATCH + Installed And PATCH + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix/setupstrings.wxl new file mode 100644 index 0000000000..ccb1a67cfb --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix/setupstrings.wxl @@ -0,0 +1,255 @@ + + + + + + + 1033 + + + + Shared Config Install Options + Select option for installation to IIS shared configuration + Update shared configuration on install + You are installing this module onto an IIS server that is using shared configuration. If additional IIS servers are using this shared configuration then you will need to install this module onto all of these machines. To minimize disruption of the individual web servers you will need to install this module in the following steps: First, on all but the last of the machines you should install the module without updating shared config. Do this by not selecting the checkbox + below. This will install all binaries and files necessary for the module on each machine without making any changes to shared config. Second, on the last machine you will need to verify that the user idenity you are running under has read and write access to the applicationhost.config file on the UNC share. Then you should install the module and select the update shared config option below. + + + Initializing WebConfig custom action + Updating web.config + + + + IIS Advanced Logging + Enables advanced logging of IIS pipeline data. + IIS Advanced Logging + Enables creation of custom log files with extensible field selection. + Update for IIS Advanced Logging + + + + IIS Transform Manager + Beta + Enables the Transform Manager IIS Media Services. + IIS Transform Manager + Enables creation of media transforms. + IIS Transform Manager Host + Service host for [ProductName]. + IIS Transform Manager + Batch convert on-demand media files to alternate file and container formats. + An IIS Transform Manager 1.0 Expression Encoder SP Task package is installed on the computer. You must uninstall it before you can install [ProductName]. + + Microsoft .NET Framework 3.5 is required to install [ProductName]. Use the 'Add Features Wizard' in Server Manager to install .NET Framework 3.5.1 Features or use 'Turn Windows features on or off' to turn on Microsoft .NET Framework 3.5. + [ProductName] requires Microsoft Windows Vista Service Pack 1 or later. + [ProductName] cannot be installed on Vista Home Basic. + [ProductName] requires Microsoft Windows 7 Service Pack 1 or later. + + + Microsoft Web Management Service 2 + Microsoft Web Management Service + Installs the basic features of the [ProductName]. + Microsoft Web Management Service 2 + The Web Management Service enables remote and delegated management capabilities for administrators to manage for the Web server, sites and applications present on this machine. + + + Microsoft URL Rewrite Module 1.1 for IIS 7 + Update for URL Rewrite Module 1.1 for IIS 7 + URL Rewrite + Enables URL and content rewriting capabilities to IIS 7. + User Interface + Configures the URL Rewrite Module feature in IIS Manager. + + + IIS URL Rewrite Module 2 + Update for IIS URL Rewrite Module 2 + URL Rewrite + Enables URL and content rewriting capabilities to IIS 7. + User Interface + Configures the URL Rewrite Module feature in IIS Manager. + + + Administration Pack for IIS 7.0 + Installs the basic features of the [ProductName]. + 1252 + Administration Pack for IIS 7.0 + Microsoft Corporation + This version of the operating system is not supported. [ProductName] can be installed only on Windows Server 2008, or Windows Vista Service Pack 1, and higher. + ASP.Net Features + ASP.NET includes Authorization and Error Pages features, which let you manage your authorization and custom error settings. + Authentication + ASP.Net Authentication Description. + Authorization + ASP.NET Authorization lets you configure rules for authorizing users to access your Web sites and applications. + Error Pages + ASP.NET Error Pages lets you configure HTTP error responses to return when errors occur. + Modules + ASP.Net Modules Description. + Handlers + ASP.Net Handers Description. + Configuration Editor + Configuration Editor lets you manage your configuration files in IIS Manager by letting you edit sections, attributes, elements, and collections in your configuration files. + Request Filtering + Request Filtering lets you configure filtering rules for your Web site, and restrict protocol and content behavior. + Fast CGI + FastCGI lets you configure process pool settings for the FastCGI applications on your Web server. + + + Dynamic IP Restrictions for IIS 7 Setup + + + + + + + + + + + + + Dynamic IP Restrictions for IIS 7 - Beta + Dynamic IP Restrictions for IIS 7 - Beta 2 + Dynamic IP Restrictions for IIS 7 - Beta 3 + + Dynamic IP Restrictions for IIS 7 - Release Candidate + Dynamic IP Restrictions for IIS 7 - Release Candidate 2 + Dynamic IP Restrictions for IIS 7 - Release Candidate 3 + + Dynamic IP Restrictions for IIS 7 + + Dynamic IP Restrictions for IIS 7 + Dynamic IP Restrictions User Interface for IIS 7 + + Dynamic IP Restrictions for IIS 7 - Beta was found on this machine. Please uninstall it and try again + + + WebDAV 7.5 For IIS 7.0 + The IIS 7.0 CoreWebEngine and W3SVC features must be installed to use this product. + WebDAV Server Module + WebDAV Administration User Interface + + + IIS Search Engine Optimization Toolkit 1.0 + IIS Search Engine Optimization Toolkit 1.0 + Search Engine Optimization (SEO) Toolkit 1.0 + This installer database contains the logic and data required to install IIS Search Engine Optimization Toolkit 1.0. + + + IIS Editor + + + IIS Reports + Log Parser is not installed on this machine, Please install Log Parser 2.2 from http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07 and then proceed with IIS Reports installation + + + Microsoft Web Farm Framework + Microsoft External Cache + Web Farm Framework is a requisite for installing Application Request Routing. Please install the Web Farm Framework. + Microsoft Application Request Routing 3.0 + Runtime + Adds the Application Request Routing capabilities to IIS. + User Interface + Configures the Application Request Routing feature in IIS Manager. + + + Microsoft CORS Module + IIS CORS Runtime + Adds the support of cross-origin resource sharing (CORS) to IIS. + + + Microsoft IIS Compression + IIS Compression + Adds the Zlib and Brotli compression schemes to IIS. + + + IIS Team Template Module + Template Module Runtime + An example of an IIS module. + + + Microsoft Windows PowerShell snap-in for IIS 7.0 + + + IIS Manager Publishing for IIS 7.0 + Publishing User Interface + + + Application Warm-Up 1.0 for IIS 7.5 + + + + An incompatible product, [CONFLICTING_PRODUCT_NAME], is on this computer. Installation of [ProductName] cannot continue. To install this product, use Add/Remove Programs on the Control Panel to remove [CONFLICTING_PRODUCT_NAME]. + Administrator privilege is required to install [ProductName]. + IIS Version 7.0 is required to use [ProductName]. + IIS Version 7.0 or greater is required to install [ProductName]. + IIS Version 7.5 or greater is required to install [ProductName]. + IIS Version 7 or 7.5 is required to install [ProductName]. + IIS Version 8.0 or greater is required to install [ProductName]. + The beta version of [ProductName] was found on this machine. + A newer version of [ProductName] was found on this machine. + Setup cannot continue because another instance of [ProductName] is already installed on this computer. Please uninstall it first and then re-launch this installation. + The IIS 7.0 CoreWebEngine and W3SVC features must be installed to use [ProductName]. + The IIS Management Console must be installed to use [ProductName]. + Please stop both services Windows Process Activation Service (WAS) and Web Management Service (WMSvc) before installing [ProductName]. You will need to start the services after installing [ProductName]. + IIS Metabase is required to install [ProductName]. + The 64-bit version of [ProductName] cannot be installed on a 32-bit edition of Microsoft Windows. + The 32-bit version of [ProductName] cannot be installed on a 64-bit edition of Microsoft Windows. + Microsoft .NET Framework Version 2.0 or greater is required to install [ProductName]. + Microsoft .NET Framework Version 3.5 or greater is required to install [ProductName]. Use 'Add Features' under the Server Manager to install Microsoft .Net Version 3.5. + Microsoft .NET Framework Version 4.0 or greater is required to install [ProductName]. + Please install Microsoft .NET Framework Version 2.0 Service Pack 1 (or a later service pack), before installing [ProductName]. + The Windows Update (wuauserv) service cannot be disabled, it is required to install [ProductName]. + The PowerShell snap-in is part of Windows Operating System. Please install it via 'Programs and Features' or 'Server Manager'. + Microsoft Web Platform Installer Version 3.0 or greater is required to install [ProductName]. + + Setup failed to detect shared configuration. + Shared configuration is enabled for IIS. Installing [ProductName] is not supported when using shared configuration. Please disable shared configuration before installing this feature. + + Please stop World Wide Web Publishing Service (W3SVC) before installing [ProductName]. You will need to start the service after installation. + IIS PowerShell Management Console + IIS PowerShell snap-in + IIS PowerShell snap-in requires PowerShell v1.0 or v2.0 installed + IIS PowerShell snap-in requires WAS and configuration installed + This is a bogus string. + + + Microsoft Web Farm Framework Version 2.2 + Microsoft Web Farm Agent Version 2.2 + Web Farm Service + Web Farm Service + Web Farm Controller Service + Web Farm Controller Service + Web Farm Agent Service + Web Farm Agent Service + Web Platform Installer is a pre-requisite for installing Web Farm Framework. Please install the Web Plaform Installer from http://www.microsoft.com/web/downloads/platform.aspx. + Web Deployment Tool is a pre-requisite for installing Web Farm Framework. Please install the Web Deployment Tool from http://www.iis.net/download/WebDeploy. + + + Microsoft Web Hosting Framework + Web Hosting Framework + Web Hosting roles and features. + Hosting Framework + Hosting Framework provides API's and PowerShell commands for managing the Web Hosting. + Web Role + Web Role installs Dynamic WAS service and URL Rewrite provider for Web Hosting. + Antares Express + Deploys a Control Panel configuration optimized for single machine setup. + Load Balancer Role + Load Balancer Role configures Application Request Router to route based on Web Hosting rules. + Hosting Controller + Hosting Controller extends the Web Farm Framework 2.0 to work with Web Hosting. + Publishing Role + Installs support for Web Deploy and FTP publishing. + This is a PowerShell snap-in that contains cmdlets for managing Microsoft Web Hosting infrastructure. + Dynamic WAS Service + Windows Process Activation service optimized for high density Web Hosting. + Resource Metering Service + Installs the Resource Metering service that enables collecting and publishing both runtime and health information. + Resource Metering + Enables collecting and publishing runtime and health information from Web Role. + Hosting Quota Enforcement + Monitors the web sites resource usage and executes custom actions when usage quota is exceeded. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/ElevatedShortcut.wxi b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/ElevatedShortcut.wxi new file mode 100644 index 0000000000..ee5e988a1b --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/ElevatedShortcut.wxi @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + NOT SKIPMAKESHORTCUTELEVATED + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/FixPatchingBehavior.wxi b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/FixPatchingBehavior.wxi new file mode 100644 index 0000000000..ae6e3b76d5 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/FixPatchingBehavior.wxi @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + Installed And PATCH + Installed And PATCH + Installed And PATCH + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/HttpListener.wxi b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/HttpListener.wxi new file mode 100644 index 0000000000..68db6852d1 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/HttpListener.wxi @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NOT SKIPINSTALLHTTPLISTENER + NOT SKIPUNINSTALLHTTPLISTENER + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/ShortcutConsoleProperties.wxi b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/ShortcutConsoleProperties.wxi new file mode 100644 index 0000000000..236e0f51ef --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/ShortcutConsoleProperties.wxi @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + NOT SKIPSETCONSOLEPROPERTIES + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/WindowsHotfix.wxi b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/WindowsHotfix.wxi new file mode 100644 index 0000000000..78b26d6404 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/WindowsHotfix.wxi @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + NOT SKIPINSTALLWINDOWSHOTFIX + NOT SKIPREBOOTIFREQUIRED + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/iisca.wxs b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/iisca.wxs new file mode 100644 index 0000000000..68324e1484 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/wix3/iisca.wxs @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + NOT SKIPINSTALLCA + (NOT SKIPUNINSTALLCA) AND (IISCOREWEBENGINEINSTALLED = "#1") AND (IISW3SVCINSTALLED = "#1") + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/include.wxi b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/include.wxi new file mode 100644 index 0000000000..e22cdce8a4 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/include.wxi @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CHS/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CHS/misc/setupstrings.wxl new file mode 100644 index 0000000000..3acd415df3 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CHS/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 2052 + + + + 共享配置安装选项 + 选择用于安装到 IIS 共享配置的选项 + 安装时更新共享配置 + 您要将此模块安装到使用共享配置的 IIS 服务器上。如果其他 IIS 服务器正在使用此共享配置,则您需要将此模块安装到所有这些计算机上。为了尽可能减少对各个 Web 服务器的中断,您需要按以下步骤安装此模块: 首先,在除最后一台计算机外的所有其他计算机上,安装此模块但不更新共享配置。可通过不选中下面的复选框来执行 +此操作。这将在每台计算机上安装模块所需的所有二进制文件和其他文件,而不对共享配置进行任何更改。其次,在最后一台计算机上,您需要确保运行时使用的用户标识对 UNC 共享上的 applicationhost.config 文件具有读取和写入权限。然后,您应安装此模块并选中下面的更新共享配置选项。 + + + 正在初始化 WebConfig 自定义操作 + 正在更新 web.config + + + + IIS 高级日志 + 启用 IIS 管道数据高级日志。 + IIS 高级日志 + 允许通过选择可扩展的字段来创建自定义日志文件。 + 适用于 IIS 高级日志记录的更新 + + + + IIS Transform Manager + Beta + 启用 Transform Manager IIS 媒体服务。 + IIS Transform Manager + 允许创建媒体转换。 + IIS Transform Manager 主机 + [ProductName] 的服务主机。 + IIS Transform Manager + 根据需要将媒体文件批量转换为其他文件和容器格式。 + 计算机上安装了某个 IIS Transform Manager 1.0 表达式编码器 SP 任务包。您必须先将它卸载,然后才能安装 [ProductName]。 + + 安装 [ProductName] 需要 Microsoft .NET Framework 3.5。可在服务器管理器中使用“添加功能向导”来安装 .NET Framework 3.5.1 功能,或使用“打开或关闭 Windows 功能”来打开 Microsoft .NET Framework 3.5。 + + + + IIS 数字版权管理 + Beta + 启用平滑流式处理演示的数字版权管理。 + + + 未安装 ASP.NET + + + + + + + + + 此计算机上找到了 IIS 平滑流式处理 - Beta。无法继续安装 [ProductName]。若要安装此产品,请使用控制面板中的“添加/删除程序”将 IIS 平滑流式处理 - Beta 删除。 + 此计算机上装有 IIS Media Services 的不兼容版本。无法继续安装 [ProductName]。若要安装此产品,请使用控制面板中的“添加/删除程序”将 IIS Media Services 删除。 + 此计算机上已安装了该产品的新版本,或者可以在此计算机上安装该产品的新版本。无法继续安装 [ProductName]。若要安装该产品的新版本,请使用控制面板上的“添加/删除程序”更新 IIS Media Services。 + 需要进行播放列表文件转换 + + + + + 发现早期版本的 IIS Media Services 文件 + + + + + 发现 Beta IIS Media Services 文件 + + + + + + IIS Media Pack 1.0 + 适用于 IIS Media Pack 1.0 的更新 + IIS Media Services 2.0 + 适用于 IIS Media Services 2.0 的更新 + IIS Media Services 3.0 + IIS Media Services 3.0 TAP 2 + 适用于 IIS Media Services 3.0 的更新 + IIS Media Services 功能和工具。 + IIS Media Services 5 Premium 功能和工具。 + IIS Media Services 4.0 Beta 1 + IIS Media Services 4.0 + IIS Media Services 4.5 Beta 1 + IIS Media Services 5 Premium + + Web 播放列表 + 对客户端播放在播放列表中引用的媒体资产的行为进行控制。 + 会话帮助程序 + 启用 ASP.NET 会话状态持续性。(需要适用于 Web 服务器(IIS)的 ASP.NET 角色服务)。 + 用户界面 + 在 IIS 管理器中配置 Web 播放列表功能。 + + 比特率限制 + 对客户端下载的文件的传送进行限制,从而节省带宽。 + 用户界面 + 在 IIS 管理器中配置比特率限制功能。 + + 资产 + 对客户端的按需资产启用 HTTP 自适应流式处理。 + 用户界面 + 在 IIS 管理器中配置平滑流式处理功能。 + + 频道 + 对客户端的频道广播启用 HTTP 自适应流式处理。 + 用户界面 + 在 IIS 管理器中配置实时平滑流式处理功能。 + + 数字版权管理 + 提供平滑流式处理媒体的加密和许可。 + 用户界面 + 配置 IIS 管理器中的数字版权管理功能。 + + [ProductName] 需要 Microsoft Windows Vista Service Pack 1 或更高版本。 + 无法在 Vista Home Basic 上安装 [ProductName]。 + [ProductName] 需要 Microsoft Windows 7 Service Pack 1 或更高版本。 + + + IIS 数据库管理器 + IIS 数据库管理器 + + + Microsoft Web 管理服务 2 + Microsoft Web 管理服务 + 安装 [ProductName] 的基本功能。 + Microsoft Web 管理服务 2 + Web 管理服务提供远程和委派管理功能,供管理员管理位于此计算机上的 Web 服务器、站点和应用程序。 + + + 用于 IIS 7 的 Microsoft URL 重写模块 1.1 + 对用于 IIS 7 的 URL 重写模块 1.1 的更新 + URL 重写 + 对 IIS 7 启用 URL 和内容重写功能。 + 用户界面 + 在 IIS 管理器中配置 URL 重写模块功能。 + + + IIS URL 重写模块 2 + 适用于 IIS URL 重写模块 2 的更新 + URL 重写 + 对 IIS 7 启用 URL 和内容重写功能。 + 用户界面 + 在 IIS 管理器中配置 URL 重写模块功能。 + + + Administration Pack for IIS 7.0 + 安装 [ProductName] 的基本功能。 + 1252 + Administration Pack for IIS 7.0 + Microsoft Corporation + 不支持此操作系统版本。[ProductName] 只能安装在 Windows Server 2008 或 Windows Vista Service Pack 1 及更高版本上。 + ASP.Net 功能 + ASP.NET 包括“授权”和“错误页”功能,利用这些功能,您可以管理您的授权和自定义错误设置。 + 身份验证 + ASP.Net 身份验证说明。 + 授权 + 利用 ASP.NET 授权,您可以配置规则,以便允许用户访问您的网站和应用程序。 + 错误页 + 利用 ASP.NET 错误页,您可以配置要在发生错误时返回的 HTTP 错误响应。 + 模块 + ASP.Net 模块说明。 + 处理程序 + ASP.Net 处理程序说明。 + 配置编辑器 + 利用配置编辑器,您可以编辑配置文件中的节、属性、元素和集合,从而在 IIS 管理器中管理配置文件。 + 请求筛选 + 利用请求筛选,您可以为您的网站配置筛选规则,并限制协议和内容行为。 + FastCGI + 利用 FastCGI,您可以在 Web 服务器上为 FastCGI 应用程序配置进程池设置。 + + + 安装 Dynamic IP Restrictions for IIS 7 + + + + + + + + + + + + + Dynamic IP Restrictions for IIS 7 - Beta + Dynamic IP Restrictions for IIS 7 - Beta 2 + Dynamic IP Restrictions for IIS 7 - Beta 3 + + Dynamic IP Restrictions for IIS 7 - 候选发布 + Dynamic IP Restrictions for IIS 7 - 候选发布 2 + Dynamic IP Restrictions for IIS 7 - 候选发布 3 + + Dynamic IP Restrictions for IIS 7 - RTW + + Dynamic IP Restrictions for IIS 7 + Dynamic IP Restrictions for IIS 7 用户界面 + + IIS 7 的动态 IP 限制 - 在此计算机上找到 Beta 版本。请卸载它,然后重试 + + + WebDAV 7.5 For IIS 7.0 + 若要使用此产品,必须安装 IIS 7.0 CoreWebEngine 和 W3SVC 功能。 + WebDAV 服务器模块 + WebDAV 管理用户界面 + + + IIS 搜索引擎优化工具包 1.0 + IIS 搜索引擎优化工具包 1.0 + 搜索引擎优化(SEO)工具包 1.0 + 此安装程序数据库包含安装 IIS 搜索引擎优化工具包 1.0 所需的逻辑和数据。 + + + IIS 编辑器 + + + IIS Reports + 未在此计算机上安装 Log Parser,请通过 http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07 安装 Log Parser 2.2,然后继续安装 IIS Reports + + + 未找到系统必备包。请运行 setup.exe 以解析依赖关系并安装此程序。 + Microsoft SQL Server 2008 管理对象是安装 IIS 数据库管理器的必备组件。可以从 http://go.microsoft.com/fwlink/?LinkID=150946 安装 Micrsoft SQL Server 2008 管理对象。 + Microsoft SQL Server System CLR Types 是安装 IIS 数据库管理器的必备组件。可以从 http://go.microsoft.com/fwlink/?LinkID=150949 安装 Microsoft SQL Server System CLR Types。 + + + Microsoft Web Farm Framework + Microsoft External Cache + Web Farm Framework 是安装 Application Request Routing 的必备组件。请安装 Web Farm Framework。 + Microsoft Application Request Routing 2.5 + 运行时 + 向 IIS 7 添加 Application Request Routing 功能。 + 用户界面 + 在 IIS 管理器中配置应用程序请求路由功能。 + + + 用于 IIS 7.0 的 Microsoft Windows PowerShell 管理单元 + + + Microsoft Web 平台安装程序 4.0 + Microsoft Web 平台安装程序 + [ProductName] 需要 Windows XP SP2、Windows 2003 SP1、Windows Vista 或更高版本。 + [ProductName] 需要 Windows XP Service Pack 3、Windows Server 2003 Service Pack 2 或更高版本。 + + + Microsoft Windows Azure 服务安装程序 + Microsoft Windows Azure 服务安装程序 + + + Internet Information Services (IIS) 7+ 管理器 + IIS 管理器客户端 + 远程支持 + 此产品需要 Windows XP SP2、Windows 2003 SP1、Windows Vista SP1 或 Windows 7 或更高版本 + 未安装 IIS 管理控制台,但需要此控制台才能管理远程 IIS 服务器。在安装远程管理支持之前,请先安装 IIS 管理控制台,方法是打开“控制面板”->“程序”->“打开或关闭 Windows 功能”,然后在 Ineternet Information Services 功能中选择 IIS 管理控制台。 + 此产品在 Windows Server 2008、Windows Server 2008 R2 或更高版本中不是必需的。请打开服务器管理器并在 Web 服务器角色的角色服务中选择 IIS 管理控制台,从而安装 IIS 管理控制台。 + + + IIS Manager Publishing for IIS 7.0 + Publishing 用户界面 + + + Application Warm-Up 1.0 for IIS 7.5 + + + + 此计算机上安装了不兼容的产品 [CONFLICTING_PRODUCT_NAME]。无法继续安装 [ProductName]。要安装此产品,请使用控制面板上的“添加/删除程序”来删除 [CONFLICTING_PRODUCT_NAME]。 + 若要安装 [ProductName],需要管理员特权。 + 若要使用 [ProductName],需要 IIS 7.0 版。 + 若要安装 [ProductName],需要 IIS 7.0 版或更高版本。 + 安装 [ProductName] 必须具有 IIS 7.5 版或更高版本。 + 要安装 [产品名称],要求使用 IIS 版本 7 或 7.5。 + 已在此计算机上找到 [ProductName] 的 Beta 版本。 + 已在此计算机上找到 [ProductName] 的新版本。 + 安装程序无法继续,因为已在此计算机上安装了另一个 [ProductName] 实例。请先将其卸载,然后重新启动此安装。 + 若要使用 [ProductName],必须安装 IIS 7.0 CoreWebEngine 和 W3SVC 功能。 + 要使用 [ProductName],必须安装 IIS 管理控制台。 + 请先停止 Windows Process Activation Service (WAS)和 Web 管理服务(WMSvc),然后安装 [ProductName]。您将需要在安装 [ProductName] 后启动这两个服务。 + 若要安装 [ProductName],需要 IIS 元数据库。 + 无法在 32 位版本的 Microsoft Windows 上安装 64 位版本的 [ProductName]。 + 无法在 64 位版本的 Microsoft Windows 上安装 32 位版本的 [ProductName]。 + 若要安装 [ProductName],需要 Microsoft .NET Framework 2.0 版或更高版本。 + 需要有 Microsoft .NET Framework 3.5 版或更高版本才能安装 [ProductName]。使用“服务器管理器”下的“添加功能”可安装 Microsoft .Net 3.5 版。 + 需要有 Microsoft .NET Framework 4.0 版或更高版本才能安装 [ProductName]。 + 请先安装 Microsoft .NET Framework 2.0 Service Pack 1(或更高版本的 Service Pack),然后再安装 [ProductName]。 + 不能禁用 Windows Update (wuauserv)服务,安装 [ProductName] 需要此服务。 + PowerShell 管理单元是 Windows 操作系统的一部分。请通过“程序和功能”或“服务器管理器”来安装它。 + 需要有 Microsoft Web 平台安装程序 3.0 版或更高版本才能安装 [ProductName]。 + + 安装程序无法检测到共享配置。 + 已为 IIS 启用了共享配置。使用共享配置时,不支持安装 [ProductName]。请先禁用共享配置,然后再安装此功能。 + + 请在安装 [ProductName] 之前停止 World Wide Web 发布服务(W3SVC)。您将需要在安装后启动此服务。 + IIS PowerShell 管理控制台 + IIS PowerShell 管理单元 + IIS PowerShell 管理单元要求安装 PowerShell v1.0 或 v2.0 + IIS PowerShell 管理单元要求安装 WAS 和配置 + 这是一个假字符串。 + + + Microsoft Web Farm Framework 版本 2.2 + Microsoft Web 场代理版本 2.2 + Web 场服务 + Web 场服务 + Web 场控制器服务 + Web 场控制器服务 + Web 场代理服务 + Web 场代理服务 + Web 平台安装程序是安装 Web Farm Framework 的必备组件。请从 http://www.microsoft.com/web/downloads/platform.aspx 安装 Web 平台安装程序。 + Web 部署工具是安装 Web Farm Framework 的必备组件。请从 http://www.iis.net/download/WebDeploy 安装 Web 部署工具。 + + + Microsoft Web Hosting 框架 + Web Hosting 框架 + Web Hosting 角色和功能。 + Hosting 框架 + Hosting 框架提供用于管理 Web Hosting 的 API 和 PowerShell 命令。 + Web 角色 + Web 角色为 Web Hosting 安装动态 WAS 服务和 URL 重写提供程序。 + Antares Express + 部署已针对单一计算机设置优化的控制面板配置。 + 负载平衡器角色 + 负载平衡器将应用程序请求路由器配置为基于 Web Hosting 规则进行路由。 + Hosting 控制器 + Hosting 控制器扩展了 Web Farm Framework 2.0,使之能够与 Web Hosting 一起使用。 + 发布角色 + 安装针对 Web Deploy 和 FTP 发布功能的支持。 + 这是 PowerShell 管理单元,其中包含用于管理 Microsoft Web Hosting 基础架构的 cmdlet。 + 动态 WAS 服务 + 已为高密度 Web Hosting 优化了 Windows Process Activation Service。 + 资源计量服务 + 安装资源计量服务,该服务可以收集和发布运行时信息和运行状况信息。 + 资源计量 + 允许从 Web 角色收集和发布运行时信息与运行状况信息。 + 强制实施宿主配额 + 监视网站资源使用情况,并在超出使用配额时执行自定义操作。 + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CHT/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CHT/misc/setupstrings.wxl new file mode 100644 index 0000000000..fc4295abf7 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CHT/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 1028 + + + + 共用設定安裝選項 + 請選取安裝 IIS 共用設定的選項 + 在安裝時更新共用設定 + 您正在將這個模組安裝到使用共用設定的 IIS 伺服器上。如果有其他 IIS 伺服器也使用這個共用設定,您必須將這個模組安裝到所有電腦。若要將個別網頁伺服器發生中斷的情形降至最低,您必須依照下列步驟安裝這個模組: 首先,在所有電腦上 (最後一部電腦例外) 安裝模組,而且不要更新共用設定。請不要選取下面的核取方塊。 +這將會為每部電腦上的模組安裝所有二進位檔和必要檔案,而不會對共用設定進行任何變更。第二,在最後一部電腦上,您必須確認執行作業所使用的使用者識別具有讀取和寫入 UNC 共用上 applicationhost.config 檔案的權限。然後,您應安裝模組並選取下面的更新共用設定選項。 + + + 正在初始化 WebConfig 自訂動作 + 正在更新 web.config + + + + IIS 進階記錄 + 啟用 IIS 管線資料的進階記錄。 + IIS 進階記錄 + 啟用以可延伸的欄位選擇建立自訂記錄檔。 + IIS Advanced Logging 的更新 + + + + IIS Transform Manager + Beta + 啟用 Transform Manager IIS Media Services。 + IIS Transform Manager + 啟用媒體轉換的建立。 + IIS Transform Manager 主機 + [ProductName] 的服務主機。 + IIS Transform Manager + 將隨選媒體檔案批次轉換為替代的檔案及容器格式。 + IIS Transform Manager 1.0 Expression Encoder SP Task 套件已安裝於電腦。您必須先將它解除安裝,才能安裝 [ProductName]。 + + 需要 Microsoft .NET Framework 3.5 才能安裝 [ProductName]。請使用 [\[]伺服器管理員[\]] 中的 [\[]新增功能精靈[\]] 安裝 .NET Framework 3.5.1 功能,或者使用 [\[]開啟或關閉 Windows 功能[\]] 開啟 Microsoft .NET Framework 3.5。 + + + + IIS 數位版權管理 + Beta + 啟用 Smooth Streaming 展示檔的數位版權管理。 + + + 未安裝 ASP.NET + + + + + + + + + 在這部電腦上找到 IIS Smooth Streaming - Beta。[ProductName] 的安裝無法繼續。若要安裝這個產品,請使用 [控制台] 中的 [新增/移除程式] 移除 IIS Smooth Streaming - Beta。 + 這部電腦已經安裝不相容版本的 IIS Media Services。[ProductName] 的安裝無法繼續。若要安裝這個產品,請使用 [控制台] 中的 [新增/移除程式] 移除 IIS Media Services。 + 這部電腦可能已安裝這個產品的新版本或有新版本可供安裝。[ProductName] 的安裝無法繼續。若要安裝這個產品的新版本,請使用 [控制台] 中的 [新增/移除程式] 更新 IIS Media Services。 + 需要播放清單檔案轉換 + + + + + 找到舊的 IIS Media Services 檔案 + + + + + 找到 Beta IIS Media Services 檔案 + + + + + + IIS Media Pack 1.0 + IIS Media Pack 1.0 的更新 + IIS Media Services 2.0 + IIS Media Services 2.0 的更新 + IIS Media Services 3.0 + IIS Media Services 3.0 TAP 2 + IIS Media Services 3.0 的更新 + IIS Media Services 功能和工具。 + IIS Media Services 5 Premium 功能及工具。 + IIS Media Services 4.0 Beta 1 + IIS Media Services 4.0 + IIS Media Services 4.5 Beta 1 + IIS Media Services 5 Premium + + Web 播放清單 + 控制播放清單中參考之媒體資產的用戶端播放方式。 + Session Helper + 啟用 ASP.NET 工作階段狀態持續性 (需要網頁伺服器 (IIS) 的 ASP.NET 角色服務)。 + 使用者介面 + 設定 IIS 管理員中的 Web 播放清單功能。 + + 位元速度節流設定 + 藉由節流設定傳遞用戶端下載的檔案,以節省頻寬。 + 使用者介面 + 設定 IIS 管理員中的位元速度節流設定功能。 + + 資產 + 啟用對用戶端的隨選資產 HTTP 彈性資料流。 + 使用者介面 + 設定 IIS 管理員中的 Smooth Streaming 功能。 + + 通道 + 啟用對用戶端的通道廣播 HTTP 彈性資料流。 + 使用者介面 + 設定 IIS 管理員中的 Live Smooth Streaming 功能。 + + 數位版權管理 + 提供 Smooth Streaming 媒體的加密和授權。 + 使用者介面 + 設定 IIS 管理員中的數位版權管理功能。 + + [ProductName] 需要 Microsoft Windows Vista Service Pack 1 或更新版本。 + 無法將 [ProductName] 安裝在 Vista Home Basic 上。 + [ProductName] 需要 Microsoft Windows 7 Service Pack 1 或更新版本。 + + + IIS Database Manager + IIS Database Manager + + + Microsoft Web Management Service 2 + Microsoft Web Management Service + 安裝 [ProductName] 的基本功能。 + Microsoft Web Management Service 2 + Web Management Service 可啟用遠端及委派管理功能,讓系統管理員管理呈現在這部電腦上的網頁伺服器、站台及應用程式。 + + + Microsoft URL Rewrite Module 1.1 for IIS 7 + URL Rewrite Module 1.1 for IIS 7 的更新 + URL Rewrite + 啟用 IIS 7 的 URL 和內容重寫功能。 + 使用者介面 + 設定 IIS 管理員中的 URL Rewrite Module 功能。 + + + IIS URL Rewrite Module 2 + IIS URL Rewrite Module 2 的更新 + URL Rewrite + 啟用 IIS 7 的 URL 和內容重寫功能。 + 使用者介面 + 設定 IIS 管理員中的 URL Rewrite Module 功能。 + + + Administration Pack for IIS 7.0 + 安裝 [ProductName] 的基本功能。 + 1252 + Administration Pack for IIS 7.0 + Microsoft Corporation + 不支援這個版本的作業系統。[ProductName] 只能安裝在 Windows Server 2008 或 Windows Vista Service Pack 1 和更新版本上。 + ASP.NET 功能 + ASP.NET 包含授權和錯誤網頁功能,可讓您管理授權和自訂錯誤訊息。 + 驗證 + ASP.NET 驗證描述。 + 授權 + ASP.NET 授權可讓您設定規則,來授權使用者存取您的網站和應用程式。 + 錯誤網頁 + ASP.NET 錯誤網頁可讓您設定發生錯誤時要傳回的 HTTP 錯誤回應。 + 模組 + ASP.NET 模組描述。 + 處理常式 + ASP.NET 處理常式描述。 + 設定編輯器 + 設定編輯器可讓您管理 IIS 管理員中的設定檔案,讓您編輯設定檔案中的區段、屬性、元素和集合。 + 要求篩選 + 要求篩選可讓您為網站設定篩選規則,並限制通訊協定和內容的行為。 + Fast CGI + FastCGI 可讓您設定您的網頁伺服器上 FastCGI 應用程式的處理序集區設定。 + + + Dynamic IP Restrictions for IIS 7 安裝程式 + + + + + + + + + + + + + Dynamic IP Restrictions for IIS 7 - Beta + Dynamic IP Restrictions for IIS 7 - Beta 2 + Dynamic IP Restrictions for IIS 7 - Beta 3 + + Dynamic IP Restrictions for IIS 7 - 發行候選版本 + Dynamic IP Restrictions for IIS 7 - 發行候選版本 2 + Dynamic IP Restrictions for IIS 7 - 發行候選版本 3 + + Dynamic IP Restrictions for IIS 7 - RTW + + Dynamic IP Restrictions for IIS 7 + IIS 7 的動態 IP 限制使用者介面 + + 在這部電腦上發現 Dynamic IP Restrictions for IIS 7 - Beta 版。請解除安裝,然後再試一次 + + + WebDAV 7.5 For IIS 7.0 + 必須安裝 IIS 7.0 CoreWebEngine 和 W3SVC 功能才能使用這個產品。 + WebDAV 伺服器模組 + WebDAV Administration 使用者介面 + + + IIS Search Engine Optimization Toolkit 1.0 + IIS Search Engine Optimization Toolkit 1.0 + Search Engine Optimization (SEO) Toolkit 1.0 + 這個安裝程式資料庫內含安裝 IIS Search Engine Optimization Toolkit 1.0 所需的邏輯和資料。 + + + IIS 編輯器 + + + IIS 報告 + 這部電腦上未安裝記錄檔剖析器。請從 http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07 安裝記錄檔剖析器 2.2,然後繼續安裝 IIS 報告 + + + 找不到必要條件封裝。請執行 setup.exe 解決相依性,然後再安裝這個程式。 + Microsoft SQL Server 2008 管理物件是安裝 IIS Database Manager 的必要條件。您可以從 http://go.microsoft.com/fwlink/?LinkID=150946 安裝 Micrsoft SQL Server 2008 管理物件。 + Microsoft SQL Server 系統 CLR 類型是安裝 IIS Database Manager 的必要條件。您可以從 http://go.microsoft.com/fwlink/?LinkID=150949 安裝 Microsoft SQL Server 系統 CLR 類型。 + + + Microsoft Web Farm Framework + Microsoft External Cache + Web Farm Framework 是安裝應用程式要求路由的必要條件。請安裝 Web Farm Framework。 + Microsoft Application Request Routing 2.5 + 執行階段 + 將應用程式要求路由功能新增至 IIS。 + 使用者介面 + 設定 IIS 管理員中的應用程式要求路由功能。 + + + IIS 7.0 的 Microsoft Windows PowerShell 嵌入式管理單元 + + + Microsoft Web Platform Installer 4.0 + Microsoft Web Platform Installer + [ProductName] 需要 Windows XP SP2、Windows 2003 SP1、Windows Vista 或更新版本。 + [ProductName] 需要 Windows XP Service Pack 3、Windows Server 2003 Service Pack 2 (含) 以上版本。 + + + Microsoft Windows Azure Services 安裝程式 + Microsoft Windows Azure Services 安裝程式 + + + Internet Information Services (IIS) 7+ 管理員 + IIS 管理員用戶端 + 遠端支援 + 這個產品需要 Windows XP SP2、Windows 2003 SP1、Windows Vista SP1、Windows 7 或更新版本 + 未安裝 IIS 管理主控台,但需要它才能管理遠端 IIS 伺服器。安裝遠端管理支援之前,請先安裝 IIS 管理主控台,安裝方式是開啟 [控制台]->[所有程式]->[開啟或關閉 Windows 功能],並在 Internet Information Services 功能中選取 [IIS 管理主控台]。 + 在 Windows Server 2008、Windows Server 2008 R2 或更新版本中不需要這個產品。請安裝 IIS 管理主控台,安裝方式是開啟伺服器管理員,然後在網頁伺服器角色的角色服務中選取 [IIS 管理主控台]。 + + + IIS Manager Publishing for IIS 7.0 + 發行使用者介面 + + + Application Warm-Up 1.0 for IIS 7.5 + + + + 不相容的產品 [CONFLICTING_PRODUCT_NAME] 出現在這部電腦上。無法繼續安裝 [ProductName]。若要安裝這個產品,請使用 [控制台] 的 [新增/移除程式移除 [CONFLICTING_PRODUCT_NAME]。 + 需要有系統管理員權限,才能安裝 [ProductName]。 + 需要 IIS 7.0 版才能使用 [ProductName]。 + 需要 IIS 7.0 版或更新版本,才能安裝 [ProductName]。 + 需要 IIS 7.5 版或更新版本,才能安裝 [ProductName]。 + 需要 IIS 第 7 版或第 7.5 版才能安裝 [ProductName]。 + 在這部電腦上發現 [ProductName] 的 Beta 版。 + 在這部電腦上發現 [ProductName] 較新的版本。 + 安裝程式無法繼續,因為這部電腦上已安裝另一份 [ProductName]。請先解除該安裝後,再重新啟動這個安裝。 + 必須安裝 IIS 7.0 CoreWebEngine 和 W3SVC 功能才能使用 [ProductName]。 + 必須安裝 IIS 管理主控台才能使用 [ProductName]。 + 安裝 [ProductName] 前,請先停止 Windows 處理序啟用服務 (WAS) 和 Web Management Service (WMSvc) 兩個服務。您必須在安裝 [ProductName] 後再啟動服務。 + 需要 IIS Metabase 才能安裝 [ProductName]。 + 無法將 64 位元版本的 [ProductName] 安裝在 32 位元版本的 Microsoft Windows 上。 + 無法將 32 位元版本的 [ProductName] 安裝在 64 位元版本的 Microsoft Windows 上。 + 需要 Microsoft .NET Framework 2.0 版本或更新版本,才能安裝 [ProductName]。 + 必須安裝 Microsoft .NET Framework 3.5 (含) 以上版本,才能安裝 [ProductName]。請使用伺服器管理員底下的「新增功能」安裝 Microsoft .NET 3.5 版。 + 需要 Microsoft .NET Framework 4 (含) 以上版本才能安裝 [ProductName]。 + 請先安裝 Microsoft .NET Framework 2.0 版 Service Pack 1 (或更新版的 Service Pack),再安裝 [ProductName]。 + 無法停用 Windows Update (wuauserv) 服務,需要它才能安裝 [ProductName]。 + PowerShell 嵌入式管理單元是 Windows 作業系統的一部分。請用 [程式和功能] 或 [伺服器管理員] 進行安裝。 + 需要 Microsoft Web Platform Installer 3.0 (含) 以上版本才能安裝 [ProductName]。 + + 安裝程式偵測不到共用設定。 + 已為 IIS 啟用共用設定。不支援在使用共用設定時安裝 [ProductName]。請先停用共用設定,再安裝這項功能。 + + 安裝 [ProductName] 前,請先停止 World Wide Web Publishing 服務 (W3SVC)。您必須在安裝後再啟動服務。 + IIS PowerShell 管理主控台 + IIS PowerShell 嵌入式管理單元 + IIS PowerShell 嵌入式管理單元要求必須已安裝 PowerShell v1.0 或 v2.0 + IIS PowerShell 嵌入式管理單元要求必須已安裝 WAS 和設定 + 這是假的字串。 + + + Microsoft Web Farm Framework 2.2版 + Microsoft Web Farm Agent 2.2 版 + Web 伺服陣列服務 + Web 伺服陣列服務 + Web 伺服陣列控制器服務 + Web 伺服陣列控制器服務 + Web 伺服陣列代理程式服務 + Web 伺服陣列代理程式服務 + Web Platform Installer 是安裝 Web Farm Framework 2.0 的必要元件。請從 http://www.microsoft.com/web/downloads/platform.aspx 安裝 Web Plaform Installer。 + Web Deployment Tool 是安裝 Web Farm Framework 的必要元件。請從 http://www.iis.net/download/WebDeploy 安裝 Web Deployment Tool。 + + + Microsoft Web Hosting Framework + Web Hosting Framework + Web Hosting 角色及功能。 + Hosting Framework + Hosting Framework 提供用於管理 Web Hosting 的 API 命令和 PowerShell 命令。 + Web 角色 + Web 角色會安裝 Web Hosting 的 Dynamic WAS 服務及 URL Rewrite 提供者。 + Antares Express + 部署已針對單一電腦環境最佳化的控制台設定。 + 負載平衡器角色 + 負載平衡器角色會將應用程式要求路由器設定為根據 Web Hosting 規則進行路由。 + 主機控制器 + 主機控制器會擴充 Web Farm Framework 2.0 以搭配 Web Hosting 運作。 + 發行角色 + 安裝 Web Deploy 及 FTP 發行的支援。 + 這是包含 Cmdlet 的 PowerShell 嵌入式管理單元,可用來管理 Microsoft Web Hosting 基礎結構。 + 動態 WAS 服務 + 針對高密度 Web Hosting 最佳化的 Windows Process Activation 服務。 + 資源計量服務 + 安裝資源計量服務,此服務可收集和發行執行階段和健康狀態資訊。 + 資源計量 + 可從 Web 角色收集及發行執行階段和健康狀態資訊。 + 主機配額強制 + 監視網站資源使用量,並且在超過使用量配額時執行自訂動作。 + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CSY/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CSY/misc/setupstrings.wxl new file mode 100644 index 0000000000..2e4fca8c5c --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/CSY/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 1029 + + + + Možnosti instalace sdílené konfigurace + Vyberte možnosti instalace pro sdílenou konfiguraci služby IIS. + Při instalaci aktualizovat sdílenou konfiguraci + Tento modul instalujete na server služby IIS, který používá sdílenou konfiguraci. Používají-li tuto sdílenou konfiguraci další servery služby IIS, bude tento modul nainstalován na všechny tyto servery. Chcete-li co nejméně narušit jednotlivé webové servery, nainstalujte tento modul následovně: Nejprve na všechny servery kromě jednoho nainstalujte modul, aniž byste aktualizovali sdílenou konfiguraci. To provedete tak, že zrušíte zaškrtnutí následujícího + políčka. Tak nainstalujete všechny binární i ostatní soubory modulu na každý server, ale sdílená konfigurace zůstane beze změn. Následně na posledním serveru ověřte, zda má uživatelský účet, se kterým jste přihlášeni, dostatečná oprávnění ke čtení a zápisu do souboru applicationhost.config ve sdíleném úložišti UNC. Poté nainstalujte modul a vyberte níže uvedenou možnost aktualizace sdílené konfigurace. + + + Probíhá inicializace vlastní akce souboru web.config. + Probíhá aktualizace souboru web.config. + + + + Rozšířené protokolování Internetové informační služby + Umožňuje rozšířené protokolování dat kanálu IIS. + Rozšířené protokolování Internetové informační služby + Umožňuje vytváření vlastních souborů protokolu s rozšířeným výběrem polí. + Aktualizace pro rozšířené protokolování Internetové informační služby + + + + Správce transformace služby IIS + Beta + Povoluje správce transformace služby IIS Media Services. + Správce transformace služby IIS + Umožňuje tvorbu mediálních transformací. + Hostitel správce transformace služby IIS + Hostitel služby pro [ProductName]. + Správce transformace služby IIS + Dávkový převod souborů médií na vyžádání na jiné formáty souborů a kontejneru + V počítači je nainstalován balíček Expression Encoder SP Task Správce transformace služby IIS 1.0. Ten je třeba před instalací produktu [ProductName] odinstalovat. + + K instalaci produktu [ProductName] je vyžadováno rozhraní Microsoft .NET Framework 3.5. Můžete nainstalovat funkce rozhraní .NET Framework 3.5.1 pomocí Průvodce přidáním funkcí ve Správci serveru nebo zapnout rozhraní Microsoft .NET Framework 3.5 pomocí položky Zapnout nebo vypnout funkce systému Windows. + + + + Správa digitálních práv služby IIS + Beta + Povoluje správu digitálních práv pro prezentace Smooth Streaming. + + + Není nainstalována součást ASP.NET. + + + + + + + + + V tomto počítači byla nalezena beta verze rozšíření IIS Smooth Streaming. Instalace produktu [ProductName] nemůže pokračovat. Pokud chcete tento produkt nainstalovat, pomocí ovládacího panelu Přidat nebo odebrat programy odeberte položku IIS Smooth Streaming – Beta. + V tomto počítači je nekompatibilní verze služby IIS Media Services. Instalace produktu [ProductName] nemůže pokračovat. Pokud chcete tento produkt nainstalovat, pomocí ovládacího panelu Přidat nebo odebrat programy odeberte položku IIS Media Services. + V tomto počítači je již nainstalována nebo je k dispozici k instalaci novější verze tohoto produktu. Instalace produktu [ProductName] nemůže pokračovat. Pokud chcete nainstalovat novější verzi tohoto produktu, pomocí ovládacího panelu Přidat nebo odebrat programy aktualizujte položku IIS Media Services. + Je nutný převod souboru seznamu stop. + + + + + Byly nalezeny starší soubory služby IIS Media Services. + + + + + Byly nalezeny soubory beta verze služby IIS Media Services. + + + + + + IIS Media Pack 1.0 + Aktualizace pro sadu IIS Media Pack 1.0 + IIS Media Services 2.0 + Aktualizace pro službu IIS Media Services 2.0 + IIS Media Services 3.0 + IIS Media Services 3.0 TAP 2 + Aktualizace pro službu IIS Media Services 3.0 + Součásti a nástroje služby IIS Media Services. + Funkce a nástroje služby IIS Media Services 5 Premium + IIS Media Services 4.0 Beta 1 + IIS Media Services 4.0 + IIS Media Services 4.5 Beta 1 + IIS Media Services 5 Premium + + Webové seznamy stop + Řídí přehrávání mediálních materiálů odkazovaných v seznamech stop pro klienta. + Pomocník relace + Umožňuje trvalost stavu relace ASP.NET. (Je požadována služba role ASP.NET pro roli Webový server (IIS)). + Uživatelské rozhraní + Konfiguruje funkci Webové seznamy stop ve Správci služby IIS. + + Omezení přenosové rychlosti + Uspoří šířku pásma omezením doručování souborů stahovaných klienty. + Uživatelské rozhraní + Konfiguruje funkci Omezení přenosové rychlosti ve Správci služby IIS. + + Aktiva + Umožňuje vysílání adaptivních datových proudů protokolu HTTP aktiv na vyžádání pro klienty. + Uživatelské rozhraní + Konfiguruje funkci Smooth Streaming ve Správci služby IIS. + + Kanály + Umožňuje vysílání adaptivních datových proudů protokolu HTTP všesmerového vysílání kanálů pro klienty. + Uživatelské rozhraní + Konfiguruje funkci Live Smooth Streaming ve Správci služby IIS. + + Správa digitálních práv (DRM) + Zajišťuje šifrování a správu licencí médií Smooth Streaming. + Uživatelské rozhraní + Konfiguruje funkci správy digitálních práv ve správci služby IIS. + + [ProductName] požaduje systém Microsoft Windows Vista Service Pack 1 nebo novější. + [ProductName] nelze nainstalovat v systému Vista Home Basic. + [ProductName] požaduje systém Microsoft Windows 7 Service Pack 1 nebo novější. + + + Správce databáze služby IIS + Správce databáze služby IIS + + + Služba webové správy Microsoft 2 + Služba webové správy Microsoft + Nainstaluje základní součásti produktu [ProductName]. + Služba webové správy Microsoft 2 + Služba webové správy umožňuje vzdáleným a delegovaným funkcím správy pracovat s webovým serverem, weby a aplikacemi, které jsou uloženy v tomto počítači. + + + Microsoft URL Rewrite Module 1.1 for IIS 7 + Aktualizace pro produkt URL Rewrite Module 1.1 for IIS 7 + Přepisování adres URL + Dává službě IIS 7 možnost přepisovat adresy URL a obsah. + Uživatelské rozhraní + Konfiguruje funkci URL Rewrite Module ve Správci služby IIS. + + + IIS URL Rewrite Module 2 + Aktualizace pro produkt IIS URL Rewrite Module 2 + Přepisování adres URL + Dává službě IIS 7 možnost přepisovat adresy URL a obsah. + Uživatelské rozhraní + Konfiguruje funkci URL Rewrite Module ve Správci služby IIS. + + + Balíček pro správu služby IIS 7.0 + Nainstaluje základní součásti produktu [ProductName]. + 1250 + Balíček pro správu služby IIS 7.0 + Microsoft Corporation + Tato verze operačního systému není podporována. Produkt [ProductName] lze nainstalovat pouze v systémech Windows Server 2008 nebo Windows Vista Service Pack 1 a novějších. + Součásti ASP.NET + Technologie ASP.NET obsahuje součásti Autorizace a Chybové stránky, které umožňují spravovat nastavení autorizace a vlastních chyb. + Ověřování + Popis ověřování ASP.NET. + Autorizace + Autorizace ASP.NET umožňuje konfigurovat pravidla pro autorizaci uživatelů pro přístup k vašim webům a aplikacím. + Chybové stránky + Součást Chybové stránky ASP.NET umožňuje konfigurovat chybové odpovědi protokolu HTTP (stránky vrácené při chybě). + Moduly + Popis modulů ASP.NET. + Obslužné rutiny + Popis obslužných rutin ASP.NET. + Editor konfigurací + Editor konfigurací umožňuje spravovat konfigurační soubory ve Správci služby IIS. Umožňuje upravovat sekce, atributy, elementy a kolekce v konfiguračních souborech. + Filtrování požadavků + Funkce Filtrování žádostí umožňuje konfigurovat pravidla filtrování pro vaše weby a stanovit omezení pro protokol a chování obsahu. + FastCGI + Rozšíření FastCGI umožňuje konfigurovat nastavení fondu procesů pro aplikace FastCGI na vašem webovém serveru. + + + Dynamická omezení IP adres pro službu IIS 7 – instalace + + + + + + + + + + + + + Dynamická omezení IP adres pro službu IIS 7 – beta + Dynamická omezení IP adres pro službu IIS 7 – beta 2 + Dynamická omezení IP adres pro službu IIS 7 – beta 3 + + Dynamická omezení IP adres pro službu IIS 7 – Release Candidate + Dynamická omezení IP adres pro službu IIS 7 – Release Candidate 2 + Dynamická omezení IP adres pro službu IIS 7 – Release Candidate 3 + + Dynamická omezení IP adres pro službu IIS 7 – RTW + + Dynamická omezení IP adres pro službu IIS 7 + Uživatelské rozhraní pro dynamického omezení IP adres pro službu IIS 7 + + Na tomto serveru byla zjištěn dynamická omezení IP adres pro službu IIS 7 – Beta. Odinstalujte službu a opakujte akci. + + + WebDAV 7.5 pro službu IIS 7.0 + Tento produkt lze používat pouze tehdy, jsou-li nainstalovány součásti webového jádra a W3SVC služby IIS 7.0. + Modul serveru WebDAV + Uživatelské rozhraní pro správu protokolu WebDAV + + + Sada nástrojů optimalizace pro vyhledávací weby 1.0 + Sada nástrojů optimalizace pro vyhledávací weby 1.0 + Sada nástrojů optimalizace pro vyhledávací weby (SEO) 1.0 + Databáze instalačního programu obsahuje logiku a data vyžadovaná k instalaci sady nástrojů optimalizace pro vyhledávací weby služby IIS ve verzi 1.0. + + + Editor služby IIS + + + Sestavy služby IIS + V tomto počítači není nainstalován analyzátor protokolu Log Parser. Nainstalujte nástroj Log Parser 2.2 ze stránky http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07 a pokračujte dále v instalaci součásti Sestavy služby IIS. + + + Nebyly nalezeny požadované balíčky. Spusťte soubor setup.exe, abyste vyřešili potíže se závislostmi, a potom nainstalujte tento program. + Microsoft SQL Server 2008 Management Objects je požadovaným produktem pro instalaci Správce databáze služby IIS. Produkt Microsoft SQL Server 2008 Management Objects lze nainstalovat ze stránky http://go.microsoft.com/fwlink/?LinkID=150946. + Microsoft SQL Server System CLR Types je požadovaným produktem pro instalaci Správce databáze služby IIS. Produkt Microsoft SQL Server System CLR Types lze nainstalovat ze stránky http://go.microsoft.com/fwlink/?LinkID=150949. + + + Microsoft Web Farm Framework + Microsoft External Cache + Technologie Směrování žádostí na aplikace požaduje, aby byla nainstalováno rozhraní Web Farm Framework. Nainstalujte rozhraní Web Farm Framework. + Microsoft Application Request Routing 2.5 + Modul runtime + Přidá do služby IIS možnosti směrování žádostí na aplikace. + Uživatelské rozhraní + Konfiguruje funkci směrování žádostí na aplikace ve správci služby IIS. + + + Modul snap-in Microsoft Windows PowerShell pro službu IIS 7.0 + + + Instalace webové platformy Microsoft 4.0 + Instalační služba webové platformy Microsoft + Produkt [ProductName] požaduje systém Windows XP SP2, Windows 2003 SP1, Windows Vista nebo novější. + Produkt [ProductName] vyžaduje systém Windows XP Service Pack 3, Windows Server 2003 Service Pack 2 nebo novější. + + + Instalační program služby Microsoft Windows Azure Services + Instalační program služby Microsoft Windows Azure Services + + + Správce Internetové informační služby (IIS) 7+ + Klient Správce služby IIS + Podpora vzdálené komunikace + Tento produkt vyžaduje systém Windows XP SP2, Windows 2003 SP1, Windows Vista SP1, Windows 7 nebo novější. + Není nainstalována konzola pro správu služby IIS, která je nutná pro správu vzdálených serverů služby IIS. Před instalací podpory vzdálené správy nainstalujte konzolu pro správu služby IIS: Přejděte na Ovládací panely ->Programy-> Zapnout nebo vypnout funkce systému Windows a v součásti Internetová informační služba vyberte položku Konzola pro správu služby IIS. + Tento produkt není požadován v systémech Windows Server 2008 nebo Windows Server 2008 R2 nebo novějších. Nainstalujte konzolu pro správu služby IIS otevřením Správce serveru a výběrem položky Konzola pro správu služby IIS v uzlu Služby rolí pro roli Webový server. + + + Publikování Správce služby IIS pro službu IIS 7.0 + Uživatelské rozhraní publikování + + + Application Warm-Up 1.0 pro službu IIS 7.5 + + + + V tomto počítači je nekompatibilní produkt [CONFLICTING_PRODUCT_NAME]. Instalace produktu [ProductName] nemůže pokračovat. Chcete-li tento produkt nainstalovat, odeberte pomocí funkce Přidat nebo odebrat programy v Ovládacích panelech produkt [CONFLICTING_PRODUCT_NAME]. + K instalaci produktu [ProductName] jsou nutná oprávnění správce. + Produkt [ProductName] lze používat pouze ve verzi 7.0 služby IIS. + K instalaci produktu [ProductName] je požadována služba IIS verze 7.0 nebo vyšší. + K instalaci produktu [ProductName] je požadována služba IIS verze 7.5 nebo vyšší. + K instalaci produktu [ProductName] je vyžadována služba IIS verze 7 nebo 7.5. + V tomto počítači byla nalezena beta verze produktu [ProductName]. + V tomto počítači byla nalezena novější verze produktu [ProductName]. + Instalační program nemůže pokračovat, protože v tomto počítači je již nainstalována jiná instance produktu [ProductName]. Odinstalujte tuto instanci a poté znovu spusťte instalaci. + Produkt [ProductName] lze používat pouze tehdy, jsou-li nainstalovány součásti webového jádra a W3SVC služby IIS 7.0. + Produkt [ProductName] lze používat pouze v případě, že je nainstalována konzola pro správu služby IIS. + Před instalací produktu [ProductName] je třeba zastavit Aktivační službu procesů systému Windows (WAS) a Službu webové správy (WMSvc). Po instalaci produktu [ProductName] bude třeba tyto služby opět spustit. + K instalaci produktu [ProductName] je požadována metabáze služby IIS. + 64bitovou verzi produktu [ProductName] nelze nainstalovat do 32bitové edice systému Microsoft Windows. + 32bitovou verzi produktu [ProductName] nelze nainstalovat do 64bitové edice systému Microsoft Windows. + K instalaci produktu [ProductName] je požadováno rozhraní Microsoft .NET Framework 2.0 nebo vyšší. + K instalaci produktu [ProductName] je vyžadováno rozhraní Microsoft .NET Framework 3.5 nebo vyšší. Nainstalujte toto rozhraní pomocí tlačítka Přidat funkce ve správci serveru. + K instalaci produktu [ProductName] je vyžadováno rozhraní Microsoft .NET Framework 4.0 nebo vyšší. + Před instalací produktu [ProductName] nainstalujte rozhraní Microsoft .NET Framework verze 2.0 Service Pack 1 (nebo novější aktualizaci Service Pack). + Služba Windows Update (wuauserv) nemůže být zakázána. Je požadována pro instalaci produktu [ProductName]. + Modul snap-in PowerShell je součástí operačního systému Windows. Nainstalujte jej prostřednictvím ovládacího panelu Programy a funkce nebo prostřednictvím Správce serveru. + K instalaci produktu [ProductName] je vyžadována Instalace webové platformy společnosti Microsoft verze 3.0 nebo vyšší. + + Instalačnímu programu se nepodařilo zjistit sdílenou konfiguraci. + Pro službu IIS je povolena sdílená konfigurace. Instalace produktu [ProductName] není podporována při použití sdílené konfigurace. Před instalací této součásti je třeba sdílenou konfiguraci zakázat. + + Před instalací produktu [ProductName] zastavte Službu publikování na webu (W3SVC). Po instalaci bude třeba ji opět spustit. + Konzola pro správu prostředí PowerShell služby IIS + Modul snap-in PowerShell služby IIS + Modul snap-in PowerShell služby IIS požaduje, aby byl nainstalována součást PowerShell v1.0 nebo v2.0. + Modul snap-in PowerShell služby IIS požaduje, aby byl nainstalována služba WAS a konfigurace. + Toto je nepravý řetězec. + + + Rozhraní Microsoft Web Farm Framework verze 2.2 + Agent Microsoft Web Farm verze 2.2 + Služba Web Farm + Služba Web Farm + Služba řadiče Web Farm + Služba řadiče Web Farm + Služba agenta Web Farm + Služba agenta Web Farm + K instalaci rozhraní Web Farm Framework je vyžadován průvodce Instalace webové platformy. Nainstalujte jej z adresy http://www.microsoft.com/web/downloads/platform.aspx. + K instalaci rozhraní Web Farm Framework je vyžadován Nástroj pro nasazení webu. Nainstalujte jej z adresy http://www.iis.net/download/WebDeploy. + + + Architektura webových hostitelských služeb společnosti Microsoft + Architektura webových hostitelských služeb + Role a funkce webových hostitelských služeb + Architektura hostitelských služeb + Architektura hostitelských služeb poskytuje příkazy rozhraní API a prostředí PowerShell pro správu webových hostitelských služeb. + Webová role + Webová role nainstaluje Dynamickou službu WAS a zprostředkovatele pro přepis adresy URL pro webové hostitelské služby. + Antares Express + Nasadí konfiguraci ovládacích panelů optimalizovanou pro instalaci v jednom počítači. + Role nástroje pro vyrovnávání zatížení + Role nástroje pro vyrovnávání zatížení nakonfiguruje směrovač žádostí aplikace na směrování na základě pravidel webových hostitelských služeb. + Řadič hostingu + Řadič hostitelských služeb rozšiřuje rozhraní Web Farm Framework 2.0 na práci s webovými hostitelskými službami. + Role publikování + Nainstaluje podporu pro nasazení webu a publikování FTP. + Jde o modul snap-in prostředí PowerShell obsahující rutiny umožňující správu infrastruktury Microsoft Web Hosting. + Dynamická služba WAS + Aktivační služba procesů systému Windows optimalizovaná pro webové hostitelské služby s vysokou hustotou + Služba měření četnosti odesílání dat ze zdrojů + Nainstaluje službu měření četnosti odesílání dat ze zdrojů, která umožňuje shromažďovat a publikovat informace o běhu i o stavu. + Resource Metering + Povolí shromažďování a publikování informací o běhu a stavu z webové role. + Vynucení kvóty hostitelských služeb + Monitoruje využití prostředků na webech a v případě překročení kvóty použití spustí vlastní akce. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/DEU/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/DEU/misc/setupstrings.wxl new file mode 100644 index 0000000000..436243b9ad --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/DEU/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 1031 + + + + Installationsoptionen für freigegebene Konfiguration + Wählen Sie eine Option für die Installation in der freigegebenen IIS-Konfiguration aus. + Freigegebene Konfiguration bei Installation aktualisieren + Die Installation des Moduls erfolgt auf einem IIS-Server, der eine freigegebene Konfiguration verwendet. Wenn weitere IIS-Server diese freigegebene Konfiguration verwenden, müssen Sie dieses Modul auf allen beteiligten Computern installieren. Um Unterbrechungen auf den einzelnen Webservern zu vermeiden, beachten Sie bei der Installation des Moduls die folgenden Schritte: Führen Sie die Modulinstallation auf allen bis auf dem letzten Computer durch, ohne die freigegebene Konfiguration zu aktualisieren. Deaktivieren Sie hierzu das folgende + Kontrollkästchen. Dadurch werden alle Binärdateien und andere für das Modul benötigten Dateien auf jedem Computer installiert, ohne Änderungen an der freigegebenen Konfiguration vorzunehmen. Anschließend müssen Sie auf dem letzten Computer sicherstellen, dass das verwendete Benutzerkonto über Lese- und Schreibzugriff auf die Datei "applicationhost.config" auf der UNC-Freigabe verfügt. Installieren Sie dann das Modul, und aktivieren Sie dabei die folgend gezeigte Option zum Aktualisieren der freigegebenen Konfiguration. + + + Die benutzerdefinierte WebConfig-Aktion wird initialisiert. + "web.config" wird aktualisiert. + + + + IIS Advanced Logging + Aktiviert die erweiterte Protokollierung von IIS-Pipelinedaten. + IIS Advanced Logging + Aktiviert die Erstellung von Protokolldateien mit umfangreicher Feldauswahl. + Update für IIS Advanced Logging + + + + IIS Transform Manager + Beta + Aktiviert die Transform Manager IIS Media Services. + IIS Transform Manager + Aktiviert die Erstellung von Medientransformationen. + IIS Transform Manager-Host + Diensthost für [ProductName]. + IIS Transform Manager + Bedarfsgesteuerte Batchkonvertierung von Mediendateien in andere Datei- und Containerformate. + Ein IIS Transform Manager 1.0 Expression Encoder SP-Aufgabenpaket ist auf dem Computer installiert. Sie müssen das Paket deinstallieren, bevor Sie [ProductName] installieren können. + + Microsoft .NET Framework 3.5 ist für die Installation von [ProductName] erforderlich. Verwenden Sie den Assistenten zum Hinzufügen von Features im Server-Manager, um .NET Framework 3.5.1-Features zu installieren, oder verwenden Sie die Option "Windows-Features ein- oder ausschalten" zum Aktivieren von Microsoft .NET Framework 3.5. + + + + IIS-Verwaltung digitaler Rechte (DRM) + Beta + Aktiviert die Verwaltung digitaler Rechte (DRM) für Smooth Streaming-Präsentationen. + + + ASP.NET ist nicht installiert. + + + + + + + + + IIS Smooth Streaming Beta wurde auf diesem Computer gefunden. Die Installation von [ProductName] kann nicht fortgesetzt werden. Um dieses Produkt zu installieren, können Sie IIS Smooth Streaming Beta über die Funktion "Software" in der Systemsteuerung entfernen. + Auf diesem Computer befindet sich eine inkompatible Version der IIS Media Services. Die Installation von [ProductName] kann nicht fortgesetzt werden. Um dieses Produkt zu installieren, können Sie IIS Media Services über die Funktion "Software" in der Systemsteuerung entfernen. + Eine neuere Version dieses Produkts ist entweder bereits installiert oder für die Installation auf diesem Computer verfügbar. Die Installation von [ProductName] kann nicht fortgesetzt werden. Zum Installieren einer neueren Version des Produkts rufen Sie die Systemsteuerung auf, wählen 'Software' und aktualisieren dann die IIS Media Services. + Die Konvertierung der Wiedergabelistendatei ist erforderlich. + + + + + Es wurden ältere IIS Media Services-Dateien gefunden. + + + + + Es wurden IIS Media Services-Dateien der Betaversion gefunden. + + + + + + IIS Media Pack 1.0 + Update für IIS Media Pack 1.0 + IIS Media Services 2.0 + Update für IIS Media Services 2.0 + IIS Media Services 3.0 + IIS Media Services 3.0 TAP 2 + Update für IIS Media Services 3.0 + Features und Tools der IIS Media Services. + Features und Tools der IIS Media Services 5 Premium. + IIS Media Services 4.0 Beta 1 + IIS Media Services 4.0 + IIS Media Services 4.5 Beta 1 + IIS Media Services 5 Premium + + Internet-Wiedergabelisten + Steuert die Clientwiedergabe von Medienobjekten, auf die in Wiedergabelisten verwiesen wird. + Session Helper + Aktiviert die Dauerhaftigkeit des ASP.NET-Sitzungszustands (erfordert den ASP.NET-Rollendienst für Webserver (IIS)). + Benutzeroberfläche + Konfiguriert das Feature 'Internet-Wiedergabelisten' im IIS-Manager. + + Bitratendrosselung + Spart Bandbreite durch Drosselung der Übermittlung von Dateien ein, die von Clients heruntergeladen wurden. + Benutzeroberfläche + Konfiguriert das Feature 'Bitratendrosselung' im IIS-Manager. + + Objekte + Aktiviert adaptives HTTP-Streaming von bedarfsgesteuerten Objekten an Clients. + Benutzeroberfläche + Konfiguriert das Feature 'Smooth Streaming' im IIS-Manager. + + Kanäle + Aktiviert adaptives HTTP-Streaming von Kanalübertragungen an Clients. + Benutzeroberfläche + Konfiguriert das Live Smooth Streaming-Feature im IIS-Manager. + + Verwaltung digitaler Rechte (DRM) + Stellt Verschlüsselung und Lizenzierung für Smooth Streaming-Medien bereit. + Benutzeroberfläche + Konfiguriert die Funktion zur Verwaltung digitaler Rechte (DRM) im IIS-Manager. + + [ProductName] erfordert Microsoft Windows Vista Service Pack 1 oder höher. + [ProductName] darf nicht unter Vista Home Basic installiert werden. + [ProductName] erfordert Microsoft Windows 7 Service Pack 1 oder höher. + + + IIS-Datenbank-Manager + IIS-Datenbank-Manager + + + Microsoft-Webverwaltungsdienst 2 + Microsoft-Webverwaltungsdienst + Installiert die grundlegenden Features von [ProductName]. + Microsoft-Webverwaltungsdienst 2 + Der Webverwaltungsdienst bietet Remote- und delegierte Verwaltungsfunktionen für Administratoren zur Verwaltung des Webservers, der Websites und der Anwendungen auf diesem Computer. + + + Microsoft URL Rewrite-Modul 1.1 für IIS 7 + Update für das URL Rewrite-Modul 1.1 für IIS 7 + URL Rewrite + Aktiviert URL- und Inhaltsumschreibfunktionen für IIS 7. + Benutzeroberfläche + Konfiguriert das Feature 'URL Rewrite-Modul' im IIS-Manager. + + + IIS-URL-Rewrite-Modul 2 + Update für IIS-URL-Rewrite-Modul 2 + URL Rewrite + Aktiviert URL- und Inhaltsumschreibfunktionen für IIS 7. + Benutzeroberfläche + Konfiguriert das Feature 'URL Rewrite-Modul' im IIS-Manager. + + + Administration Pack für IIS 7.0 + Installiert die grundlegenden Features von [ProductName]. + 1252 + Administration Pack für IIS 7.0 + Microsoft Corporation + Diese Version des Betriebssystems wird nicht unterstützt. [ProductName] kann nur unter Windows Server 2008 oder Windows Vista Service Pack 1 und höher installiert werden. + ASP.NET-Features + ASP.NET umfasst Features für Autorisierung und Fehlerseiten, mit denen Sie die Autorisierungs- und benutzerdefinierten Fehlereinstellungen verwalten können. + Authentifizierung + ASP.NET-Authentifizierungsbeschreibung. + Autorisierung + Mit der ASP.NET-Autorisierung können Sie Regeln für die Autorisierung von Benutzern für den Zugriff auf Websites und Anwendungen konfigurieren. + Fehlerseiten + Mit den ASP.NET-Fehlerseiten können Sie HTTP-Fehlerreaktionen konfigurieren. + Module + ASP.NET-Modulbeschreibung. + Handler + ASP.NET-Handlerbeschreibung. + Konfigurations-Editor + Mit dem Konfigurations-Editor können Sie Konfigurationsdateien im IIS-Manager verwalten, indem Sie Abschnitte, Attribute, Elemente und Sammlungen der Konfigurationsdateien bearbeiten. + Anforderungsfilterung + Bei der Anforderungsfilterung können Sie Filterregeln für Ihre Website konfigurieren und das Protokoll- und Inhaltsverhalten beschränken. + FastCGI + Mit 'FastCGI' können Sie Prozesspooleinstellungen für die FastCGI-Anwendungen auf Ihrem Webserver konfigurieren. + + + Dynamische IP-Einschränkungen für die IIS 7-Konfiguration + + + + + + + + + + + + + Dynamische IP-Einschränkungen für IIS 7 - Beta + Dynamische IP-Einschränkungen für IIS 7 - Beta 2 + Dynamische IP-Einschränkungen für IIS 7 - Beta 3 + + Dynamische IP-Einschränkungen für IIS 7 - Release Candidate + Dynamische IP-Einschränkungen für IIS 7 - Release Candidate 2 + Dynamische IP-Einschränkungen für IIS 7 - Release Candidate 3 + + Dynamische IP-Einschränkungen für IIS 7 - RTW + + Dynamische IP-Einschränkungen für IIS 7 + Dynamische IP-Einschränkungen - Benutzeroberfläche für IIS 7 + + Dynamische IP-Einschränkungen für IIS 7 - Beta wurde auf diesem Computer gefunden. Deinstallieren Sie diese Anwendung, und versuchen Sie es erneut. + + + WebDAV 7.5 für IIS 7.0 + Die IIS 7.0-Features CoreWebEngine und W3SVC müssen für die Verwendung dieses Produkts installiert sein. + WebDAV-Servermodul + WebDAV-Administrationsbenutzeroberfläche + + + IIS Search Engine Optimization Toolkit 1.0 + IIS Search Engine Optimization Toolkit 1.0 + Search Engine Optimization (SEO) Toolkit 1.0 + Diese Installer-Datenbank enthält die zum Installieren von IIS Search Engine Optimization Toolkit 1.0 erforderliche Logik. + + + IIS-Editor + + + IIS-Berichte + Der Protokollparser ist nicht auf diesem Computer installiert. Installieren Sie Log Parser 2.2 über http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07, und setzen Sie dann die Installation der IIS-Berichte fort. + + + Erforderliche Pakete wurden nicht gefunden. Führen Sie 'setup.exe' aus, um Abhängigkeiten aufzulösen und dieses Programm zu installieren. + Microsoft SQL Server 2008 Management Objects ist eine Voraussetzung für die Installation von IIS-Datenbank-Manager. Sie können Microsoft SQL Server 2008 Management Objects über http://go.microsoft.com/fwlink/?LinkID=150946 installieren. + Microsoft SQL Server System CLR Types ist eine Voraussetzung für die Installation von IIS-Datenbank-Manager. Sie können Microsoft SQL Server System CLR Types über http://go.microsoft.com/fwlink/?LinkID=150949 installieren. + + + Microsoft Web Farm Framework + Microsoft External Cache + Web Farm Framework ist eine Voraussetzung für die Installation des Routings von Anwendungsanforderungen. Installieren Sie Web Farm Framework. + Microsoft Application Request Routing 2.5 + Laufzeit + Fügt die Funktionen des Routings von Anwendungsanforderungen zu IIS hinzu. + Benutzeroberfläche + Konfiguriert das Feature "Routing von Anwendungsanforderungen" im IIS-Manager. + + + Microsoft Windows PowerShell snap-in für IIS 7.0 + + + Microsoft-Webplattform-Installer 4.0 + Microsoft-Webplattform-Installer + [ProductName] erfordert Windows XP SP2, Windows 2003 SP1, Windows Vista oder höher. + [ProductName] benötigt Windows XP Service Pack 3, Windows Server 2003 Service Pack 2 oder höher. + + + Microsoft Windows Azure Services Installer + Microsoft Windows Azure Services Installer + + + Internetinformationsdienste (IIS) 7+-Manager + IIS-Manager-Client + Remotesupport + Das Produkt erfordert Windows XP SP2, Windows 2003 SP1, Windows Vista SP1 oder Windows 7 oder höher. + Die IIS-Verwaltungskonsole ist nicht installiert, sie ist aber zur Verwaltung von Remote-IIS-Servern erforderlich. Installieren Sie die IIS-Verwaltungskonsole vor der Installation des Remoteverwaltungssupports durch Öffnen von 'Systemsteuerung->Programme->Windows-Funktionen ein- oder ausschalten' und Auswahl der IIS-Verwaltungskonsole im Feature 'Internetinformationsdienste'. + Dieses Produkt ist in Windows Server 2008 oder Windows Server 2008 R2 oder höher nicht erforderlich. Installieren Sie die IIS-Verwaltungskonsole durch Öffnen des Server-Managers und Auswahl der IIS-Verwaltungskonsole in den Rollendiensten für die Webserverrolle. + + + IIS-Manager-Publishing für IIS 7.0 + Publishing-Benutzeroberfläche + + + Application Warm-Up 1.0 für IIS 7.5 + + + + Ein inkompatibles Produkt ( [CONFLICTING_PRODUCT_NAME]) ist auf dem Computer. installiert. Die Installation von [ProductName] kann nicht fortgesetzt werden. Verwenden Sie zum Installieren dieses Produkts "Software" in der Systemsteuerung, um [CONFLICTING_PRODUCT_NAME] zu entfernen. + Administratorberechtigungen sind für die Installation von [ProductName] erforderlich. + IIS Version 7.0 ist für die Verwendung von [ProductName] erforderlich. + IIS Version 7.0 oder höher ist für die Installation von [ProductName] erforderlich. + IIS Version 7.5 oder höher ist für die Installation von [ProductName] erforderlich. + IIS Version 7.0 oder 7.5 ist für die Installation von [ProductName] erforderlich. + Eine Betaversion von [ProductName] wurde auf diesem Computer gefunden. + Eine neuere Version von [ProductName] wurde auf diesem Computer gefunden. + Die Installation kann nicht fortgesetzt werden, da eine andere Instanz von [ProductName] bereits auf diesem Computer installiert ist. Deinstallieren Sie diese zuerst, und starten Sie die Installation dann erneut. + Die IIS 7.0-Features CoreWebEngine und W3SVC müssen für die Verwendung von [ProductName] installiert sein. + Die IIS-Verwaltungskonsole muss für die Verwendung von [ProductName] installiert sein. + Halten Sie die den Windows-Prozessaktivierungsdienst (WAS) und den Webverwaltungsdienst (WMSvc) vor der Installation von [ProductName] an. Sie müssen die Dienste nach der Installation von [ProductName] wieder starten. + IIS-Metabasis ist für die Installation von [ProductName] erforderlich. + Die 64-Bit-Version von [ProductName] kann nicht in einer 32-Bit-Version von Microsoft Windows installiert werden. + Die 32-Bit-Version von [ProductName] kann nicht in einer 64-Bit-Version von Microsoft Windows installiert werden. + Microsoft .NET Framework Version 2.0 oder höher ist für die Installation von [ProductName] erforderlich. + Microsoft .NET Framework Version 3.5 oder höher ist für die Installation von [ProductName] erforderlich. Verwenden Sie die Option "Features hinzufügen" im Server-Manager, um Microsoft .Net Version 3.5 zu installieren. + Microsoft .NET Framework Version 4.0 oder höher ist für die Installation von [ProductName] erforderlich. + Installieren Sie Microsoft .NET Framework Version 2.0 Service Pack 1 (oder ein höheres Service Pack) vor der Installation von [ProductName]. + Der Windows Update (wuauserv)-Dienst kann nicht deaktiviert werden, er ist zur Installation von [ProductName] erforderlich. + Das PowerShell-Snap-In ist Teil des Windows-Betriebssystems. Installieren Sie es über 'Programme und Funktionen' oder 'Server-Manager'. + Microsoft-Webplattform-Installer Version 3.0 oder höher ist für die Installation von [ProductName] erforderlich. + + Die freigegebene Konfiguration konnte nicht ermittelt werden. + Die freigegebene Konfiguration ist für IIS aktiviert. Die Installation von [ProductName] wird bei Verwendung der freigegebenen Konfiguration nicht unterstützt. Deaktivieren Sie die freigegebene Konfiguration vor der Installation des Features. + + Halten Sie den WWW-Publishingdienst (W3SVC) vor der Installation von [ProductName] an. Sie müssen den Dienst nach der Installation wieder starten. + IIS-PowerShell-Verwaltungskonsole + IIS-PowerShell-Snap-In + Das IIS-PowerShell-Snap-In erfordert die Installation von PowerShell v1.0 oder v2.0. + Das IIS-PowerShell-Snap-In erfordert die Installation des Windows-Prozessaktivierungsdiensts und der Konfiguration. + Dies ist eine Platzhalter-Zeichenfolge. + + + Microsoft Web Farm Framework Version 2.2 + Microsoft Webfarm-Agent Version 2.2 + Webfarmdienst + Webfarmdienst + Webfarm-Controllerdienst + Webfarm-Controllerdienst + Webfarm-Agent-Dienst + Webfarm-Agent-Dienst + Webplattform-Installer ist eine Voraussetzung für die Installation von Web Farm Framework. Installieren Sie den Webplattform-Installer von "http://www.microsoft.com/web/downloads/platform.aspx". + Die Webbereitstellungstools sind eine Voraussetzung für die Installation von Web Farm Framework. Installieren Sie das Webbereitstellungstool von "http://www.iis.net/download/WebDeploy". + + + Microsoft Web Hosting Framework + Web Hosting Framework + Rollen und Funktionen für Web Hosting. + Hosting Framework + Hosting Framework stellt APIs und PowerShell-Befehle zum Verwalten von Web Hosting zur Verfügung. + Webrolle + Die Webrolle installiert den dynamischen WAS-Dienst und den URL-Rewrite-Anbieter für Web Hosting. + Antares Express + Stellt eine Systemsteuerungskonfiguration bereit, die für die Einrichtung eines einzelnen Computers optimiert ist. + Lastenausgleichsrolle + Die Lastenausgleichsrolle konfiguriert den Anwendungsanforderungsrouter für Routing basierend auf Web Hosting-Regeln. + Hostingcontroller + Der Hostingcontroller erweitert Web Farm Framework 2.0 für die Zusammenarbeit mit Web Hosting. + Veröffentlichungsrolle + Installiert Unterstützung für Web Deploy und FTP-Veröffentlichung. + Hierbei handelt es sich um ein PowerShell-Snap-In mit Cmdlets zur Verwaltung der Microsoft Web Hosting-Infrastruktur. + Dynamischer WAS-Dienst + Windows-Prozessaktivierungsdienst, der für HD-Web Hosting optimiert ist. + Resource Metering-Dienst + Installiert den Resource Metering-Dienst, der das Sammeln und Veröffentlichen von Laufzeit- und Systemintegritätsinformationen ermöglicht. + Resource Metering + Aktiviert das Sammeln und Veröffentlichen von Laufzeit- und Systemintegritätsinformationen aus der Webrolle. + Durchsetzung des Hostingkontingents + Überwacht den Website-Ressourceneinsatz und führt benutzerdefinierte Aktionen aus, wenn das Verwendungskontingent überschritten wurde. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/ESN/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/ESN/misc/setupstrings.wxl new file mode 100644 index 0000000000..ea1579e794 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/ESN/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 3082 + + + + Opciones de instalación de la configuración compartida + Seleccionar la opción de instalación en la configuración compartida de IIS + Actualizar configuración compartida al instalar + Está instalando este módulo en un servidor IIS que usa una configuración compartida. Si otros servidores IIS usan esta configuración compartida, tendrá que instalar este módulo en todas estas máquinas. Para minimizar las interrupciones de los servidores web individuales, tendrá que instalar este módulo realizando los pasos siguientes. En primer lugar, en todas las máquinas, excepto en la última, debe instalar el módulo sin actualizar la configuración compartida. Hágalo sin activar la casilla + siguiente. Esto instalará todos los binarios y archivos necesarios para el módulo en cada máquina sin modificar la configuración compartida. En segundo lugar, en la última máquina tendrá que comprobar que la identidad del usuario con la que está trabajando tiene acceso de lectura y escritura al archivo applicationhost.config del recurso compartido UNC. Después, debe instalar el módulo y seleccionar la opción de actualización de configuración compartida que figura a continuación. + + + Inicialización de acción personalizada de WebConfig + Actualización de archivo web.config + + + + Registro avanzado de IIS + Permite el registro avanzado de datos de canalización de IIS. + Registro avanzado de IIS + Permite la creación de archivos de registro personalizados con selección de campos extensible. + Actualización de Advanced Logging de IIS + + + + Transform Manager para IIS + Beta + Habilita los Servicios multimedia de IIS para Transform Manager. + Transform Manager para IIS + Habilita la creación de transformaciones multimedia. + Host de Transform Manager para IIS + Host de servicios para [ProductName]. + Transform Manager para IIS + Permite convertir por lotes archivos multimedia a petición para alternar formatos de archivo y contenedor. + Existe un paquete de tareas de IIS Transform Manager 1.0 Expression Encoder SP instalado en el equipo. Deberá desinstalarlo antes de instalar [ProductName]. + + Se necesita Microsoft .NET Framework 3.5 para instalar [ProductName]. Use el 'Asistente para agregar características' del Administrador del servidor para instalar las características de .NET Framework 3.5.1 o la opción 'Activar o desactivar las características de Windows' para activar Microsoft .NET Framework 3.5. + + + + Administración de derechos digitales de IIS + Beta + Habilita la administración de derechos digitales de presentaciones de transmisión por secuencias suave. + + + ASP.NET no está instalado + + + + + + + + + Se encontró IIS Smooth Streaming - Beta en este equipo. La instalación de [ProductName] no puede continuar. Para instalar este producto, use Agregar o quitar programas en el Panel de control para quitar IIS Smooth Streaming - Beta. + Este equipo cuenta con una versión no compatible de Servicios multimedia de IIS. La instalación de [ProductName] no puede continuar. Para instalar este producto, use Agregar o quitar programas en el Panel de control para quitar Servicios multimedia de IIS. + Una versión más reciente de este producto está ya instalada o disponible para instalarla en este equipo. La instalación de [ProductName] no puede continuar. Para instalar la versión más reciente de este producto, use Agregar o quitar programas en el Panel de control para actualizar Servicios multimedia de IIS. + Conversión necesaria de archivo de lista de reproducción + + + + + Archivos de versiones anteriores de Servicios multimedia de IIS encontrados + + + + + Versión beta de los Servicios Multimedia de IIS encontrada + + + + + + IIS Media Pack 1.0 + Actualización de IIS Media Pack 1.0 + Servicios multimedia 2.0 de IIS + Actualización de Servicios multimedia 2.0 de IIS + Servicios multimedia 3.0 de IIS + Servicios multimedia 3.0 de IIS (TAP 2) + Actualización de Servicios multimedia 3.0 de IIS + Características y herramientas de Servicios multimedia de IIS. + Características y herramientas de Servicios multimedia de IIS 5 Premium. + Servicios multimedia 4.0 beta 1 de IIS + Servicios multimedia 4.0 de IIS + Servicios multimedia 4.5 beta 1 de IIS + Servicios multimedia de IIS 5 Premium + + Listas de reproducción en web + Controla la reproducción en clientes de recursos multimedia digitales a los que se hace referencia en listas de reproducción. + Aplicación auxiliar para sesiones + Habilita la persistencia de estado de sesión de ASP.NET. Requiere el servicio de rol ASP.NET para el rol Servidor web (IIS). + Interfaz de usuario + Configura la característica Listas de reproducción en web en el Administrador de IIS. + + Limitación de velocidad de bits + Ahorra ancho de banda limitando la entrega de archivos descargados por los clientes. + Interfaz de usuario + Configura la característica Limitación de velocidad de bits en el Administrador de IIS. + + Activos + Habilita la transmisión por secuencias adaptativa HTTP de archivos a petición a los clientes. + Interfaz de usuario + Configura la característica Transmisión por secuencias suave en el Administrador de IIS. + + Canales + Habilita la transmisión por secuencias adaptativa HTTP de las difusiones de canal a los clientes. + Interfaz de usuario + Configura la característica Live Smooth Streaming en el Administrador de IIS. + + Administración de derechos digitales + Proporciona cifrado y licencias de medios de transmisión por secuencias suave. + Interfaz de usuario + Configura la característica de administración de derechos digitales en el administrador de IIS. + + [ProductName] requiere Microsoft Windows Vista Service Pack 1 o posterior. + [ProductName] no se puede instalar en Vista Home Basic. + [ProductName] requiere Microsoft Windows 7 Service Pack 1 o posterior. + + + Administrador de bases de datos de IIS + Administrador de bases de datos de IIS + + + Servicio de administración web de Microsoft 2 + Servicio de administración web de Microsoft + Instala las características básicas de [ProductName]. + Servicio de administración web de Microsoft 2 + El Servicio de administración web habilita funciones de administración remota y delegada para quienes administren los sitios, las aplicaciones y el servidor web presentes en este equipo. + + + Módulo URL Rewrite 1.1 para IIS 7 + Actualización de Módulo URL Rewrite 1.1 para IIS 7 + URL Rewrite + Habilita la reescritura de direcciones URL y contenido en IIS 7. + Interfaz de usuario + Configura la característica Módulo URL Rewrite en el Administrador de IIS. + + + Módulo URL Rewrite 2 de IIS + Actualización de Módulo URL Rewrite 2 de IIS + URL Rewrite + Habilita la reescritura de direcciones URL y contenido en IIS 7. + Interfaz de usuario + Configura la característica Módulo URL Rewrite en el Administrador de IIS. + + + Administration Pack para IIS 7.0 + Instala las características básicas de [ProductName]. + 1252 + Administration Pack para IIS 7.0 + Microsoft Corporation + No se admite esta versión del sistema operativo. [ProductName] se puede instalar sólo en Windows Server 2008 o Windows Vista Service Pack 1 y posterior. + Características de ASP.NET + ASP.NET incluye las características Autorización y Páginas de errores, que permiten administrar la autorización y la configuración de errores personalizada. + Autenticación + Descripción de autenticación ASP.NET. + Autorización + Autorización de ASP.NET permite configurar reglas para autorizar a usuarios a obtener acceso a sitios y aplicaciones web. + Páginas de errores + Páginas de errores de ASP.NET permite configurar respuestas a errores HTTP para devolverlas cuando se producen errores. + Módulos + Descripción de módulos de ASP.NET. + Controladores + Descripción de controladores de ASP.NET. + Editor de configuración + El Editor de configuración permite administrar los archivos de configuración en el Administrador de IIS. Permite editar secciones, atributos, elementos y colecciones en los archivos de configuración. + Filtrado de solicitudes + Filtrado de solicitudes permite configurar reglas de filtrado para un sitio web y restringir el comportamiento de protocolo y contenido. + FastCGI + FastCGI permite configurar grupos de procesos para aplicaciones FastCGI del servidor web. + + + Programa de instalación de Restricciones de IP dinámicas para IIS 7 + + + + + + + + + + + + + Restricciones de IP dinámicas para IIS 7 - Beta + Restricciones de IP dinámicas para IIS 7 - Beta 2 + Restricciones de IP dinámicas para IIS 7 - Beta 3 + + Restricciones de IP dinámicas para IIS 7 - Release Candidate + Restricciones de IP dinámicas para IIS 7 - Release Candidate 2 + Restricciones de IP dinámicas para IIS 7 - Release Candidate 3 + + Restricciones de IP dinámicas para IIS 7 - RTW + + Restricciones de IP dinámicas para IIS 7 + Interfaz de usuario de Restricciones de IP dinámicas para IIS 7 + + Se encontraron restricciones de IP dinámicas para IIS 7 - Beta en esta máquina. Desinstálelo e inténtelo de nuevo. + + + WebDAV 7.5 para IIS 7.0 + Deben instalarse las características CoreWebEngine y W3SVC de IIS 7.0 para usar este producto. + Módulo de servidor de WebDAV + Interfaz de usuario de administración de WebDAV + + + Herramientas de optimización para el motor de búsqueda de IIS 1.0 + Herramientas de optimización para el motor de búsqueda de IIS 1.0 + Herramientas de optimización para el motor de búsqueda (SEO) de IIS 1.0 + Esta base de datos de instalador contiene la lógica y los datos necesarios para instalar las Herramientas de optimización para el motor de búsqueda de IIS 1.0. + + + Editor de IIS + + + Informes de IIS + Log Parser no está instalado en esta máquina. Instale Log Parser 2.2 desde http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07 y después continúe con la instalación de Informes de IIS. + + + No se encontraron algunos paquetes de requisitos previos. Ejecute setup.exe para resolver las dependencias e instalar este programa. + Objetos de administración de Microsoft SQL Server 2008 es un requisito previo para instalar el Administrador de bases de datos de IIS. Puede instalar Objetos de administración de Microsoft SQL Server 2008 desde http://go.microsoft.com/fwlink/?LinkID=150946 . + Microsoft SQL Server System CLR Types es un requisito previo para instalar el Administrador de bases de datos de IIS. Puede instalar Microsoft SQL Server System CLR Types desde http://go.microsoft.com/fwlink/?LinkID=150949 . + + + Microsoft Web Farm Framework + Microsoft External Cache + Web Farm Framework es un requisito para instalar Enrutamiento de solicitud de aplicaciones. Instale Web Farm Framework. + Enrutamiento de solicitud de aplicaciones de Microsoft 2.5 + Runtime + Agrega las capacidades de Enrutamiento de solicitud de aplicaciones a IIS. + Interfaz de usuario + Configura la característica Enrutamiento de solicitud de aplicaciones en el Administrador de IIS. + + + Complemento PowerShell de Microsoft Windows para IIS 7.0 + + + Instalador de plataforma web 4.0 de Microsoft + Instalador de plataforma web de Microsoft + [ProductName] requiere Windows XP SP2, Windows 2003 SP1, Windows Vista o posterior. + [ProductName] requiere Windows XP Service Pack 3, Windows Server 2003 Service Pack 2 o posterior. + + + Instalador de Microsoft Windows Azure Services + Instalador de Microsoft Windows Azure Services + + + Administrador de Internet Information Services (IIS) 7 o posterior + Cliente del Administrador de IIS + Compatibilidad con comunicación remota + Este producto requiere Windows XP SP2, Windows 2003 SP1, Windows Vista SP1, Windows 7 o posterior. + La Consola de administración de IIS no está instalada, pero es necesaria para administrar servidores IIS remotos. Instale la Consola de administración de IIS antes de instalar la compatibilidad con administración remota. Para ello, abra 'Panel de control->Programas->Activar o desactivar las características de Windows' y seleccione Consola de administración de IIS en la característica Internet Information Services. + Este producto no es necesario en Windows Server 2008 ni Windows Server 2008 R2 o posterior. Para instalar la Consola de administración de IIS, abra el Administrador del servidor y seleccione Consola de administración de IIS en los servicios del rol Servidor web. + + + Servicio de publicación del Administrador de IIS para IIS 7.0 + Interfaz de usuario para publicación + + + Application Warm-Up 1.0 para IIS 7.5 + + + + El equipo tiene un producto no compatible, [CONFLICTING_PRODUCT_NAME]. No es posible continuar con la instalación de [ProductName]. Para instalar este producto, vaya a Panel de control > Agregar o quitar programas para quitar [CONFLICTING_PRODUCT_NAME]. + Es necesario el privilegio de administrador para instalar [ProductName]. + Es necesaria la versión 7.0 de IIS para usar [ProductName]. + Es necesaria la versión 7.0 o posterior de IIS para instalar [ProductName]. + Es necesaria la versión 7.5 o posterior de IIS para instalar [ProductName]. + Se requiere la versión 7 o 7.5 de IIS para instalar [ProductName]. + Se encontró la versión beta de [ProductName] en esta máquina. + Se encontró una versión más reciente de [ProductName] en esta máquina. + El programa de instalación no puede continuar porque ya hay instalada otra instancia de [ProductName] en esta máquina. Desinstale primero esa instancia y vuelva a iniciar esta instalación. + Deben estar instaladas las características CoreWebEngine y W3SVC de IIS 7.0 para usar [ProductName]. + Para usar [ProductName], debe estar instalada la Consola de administración de IIS. + Detenga los servicios WAS (Windows Process Activation) y WMSvc (Servicio de administración web) antes de instalar [ProductName]. Deberá iniciar los servicios después de instalar [ProductName]. + Es necesaria la metabase de IIS para instalar [ProductName]. + No se puede instalar la versión de 64 bits de [ProductName] en una edición de 32 bits de Microsoft Windows. + No se puede instalar la versión de 32 bits de [ProductName] en una edición de 64 bits de Microsoft Windows. + Es necesario Microsoft .NET Framework 2.0 o posterior para instalar [ProductName]. + Se requiere Microsoft .NET Framework, versión 3.5 o posterior, para instalar [ProductName]. Use la opción 'Agregar características' del Administrador del servidor para instalar Microsoft .Net, versión 3.5. + Se requiere Microsoft .NET Framework, versión 4.0 o posterior, para instalar [ProductName]. + Instale Microsoft .NET Framework 2.0 Service Pack 1 (o un Service Pack posterior) antes de instalar [ProductName]. + No se puede deshabilitar el servicio Windows Update (wuauserv), porque es necesario para instalar [ProductName]. + El complemento PowerShell forma parte del sistema operativo Windows. Instálelo desde 'Programas y características' o 'Administrador del servidor'. + Se requiere Instalador de plataforma web de Microsoft, versión 3.0 o posterior, para instalar [ProductName]. + + El programa de instalación no detectó ninguna configuración compartida. + Está habilitada la configuración compartida para IIS. No se admite la instalación de [ProductName] cuando se usa configuración compartida. Deshabilite la configuración compartida antes de instalar esta característica. + + Detenga el servicio de publicación World Wide Web (W3SVC) antes de instalar [ProductName]. Deberá iniciar el servicio después de la instalación. + Consola de administración de PowerShell para IIS + Complemento PowerShell para IIS + El complemento PowerShell para IIS requiere que esté instalado PowerShell v1.0 o v2.0. + El complemento PowerShell para IIS requiere que estén instalados el servicio WAS y la configuración. + This is a bogus string. + + + Microsoft Web Farm Framework versión 2.2 + Microsoft Web Farm Agent versión 2.2 + Servicio de Web Farm + Servicio de Web Farm + Servicio de controlador de Web Farm + Servicio de controlador de Web Farm + Servicio de agente de Web Farm + Servicio de agente de Web Farm + El Instalador de plataforma web es un requisito previo para instalar Web Farm Framework. Instale el Instalador de plataforma web desde http://www.microsoft.com/web/downloads/platform.aspx. + La Herramienta de implementación web es un requisito previo para instalar Web Farm Framework. Instale la Herramienta de implementación web desde http://www.iis.net/download/WebDeploy. + + + Microsoft Web Hosting Framework + Web Hosting Framework + Roles y características de Microsoft Web Hosting. + Hosting Framework + Hosting Framework ofrece comandos de las API y PowerShell para administrar Web Hosting. + Rol web + El rol web instala el servicio WAS dinámico y el proveedor de URL Rewrite para Web Hosting. + Antares Express + Implementa una configuración de Panel de control optimizada para la configuración de un único equipo. + Rol Equilibrador de carga + El rol Equilibrador de carga configura Application Request Router para enrutar en función de las reglas de Web Hosting. + Controlador de hospedaje + El controlador de hospedaje amplía Web Farm Framework 2.0 para que funcione con Web Hosting. + Rol de publicación + Instala el soporte para la publicación FTP y de Web Deploy. + Se trata de un complemento de PowerShell que contiene cmdlets para administrar la infraestructura de Microsoft Web Hosting. + Servicio WAS dinámico + Servicio WAS (Windows Process Activation) optimizado para hospedaje web de alta densidad. + Servicio de medición de recursos + Instala el servicio Medición de recursos que habilita la recopilación y la publicación de información de estado y en tiempo de ejecución. + Medición de recursos + Habilita la recopilación y publicación de información de estado y en tiempo de ejecución del rol web. + Cumplimiento de cuota de hospedaje + Supervisa el uso de recursos de los sitios web y ejecuta acciones personalizadas si se supera la cuota. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/FRA/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/FRA/misc/setupstrings.wxl new file mode 100644 index 0000000000..c00688e50c --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/FRA/misc/setupstrings.wxl @@ -0,0 +1,352 @@ + + + + + + + 1036 + + + + Options d'installation pour la configuration partagée + Sélectionnez une option pour l'installation dans une partagée IIS + Mettre à jour la configuration partagée lors de l'installation + Vous installez ce module sur un serveur IIS qui utilise une configuration partagée. Si des serveurs IIS supplémentaires utilisent cette configuration partagée, vous devez installer ce module sur tous ces ordinateurs. Pour réduire le risque d'interruptions sur les différents serveurs Web, installez ce module en respectant les étapes suivantes : premièrement, sur tous les ordinateurs à l'exception du dernier, vous devez installer le module sans mettre à jour la configuration partagée. Pour ce faire, n'activez pas la case à cocher + ci-dessous. Cette opération installe l'ensemble des fichiers et ressources binaires requis pour le module sur chaque ordinateur sans apporter de modifications à la configuration partagée. Deuxièmement, sur le dernier ordinateur, vous devez vérifier que l'identité d'utilisateur que vous utilisez actuellement dispose d'un accès en lecture/écriture au fichier applicationhost.config du partage UNC. Vous devez ensuite installer le module et sélectionner l'option de mise à jour de la configuration partagée ci-dessous. + + + Initialisation de l'action personnalisée WebConfig + Mise à jour de web.config + + + + IIS Advanced Logging + Active la journalisation avancée des données de pipeline IIS. + IIS Advanced Logging + Permet la création de fichiers journaux personnalisés avec une sélection de champ extensible. + Mise à jour pour IIS Advanced Logging + + + + IIS Transform Manager + Bêta + Active IIS Services Multimédia pour Transform Manager. + IIS Transform Manager + Active la création de transformations multimédias. + Hôte IIS Transform Manager + Hôte de service pour [ProductName]. + IIS Transform Manager + Convertir sous forme de lot sur demande les fichiers multimédias en d'autres formats de fichier et de conteneur. + Un package IIS Transform Manager 1.0 Expression Encoder SP Task est installé sur l'ordinateur. Vous devez le désinstaller avant d'installer [ProductName]. + + Microsoft .NET Framework 3.5 est requis pour installer [ProductName]. Utilisez l'Assistant Ajout de fonctionnalités du Gestionnaire de serveur pour installer le composant Fonctionnalités du .NET Framework 3.5.1, ou utilisez l'option Activer ou désactiver des fonctionnalités Windows pour activer Microsoft .NET Framework 3.5. + + + + Gestion des droits numériques (DRM) IIS + Bêta + Active la gestion des droits numériques (DRM) des présentations de diffusion en continu lisse. + + + ASP.NET n'est pas installé + + + + + + + + + Diffusion en continu lisse IIS - Bêta a été détecté sur cet ordinateur. L'installation de [ProductName] ne peut pas continuer. Pour installer ce produit, utilisez Ajouter ou supprimer des programmes dans le Panneau de configuration afin de supprimer Diffusion en continu lisse IIS - Bêta. + Une version incompatible d'IIS Services Multimédia se trouve sur cet ordinateur. L'installation de [ProductName] ne peut pas continuer. Pour installer ce produit, utilisez Ajouter ou supprimer des programme dans le Panneau de configuration afin de supprimer IIS Services Multimédia. + Une version plus récente de ce produit est déjà installée ou disponible à l'installation sur cet ordinateur. L'installation de [ProductName] ne peut pas continuer. Pour installer la version la plus récente de ce produit, utilisez Ajouter ou supprimer des programme dans le Panneau de configuration pour mettre à jour IIS Services Multimédia. + Conversion du fichier de sélections requise + + + + + Anciens fichiers IIS Services Multimédia trouvés + + + + + Fichiers IIS Services Multimédia Bêta trouvés + + + + + + IIS Pack Multimédia 1.0 + Mise à jour pour IIS Pack Multimédia 1.0 + IIS Services Multimédia 2.0 + Mise à jour pour IIS Services Multimédia 2.0 + IIS Services Multimédia 3.0 + IIS Services Multimédia 3.0 TAP 2 + Mise à jour pour IIS Services Multimédia 3.0 + Fonctionnalités et outils IIS Services Multimédia. + Fonctionnalités et outils IIS Media Services 5. + IIS Services Multimédia 4.0 Bêta 1 + IIS Services Multimédia 4.0 + IIS Services Multimédia 4.5 Bêta 1 + IIS Media Services 5 Premium + + Sélections Web + Contrôle la lecture sur le client des fichiers multimédias référencés dans les sélections. + Session Helper + Active la persistance d'état de session ASP.NET. (Requiert le service de rôle ASP.NET pour le serveur Web (IIS)). + Interface utilisateur + Configure la fonctionnalité Sélections Web dans le Gestionnaire des services Internet. + + Bit Rate Throttling + Économise la bande passante en limitant la remise de fichiers téléchargés par les clients. + Interface utilisateur + Configure la fonctionnalité Bit Rate Throttling dans le Gestionnaire des services Internet. + + Éléments + Active la diffusion adaptive en continu HTTP d’éléments à la demande sur les clients. + Interface utilisateur + Configure la fonctionnalité de diffusion en continu lisse dans le Gestionnaire des services Internet. + + Canaux + Active la diffusion adaptive en continu HTTP de canaux sur les clients. + Interface utilisateur + Configure la fonctionnalité Live Smooth Streaming dans le Gestionnaire des services Internet. + + Gestion des droits numériques (DRM) + Fournit le chiffrement et la licence des médias de diffusion en continu lisse. + Interface utilisateur + Configure la fonctionnalité Gestion des droits numériques (DRM) dans le Gestionnaire des services Internet. + + [ProductName] requiert Microsoft Windows Vista Service Pack 1 ou version ultérieure. + [ProductName] ne peut pas être installé sur Vista Édition Familiale Basique. + [ProductName] requiert Microsoft Windows 7 Service Pack 1 ou version ultérieure. + + + Gestionnaire de bases de données IIS + Gestionnaire de bases de données IIS + + + Service de gestion Web Microsoft 2 + Service de gestion Web Microsoft + Installe les fonctionnalités de base de [ProductName]. + Service de gestion Web Microsoft 2 + Le service de gestion Web offre des fonctionnalités de gestion déléguée et à distance permettant aux administrateurs de gérer le serveur Web, les sites et les applications présents sur cet ordinateur. + + + Module de réécriture d'URL 1.1 Microsoft pour IIS 7 + Mise à jour pour le Module de réécriture d'URL 1.1 pour IIS 7 + Réécriture d'URL + Active des fonctionnalités de réécriture d'URL et de contenu pour IIS 7. + Interface utilisateur + Configure la fonctionnalité Module de réécriture d'URL dans le Gestionnaire des services Internet. + + + Module de réécriture d'URL 2 d'IIS + Mise à jour pour le Module de réécriture d'URL 2 d'IIS + Réécriture d'URL + Active des fonctionnalités de réécriture d'URL et de contenu pour IIS 7. + Interface utilisateur + Configure la fonctionnalité Module de réécriture d'URL dans le Gestionnaire des services Internet. + + + Pack d'administration IIS 7.0 + Installe les fonctionnalités de base de [ProductName]. + 1252 + Pack d'administration IIS 7.0 + Microsoft Corporation + Cette version du système d'exploitation n'est pas prise en charge. [ProductName] ne peut être installé que sur Windows Server 2008 ou Windows Vista Service Pack 1 et versions ultérieures. + Fonctionnalités ASP.Net + ASP.NET comprend les fonctionnalités d'autorisation et de pages d'erreurs, qui vous permettent de gérer les paramètres d'autorisations et d'erreurs personnalisées. + Authentification + Description de l'authentification ASP.Net. + Autorisation + L'autorisation ASP.NET vous permet de configurer des règles pour autoriser les utilisateurs à accéder à vos applications et sites Web. + Pages d'erreurs + Les pages d'erreurs ASP.NET vous permettent de configurer les réponses d'erreurs HTTP à retourner lorsque des erreurs se produisent. + Modules + Description des modules ASP.Net. + Gestionnaires + Description des gestionnaires ASP.Net. + Éditeur de configuration + L'éditeur de configuration vous permet de gérer vos fichiers de configuration dans le Gestionnaire des services Internet en vous permettant de modifier des sections, des attributs, des éléments et des collections dans vos fichiers de configuration. + Filtrage des demandes + Le filtrage des demandes vous permet de configurer les règles de filtrage pour votre site Web et de limiter le comportement du protocole et du contenu. + FastCGI + FastCGI vous permet de configurer les paramètres du pool de processus pour les applications FastCGI sur votre serveur Web. + + + Programme d'installation de Restrictions dynamiques d'adresse IP pour IIS 7 + + + + + + + + + + + + + Restrictions dynamiques d'adresse IP pour IIS 7 - Bêta + Restrictions dynamiques d'adresse IP pour IIS 7 - Bêta 2 + Restrictions dynamiques d'adresse IP pour IIS 7 - Bêta 3 + + Restrictions dynamiques d'adresse IP pour IIS 7 - version finale (RC) + Restrictions dynamiques d'adresse IP pour IIS 7 - version finale (RC) 2 + Restrictions dynamiques d'adresse IP pour IIS 7 - version finale (RC) 3 + + Restrictions dynamiques d'adresse IP pour IIS 7 - RTW + + Restrictions dynamiques d'adresse IP pour IIS 7 + Interface utilisateur de Restrictions dynamiques d'adresse IP pour IIS 7 + + Restrictions d'adressage IP dynamique pour IIS 7 - Une version bêta a été détectée sur cet ordinateur. Désinstallez-la, puis réessayez + + + WebDAV 7.5 pour IIS 7.0 + Les fonctionnalités IIS 7.0 CoreWebEngine et W3SVC doivent être installées pour utiliser ce produit. + Module serveur WebDAV + Interface utilisateur de l'administration WebDAV + + + Kit de ressources d'optimisation du référencement d'un site auprès d'un moteur de recherche IIS 1.0 + Kit de ressources d'optimisation du référencement d'un site auprès d'un moteur de recherche IIS 1.0 + Kit de ressources d'optimisation du référencement d'un site auprès d'un moteur de recherche (SEO) 1.0 + La base de données de ce programme d'installation contient la logique et les données requises pour installer le Kit de ressources d'optimisation du référencement d'un site auprès d'un moteur de recherche IIS 1.0. + + + Éditeur IIS + + + Rapports IIS + Log Parser n'est pas installé sur cet ordinateur. Installez Log Parser 2.2 à partir de http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07, puis installez les rapports IIS + + + Les packages de composants requis sont introuvables. Exécutez setup.exe pour résoudre les dépendances et installer ce programme. + Microsoft SQL Server 2008 Management Objects doit être installé avant l'installation du Gestionnaire de bases de données IIS. Vous pouvez installer Microsoft SQL Server 2008 Management Objects à partir de http://go.microsoft.com/fwlink/?LinkID=150946 . + Microsoft SQL Server System CLR Types doit être installé avant l'installation du Gestionnaire de bases de données IIS. Vous pouvez installer Microsoft SQL Server System CLR Types à partir de http://go.microsoft.com/fwlink/?LinkID=150949. + + + Microsoft Web Farm Framework + Microsoft External Cache + Web Farm Framework est un composant requis pour l'installation d'Application Request Routing. Installez Web Farm Framework. + Microsoft Application Request Routing 2.5 + Exécution + Ajoute les fonctionnalités d'Application Request Routing à IIS. + Interface utilisateur + Configure la fonctionnalité Application Request Routing dans le Gestionnaire des services Internet. + + + Composant logiciel enfichable Microsoft Windows PowerShell pour IIS 7.0 + + + Microsoft Web Platform Installer 4.0 + + Microsoft Web Platform Installer + [ProductName] requiert Windows XP SP2, Windows 2003 SP1, Windows Vista ou versions ultérieures. + [ProductName] requiert Windows XP Service Pack 3, Windows Server 2003 Service Pack 2 ou versions ultérieures. + + + Programme d'installation des services Microsoft Windows Azure + Programme d'installation des services Microsoft Windows Azure + + + Gestionnaire des services Internet (IIS) 7+ + Client du Gestionnaire des services Internet + Support à distance + Ce produit requiert Windows XP SP2, Windows 2003 SP1, Windows Vista SP1, Windows 7 ou une version supérieure + La console de gestion IIS n'est pas installée, mais est requise pour gérer les serveurs IIS distants. Installez la console de gestion IIS avant d'installer le support de gestion à distance en ouvrant 'Panneau de configuration->Programmes->Activer ou désactiver des fonctionnalités Windows' et en sélectionnant la console de gestion IIS dans la fonctionnalité Services Internet. + Ce produit n'est pas requis dans Windows Server 2008 ou Windows Server 2008 R2 ou une version ultérieure. Installez la console de gestion IIS en ouvrant le Gestionnaire de serveur et en sélectionnant la console de gestion IIS dans les services de rôle pour le rôle Serveur Web. + + + Gestionnaire de publication pour IIS 7.0 + Interface utilisateur de publication + + + Application Warm-Up 1.0 pour IIS 7.5 + + + + Un produit incompatible, [CONFLICTING_PRODUCT_NAME], se trouve sur cet ordinateur. Impossible de poursuivre l'installation de [ProductName]. Pour installer ce produit, utilisez Ajouter/Supprimer les programmes dans le Panneau de configuration pour supprimer [CONFLICTING_PRODUCT_NAME]. + Des privilèges administrateur sont requis pour installer [ProductName]. + IIS version 7.0 est requis pour utiliser [ProductName]. + IIS version 7.0 ou supérieure est requis pour installer [ProductName]. + IIS version 7.5 ou supérieure est requis pour installer [ProductName]. + IIS version 7 ou 7.5 est requis pour installer [ProductName]. + La version bêta de [ProductName] est installée sur cet ordinateur. + Une version plus récente de [ProductName] est installée sur cet ordinateur. + Le programme d'installation ne peut pas continuer car une autre instance de [ProductName] est déjà installée sur cet ordinateur. Désinstallez-la, puis relancez l'installation. + Les fonctionnalités IIS 7.0 CoreWebEngine et W3SVC doivent être installées pour utiliser [ProductName]. + Les fonctionnalités de la console de gestion IIS doivent être installées pour utiliser [ProductName]. + Arrêtez les services d'activation des processus Windows (WAS) et de gestion Web (WMSvc) avant d'installer [ProductName]. Vous devrez redémarrer les services après avoir installé [ProductName]. + La métabase IIS est requise pour installer [ProductName]. + La version 64 bits de [ProductName] ne peut pas être installée sur une édition 32 bits de Microsoft Windows. + La version 32 bits de [ProductName] ne peut pas être installée sur une édition 64 bits de Microsoft Windows. + Microsoft .NET Framework version 2.0 ou supérieure est requise pour installer [ProductName]. + Microsoft .NET Framework version 3.5 ou supérieure est requis pour installer [ProductName]. Utilisez l'option d'ajout de fonctionnalités du Gestionnaire de serveur pour installer Microsoft .NET Framework version 3.5. + Microsoft .NET Framework version 4.0 ou supérieure est requis pour installer [ProductName]. + Installez Microsoft .NET Framework version 2.0 Service Pack 1 (ou SP supérieur), avant d'installer [ProductName]. + Le service Windows Update (wuauserv) ne peut pas être désactivé, il est requis pour installer [ProductName]. + Le composant logiciel enfichable PowerShell fait partie du système d'exploitation Windows. Installez-le via 'Programmes et fonctionnalités' ou 'Gestionnaire de serveur'. + Microsoft Web Platform Installer version 3.0 ou supérieure est requis pour installer [ProductName]. + + Le programme d'installation n'a pas réussi à détecter la configuration partagée. + La configuration partagée est activée pour IIS. L'installation de [ProductName] n'est pas prise en charge lors de l'utilisation d'une configuration partagée. Désactivez la configuration partagée avant d'installer cette fonctionnalité. + + Arrêtez le service de publication World Wide Web (W3SVC) avant d'installer [ProductName]. Vous devrez le redémarrer après l'installation. + Console de gestion PowerShell IIS + Composant logiciel enfichable PowerShell IIS + Le composant logiciel enfichable PowerShell IIS requiert PowerShell v1.0 ou v2.0 + Le composant logiciel enfichable PowerShell IIS requiert WAS et une configuration + Chaîne d'exemple. + + + Microsoft Web Farm Framework Version 2.2 + Microsoft Web Farm Agent Version 2.2 + Service de batterie de serveurs Web + Service de batterie de serveurs Web + Service du contrôleur de batterie de serveurs Web + Service du contrôleur de batterie de serveurs Web + Service de l'agent de batterie de serveurs Web + Service de l'agent de batterie de serveurs Web + Web Platform Installer est un composant requis pour l'installation de Web Farm Framework 2.0. Installez Web Platform Installer à partir de http://www.microsoft.com/web/downloads/platform.aspx. + L'Outil de déploiement Web est un composant requis pour l'installation de Web Farm Framework. Installez l'Outil de déploiement Web à partir de http://www.iis.net/download/WebDeploy. + + + Microsoft Web Hosting Framework + Web Hosting Framework + Rôles et fonctionnalités de l'hébergement Web. + Hosting Framework + Hosting Framework fournit les commandes des API et de PowerShell pour la gestion de l'hébergement Web. + Rôle Web + Le rôle Web installe le service dynamique WAS et le fournisseur de réécriture d'URL pour l'hébergement Web. + Antares Express + Déploie une configuration du Panneau de configuration optimisée pour l'installation sur un seul ordinateur. + Rôle de l'équilibrage de charge + Le rôle de l'équilibrage de charge configure le routeur des requêtes d'applications pour diriger les règles d'hébergement Web. + Contrôleur d'hébergement + Le contrôleur d'hébergement étend Web Farm Framework 2.0 pour être utilisé avec l'hébergement Web. + Rôle de publication + Installe le support pour le déploiement Web et la publication FTP. + Il s'agit d'un composant logiciel enfichable PowerShell qui contient des applets de commande pour gérer l'infrastructure Microsoft Web Hosting. + Service WAS dynamique + Service d'activation de processus Windows optimisé pour l'hébergement Web grande densité. + Service Contrôle des ressources + Installe le service Contrôle des ressources qui permet de collecter et de publier des informations d'exécution et d'intégration. + Contrôle des ressources + Active la collecte et la publication des informations sur l'exécution et l'intégration à partir du rôle Web. + Hébergement de l'application des quotas + Surveille l'utilisation des ressources des sites Web et exécute des actions personnalisées lorsque le quota d'utilisation est dépassé. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/ITA/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/ITA/misc/setupstrings.wxl new file mode 100644 index 0000000000..238a9292f9 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/ITA/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 1040 + + + + Opzioni di installazione configurazione condivisa + Selezionare un'opzione per l'installazione nella configurazione condivisa di IIS + Aggiorna configurazione condivisa al momento dell'installazione + Questo modulo verrà installato su un server IIS che utilizza una configurazione condivisa. Se altri server IIS utilizzano la medesima configurazione condivisa, sarà necessario installare il modulo in ciascuno di essi. Per ridurre al minimo l'interruzione dei servizi dei singoli server Web, sarà necessario installare il modulo attenendosi alla procedura seguente: in tutti i computer tranne l'ultimo installare il modulo senza aggiornare la configurazione condivisa. A tale scopo, non selezionare la casella di controllo sotto. +In questo modo, verranno installati tutti i dati binari e i file necessari per il modulo in ogni computer senza apportare modifiche alla configurazione condivisa. A questo punto, nell'ultimo computer sarà necessario verificare che l'identità dell'utente in uso disponga di accesso in lettura e scrittura al file applicationhost.config nella condivisione UNC. Installare quindi il modulo e selezionare l'opzione di configurazione aggiornata sotto. + + + Inizializzazione dell'azione personalizzata WebConfig + Aggiornamento di web.config + + + + Registrazione avanzata IIS + Consente la registrazione avanzata dei della pipeline IIS. + Registrazione avanzata IIS + Consente la creazione di file di registro personalizzati con selezione campi estendibile. + Aggiornamento per IIS Advanced Logging + + + + IIS Transform Manager + Beta + Abilita IIS Media Services di Transform Manager. + IIS Transform Manager + Abilita la creazione di trasformazioni multimediali. + Host di IIS Transform Manager + Host del servizio per [ProductName]. + IIS Transform Manager + Esegue la conversione batch dei file multimediali su richiesta per alternare formati di file e contenitori. + Nel computer è installato un pacchetto IIS Transform Manager 1.0 Expression Encoder SP Task. È necessario disinstallarlo prima di eseguire l'installazione di [ProductName]. + + Per installare [ProductName] è necessario Microsoft .NET Framework 3.5. Utilizzare 'Aggiunta guidata funzionalità' in Server Manager per installare Funzionalità di .NET Framework 3.5.1 oppure utilizzare 'Attiva o disattiva le funzionalità Windows' per attivare Microsoft .NET Framework 3.5. + + + + IIS Digital Rights Management + Beta + Abilita Digital Rights Management di presentazioni Smooth Streaming. + + + ASP.NET non installato + + + + + + + + + IIS Smooth Streaming - Beta rilevato in questo computer. Impossibile continuare l'installazione di [ProductName]. Per installare il prodotto, utilizzare Installazione applicazioni nel Pannello di controllo per rimuovere IIS Smooth Streaming - Beta. + Una versione non compatibile di IIS Media Services è stata rilevata in questo computer. Impossibile continuare l'installazione di [ProductName]. Per installare il prodotto, utilizzare Installazione applicazioni nel Pannello di controllo per rimuovere IIS Media Services. + Nel computer in uso è già installata o disponibile per l'installazione una versione più recente del prodotto. Impossibile continuare l'installazione di [ProductName]. Per installare la versione più recente del prodotto, utilizzare Installazione applicazioni nel Pannello di controllo per aggiornare IIS Media Services. + Conversione file elenco di riproduzione obbligatoria + + + + + Rilevati file di una versione precedente di IIS Media Services + + + + + Rilevati file di una versione beta di IIS Media Services + + + + + + IIS Media Pack 1.0 + Aggiornamento per IIS Media Pack 1.0 + IIS Media Services 2.0 + Aggiornamento per IIS Media Services 2.0 + IIS Media Services 3.0 + IIS Media Services 3.0 TAP 2 + Aggiornamento per IIS Media Services 3.0 + Funzionalità e strumenti di IIS Media Services. + Funzionalità e strumenti di IIS Media Services 5 Premium. + IIS Media Services 4.0 Beta 1 + IIS Media Services 4.0 + IIS Media Services 4.5 Beta 1 + IIS Media Services 5 Premium + + Web Playlists + Controlla la riproduzione del client di asset di file multimediali a cui si fa riferimento negli elenchi di riproduzione. + Session Helper + Consente la persistenza dello stato della sessione ASP.NET. Richiede il servizio ruolo ASP.NET per Server Web (IIS). + Interfaccia utente + Configura la funzionalità Web Playlists in Gestione IIS. + + Bit Rate Throttling + Riduce la larghezza di banda necessaria limitando il recapito dei file scaricati dai client. + Interfaccia utente + Configura la funzionalità Bit Rate Throttling in Gestione IIS. + + Asset + Consente il flusso adattivo HTTP degli asset su richiesta nei client. + Interfaccia utente + Configura la funzionalità Smooth Streaming in Gestione IIS. + + Canali + Consente il flusso adattivo HTTP delle trasmissioni di canale ai client. + Interfaccia utente + Configura la funzionalità Live Smooth Streaming in Gestione IIS. + + Digital Rights Management + Fornisce crittografia e licenze dei file multimediali Smooth Streaming. + Interfaccia utente + Configura la funzionalità Digital Rights Management in Gestione IIS. + + [ProductName] richiede Microsoft Windows Vista Service Pack 1 o versione successiva. + Impossibile installare [ProductName] in Vista Home Basic. + [ProductName] richiede Microsoft Windows 7 Service Pack 1 o versione successiva. + + + IIS Database Manager + IIS Database Manager + + + Servizio Gestione Web Microsoft 2 + Servizio Gestione Web Microsoft + Installa le funzionalità di base di [ProductName]. + Servizio Gestione Web Microsoft 2 + Il servizio Gestione Web offre agli amministratori funzionalità di gestione remota e delegata per il server Web, i siti e le applicazioni presenti nel computer. + + + Microsoft URL Rewrite Module 1.1 per IIS 7 + Aggiornamento per URL Rewrite Module 1.1 per IIS 7 + URL Rewrite + Abilita le funzionalità di riscrittura del contenuto e degli URL in IIS 7. + Interfaccia utente + Configura la funzionalità URL Rewrite Module in Gestione IIS. + + + IIS URL Rewrite Module 2 + Aggiornamento per IIS URL Rewrite Module 2 + URL Rewrite + Abilita le funzionalità di riscrittura del contenuto e degli URL in IIS 7. + Interfaccia utente + Configura la funzionalità URL Rewrite Module in Gestione IIS. + + + Administration Pack per IIS 7.0 + Installa le funzionalità di base di [ProductName]. + 1252 + Administration Pack per IIS 7.0 + Microsoft Corporation + Questa versione del sistema operativo non è supportata. [ProductName] può essere installato solo con Windows Server 2008 o Windows Vista Service Pack 1 e versioni successive. + Funzionalità ASP.Net + ASP.NET include le funzionalità Pagine errori e autorizzazione, che consentono di gestire le impostazioni di errori personalizzati e di autorizzazione. + Autenticazione + Descrizione dell'autenticazione ASP.Net. + Autorizzazione + L'autorizzazione ASP.NET consente di configurare le regole per autorizzare gli utenti ad accedere a siti Web e applicazioni. + Pagine errori + Le pagine errori ASP.NET consentono di configurare le risposte di errore HTTP da restituire in caso di errori. + Moduli + Descrizione dei moduli ASP.Net. + Gestori + Descrizione dei gestori ASP.Net. + Editor di configurazione + Editor di configurazione consente di gestire i file di configurazione in Gestione IIS offrendo la possibilità di modificare sezioni, attributi, elementi e raccolte all'interno dei file di configurazione. + Filtro richieste + Filtro richieste consente di configurare le regole di filtro per il sito Web e di limitare il comportamento di protocollo e contenuto. + FastCGI + FastCGI consente di configurare le impostazioni del pool di processi per le applicazioni FastCGI del server Web. + + + Restrizioni IP dinamico per l'installazione di IIS 7 + + + + + + + + + + + + + Restrizioni IP dinamico per IIS 7 - Beta + Restrizioni IP dinamico per IIS 7 - Beta 2 + Restrizioni IP dinamico per IIS 7 - Beta 3 + + Restrizioni IP dinamico per IIS 7 - Versione finale candidata + Restrizioni IP dinamico per IIS 7 - Versione finale candidata 2 + Restrizioni IP dinamico per IIS 7 - Versione finale candidata 3 + + Restrizioni IP dinamico per IIS 7 - RTW + + Restrizioni IP dinamico per IIS 7 + Interfaccia utente di Restrizioni IP dinamico per IIS 7 + + Restrizioni IP dinamico per IIS 7 - Beta rilevato nel computer. Disinstallarlo, quindi riprovare + + + WebDAV 7.5 per IIS 7.0 + Per utilizzare questo prodotto, è necessario installare le funzionalità CoreWebEngine e W3SVC di IIS 7.0. + Modulo server WebDAV + Interfaccia utente di amministrazione WebDAV + + + IIS Search Engine Optimization Toolkit 1.0 + IIS Search Engine Optimization Toolkit 1.0 + Search Engine Optimization (SEO) Toolkit 1.0 + Il database del programma di installazione contiene la logica e i dati necessari per l'installazione di IIS Search Engine Optimization Toolkit 1.0. + + + Editor IIS + + + Report IIS + Log Parser non installato nel computer in uso. Installare Log Parser 2.2 dal sito Web http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07, quindi continuare con l'installazione di Report IIS. + + + Pacchetti dei prerequisiti non trovati. Eseguire setup.exe per risolvere le dipendenze e installare il programma. + Microsoft SQL Server 2008 Management Objects è un prerequisito per l'installazione di IIS Database Manager. È possibile installare Microsoft SQL Server 2008 Management Objects dal sito http://go.microsoft.com/fwlink/?LinkID=150946. + Microsoft SQL Server System CLR Types è un prerequisito per l'installazione di IIS Database Manager. È possibile installare Microsoft SQL Server System CLR Types dal sito http://go.microsoft.com/fwlink/?LinkID=150949. + + + Microsoft Web Farm Framework + Microsoft External Cache + Web Farm Framework è un requisito per l'installazione di Application Request Routing. Installare Web Farm Framework. + Microsoft Application Request Routing 2.5 + Runtime + Aggiunge le funzionalità di Application Request Routing a IIS. + Interfaccia utente + Configura la funzionalità Application Request Routing in Gestione IIS. + + + Snap-in di Microsoft Windows PowerShell per IIS 7.0 + + + Installazione guidata piattaforma Web Microsoft 4.0 + Installazione guidata piattaforma Web Microsoft + [ProductName] richiede Windows XP SP2, Windows 2003 SP1, Windows Vista o versione successiva. + [ProductName] richiede Windows XP Service Pack 3, Windows Server 2003 Service Pack 2 o versione successiva. + + + Programma di installazione servizi Microsoft Windows Azure + Programma di installazione servizi Microsoft Windows Azure + + + Gestione Internet Information Services (IIS) 7+ + Client Gestione IIS + Remoting Support + Per questo prodotto è necessario Windows XP SP2, Windows 2003 SP1, Windows Vista SP1, Windows 7 o versione successiva + La Console di gestione IIS necessaria per la gestione dei server IIS remoti non è installata. Installare la Console di gestione IIS prima di installare il supporto di gestione remoto. A tale scopo, aprire "Pannello di controllo->Programmi->Attiva o disattiva le funzionalità Windows" e selezionare Console di gestione IIS nella funzionalità Internet Information Services. + Questo prodotto non è necessario in Windows Server 2008 o in Windows Server 2008 R2 o versione successiva. Per installare la Console di gestione IIS, aprire Gestione server e selezionare la Console di gestione IIS nei Servizi ruolo per il ruolo Server Web. + + + IIS Manager Publishing per IIS 7.0 + Interfaccia utente di pubblicazione + + + Application Warm-Up 1.0 per IIS 7.5 + + + + Nel computer è installato un prodotto incompatibile, [CONFLICTING_PRODUCT_NAME]. Non è possibile continuare l'installazione di [ProductName]. Per installare il prodotto, utilizzare Installazione applicazioni nel Pannello di controllo e rimuovere [CONFLICTING_PRODUCT_NAME]. + Per installare [ProductName], sono richiesti i privilegi di amministratore. + Per utilizzare [ProductName], è richiesto IIS versione 7.0. + Per installare [ProductName], è richiesto IIS versione 7.0 o versione successiva. + Per installare [ProductName] è necessario IIS 7.5 o versione successiva. + Per installare [ProductName] è necessario IIS versione 7 o 7.5. + Versione beta di [ProductName] rilevata nel computer in uso. + Nel computer in uso è stata rilevata una versione più recente di [ProductName]. + L'installazione non può continuare poiché un'altra istanza di [ProductName] è già installata nel computer in uso. Disinstallarla e quindi riavviare l'installazione. + Per utilizzare [ProductName], è necessario installare le funzionalità CoreWebEngine e W3SVC di IIS 7.0. + Per utilizzare [ProductName], è necessario installare la Console di gestione IIS. + Arrestare Servizio Attivazione processo Windows (WAS) e Servizio di gestione Web (WMSvc) prima di installare [ProductName]. Avviare i servizi dopo l'installazione di [ProductName]. + Per installare [ProductName], è richiesta la metabase IIS. + Impossibile installare la versione a 64 bit di [ProductName] in un'edizione a 32 bit di Microsoft Windows. + Impossibile installare la versione a 32 bit di [ProductName] in un'edizione a 64 bit di Microsoft Windows. + Per installare [ProductName], è richiesto Microsoft .NET Framework versione 2.0 o versione successiva. + Microsoft .NET Framework versione 3.5 o successiva necessario per installare [ProductName]. Utilizzare 'Aggiungi funzionalità' in Server Manager per installare Microsoft .NET versione 3.5. + Microsoft .NET Framework versione 4.0 o successiva necessario per installare [ProductName]. + Prima di installare [ProductName], installare Microsoft .NET Framework versione 2.0 Service Pack 1 o versione successiva. + Impossibile disabilitare il servizio Windows Update (wuauserv). È richiesto per installare [ProductName]. + Lo snap-in di PowerShell fa parte del sistema operativo Windows. Installarlo mediante 'Programmi e funzionalità' o 'Server Manager'. + Installazione guidata piattaforma Web di Microsoft versione 3.0 o successiva necessaria per installare [ProductName]. + + Impossibile rilevare la configurazione condivisa. + Configurazione condivisa abilitata per IIS. L'installazione di [ProductName] non è supportata quando si utilizza la configurazione condivisa. Disabilitare la configurazione condivisa prima di installare questa funzionalità. + + Arrestare il Servizio Pubblicazione sul Web (W3SVC) prima di installare [ProductName]. Avviare il servizio dopo l'installazione. + Console di gestione IIS PowerShell + Snap-in di IIS PowerShell + Lo snap-in di IIS PowerShell richiede l'installazione di PowerShell v1.0 o v2.0 + Lo snap-in di IIS PowerShell richiede l'installazione di WAS e della configurazione + Stringa non valida. + + + Microsoft Web Farm Framework versione 2.2 + Microsoft Web Farm Agent versione 2.2 + Servizio Web Farm + Servizio Web Farm + Servizio controller Web Farm + Servizio controller Web Farm + Servizio agente Web Farm + Servizio agente Web Farm + L'Installazione guidata piattaforma Web è un prerequisito per l'installazione di Web Farm Framework. Eseguire l'Installazione guidata piattaforma Web dall'indirizzo http://www.microsoft.com/web/downloads/platform.aspx. + Lo Strumento di distribuzione Web è un prerequisito per l'installazione di Web Farm Framework. Installare lo Strumento di distribuzione Web dall'indirizzo http://www.iis.net/download/WebDeploy. + + + Microsoft Web Hosting Framework + Web Hosting Framework + Ruoli e funzionalità di Web Hosting. + Framework di hosting + Framework di hosting fornisce le API e i comandi PowerShell per la gestione di Web Hosting. + Ruolo Web + Ruolo Web esegue l'installazione del Servizio Attivazione processo Windows dinamico e del provider di URL Rewrite per Web Hosting. + Antares Express + Esegue la distribuzione di una configurazione del Pannello di controllo ottimizzata per l'installazione su singolo computer. + Ruolo bilanciamento del carico + Ruolo bilanciamento del carico configura Application Request Router per il routing in base alle regole di Web Hosting. + Controller di hosting + Controller di hosting estende Web Farm Framework 2.0 per consentirne il funzionamento con Web Hosting. + Ruolo di pubblicazione + Installa il supporto per la pubblicazione mediante Distribuzione Web e FTP. + Lo snap-in di PowerShell contiene i cmdlet per gestire l'infrastruttura Microsoft Web Hosting. + Servizio Attivazione processo Windows dinamico + Servizio Attivazione processo Windows dinamico ottimizzato per Web Hosting ad alta densità. + Servizio Misurazione risorse + Installa il servizio Misurazione risorse che abilita la raccolta e la pubblicazione delle informazioni sul runtime e sull'integrità. + Misurazione risorse + Abilita la raccolta e la pubblicazione delle informazioni sul runtime e sull'integrità da parte di Ruolo Web. + Imposizione quota hosting + Esegue il monitoraggio dell'utilizzo delle risorse dei siti Web ed esegue azioni personalizzate quando la quota relativa all'utilizzo viene superata. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/JPN/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/JPN/misc/setupstrings.wxl new file mode 100644 index 0000000000..ac70825d59 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/JPN/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 1041 + + + + 共有構成のインストール オプション + IIS 共有構成をインストールするためのオプションを選択します + インストール時に共有構成を更新する + 共有構成を使用する IIS サーバーに、このモジュールをインストールしようとしています。その他の IIS サーバーでこの共有構成を使用している場合は、これらすべてのコンピューターにこのモジュールをインストールする必要があります。個々の Web サーバーの障害を最小限に抑えるには、以下の手順でこのモジュールをインストールします。まず、最後の 1 台を除くすべてのコンピューターに、共有構成を更新せずにモジュールをインストールします。そのためには、下のチェック ボックスをオフにします。 +これにより、共有構成に変更を加えることなく、各コンピューターでモジュールに必要なバイナリとファイルがすべてインストールされます。次に、最後のコンピューターで、実行に使用しているユーザー ID が、UNC 共有にある applicationhost.config ファイルに対する読み取りと書き込みのアクセス権を持っていることを確認します。そのうえで、モジュールをインストールし、下にある [インストール時に共有構成を更新する] チェック ボックスをオンにします。 + + + WebConfig カスタム アクションを初期化しています + web.config を更新しています + + + + IIS 詳細ログ + IIS パイプライン データの詳細ログを有効にします。 + IIS 詳細ログ + 拡張可能なフィールド選択機能を備えたカスタム ログ ファイルの作成を有効にします。 + IIS 詳細ログの更新 + + + + IIS Transform Manager + Beta + Transform Manager の IIS Media Services を有効にします。 + IIS Transform Manager + メディア変換の作成を有効にします。 + IIS Transform Manager ホスト + [ProductName] 用のサービス ホスト。 + IIS Transform Manager + オンデマンド メディア ファイルを代替ファイルおよびコンテナー形式にバッチで変換します。 + IIS Transform Manager 1.0 Expression Encoder SP Task パッケージがコンピューターにインストールされています。[ProductName] をインストールする前にそのパッケージをアンインストールする必要があります。 + + [ProductName] をインストールするには、Microsoft .NET Framework 3.5 が必要です。サーバー マネージャーの機能の追加ウィザードを使用して .NET Framework 3.5.1 の各機能をインストールするか、[Windows の機能の有効化または無効化] を使用して Microsoft .NET Framework 3.5 を有効にします。 + + + + IIS デジタル著作権管理 + Beta + Smooth Streaming プレゼンテーションのデジタル著作権管理を有効にします。 + + + ASP.NET がインストールされていません + + + + + + + + + このコンピューターで、IIS Smooth Streaming - Beta が見つかりました。[ProductName] のインストールを続行できません。この製品をインストールするには、コントロール パネルの [プログラムの追加と削除] を使用して、IIS Smooth Streaming - Beta をアンインストールしてください。 + このコンピューターには、互換性のないバージョンの IIS Media Services が存在します。[ProductName] のインストールを続行できません。この製品をインストールするには、コントロール パネルの [プログラムの追加と削除] を使用して、IIS Media Services をアンインストールしてください。 + このコンピューターには、この製品の新しいバージョンが既にインストールされているか、新しいバージョンを入手してインストールすることができます。[ProductName] のインストールを続行できません。この製品のより新しいバージョンをインストールするには、コントロール パネルの [プログラムの追加と削除] を使用して、IIS Media Services を更新してください。 + プレイリスト ファイルの変換が必要 + + + + + 古い IIS Media Services ファイルが見つかりました + + + + + ベータ版の IIS Media Services ファイルが見つかりました + + + + + + IIS Media Pack 1.0 + IIS Media Pack 1.0 の更新 + IIS Media Services 2.0 + IIS Media Services 2.0 の更新 + IIS Media Services 3.0 + IIS Media Services 3.0 TAP 2 + IIS Media Services 3.0 の更新 + IIS Media Services の機能とツール。 + IIS Media Services 5 Premium の機能およびツール。 + IIS Media Services 4.0 Beta 1 + IIS Media Services 4.0 + IIS Media Services 4.5 Beta 1 + IIS Media Services 5 Premium + + Web プレイリスト + プレイリストで参照されたメディア アセットに対するクライアントの再生を制御します。 + セッション ヘルパー + ASP.NET セッション状態保持を有効にします (Web サーバー (IIS) の ASP.NET 役割サービスが必要)。 + ユーザー インターフェイス + IIS マネージャーで Web プレイリスト機能を構成します。 + + ビット レート調整 + クライアントによってダウンロードされるファイルの配信を制限することによって帯域幅を節約します。 + ユーザー インターフェイス + IIS マネージャーでビット レート調整機能を構成します。 + + アセット + クライアントに対し、オンデマンド アセットの HTTP アダプティブ ストリーミングを有効にします。 + ユーザー インターフェイス + IIS マネージャーで Smooth Streaming 機能を構成します。 + + チャネル + クライアントに対し、チャネル ブロードキャストの HTTP アダプティブ ストリーミングを有効にします。 + ユーザー インターフェイス + IIS Manager で Live Smooth Streaming 機能を構成します。 + + デジタル著作権管理 + Smooth Streaming メディアの暗号化とライセンスを提供します。 + ユーザー インターフェイス + IIS マネージャーでデジタル著作権管理機能を構成します。 + + [ProductName] には Microsoft Windows Vista Service Pack 1 以降が必要です。 + [ProductName] を Vista Home Basic にインストールすることはできません。 + [ProductName] には Microsoft Windows 7 Service Pack 1 以降が必要です。 + + + IIS Database Manager + IIS Database Manager + + + Microsoft Web Management Service 2 + Microsoft Web Management Service + [ProductName] の基本的な機能をインストールします。 + Microsoft Web Management Service 2 + Web 管理サービスでは、管理者がこのコンピューターの Web サーバー、サイトおよびアプリケーションを管理する機能をリモートで操作したり、委任したりすることができます。 + + + Microsoft URL Rewrite Module 1.1 for IIS 7 + URL Rewrite Module 2 for IIS 7 の更新 + URL 書き換え + IIS 7 への URL およびコンテンツの書き換え機能を有効にします。 + ユーザー インターフェイス + URL 書き換えモジュール機能を IIS マネージャーで構成します。 + + + IIS URL Rewrite Module 2 + IIS URL Rewrite Module 2 の更新プログラム + URL 書き換え + IIS 7 への URL およびコンテンツの書き換え機能を有効にします。 + ユーザー インターフェイス + URL 書き換えモジュール機能を IIS マネージャーで構成します。 + + + Administration Pack for IIS 7.0 + [ProductName] の基本的な機能をインストールします。 + 1252 + Administration Pack for IIS 7.0 + Microsoft Corporation + このバージョンのオペレーティング システムはサポートされません。[ProductName] は、Windows Server 2008 か、または Windows Vista Service Pack 1 以降にのみインストールできます。 + ASP.Net の機能 + ASP.NET には、承認とエラー ページの機能があり、それを使って承認やカスタム エラーの設定を管理できます。 + 認証 + ASP.Net 認証の説明。 + 承認 + ASP.NET の承認では、Web サイトおよびアプリケーションへのユーザーのアクセスを承認するための規則を構成できます。 + エラー ページ + ASP.NET エラー ページでは、エラー発生時に返す HTTP エラー応答を構成できます。 + モジュール + ASP.Net モジュールの説明。 + ハンドラー + ASP.Net ハンドラーの説明。 + 構成エディター + 構成エディターを使用して、IIS マネージャー内の構成ファイルを管理できます。構成ファイル内のセクション、属性、要素、およびコレクションを編集することができます。 + 要求のフィルタリング + 要求のフィルタリングでは、Web サイトのフィルタリング規則を構成したり、プロトコルやコンテンツの動作を制限したりできます。 + Fast CGI + FastCGI では、Web サーバー上の FastCGI アプリケーション用のプロセス プール設定を構成できます。 + + + Dynamic IP Restrictions for IIS 7 セットアップ + + + + + + + + + + + + + Dynamic IP Restrictions for IIS 7 - Beta + Dynamic IP Restrictions for IIS 7 - Beta 2 + Dynamic IP Restrictions for IIS 7 - Beta 3 + + Dynamic IP Restrictions for IIS 7 - リリース候補 + Dynamic IP Restrictions for IIS 7 - リリース候補 2 + Dynamic IP Restrictions for IIS 7 - リリース候補 3 + + Dynamic IP Restrictions for IIS 7 - RTW + + Dynamic IP Restrictions for IIS 7 + Dynamic IP Restrictions for IIS 7 のユーザー インターフェイス + + このコンピューターに Dynamic IP Restrictions for IIS 7 - Beta が見つかりました。アンインストールしてからやり直してください + + + WebDAV 7.5 For IIS 7.0 + この製品を使用するには、IIS 7.0 の CoreWebEngine および W3SVC 機能をインストールする必要があります。 + WebDAV サーバー モジュール + WebDAV 管理ユーザー インターフェイス + + + IIS Search Engine Optimization ツールキット 1.0 + IIS Search Engine Optimization ツールキット 1.0 + Search Engine Optimization (SEO) ツールキット 1.0 + このインストーラー データベースには、IIS Search Engine Optimization ツールキット 1.0 のインストールに必要なロジックとデータが含まれています。 + + + IIS エディター + + + IIS レポート + このコンピューターには、Log Parser がインストールされていません。http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07 から Log Parser 2.2 をインストールし、IIS レポートのインストールを続行してください。 + + + 前提条件のパッケージが見つかりませんでした。setup.exe を実行して依存関係を解決してから、このプログラムをインストールしてください。 + IIS Database Manager のインストールの前提条件として、Microsoft SQL Server 2008 管理オブジェクトが必要です。Micrsoft SQL Server 2008 管理オブジェクトは http://go.microsoft.com/fwlink/?LinkID=150946 からインストールできます。 + IIS Database Manager のインストールの前提要件として、Microsoft SQL Server System CLR Types が必要です。Microsoft SQL Server System CLR Types は、http://go.microsoft.com/fwlink/?LinkID=150949 からインストールできます。 + + + Microsoft Web Farm Framework + Microsoft External Cache + アプリケーション要求ルーティング処理の前提条件として、Web Farm Framework が必要です。Web Farm Framework をインストールしてください。 + Microsoft Application Request Routing 2.5 + ランタイム + アプリケーション要求ルーティング処理の機能を IIS に追加します。 + ユーザー インターフェイス + アプリケーション要求ルーティング処理の機能を IIS マネージャーで構成します。 + + + Microsoft Windows PowerShell snap-in for IIS 7.0 + + + Microsoft Web Platform Installer 4.0 + Microsoft Web Platform Installer + [ProductName] には、Windows XP SP2、Windows 2003 SP1、Windows Vista 以降が必要です。 + [ProductName] には、Windows XP Service Pack 3、Windows Server 2003 Service Pack 2 以降が必要です。 + + + Microsoft Windows Azure サービス インストーラー + Microsoft Windows Azure サービス インストーラー + + + インターネット インフォメーション サービス (IIS) 7 以上のマネージャー + IIS マネージャー クライアント + リモート処理サポート + この製品には、Windows XP SP2、Windows 2003 SP1、Windows Vista SP1、または Windows 7 以上が必要です。 + リモート IIS サーバーを管理するために必要な IIS 管理コンソールがインストールされていません。コントロール パネルの [プログラム] で、[Windows の機能の有効化または無効化] を開き、Ineternet Information Services 機能から [IIS 管理コンソール] を選択して、IIS 管理コンソールをインストールしてから、リモート管理サポートをインストールしてください。 + この製品は、Windows Server 2008 または Windows Server 2008 R2 以上では必須ではありません。サーバー マネージャーを開き、Web サーバーの役割の役割サービスで [IIS 管理コンソール] を選択して、IIS 管理コンソールをインストールしてください。 + + + IIS Manager Publishing for IIS 7.0 + Publishing のユーザー インターフェイス + + + Application Warm-Up 1.0 for IIS 7.5 + + + + 互換性のない製品 [CONFLICTING_PRODUCT_NAME] がこのコンピューター上にあります。[ProductName] のインストールを続行できません。この製品をインストールするには、[コントロール パネル] の [プログラムの追加と削除] を使用して、[CONFLICTING_PRODUCT_NAME] を削除してください。 + [ProductName] をインストールするには管理者特権が必要です。 + [ProductName] を使用するには、IIS Version 7.0 が必要です。 + [ProductName] をインストールするには、IIS Version 7.0 以降が必要です。 + [ProductName] をインストールするには、IIS Version 7.5 以降が必要です。 + [ProductName] をインストールするには、IIS Version 7 または 7.5 が必要です。 + このコンピューターに [ProductName] のベータ版が見つかりました。 + このコンピューターに、より新しいバージョンの [ProductName] が見つかりました。 + このコンピューターには、[ProductName] の別のインスタンスが既にインストールされているため、セットアップを続行できません。最初にアンインストールしてから、再度インストールを行ってください。 + [ProductName] を使用するには、IIS 7.0 の CoreWebEngine および W3SVC 機能をインストールする必要があります。 + [ProductName] を使用するには、IIS 管理コンソールをインストールする必要があります。 + Windows プロセス起動サービス (WAS) と Web 管理サービス (WMSvc) の両方のサービスを停止してから、[ProductName] をインストールしてください。[ProductName] のインストール後にサービスを起動する必要があります。 + [ProductName] をインストールするには、IIS メタベースが必要です。 + 64 ビット版の [ProductName] を 32 ビット版の Microsoft Windows にインストールすることはできません。 + 32 ビット版の [ProductName] を 64 ビット版の Microsoft Windows にインストールすることはできません。 + [ProductName] をインストールするには、Microsoft .NET Framework Version 2.0 以降が必要です。 + [ProductName] をインストールするには、Microsoft .NET Framework Version 3.5 以降が必要です。サーバー マネージャーの [機能の追加] を使用して、Microsoft .Net Version 3.5 をインストールしてください。 + [ProductName] をインストールするには、Microsoft .NET Framework Version 4.0 以降が必要です。 + [ProductName] をインストールする前に、Microsoft .NET Framework Version 2.0 Service Pack 1 (またはそれ以降の Service Pack) をインストールしてください。 + Windows Update (wuauserv) サービスを無効にすることはできません。[ProductName] をインストールする場合は必須です。 + PowerShell スナップインは、Windows オペレーティング システムに付属しています。[プログラムと機能] またはサーバー マネージャーからインストールしてください。 + [ProductName] をインストールするには、Microsoft Web Platform Installer Version 3.0 以降が必要です。 + + 共有構成を検出できませんでした。 + IIS に対して共有構成が有効になっています。共有構成を使用している場合、[ProductName] をインストールすることはサポートされません。この機能をインストールする場合は、あらかじめ共有構成を無効にしてください。 + + [ProductName] をインストールする前に、World Wide Web 発行サービス (W3SVC) を停止してください。インストール後は、このサービスを起動する必要があります。 + IIS PowerShell 管理コンソール + IIS PowerShell スナップイン + IIS PowerShell スナップインを使用するには、PowerShell v1.0 または v2.0 がインストールされている必要があります。 + IIS PowerShell スナップインを使用するには、WAS および構成がインストールされている必要があります。 + これは仮の文字列です。 + + + Microsoft Web Farm Framework Version 2.2 + Microsoft Web Farm Agent Version 2.2 + Web Farm サービス + Web Farm サービス + Web Farm コントローラー サービス + Web Farm コントローラー サービス + Web Farm エージェント サービス + Web Farm エージェント サービス + Web Farm Framework をインストールする前提条件として、Web Platform Installer が必要です。http://www.microsoft.com/web/downloads/platform.aspx から Web Platform Installer をインストールしてください。 + Web Farm Framework をインストールする前提条件として、Web 配置ツールが必要です。http://www.microsoft.com/downloads/details.aspx?displaylang=ja&FamilyID=c7ca4240-5427-42ba-bd46-29a755549e37 (x64) または、http://www.microsoft.com/downloads/details.aspx?displaylang=ja&FamilyID=f2b0fe35-15ae-4638-b72e-f96535c64591 (x86) から Web 配置ツールをインストールしてください。 + + + Microsoft Web Hosting Framework + Web Hosting Framework + Web ホスティングの役割と機能。 + Hosting Framework + Hosting Framework は、Web ホスティングを管理するための API と PowerShell コマンドを提供します。 + Web ロール + Web ロールは、Web ホスティングのための動的 WAS サービスおよび URL 書き換えプロバイダーをインストールします。 + Antares Express + シングル コンピューター セットアップ用に最適化されたコントロール パネルの構成を展開します。 + 負荷分散装置の役割 + 負荷分散装置の役割は、Web ホスティングの規則を基にしてルーティングするようにアプリケーション要求ルーターを構成します。 + ホスティング コントローラー + ホスティング コントローラーは、Web ホスティングと連携するように Web Farm Framework 2.0 を拡張します。 + Publishing ロール + Web 配置および FTP 発行のサポートをインストールします。 + これは、Microsoft Web Hosting インフラストラクチャを管理するためのコマンドレットを含む PowerShell スナップインです。 + 動的 WAS サービス + 高密度な Web ホスティング用に最適化された Windows プロセス アクティブ化サービス。 + リソース メータリング サービス + ランタイムおよび正常性情報の両方の収集と発行を有効にする、リソース メータリング サービスをインストールします。 + リソース メータリング + Web ロールからのランタイムおよび正常性情報の収集と発行を有効にします。 + ホスティング クォータの強制 + Web サイトのリソースの使用率を監視し、使用率のクォータを超えた場合にカスタム アクションを実行します。 + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/KOR/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/KOR/misc/setupstrings.wxl new file mode 100644 index 0000000000..f4cb5f3312 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/KOR/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 1042 + + + + 공유 구성 설치 옵션 + IIS 공유 구성 설치 옵션을 선택합니다. + 설치 시 공유 구성 업데이트 + 공유 구성을 사용 중인 IIS 서버에 이 모듈을 설치하는 중입니다. 이 공유 구성을 사용하는 IIS 서버가 더 있는 경우 해당하는 모든 컴퓨터에 이 모듈을 설치해야 합니다. 각 웹 서버의 장애를 최소화하려면 다음 절차에 따라 이 모듈을 설치해야 합니다. 첫째, 마지막 컴퓨터를 제외한 모든 컴퓨터에서 공유 구성을 업데이트하지 않고 모듈을 설치합니다. 아래의 확인란을 선택하지 않고 이 작업을 실행하십시오. +이렇게 하면 공유 구성을 변경하지 않고 모듈에 필요한 모든 파일 및 이진 파일이 각 컴퓨터에 설치됩니다. 둘째, 마지막 컴퓨터에서 사용자가 실행 중인 사용자 ID에 UNC 공유의 applicationhost.config 파일에 대한 읽기 및 쓰기 권한이 있는지 확인합니다. 그런 다음 모듈을 설치하고 아래의 업데이트 공유 구성 옵션을 선택합니다. + + + WebConfig 사용자 지정 작업을 초기화하는 중 + web.config 업데이트 중 + + + + IIS 고급 로깅 + IIS 파이프라인 데이터의 고급 로깅을 사용합니다. + IIS 고급 로깅 + 확장 가능한 필드 선택으로 사용자 지정 로그 파일을 만들 수 있도록 설정합니다. + IIS 고급 로깅 업데이트 + + + + IIS Transform Manager + 베타 + Transform Manager IIS 미디어 서비스를 활성화합니다. + IIS Transform Manager + 미디어 변환을 만들 수 있도록 설정합니다. + IIS Transform Manager 호스트 + [ProductName]의 서비스 호스트입니다. + IIS Transform Manager + 요청 시 미디어 파일을 대체 파일 및 컨테이너 형식으로 일괄 변환합니다. + 컴퓨터에 IIS Transform Manager 1.0 Expression Encoder SP 작업 패키지가 설치되어 있습니다. [ProductName]을(를) 설치하기 전에 IIS Transform Manager 1.0 Expression Encoder SP 작업 패키지를 제거해야 합니다. + + [ProductName]을(를) 설치하려면 Microsoft .NET Framework 3.5가 필요합니다. 서버 관리자에서 '기능 추가 마법사'를 사용하여 .NET Framework 3.5.1 기능을 설치하거나 'Windows 기능 사용/사용 안 함'을 사용하여 Microsoft .NET Framework 3.5 기능을 활성화합니다. + + + + IIS 디지털 권한 관리 + 베타 + 부드러운 스트리밍 프레젠테이션의 디지털 권한 관리를 활성화합니다. + + + ASP.NET이 설치되어 있지 않습니다. + + + + + + + + + 이 컴퓨터에 IIS 부드러운 스트리밍 - 베타가 있으므로 [ProductName] 설치를 계속할 수 없습니다. 이 제품을 설치하려면 제어판의 [프로그램 추가/제거]를 사용하여 IIS 부드러운 스트리밍 - 베타를 제거하십시오. + 이 컴퓨터에 IIS 미디어 서비스의 비호환 버전이 있으므로 [ProductName] 설치를 계속할 수 없습니다. 이 제품을 설치하려면 제어판의 [프로그램 추가/제거]를 사용하여 IIS 미디어 서비스를 제거하십시오. + 컴퓨터에 이 제품의 최신 버전이 이미 설치되어 있거나 설치에 사용할 수 있으므로 [ProductName] 설치를 계속할 수 없습니다. 이 제품의 최신 버전을 설치하려면 [제어판]에서 [프로그램 추가/제거]를 사용하여 IIS Media Services를 업데이트하십시오. + 재생 목록 파일 변환이 필요합니다. + + + + + 이전 IIS 미디어 서비스 파일이 있습니다. + + + + + 베타 IIS 미디어 서비스 파일이 있습니다. + + + + + + IIS Media Pack 1.0 + IIS Media Pack 1.0에 대한 업데이트 + IIS Media Services 2.0 + IIS Media Services 2.0에 대한 업데이트 + IIS Media Services 3.0 + IIS 미디어 서비스 3.0 TAP 2 + IIS Media Services 3.0에 대한 업데이트 + IIS Media Services 기능 및 도구입니다. + IIS Media Services 5 Premium 기능 및 도구입니다. + IIS 미디어 서비스 4.0 베타 1 + IIS 미디어 서비스 4.0 + IIS 미디어 서비스 4.5 베타 1 + IIS Media Services 5 Premium + + 웹 재생 목록 + 재생 목록에 참조된 미디어 자산의 클라이언트 재생을 제어합니다. + Session Helper + ASP.NET 세션 상태가 지속되도록 설정합니다(웹 서버(IIS)에 대한 ASP.NET 역할 서비스 필요). + 사용자 인터페이스 + IIS 관리자에서 웹 재생 목록 기능을 구성합니다. + + 비트 전송률 제한 + 클라이언트가 다운로드하는 파일 전달을 제한하여 대역폭을 절약합니다. + 사용자 인터페이스 + IIS 관리자에서 비트 전송률 제한 기능을 구성합니다. + + 자산 + 클라이언트에 대한 주문형 자산의 HTTP 적응 스트리밍을 사용하도록 설정합니다. + 사용자 인터페이스 + IIS 관리자에서 부드러운 스트리밍 기능을 구성합니다. + + 채널 + 클라이언트에 대한 채널 브로드캐스트의 HTTP 적응 스트리밍을 사용하도록 설정합니다. + 사용자 인터페이스 + IIS 관리자에서 Live Smooth Streaming 기능을 구성합니다. + + 디지털 권한 관리 + 부드러운 스트리밍 미디어의 암호화 및 라이선스를 제공합니다. + 사용자 인터페이스 + IIS 관리자의 디지털 권한 관리 기능을 구성합니다. + + [ProductName]에는 Microsoft Windows Vista 서비스 팩 1 이상이 필요합니다. + [ProductName]은(는) Vista Home Basic에 설치할 수 없습니다. + [ProductName]에는 Microsoft Windows 7 서비스 팩 1 이상이 필요합니다. + + + IIS 데이터베이스 관리자 + IIS 데이터베이스 관리자 + + + Microsoft Web Management Service 2 + Microsoft Web Management Service + [ProductName]의 기본 기능을 설치합니다. + Microsoft Web Management Service 2 + Web Management Service를 사용하면 관리자가 원격 및 위임된 관리 기능을 사용하여 이 컴퓨터에 있는 웹 서버, 사이트 및 응용 프로그램을 관리할 수 있습니다. + + + IIS 7용 Microsoft URL 재작성 모듈 1.1 + IIS 7용 URL 재작성 모듈 1.1에 대한 업데이트 + URL 재작성 + IIS 7에 대한 URL 및 콘텐츠 재작성 기능을 활성화합니다. + 사용자 인터페이스 + IIS 관리자에서 URL 재작성 모듈 기능을 구성합니다. + + + IIS URL 재작성 모듈 2 + IIS URL 재작성 모듈 2에 대한 업데이트 + URL 재작성 + IIS 7에 대한 URL 및 콘텐츠 재작성 기능을 활성화합니다. + 사용자 인터페이스 + IIS 관리자에서 URL 재작성 모듈 기능을 구성합니다. + + + IIS 7.0 관리 팩 + [ProductName]의 기본 기능을 설치합니다. + 1252 + IIS 7.0 관리 팩 + Microsoft Corporation + 이 운영 체제 버전은 지원되지 않습니다. [ProductName]은(는) Windows Server 2008 또는 Windows Vista 서비스 팩 1 이상에만 설치할 수 있습니다. + ASP.NET 기능 + ASP.NET에는 권한 부여 및 사용자 지정 오류 설정을 관리하는 데 사용할 수 있는 권한 부여 및 오류 페이지 기능이 있습니다. + 인증 + ASP.NET 인증에 대한 설명입니다. + 권한 부여 + ASP.NET 권한 부여를 사용하여 사용자에게 웹 사이트 및 응용 프로그램에 액세스할 수 있는 권한을 부여하는 규칙을 구성할 수 있습니다. + 오류 페이지 + ASP.NET 오류 페이지를 사용하여 오류가 발생했을 때 반환할 HTTP 오류 응답을 구성할 수 있습니다. + 모듈 + ASP.NET 모듈에 대한 설명입니다. + 처리기 + ASP.NET 처리기에 대한 설명입니다. + 구성 편집기 + 구성 편집기를 통해 구성 파일의 섹션, 특성, 요소 및 컬렉션을 편집하여 IIS 관리자의 구성 파일을 관리할 수 있습니다. + 요청 필터링 + 요청 필터링을 사용하여 웹 사이트에 대한 필터링 규칙을 구성하고 프로토콜 및 콘텐츠 동작을 제한할 수 있습니다. + Fast CGI + FastCGI를 사용하여 웹 서버의 FastCGI 응용 프로그램에 대한 프로세스 풀 설정을 구성할 수 있습니다. + + + IIS 7 설치에 대한 동적 IP 제한 + + + + + + + + + + + + + IIS 7용 동적 IP 제한 - 베타 + IIS 7용 동적 IP 제한 - 베타 2 + IIS 7용 동적 IP 제한 - 베타 3 + + IIS 7용 동적 IP 제한 - 릴리스 후보 + IIS 7용 동적 IP 제한 - 릴리스 후보 2 + IIS 7용 동적 IP 제한 - 릴리스 후보 3 + + IIS 7용 동적 IP 제한 - RTW + + IIS 7용 동적 IP 제한 + IIS 7용 동적 IP 제한 사용자 인터페이스 + + 이 시스템에서 IIS 7 - 베타에 대한 동적 IP 제한 사항이 발견되었습니다. 이 제한 사항을 제거한 후 다시 시도하십시오. + + + IIS 7.0용 WebDAV 7.5 + 이 제품을 사용하려면 IIS 7.0 CoreWebEngine 및 W3SVC 기능이 설치되어 있어야 합니다. + WebDAV 서버 모듈 + WebDAV 관리 사용자 인터페이스 + + + IIS 검색 엔진 최적화 도구 키트 1.0 + IIS 검색 엔진 최적화 도구 키트 1.0 + 검색 엔진 최적화(SEO) 도구 키트 1.0 + 이 설치 프로그램 데이터베이스에는 IIS 검색 엔진 최적화 도구 키트 1.0을 설치하는 데 필요한 논리 및 데이터가 들어 있습니다. + + + IIS 편집기 + + + IIS 보고서 + 이 컴퓨터에 Log Parser가 설치되어 있지 않습니다. http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07에서 Log Parser 2.2를 설치한 다음 IIS 보고서 설치를 계속하십시오. + + + 필수 구성 요소 패키지가 없습니다. setup.exe를 실행하여 종속성을 해결한 다음 이 프로그램을 설치하십시오. + IIS 데이터베이스 관리자를 설치하려면 Microsoft SQL Server 2008 관리 개체가 설치되어 있어야 합니다. http://go.microsoft.com/fwlink/?LinkID=150946에서 Microsoft SQL Server 2008 관리 개체를 설치할 수 있습니다. + IIS 데이터베이스 관리자를 설치하려면 Microsoft SQL Server System CLR Types가 설치되어 있어야 합니다. http://go.microsoft.com/fwlink/?LinkID=150949에서 Microsoft SQL Server System CLR Types를 설치할 수 있습니다. + + + Microsoft Web Farm Framework + Microsoft External Cache + 응용 프로그램 요청 라우팅을 설치하려면 Web Farm Framework가 설치되어 있어야 합니다. Web Farm Framework를 설치하십시오. + Microsoft 응용 프로그램 요청 라우팅 버전 2.5 + 런타임 + IIS에 응용 프로그램 요청 라우팅 기능을 추가합니다. + 사용자 인터페이스 + IIS 관리자에서 응용 프로그램 요청 라우팅 기능을 구성합니다. + + + IIS 7.0용 Microsoft Windows PowerShell 스냅인 + + + Microsoft 웹 플랫폼 설치 관리자 4.0 + Microsoft 웹 플랫폼 설치 관리자 + [ProductName]에는 Windows XP SP2, Windows 2003 SP1, Windows Vista 이상이 필요합니다. + [ProductName]을(를) 사용하려면 Windows XP 서비스 팩 3, Windows Server 2003 서비스 팩 2 이상이 필요합니다. + + + Microsoft Windows Azure Services 설치 관리자 + Microsoft Windows Azure Services 설치 관리자 + + + IIS(인터넷 정보 서비스) 7+ 관리자 + IIS 관리자 클라이언트 + 원격 지원 + 이 제품에는 Windows XP SP2, Windows 2003 SP1, Windows Vista SP1, Windows 7 이상이 있어야 합니다. + 원격 IIS 서버 관리에 필요한 IIS 관리 콘솔이 설치되어 있지 않습니다. 원격 관리 지원을 설치하기 전에 '제어판->프로그램->Windows 기능 사용/사용 안 함'을 열고 인터넷 정보 서비스 기능에서 IIS 관리 콘솔을 선택하여 IIS 관리 콘솔을 설치하십시오. + 이 제품은 Windows Server 2008 또는 Windows Server 2008 R2 이상에서 필수 사항이 아닙니다. 서버 관리자를 열고 웹 서버 역할에 대한 역할 서비스에서 IIS 관리 콘솔을 선택하여 IIS 관리 콘솔을 설치하십시오. + + + IIS 7.0용 IIS 관리자 게시 + 게시 사용자 인터페이스 + + + IIS 7.5용 응용 프로그램 웜업 + + + + 이 컴퓨터에 호환되지 않는 제품 [CONFLICTING_PRODUCT_NAME]이(가) 있습니다. [ProductName]의 설치를 계속할 수 없습니다. 이 제품을 설치하려면 제어판에서 프로그램 추가/제거를 사용하여 [CONFLICTING_PRODUCT_NAME]을(를) 제거하십시오. + [ProductName]을(를) 설치하려면 관리자 권한이 있어야 합니다. + [ProductName]을(를) 사용하려면 IIS 버전 7.0이 있어야 합니다. + [ProductName]을(를) 설치하려면 IIS 버전 7.0 이상이 있어야 합니다. + [ProductName]을(를) 설치하려면 IIS 버전 7.5 이상이 있어야 합니다. + [ProductName]을(를) 설치하려면 IIS 버전 7 또는 7.5가 있어야 합니다. + 이 컴퓨터에 [ProductName]의 베타 버전이 설치되어 있습니다. + 이 컴퓨터에 [ProductName]의 상위 버전이 설치되어 있습니다. + 컴퓨터에 [ProductName]의 다른 인스턴스가 이미 설치되어 있어서 설치를 계속할 수 없습니다. 먼저 해당 인스턴스를 제거한 다음 설치 프로그램을 다시 시작하십시오. + [ProductName]을(를) 사용하려면 IIS 7.0 CoreWebEngine 및 W3SVC 기능이 설치되어 있어야 합니다. + [ProductName]을(를) 사용하려면 IIS 관리 콘솔이 설치되어 있어야 합니다. + [ProductName]을(를) 설치하기 전에 WAS(Windows Process Activation Service) 및 WMSvc(Web Management Service)를 모두 중지하십시오. [ProductName]을(를) 설치한 후에 해당 서비스를 시작해야 합니다. + [ProductName]을(를) 설치하려면 IIS 메타베이스가 있어야 합니다. + [ProductName] 64비트 버전은 Microsoft Windows 32비트 버전에 설치할 수 없습니다. + [ProductName] 32비트 버전은 Microsoft Windows 64비트 버전에 설치할 수 없습니다. + [ProductName]을(를) 설치하려면 Microsoft .NET Framework 버전 2.0 이상이 설치되어 있어야 합니다. + [ProductName]을(를) 설치하려면 Microsoft .NET Framework 버전 3.5 이상이 필요합니다. 서버 관리자에서 '기능 추가'를 사용하여 Microsoft .Net 버전 3.5를 설치하십시오. + [ProductName]을(를) 설치하려면 Microsoft .NET Framework 버전 4.0 이상이 필요합니다. + [ProductName]을(를) 설치하기 전에 Microsoft .NET Framework 버전 2.0 서비스 팩 1 이상을 설치하십시오. + [ProductName]을(를) 설치하는 데 필요하므로 Windows Update(wuauserv) 서비스를 비활성화할 수 없습니다. + PowerShell 스냅인은 Windows 운영 체제에 포함되어 있습니다. '프로그램 및 기능' 또는 '서버 관리자'를 사용하여 설치하십시오. + [ProductName]을(를) 설치하려면 Microsoft 웹 플랫폼 설치 관리자 버전 3.0 이상이 필요합니다. + + 설치 프로그램이 공유 구성을 검색하지 못했습니다. + IIS에 대해 공유 구성이 활성화되어 있습니다. 공유 구성을 사용하는 경우 [ProductName]을(를) 설치할 수 없습니다. 이 기능을 설치하려면 공유 구성을 비활성화하십시오. + + [ProductName]을(를) 설치하려면 먼저 W3SVC(World Wide Web Publishing Service)를 중지하십시오. 설치 후 해당 서비스를 다시 시작해야 합니다. + IIS PowerShell 관리 콘솔 + IIS PowerShell 스냅인 + IIS PowerShell 스냅인을 사용하려면 PowerShell v1.0 또는 v2.0이 설치되어 있어야 합니다. + IIS PowerShell 스냅인을 사용하려면 WAS 및 구성이 설치되어 있어야 합니다. + 임시 문자열입니다. + + + Microsoft Web Farm Framework 버전 2.2 + Microsoft 웹 팜 에이전트 버전 2.2 + 웹 팜 서비스 + 웹 팜 서비스 + 웹 팜 컨트롤러 서비스 + 웹 팜 컨트롤러 서비스 + 웹 팜 에이전트 서비스 + 웹 팜 에이전트 서비스 + Web Farm Framework를 설치하려면 웹 플랫폼 설치 관리자가 설치되어 있어야 합니다. 웹 플랫폼 설치 관리자는 http://www.microsoft.com/web/downloads/platform.aspx에서 설치하십시오. + Web Farm Framework를 설치하려면 웹 배포 도구가 설치되어 있어야 합니다. 웹 배포 도구는 http://www.iis.net/download/WebDeploy에서 설치하십시오. + + + Microsoft Web Hosting Framework + Web Hosting Framework + 웹 호스팅 역할 및 기능입니다. + Hosting Framework + Hosting Framework는 웹 호스팅을 관리하기 위한 API 및 PowerShell 명령을 제공합니다. + 웹 역할 + 웹 역할은 웹 호스팅용 동적 WAS 서비스 및 URL 재작성 공급자를 설치합니다. + Antares Express + 단일 컴퓨터 설치에 대해 최적화된 제어판 구성을 배포합니다. + 부하 분산 장치 역할 + 부하 분산 장치 역할은 웹 호스팅 규칙을 기반으로 라우팅하기 위한 응용 프로그램 요청 라우터를 구성합니다. + 호스팅 컨트롤러 + 호스팅 컨트롤러는 웹 호스팅과 작동하도록 Web Farm Framework 2.0을 확장합니다. + 게시 역할 + 웹 배포 및 FTP 게시에 대한 지원을 설치합니다. + Microsoft Web Hosting 인프라 관리를 위한 cmdlets가 포함된 PowerShell 스냅인입니다. + 동적 WAS 서비스 + 고밀도 웹 호스팅에 대해 최적화된 Windows Process Activation Service입니다. + 리소스 계량 서비스 + 런타임 및 상태 정보를 둘 다 수집하고 게시하는 리소스 계량 서비스를 설치합니다. + 리소스 계량 + 웹 역할의 런타임 및 상태 정보를 수집하고 게시할 수 있습니다. + 호스팅 할당량 적용 + 웹 사이트 리소스 사용을 모니터링하고 사용 할당량을 초과하면 사용자 지정 작업을 실행합니다. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/PLK/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/PLK/misc/setupstrings.wxl new file mode 100644 index 0000000000..fccd7b5d05 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/PLK/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 1045 + + + + Opcje instalacji w konfiguracji udostępnionej + Wybierz opcję instalacji w konfiguracji udostępnionej usług IIS + Aktualizuj konfigurację udostępnioną podczas instalacji + Ten moduł zostanie zainstalowany na serwerze usług IIS korzystającym z konfiguracji udostępnionej. Jeśli z tej konfiguracji udostępnionej korzysta więcej serwerów usług IIS, należy zainstalować ten moduł na wszystkich tych komputerach. Aby zminimalizować zakłócenia pracy poszczególnych serwerów sieci Web, najlepiej jest zainstalować ten moduł w następujący sposób: Najpierw zainstaluj moduł na wszystkich komputerach z wyjątkiem ostatniego bez aktualizowania konfiguracji udostępnionej. W tym celu nie zaznaczaj poniższego pola wyboru. + Wtedy na wszystkich komputerach zostaną zainstalowane wszystkie pliki binarne i inne wymagane przez moduł, ale nie zostaną wprowadzone żadne zmiany w konfiguracji udostępnionej. Następnie na ostatnim komputerze sprawdź, czy używana tożsamość użytkownika ma dostęp z prawem do zapisu i odczytu do pliku applicationhost.config w udziale UNC. Jeśli ma, zainstaluj moduł i wybierz poniższą opcję aktualizacji konfiguracji udostępnionej. + + + Inicjowanie akcji niestandardowej WebConfig + Aktualizowanie pliku web.config + + + + Zaawansowane rejestrowanie usług IIS + Włącza zaawansowane rejestrowanie danych potoku usług IIS. + Zaawansowane rejestrowanie usług IIS + Umożliwia tworzenie niestandardowych plików dziennika przy użyciu rozszerzalnego wyboru pól. + Aktualizacja zaawansowanego rejestrowania usług IIS + + + + Menedżer transformat usług IIS + Beta + Włącza menedżera transformat usług IIS Media. + Menedżer transformat usług IIS + Włącza tworzenie transformat plików multimedialnych. + Host menedżera transformat usług IIS + Host usługi programu [ProductName]. + Menedżer transformat usług IIS + Konwersja wsadowa plików multimedialnych na żądnie w celu zmiany formatów kontenerów i plików. + Na komputerze zainstalowano pakiet „IIS Transform Manager 1.0 Expression Encoder SP Task”. Należy go odinstalować przed zainstalowaniem produktu [ProductName]. + + Do zainstalowania produktu [ProductName] jest wymagany program Microsoft .NET Framework w wersji 3.5. Aby zainstalować funkcje programu .NET Framework 3.5.1, należy użyć Kreatora dodawania funkcji w Menedżerze serwerów. Aby włączyć program Microsoft .NET Framework 3.5, należy użyć apletu Włącz lub wyłącz funkcje systemu Windows. + + + + Zarządzanie prawami cyfrowymi w usługach IIS + Beta + Włącza zarządzanie prawami cyfrowymi prezentacji w formacie Smooth Streaming. + + + Niezainstalowany program ASP.NET + + + + + + + + + Na tym komputerze wykryto funkcję Płynne przesyłanie strumieniowe w wersji beta. Nie można kontynuować instalacji produktu [ProductName]. Aby zainstalować ten produkt, usuń funkcję Płynne przesyłanie strumieniowe w wersji beta, używając apletu Dodaj/Usuń programy w Panelu sterowania. + Na tym komputerze znajduje się niezgodna wersja usług IIS Media Services. Nie można kontynuować instalacji produktu [ProductName]. Aby zainstalować ten produkt, usuń usługi IIS Media Services, używając apletu Dodaj/Usuń programy w Panelu sterowania. + Nowsza wersja tego produktu jest już zainstalowana lub dostępna do zainstalowania na tym komputerze. Nie można kontynuować instalacji produktu [ProductName]. Aby zainstalować nowszą wersję tego produktu, używaj apletu Dodaj/Usuń programy w Panelu sterowania w celu zaktualizowania usług IIS Media Services. + Wymagana konwersja pliku listy odtwarzania + + + + + Odnaleziono starsze pliki usług IIS Media Services + + + + + Odnaleziono pliki usług IIS Media Services w wersji beta + + + + + + IIS Media Pack 1.0 + Aktualizacja pakietu IIS Media Pack 1.0 + IIS Media Services 2.0 + Aktualizacja usług IIS Media Services 2.0 + IIS Media Services 3.0 + IIS Media Services 3.0 TAP 2 + Aktualizacja usług IIS Media Services 3.0 + Funkcje i narzędzia usług IIS Media Services. + Funkcje i narzędzia usług IIS Media Services 5 Premium. + Usługi IIS Media 4.0 w wersji beta 1 + IIS Media Services 4.0 + IIS Media Services 4.5 w wersji beta 1 + IIS Media Services 5 Premium + + Listy odtwarzania w sieci Web + Steruje odtwarzaniem przez klienta zasobów multimedialnych wymienionych na listach odtwarzania. + Pomocnik sesji + Umożliwia utrwalanie stanu sesji programu ASP.NET. (Wymaga usługi roli programu ASP.NET dla serwera sieci Web [IIS]). + Interfejs użytkownika + Konfiguruje funkcję Listy odtwarzania w sieci Web w Menedżerze usług IIS. + + Ograniczanie szybkości transmisji bitów + Oszczędza przepustowość, ograniczając dostarczanie plików pobieranych przez klientów. + Interfejs użytkownika + Konfiguruje funkcję Ograniczanie szybkości transmisji bitów w Menedżerze usług IIS. + + Zasoby + Włącza adaptacyjne przesyłanie strumieniowe zasobów na żądanie przez protokół HTTP do klientów. + Interfejs użytkownika + Konfiguruje funkcję Płynne przesyłanie strumieniowe w Menedżerze usług IIS. + + Kanały + Włącza adaptacyjne przesyłanie strumieniowe emisji kanałów przez protokół HTTP do klientów. + Interfejs użytkownika + Konfiguruje funkcję Płynne przesyłanie strumieniowe na żywo w Menedżerze usług IIS. + + Zarządzanie prawami cyfrowymi + Realizuje szyfrowanie i licencjonowanie plików multimedialnych w formacie Smooth Streaming. + Interfejs użytkownika + Konfiguruje funkcję zarządzania prawami cyfrowymi w module Menedżer usług IIS. + + Produkt [ProductName] wymaga systemu Microsoft Windows Vista z dodatkiem Service Pack 1 lub nowszym. + Produktu [ProductName] nie można zainstalować w systemie Vista Home Basic. + Produkt [ProductName] wymaga systemu Microsoft Windows 7 z dodatkiem Service Pack 1 lub nowszym. + + + Menedżer baz danych usług IIS + Menedżer baz danych usług IIS + + + Usługa zarządzania siecią Web firmy Microsoft 2 + Usługa zarządzania siecią Web firmy Microsoft + Instaluje podstawowe funkcje produktu [ProductName]. + Usługa zarządzania siecią Web firmy Microsoft 2 + Usługa zarządzania siecią Web zawiera mechanizmy zarządzania zdalnego i delegowanego, dzięki którym administratorzy mogą skutecznie zarządzać serwerem sieci Web, witrynami i aplikacjami obecnymi na komputerze. + + + Moduł ponownego zapisywania adresów URL firmy Microsoft w wersji 1.1 dla usług IIS 7 + Aktualizacja Modułu ponownego zapisywania adresów URL firmy Microsoft w wersji 1.1 dla usług IIS 7 + Ponowne zapisywanie adresów URL + Włącza funkcje ponownego zapisywania adresów URL i zawartości w usługach IIS 7. + Interfejs użytkownika + Konfiguruje funkcję Moduł ponownego zapisywania adresów URL w Menedżerze usług IIS. + + + Moduł ponownego zapisywania adresów URL usług IIS w wersji 2 + Aktualizacja modułu ponownego zapisywania adresów URL usług IIS w wersji 2 + Ponowne zapisywanie adresów URL + Włącza funkcje ponownego zapisywania adresów URL i zawartości w usługach IIS 7. + Interfejs użytkownika + Konfiguruje funkcję Moduł ponownego zapisywania adresów URL w Menedżerze usług IIS. + + + Pakiet administracyjny dla usług IIS 7.0 + Instaluje podstawowe funkcje produktu [ProductName]. + 1252 + Pakiet administracyjny dla usług IIS 7.0 + Microsoft Corporation + Ta wersja systemu operacyjnego jest nieobsługiwana. Produkt [ProductName] można zainstalować tylko w systemie Windows Server 2008 lub Windows Vista z dodatkiem Service Pack 1 lub nowszym. + Funkcje programu ASP.NET + Program ASP.NET zawiera funkcje Autoryzacja i Strony błędów, które umożliwiają zarządzanie ustawieniami autoryzacji i błędów niestandardowych. + Uwierzytelnianie + Opis funkcji Uwierzytelnianie programu ASP.NET. + Autoryzacja + Funkcja Autoryzacja programu ASP.NET umożliwia konfigurowanie reguł dotyczących autoryzacji użytkowników uzyskujących dostęp do witryn i aplikacji sieci Web. + Strony błędów + Funkcja Strony błędów programu ASP.NET umożliwia konfigurowanie odpowiedzi na błędy protokołu HTTP, które będą zwracane w przypadku wystąpienia błędów. + Moduły + Opis funkcji Moduły programu ASP.NET. + Obsługa + Opis funkcji Obsługa programu ASP.NET. + Edytor konfiguracji + Edytor konfiguracji służy do zarządzania plikami konfiguracji w Menedżerze usług IIS, umożliwiając edytowanie sekcji, atrybutów, elementów i kolekcji w plikach konfiguracji. + Filtrowanie żądań + Filtrowanie żądań umożliwia konfigurowania reguł filtrowania dla witryny sieci Web oraz ograniczanie zachowania protokołu i zawartości. + FastCGI + Funkcja FastCGI umożliwia konfigurowanie ustawień puli procesów dla aplikacji FastCGI na serwerze sieci Web. + + + Dynamiczne ograniczenia adresów IP dla Instalatora usług IIS 7 + + + + + + + + + + + + + Dynamiczne ograniczenia adresów IP dla usług IIS 7 — wersja Beta + Dynamiczne ograniczenia adresów IP dla usług IIS 7 — wersja Beta 2 + Dynamiczne ograniczenia adresów IP dla usług IIS 7 — wersja Beta 3 + + Dynamiczne ograniczenia adresów IP dla usług IIS 7 — wersja Release Candidate + Dynamiczne ograniczenia adresów IP dla usług IIS 7 — wersja Release Candidate 2 + Dynamiczne ograniczenia adresów IP dla usług IIS 7 — wersja Release Candidate 3 + + Dynamiczne ograniczenia adresów IP dla usług IIS 7 — wersja RTW + + Dynamiczne ograniczenia adresów IP dla usług IIS 7 + Interfejs użytkownika funkcji Dynamiczne ograniczenia adresów IP dla usług IIS 7 + + Dynamiczne ograniczenia adresu IP w usługach IIS 7 — na komputerze znaleziono wersję beta. Odinstaluj ją i spróbuj ponownie + + + WebDAV 7.5 dla usług IIS 7.0 + Aby można było używać tego produktu, muszą być zainstalowane funkcje CoreWebEngine i W3SVC usług IIS 7.0. + Moduł serwera WebDAV + Interfejs użytkownika administracji funkcją WebDAV + + + Zestaw narzędzi do optymalizacji aparatu wyszukiwania usług IIS w wersji 1.0 + Zestaw narzędzi do optymalizacji aparatu wyszukiwania usług IIS w wersji 1.0 + Zestaw narzędzi do optymalizacji aparatu wyszukiwania (SEO) w wersji 1.0 + Ta baza danych instalatora zawiera logikę i dane wymagane do zainstalowania narzędzia do optymalizacji aparatu wyszukiwania usług IIS w wersji 1.0. + + + Edytor usług IIS + + + Raporty usług IIS + Analizator dzienników nie jest zainstalowany na tym komputerze; zainstaluj funkcję Analizator dzienników w wersji 2.2 spod adresu http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07, a następnie kontynuuj instalowanie funkcji Raporty usług IIS. + + + Nie można odnaleźć wstępnie wymaganych pakietów. Uruchom plik setup.exe, aby rozpoznać zależności i zainstalować ten program. + Program Microsoft SQL Server 2008 Management Objects jest wstępnie wymaganym składnikiem instalacji Menedżera baz danych usług IIS. Program Microsoft SQL Server 2008 Management Objects można zainstalować spod adresu http://go.microsoft.com/fwlink/?LinkID=150946. + Program Microsoft SQL Server System CLR Types jest wstępnie wymaganym składnikiem instalacji Menedżera baz danych usług IIS. Program Microsoft SQL Server System CLR Types można zainstalować spod adresu http://go.microsoft.com/fwlink/?LinkID=150946. + + + Microsoft Web Farm Framework + Zewnętrzna pamięć podręczna firmy Microsoft + Struktura farmy sieci Web jest wymaganym składnikiem instalacji funkcji Routing żądań aplikacji. Zainstaluj strukturę farmy sieci Web. + Routing żądań aplikacji firmy Microsoft 2.5 + Wersja wykonawcza + Dodaje funkcje routingu żądań aplikacji do usług IIS. + Interfejs użytkownika + Konfiguruje funkcję routingu żądań aplikacji w module Menedżer usług IIS. + + + Przystawka środowiska Microsoft Windows PowerShell dla usług IIS 7.0 + + + Instalator platformy Microsoft Web 4.0 + Instalator platformy sieci Web firmy Microsoft + Produkt [ProductName] wymaga systemu Windows XP z dodatkiem SP2, Windows 2003 z dodatkiem SP1, Windows Vista lub nowszego. + Program [ProductName] wymaga systemu Windows XP z dodatkiem Service Pack 3, Windows Server 2003 z dodatkiem Service Pack 2 lub nowszego. + + + Instalator usług Microsoft Windows Azure + Instalator usług Microsoft Windows Azure + + + Menedżer internetowych usług informacyjnych (IIS) 7+ + Klient Menedżera usług IIS + Obsługa operacji zdalnych + Ten produkt wymaga systemu Windows XP z dodatkiem SP2, Windows 2003 z dodatkiem SP1, Windows Vista z dodatkiem SP1, Windows 7 lub nowszego + Konsola zarządzania usługami IIS nie jest zainstalowana, ale jest wymagana do zarządzania zdalnymi serwerami usług IIS. Zainstaluj Konsolę zarządzania usługami IIS przed zainstalowaniem obsługi operacji zdalnych, klikając polecenia Panel sterowania -> Programy -> Włącz lub wyłącz funkcje systemu Windows i wybierając opcję Konsola zarządzania usługami IIS w funkcji Internetowe usługi informacyjne. + Ten produkt nie jest wymagany w systemach Windows Server 2008 i Windows Server 2008 R2 ani w nowszych. Zainstaluj Konsolę zarządzania usługami IIS, otwierając Menedżera serwera i wybierając pozycję Konsola zarządzania usługami IIS z usług roli dla roli Serwer sieci Web. + + + Publikowanie Menedżera usług IIS dla usług IIS 7.0 + Interfejs użytkownika funkcji Publikowanie + + + Zwiększanie gotowości aplikacji w wersji 1.0 dla usług IIS 7.5 + + + + Na tym komputerze znajduje się niezgodny produkt: [CONFLICTING_PRODUCT_NAME]. Nie można kontynuować instalowania produktu [ProductName]. Aby zainstalować ten produkt, usuń produkt [CONFLICTING_PRODUCT_NAME] za pomocą apletu Dodaj/Usuń programy w Panelu sterowania. + Do zainstalowania produktu [ProductName] jest wymagane uprawnienie administratora. + Do używania produktu [ProductName] są wymagane usługi IIS w wersji 7.0. + Do używania produktu [ProductName] są wymagane usługi IIS w wersji 7.0 lub nowsze. + Do używania produktu [ProductName] są wymagane usługi IIS w wersji 7.5 lub nowsze. + Do zainstalowania produktu [ProductName] wymagany jest program IIS 7 lub 7.5. + Odnaleziono wersję beta produktu [ProductName] na tym komputerze. + Odnaleziono nowszą wersję produktu [ProductName] na tym komputerze. + Instalator nie może kontynuować, ponieważ na tym komputerze jest już zainstalowane inne wystąpienie produktu [ProductName]. Odinstaluj je, a następnie ponownie rozpocznij tę instalację. + Aby można było używać produktu [ProductName], muszą być zainstalowane funkcje CoreWebEngine i W3SVC usług IIS 7.0. + Aby można było używać produktu [ProductName], musi być zainstalowana Konsola zarządzania usługami IIS. + Przed zainstalowaniem produktu [ProductName] zatrzymaj usługę aktywacji procesów systemu Windows (WAS) i usługę zarządzania siecią Web (WMSvc). Te usługi trzeba będzie uruchomić po zainstalowaniu produktu [ProductName]. + Do zainstalowania produktu [ProductName] jest wymagana metabaza usług IIS. + Nie można zainstalować 64-bitowej wersji produktu [ProductName] w 32-bitowej wersji systemu Microsoft Windows. + Nie można zainstalować 32-bitowej wersji produktu [ProductName] w 64-bitowej wersji systemu Microsoft Windows. + Do zainstalowania produktu [ProductName] jest wymagany program .NET Framework w wersji 2.0 lub nowszy. + Do zainstalowania programu [ProductName] jest potrzebny program Microsoft .NET Framework w wersji 3.5 lub nowszej. Naciśnij przycisk „Dodaj funkcje” w sekcji Menedżer serwera, aby zainstalować program Microsoft .Net w wersji 3.5. + Do zainstalowania programu [ProductName] jest wymagany program Microsoft .NET Framework w wersji 4.0 lub nowszej. + Przed zainstalowaniem produktu [ProductName] zainstaluj dodatek Service Pack 1 (lub nowszy) dla programu Microsoft .NET Framework w wersji 2.0. + Nie można wyłączyć usługi Windows Update (wuauserv), ponieważ jest ona wymagana do zainstalowania produktu [ProductName]. + Przystawka PowerShell stanowi część systemu operacyjnego Windows. Zainstaluj ją za pomocą menu Programy i funkcje lub narzędzia Menedżer serwera. + Do zainstalowania programu [ProductName] jest wymagany instalator platformy sieci Web firmy Microsoft w wersji 3.0 lub nowszej. + + Instalator nie może wykryć konfiguracji udostępnionej. + Konfiguracja udostępniona jest włączona dla usług IIS. Instalowanie produktu [ProductName] jest nieobsługiwane, gdy jest używana konfiguracja udostępniona. Wyłącz konfigurację udostępnioną przed zainstalowaniem tej funkcji. + + Zatrzymaj usługę publikowania w sieci World Wide Web (W3SVC) przed zainstalowaniem produktu [ProductName]. Tę usługę trzeba będzie uruchomić po instalacji. + Konsola zarządzania środowiskiem IIS PowerShell + Przystawka IIS PowerShell + Przystawka IIS PowerShell wymaga zainstalowanego środowiska PowerShell w wersji 1.0 lub 2.0. + Przystawka IIS PowerShell wymaga zainstalowanej usługi WAS oraz konfiguracji. + To jest nieprawdziwy ciąg. + + + Microsoft Web Farm Framework 2.2 + Microsoft Web Farm Agent 2.2 + Usługa kolektywu serwerów sieci Web + Usługa kolektywu serwerów sieci Web + Usługa kontrolera kolektywu serwerów sieci Web + Usługa kontrolera kolektywu serwerów sieci Web + Usługa agenta kolektywu serwerów sieci Web + Usługa agenta kolektywu serwerów sieci Web + Do zainstalowania składnika Web Farm Framework jest wymagany instalator platformy sieci Web. Zainstaluj instalatora platformy sieci Web ze strony http://www.microsoft.com/web/downloads/platform.aspx. + Do zainstalowania składnika Web Farm Framework jest wymagane narzędzie Web Deployment. Zainstaluj narzędzie Web Deployment ze strony http://www.iis.net/download/WebDeploy. + + + Microsoft Web Hosting Framework + Web Hosting Framework + Role i funkcje obsługi hostingu sieci Web. + Hosting Framework + Składnik Hosting Framework udostępnia interfejsy API i polecenia programu PowerShell do zarządzania hostingiem sieci Web. + Rola sieci Web + Rola sieci Web instaluje usługę Dynamiczna usługa WAS i dostawcę Moduł ponownego zapisywania adresów URL na potrzeby hostingu sieci Web. + Antares Express + Wdraża konfigurację Panelu sterowania zoptymalizowaną pod kątem konfiguracji jednego komputera. + Rola Usługa równoważenia obciążenia + Rola Usługa równoważenia obciążenia konfiguruje router żądań aplikacji do routingu na podstawie reguł hostingu sieci Web. + Kontroler hostingu + Kontroler hostingu rozszerza funkcje składnika Web Farm Framework 2.0 o współdziałanie z hostingiem sieci Web. + Rola publikowania + Instaluje obsługę narzędzia Web Deploy i publikowana FTP. + To jest przystawka PowerShell zawierająca aplety poleceń służące do zarządzania infrastrukturą Microsoft Web Hosting. + Dynamiczna usługa WAS + Usługa aktywacji procesów systemu Windows zoptymalizowana pod kątem hostingu sieci Web o dużej gęstości. + Usługa pomiaru użycia zasobów + Instaluje usługę pomiaru użycia zasobów, która umożliwia gromadzenie i publikowanie informacji na temat środowiska wykonawczego i kondycji. + Miernik zasobów + Umożliwia gromadzenie i publikowanie informacji na temat środowiska wykonawczego i kondycji pochodzących z roli sieci Web. + Wymuszanie przydziału hostingu + Monitoruje użycie zasobów witryn sieci Web i w razie przekroczenia przydziału użycia wykonuje akcje niestandardowe. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/PTB/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/PTB/misc/setupstrings.wxl new file mode 100644 index 0000000000..4fdfeffca5 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/PTB/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 1046 + + + + Opções de Instalação da Configuração Compartilhada + Selecionar a opção de instalação na configuração compartilhada do IIS + Atualizar configuração compartilhada na instalação + Você está instalando este módulo em um servidor do IIS que usa a configuração compartilhada. Se outros servidores do IIS estiverem usando essa configuração compartilhada, você precisará instalar este módulo em todos os computadores. Para minimizar interrupções de servidores Web individuais, será preciso instalar este módulo de acordo com as seguintes etapas: primeiro, em todos os computadores, com exceção do último, você deverá instalar o módulo sem atualizar a configuração compartilhada. Para isso, não marque a caixa de seleção + a seguir. Isso instalará todos os binários e arquivos necessários para o módulo em cada computador sem fazer alterações na configuração compartilhada. Em segundo lugar, no último computador, será preciso verificar se a identidade do usuário usada por você na execução tem acesso de leitura e gravação ao arquivo applicationhost.config no compartilhamento UNC. Em seguida, instale o módulo e selecione a opção abaixo de atualização da configuração compartilhada. + + + Inicializando a ação personalizada do WebConfig + Atualizando o web.config + + + + Registro em Log Avançado do IIS + Habilita o registro em log avançado dos dados de pipeline do IIS. + Registro em Log Avançado do IIS + Habilita a criação de arquivos de log personalizados com seleção de campo extensível. + Atualização para o Registro em Log Avançado do IIS + + + + IIS Transform Manager + Beta + Habilita o IIS Media Services do Transform Manager. + IIS Transform Manager + Habilita a criação de transformações de mídia. + Host do IIS Transform Manager + Host de serviço de [ProductName]. + IIS Transform Manager + Conversão em lote de arquivos de mídia por demanda para formatos de arquivo e de contêiner alternativos. + Um pacote de Tarefa do Expression Encoder SP do IIS Transform Manager 1.0 está instalado no computador. Desinstale-o para que possa instalar o [ProductName]. + + O Microsoft .NET Framework 3.5 é exigido para instalar o produto [ProductName]. Use o "Assistente Adicionar Recursos" no Gerenciador do Servidor para instalar os Recursos do .NET Framework 3.5.1 ou use a opção "Ativar ou desativar os recursos do Windows" para ativar o Microsoft .NET Framework 3.5. + + + + Gerenciamento de Direitos Digitais do IIS + Beta + Habilita o Gerenciamento de Direitos Digitais de apresentações de Smooth Streaming. + + + O ASP.NET Não Está Instalado + + + + + + + + + O IIS Smooth Streaming - Beta foi encontrado no computador. Não é possível continuar a instalação do [ProductName]. Para instalar o produto, use Adicionar/Remover Programas no Painel de Controle para remover o IIS Smooth Streaming - Beta. + Uma versão incompatível do IIS Media Services está no computador. Não é possível continuar a instalação do [ProductName]. Para instalar o produto, use Adicionar/Remover Programas no Painel de Controle para remover o IIS Media Services. + Uma versão mais recente do produto já está instalada ou disponível para instalação neste computador. Não é possível continuar a instalação do [ProductName]. Para instalar a versão mais recente do produto, use Adicionar/Remover Programas no Painel de Controle para atualizar o IIS Media Services. + Conversão do Arquivo da Lista de Reprodução Necessária + + + + + Arquivos Antigos do IIS Media Services Encontrados + + + + + Arquivos do IIS Media Services Beta Encontrados + + + + + + IIS Media Pack 1.0 + Atualização para o IIS Media Pack 1.0 + IIS Media Services 2.0 + Atualização para o IIS Media Services 2.0 + IIS Media Services 3.0 + IIS Media Services 3.0 TAP 2 + Atualização para o IIS Media Services 3.0 + Recursos e ferramentas do IIS Media Services. + Recursos e ferramentas do IIS Media Services 5 Premium. + IIS Media Services 4.0 Beta 1 + IIS Media Services 4.0 + IIS Media Services 4.5 Beta 1 + IIS Media Services 5 Premium + + Web Playlists + Controla a reprodução no cliente de ativos de mídia referenciados em listas de reprodução. + Auxiliar de Sessão + Habilita a persistência do estado de sessão do ASP.NET. (Requer o serviço de função do ASP.NET para o Servidor Web (IIS)). + Interface do Usuário + Configura o recurso Web Playlists no Gerenciador do IIS. + + Limitação da Taxa de Bits + Economiza largura de banda limitando a entrega de arquivos baixados por clientes. + Interface do Usuário + Configura o recurso Limitação da Taxa de Bits no Gerenciador do IIS. + + Ativos + Habilita o streaming HTTP adaptável de ativos por demanda para clientes. + Interface do Usuário + Configura o recurso Smooth Streaming no Gerenciador do IIS. + + Canais + Habilita o streaming HTTP adaptável de difusões de canais para clientes. + Interface do Usuário + Configura o recurso Live Smooth Streaming no Gerenciador do IIS. + + Gerenciamento de Direitos Digitais + Fornece criptografia e licenciamento de mídia Smooth Streaming. + Interface do Usuário + Configura o recurso de Gerenciamento de Direitos Digitais no Gerenciador do IIS. + + O [ProductName] requer o Microsoft Windows Vista Service Pack 1 ou posterior. + Não é possível instalar o [ProductName] no Vista Home Basic. + O [ProductName] requer o Microsoft Windows 7 Service Pack 1 ou posterior. + + + Gerenciador de Banco de Dados do IIS + Gerenciador de Banco de Dados do IIS + + + Serviço de Gerenciamento da Web 2 da Microsoft + Serviço de Gerenciamento da Web da Microsoft + Instala os recursos básicos do [ProductName]. + Serviço de Gerenciamento da Web 2 da Microsoft + O Serviço de Gerenciamento da Web habilita recursos de gerenciamento remotos e delegados para que os administradores gerenciem o servidor Web, os sites e os aplicativos presentes neste computador. + + + Módulo 1.1 de Reescrita de URL da Microsoft para IIS 7 + Atualização do Módulo 1.1 de Reescrita de URL para IIS 7 + Reescrita de URL + Habilita os recursos de reescrita de conteúdo e URL do IIS 7. + Interface do Usuário + Configura o recurso do Módulo de Reescrita de URL no Gerenciador do IIS. + + + Módulo 2 de Reescrita de URL do IIS + Atualização do Módulo 2 de Reescrita de URL do IIS + Reescrita de URL + Habilita os recursos de reescrita de conteúdo e URL do IIS 7. + Interface do Usuário + Configura o recurso do Módulo de Reescrita de URL no Gerenciador do IIS. + + + Administration Pack para IIS 7.0 + Instala os recursos básicos do [ProductName]. + 1252 + Administration Pack para IIS 7.0 + Microsoft Corporation + Não há suporte a esta versão do sistema operacional. Só é possível instalar o [ProductName] no Windows Server 2008 ou no Windows Vista Service Pack 1 ou posterior. + Recursos do ASP.Net + O ASP.NET inclui os recursos Páginas de Erro e Autorização, que permitem o gerenciamento das configurações de erro personalizadas e de autorizações. + Autenticação + Descrição da Autenticação do ASP.Net. + Autorização + A Autorização do ASP.NET permite a configuração de regras para autorizar usuários a acessar seus sites e aplicativos. + Páginas de Erro + As Páginas de Erro do ASP.NET permitem a configuração de respostas de erro de HTTP retornadas quando um erro ocorre. + Módulos + Descrição dos Módulos do ASP.Net. + Manipuladores + Descrição dos Manipuladores do ASP.Net. + Editor de Configurações + O Editor de Configurações permite o gerenciamento de arquivos de configuração no Gerenciador do IIS por meio da edição de seções, atributos, elementos e coleções nos arquivos de configuração. + Filtragem de Solicitações + A Filtragem de Solicitações permite a configuração de regras de filtragem para o seu site, protocolo restrito e comportamento de conteúdo. + FastCGI + O FastCGI permite a definição de configurações do pool de processos para os aplicativos FastCGI no servidor Web. + + + Instalação de Restrições de IP Dinâmico para IIS 7 + + + + + + + + + + + + + Restrições de IP Dinâmico para IIS 7 - Beta + Restrições de IP Dinâmico para IIS 7 - Beta 2 + Restrições de IP Dinâmico para IIS 7 - Beta 3 + + Restrições de IP Dinâmico para IIS 7 - Versão Release Candidate + Restrições de IP Dinâmico para IIS 7 - Versão Release Candidate 2 + Restrições de IP Dinâmico para IIS 7 - Versão Release Candidate 3 + + Restrições de IP Dinâmico para IIS 7 - RTW + + Restrições de IP Dinâmico para IIS 7 + Interface do Usuário de Restrições de IP Dinâmico para IIS 7 + + Restrições de IP Dinâmico para IIS 7 - Beta encontradas neste computador. Desinstale-as e tente novamente + + + WebDAV 7.5 para IIS 7.0 + Os recursos CoreWebEngine e W3SVC do IIS 7.0 devem ser instalados para usar este produto. + Módulo do Servidor WebDAV + Interface do Usuário de Administração do WebDAV + + + Toolkit de Otimização do Mecanismo de Pesquisa do IIS 1.0 + Toolkit de Otimização do Mecanismo de Pesquisa do IIS 1.0 + Toolkit de SEO (Otimização do Mecanismo de Pesquisa) 1.0 + Este banco de dados de instalador contém a lógica e os dados necessários para instalar o Kit de Ferramentas de Otimização do Mecanismo de Pesquisa do IIS 1.0. + + + Editor do IIS + + + Relatórios do IIS + O Analisador de Log não foi instalado neste computador. Instale o Analisador de Log 2.2 de http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07 e continue a instalação dos Relatórios do IIS + + + Os pacotes de pré-requisito não foram encontrados. Execute setup.exe para resolver as dependências e instalar o programa. + O Microsoft SQL Server 2008 Management Objects é um pré-requisito para a instalação do Gerenciador de Banco de Dados do IIS. É possível instalar o Microsoft SQL Server 2008 Management Objects de http://go.microsoft.com/fwlink/?LinkID=150946. + Os Microsoft SQL Server System CLR Types são um pré-requisito para a instalação do Gerenciador de Banco de Dados do IIS. É possível instalar os Microsoft SQL Server System CLR Types de http://go.microsoft.com/fwlink/?LinkID=150949. + + + Microsoft Web Farm Framework + Microsoft External Cache + O Web Farm Framework é um requisito para a instalação do Application Request Routing. Instale o Web Farm Framework. + Microsoft Application Request Routing 2.5 + Tempo de Execução + Adiciona os recursos de Roteamento de Solicitações de Aplicativo no IIS. + Interface do Usuário + Configura o recurso de Roteamento de Solicitações de Aplicativo no Gerenciador do IIS. + + + Snap-in do Microsoft Windows PowerShell para o IIS 7.0 + + + Microsoft Web Platform Installer 4.0 + Microsoft Web Platform Installer + O [ProductName] requer o Windows XP SP2, o Windows 2003 SP1, o Windows Vista ou posterior. + O [ProductName] exige o Windows XP Service Pack 3, o Windows Server 2003 Service Pack 2 ou versão posterior. + + + Instalador de Serviços do Microsoft Windows Azure + Instalador de Serviços do Microsoft Windows Azure + + + Gerenciador do IIS (Serviços de Informações da Internet) 7+ + Cliente do Gerenciador do IIS + Suporte Remoto + Este produto requer o Windows XP SP2, o Windows 2003 SP1, o Windows Vista SP1, o Windows 7 ou mais recente + O Console de Gerenciamento do IIS não foi instalado, mas é necessário para o gerenciamento de servidores remotos do IIS. Para instalar o Console de Gerenciamento do IIS antes de instalar o suporte de gerenciamento remoto, abra o 'Painel de Controle->Programas->Ativar ou Desativar Recursos do Windows' e selecione o Console de Gerenciamento do IIS no recurso Serviços de Informações da Internet. + Este produto não é necessário no Windows Server 2008 ou no Windows Server 2008 R2 ou mais recente. Para instalar o Console de Gerenciamento do IIS, abra o Gerenciador do Servidor e selecione o Console de Gerenciamento do IIS em Serviços de Função para a Função de Servidor Web. + + + IIS Manager Publishing para IIS 7.0 + Interface do Usuário de Publicação + + + Application Warm-Up 1.0 para IIS 7.5 + + + + Este computador contém um produto incompatível, [CONFLICTING_PRODUCT_NAME]. A instalação do [ProductName] não pode continuar. Para instalar esse produto, use Adicionar/Remover Programas no Painel de Controle para remover o [CONFLICTING_PRODUCT_NAME]. + São necessários privilégios de Administrador para instalar o [ProductName]. + É necessário o IIS Versão 7.0 para usar o [ProductName]. + É necessário o IIS Versão 7.0 ou posterior para instalar o [ProductName]. + É necessário o IIS Versão 7.5 ou posterior para instalar o [ProductName]. + É necessário o IIS versão 7 ou 7.5 para instalar o [ProductName]. + A versão beta do [ProductName] foi encontrada no computador. + Uma versão mais recente do [ProductName] foi encontrada no computador. + Não é possível continuar a instalação, pois outra instância do [ProductName] já está instalada no computador. Desinstale a versão antiga e reinicie a instalação. + Os recursos CoreWebEngine e W3SVC do IIS 7.0 devem estar instalados para usar o [ProductName]. + O Console de Gerenciamento do IIS deve estar instalado para usar o [ProductName]. + Interrompa o WAS (Serviço de Ativação de Processos do Windows) e o WMSvc (Serviço de Gerenciamento da Web) antes de instalar o [ProductName]. Será necessário instalar os serviços após a instalação do [ProductName]. + É necessária a Metabase do IIS para instalar o [ProductName]. + Não é possível instalar a versão de 64 bits do [ProductName] em uma edição de 32 bits do Microsoft Windows. + Não é possível instalar a versão de 32 bits do [ProductName] em uma edição de 64 bits do Microsoft Windows. + É necessário o Microsoft .NET Framework Versão 2.0 ou posterior para instalar o [ProductName]. + O Microsoft .NET Framework Versão 3.5 ou posterior é necessário para instalar o [ProductName]. Use 'Adicionar Recursos' no Gerenciador do Servidor para instalar o Microsoft .Net Versão 3.5. + O Microsoft .NET Framework Versão 4.0 ou posterior é necessário para instalar o [ProductName]. + Instale o Microsoft .NET Framework Service Pack 1 Versão 2.0, ou um service pack posterior, antes de instalar o [ProductName]. + Não é possível desabilitar o serviço Windows Update (wuauserv), pois ele é necessário para instalar o [ProductName]. + O snap-in do PowerShell é parte o Sistema Operacional Windows. Instale o snap-in por meio dos 'Programas e Recursos' ou 'Gerenciador do Servidor'. + O Microsoft Web Platform Installer Versão 3.0 ou posterior é necessário para instalar o [ProductName]. + + A instalação não detectou configurações compartilhadas. + A configuração compartilhada está habilitada para o IIS. Não há suporte à instalação do [ProductName] quando é usada uma configuração compartilhada. Desabilite a configuração compartilhada antes de instalar este recurso. + + Interrompa o Serviço de Publicação na World Wide Web (W3SVC) antes de instalar o [ProductName]. Será necessário iniciar o serviço após a instalação. + Console de Gerenciamento do PowerShell do IIS + Snap-in do PowerShell do IIS + O snap-in do PowerShell do IIS requer o PowerShell versão 1.0 ou 2.0 instalado + O snap-in do PowerShell do IIS requer WAS e configuração instalados + Cadeia de caracteres inválida. + + + Estrutura do Microsoft Web Farm Versão 2.2 + Agente do Microsoft Web Farm Versão 2.2 + Serviço de Web Farm + Serviço de Web Farm + Serviço Controlador de Web Farm + Serviço Controlador de Web Farm + Serviço de Agente de Web Farm + Serviço de Agente de Web Farm + O Web Plaform Installer é um pré-requisito para instalar a Estrutura do Web Farm. Instale o Web Plaform Installer a partir de http://www.microsoft.com/web/downloads/platform.aspx. + A Ferramenta de Implantação da Web é um pré-requisito para instalar a Estrutura do Web Farm. Instale a Ferramenta de Implantação da Web a partir de http://www.iis.net/download/WebDeploy. + + + Estrutura de Hospedagem na Web da Microsoft + Estrutura de Hospedagem na Web + Funções e recursos de Hospedagem na Web. + Estrutura de Hospedagem + A Estrutura de Hospedagem oferece comandos de API e PowerShell para gerenciamento de Hospedagem na Web. + Função da Web + A Função Web instala o serviço WAS Dinâmico e o provedor de Reescrita de URL de Hospedagem na Web. + Antares Express + Implanta uma configuração do Painel de Controle otimizada para configuração de máquina única. + Função do Balanceador de Carga + A Função do Balanceador de Carga configura o Roteador de Solicitação de Aplicativo para rotear com base nas regras de Hospedagem na Web. + Controlador de Hospedagem + O Controlador de Hospedagem estende a Estrutura do Web Farm 2.0 para trabalhar com Hospedagem na Web. + Função de Publicação + Instala suporte para Implantação da Web e publicação em FTP. + Este é um snap-in do PowerShellque contém cmdlets para gerenciar a infraestrutura de Hospedagem na Web da Microsoft. + Serviço WAS Dinâmico + Serviço de Ativação de Processos do Windows otimizado para Hospedagem na Web de alta densidade. + Serviço de Medição de Recursos + Instala o serviço de Medição de Recursos que habilita a coleta e a publicação de informações de integridade e tempo de execução. + Medição de Recursos + Habilita a coleta e a publicação de informações de tempo de execução e integridade a partir da Função Web. + Imposição de Cota de Hospedagem + Monitora o uso de recursos de sites e executa ações personalizadas quando a cota de uso é excedida. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/RUS/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/RUS/misc/setupstrings.wxl new file mode 100644 index 0000000000..e9613c04ec --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/RUS/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 1049 + + + + Параметры установки общей конфигурации + Выбор параметров установки общей конфигурации IIS + Обновить общую конфигурацию при установке + Вы устанавливаете этот модуль на сервер IIS, использующий общую конфигурацию. Если дополнительные серверы IIS используют эту общую конфигурацию, вам необходимо установить этот модуль на все эти компьютеры. Чтобы минимизировать нарушение работы отдельных веб-серверов, вам потребуется устанавливать этот модуль в соответствии с шагами, описанными ниже. Сначала следует установить модуль на все компьютеры, кроме последнего, не обновляя при этом общую конфигурацию. Для этого не устанавливайте флажок ниже. +При этом на каждый компьютер будут установлены все файлы, необходимые для модуля, но не будет изменена общая конфигурация. Затем на последнем компьютере следует убедиться в том, что у используемой для работы учетной записи есть права чтения и записи файла applicationhost.config, расположенного на общем ресурсе UNC. Затем следует установить модуль и установить флажок "Обновить общую конфигурацию" ниже. + + + Инициализируется настраиваемое действие WebConfig + Обновляется файл web.config + + + + Расширенное ведение журнала IIS + Обеспечивает расширенные возможности ведения журнала данных конвейера IIS. + Расширенное ведение журнала IIS + Позволяет создавать настраиваемые файлы журналов с расширяемым набором полей. + Обновление для расширенного ведения журнала + + + + IIS Transform Manager + Бета-версия + Включает диспетчер Transform Manager IIS Media Services. + IIS Transform Manager + Включает создание преобразований мультимедиа. + Узел диспетчера IIS Transform Manager + Узел службы для [ProductName]. + IIS Transform Manager + Пакетное преобразование файлов мультимедиа в альтернативные форматы файлов и контейнеров по запросу. + На компьютере установлен пакет задач IIS Transform Manager 1.0 Expression Encoder SP. Его следует удалить перед установкой [ProductName]. + + Microsoft .NET Framework 3.5 требуется для установки [ProductName]. Используйте мастер добавления компонентов в диспетчере сервера, чтобы установить компоненты .NET Framework 3.5.1, или используйте параметр "Включение или отключение компонентов Windows", чтобы включить Microsoft .NET Framework 3.5. + + + + IIS: управление цифровыми правами + Бета-версия + Включает управление цифровыми правами для презентаций Smooth Streaming. + + + ASP.NET не установлен + + + + + + + + + На компьютере обнаружена бета-версия IIS Smooth Streaming. Установка [ProductName] не будет продолжена. Чтобы установить этот продукт, используйте компонент "Установка и удаление программ" панели управления для удаления бета-версии IIS Smooth Streaming. + На компьютере имеется несовместимая версия служб IIS Media Services. Установка [ProductName] не будет продолжена. Чтобы установить этот продукт, используйте компонент "Установка и удаление программ" панели управления для удаления служб IIS Media Services. + Более новая версия этого продукта уже установлена или доступна для установки на этом компьютере. Установка [ProductName] не будет продолжена. Чтобы установить более новую версию этой программы, используйте элемент панели управления "Установка и удаление программ" для обновления служб мультимедиа IIS. + Необходимо преобразовать файл списка воспроизведения + + + + + Обнаружены старые файлы служб IIS Media + + + + + Обнаружены старые файлы бета-версии служб IIS Media + + + + + + IIS Media Pack 1.0 + Обновление для IIS Media Pack 1.0 + IIS Media Services 2.0 + Обновление для IIS Media Services 2.0 + IIS Media Services 3.0 + IIS Media Services 3.0 TAP 2 + Обновление для IIS Media Services 3.0 + Средства и компоненты IIS Media Services. + Средства и компоненты IIS Media Services 5 Premium. + Бета-версия 1 служб IIS Media Services 4.0 + Службы IIS Media Services 4.0 + Бета-версия 1 служб IIS Media Services 4.5 + IIS Media Services 5 Premium + + Веб-списки воспроизведения + Управляет воспроизведением клиентами данных мультимедиа, на которые есть ссылки в списках воспроизведения. + Модуль поддержки сеансов + Поддерживает сохранение сеансов ASP.NET. (Требуется служба роли ASP.NET ля веб-сервера (IIS)). + Пользовательский интерфейс + Настройка компонента веб-списков воспроизведения в диспетчере IIS. + + Регулирование скорости + Экономия полосы пропускания путем регулирования доставки файлов, загружаемых клиентами. + Пользовательский интерфейс + Настройка функции регулирования скорости в диспетчере IIS. + + Файлы + Поддерживает адаптивную потоковую передачу файлов по запросу клиентам. + Пользовательский интерфейс + Настройка Smooth Streaming в диспетчере IIS. + + Каналы + Поддерживает адаптивную потоковую передачу при канальной широковещательной трансляции клиентам. + Пользовательский интерфейс + Настраивает компонент Live Smooth Streaming в диспетчере IIS. + + Управление цифровыми правами + Обеспечивает шифрование и лицензирование содержимого Smooth Streaming. + Пользовательский интерфейс + Настройка функции управления цифровыми правами в диспетчере IIS. + + Для [ProductName] требуется Microsoft Windows Vista с пакетом обновления 1 (SP1) или более поздней версии. + Невозможно установить [ProductName] в операционной системе Vista Home Basic. + Для [ProductName] требуется Microsoft Windows 7 с пакетом обновления 1 (SP1) или более поздней версии. + + + Диспетчер баз данных IIS + Диспетчер баз данных IIS + + + Служба веб-управления 2 (Майкрософт) + Служба веб-управления (Майкрософт) + Установка основных компонентов [ProductName]. + Служба веб-управления 2 (Майкрософт) + Служба управления сетью предоставляет для администраторов удаленные и делегированные возможности управления веб-сервером, сайтами и приложениями, существующими на данном компьютере. + + + Модуль 1.1 видоизменения URL-адресов (Майкрософт) для IIS 7 + Обновление для модуля 1.1 видоизменения URL-адресов для IIS 7 + Видоизменение URL-адресов + Включает функции, отвечающие за видоизменение URL-адресов и содержимого в IIS 7. + Пользовательский интерфейс + Настраивает компонент "модуль видоизменения URL-адресов" в диспетчере служб IIS. + + + Модуль переопределения URL-адресов 2 для IIS + Обновление для модуля 2 переопределения URL-адресов для IIS + Видоизменение URL-адресов + Включает функции, отвечающие за видоизменение URL-адресов и содержимого в IIS 7. + Пользовательский интерфейс + Настраивает компонент "модуль видоизменения URL-адресов" в диспетчере служб IIS. + + + Пакет администрирования IIS 7.0 + Установка основных компонентов [ProductName]. + 1251 + Пакет администрирования IIS 7.0 + Корпорация Майкрософт + Эта версия операционной системы не поддерживается. [ProductName] можно установить только в Windows Server 2008 или Windows Vista с пакетом обновления 1 (SP1) или более поздних версий. + Компоненты ASP.Net + В ASP.NET содержатся компоненты авторизации и страниц ошибок, позволяющие управлять параметрами авторизации и настраиваемых сообщений об ошибках. + Проверка подлинности + Описание проверки подлинности ASP.Net. + Авторизация + Модуль проверки подлинности ASP.NET позволяет настраивать правила проверки подлинности пользователей для доступа к веб-сайтам и приложениям. + Страницы ошибок + Страницы ошибок ASP.NET позволяют настраивать отклики на ошибки HTTP, отображаемые при возникновении таких ошибок. + Модули + Описание модулей ASP.Net. + Обработчики + Описание обработчиков ASP.Net. + Редактор конфигураций + Редактор конфигурации позволяет управлять файлами конфигурации в диспетчере IIS, обеспечивая возможность изменять разделы, атрибуты, элементы и семейства в файлах конфигурации. + Фильтрация запросов + Фильтрация запросов позволяет настраивать правила фильтрации для веб-сайта, ограничивать поведение протоколов и содержимого. + Fast CGI + FastCGI позволяет настраивать параметры пула процессов для приложений FastCGI на веб-сервере. + + + Программа установки ограничения динамических IP-адресов для IIS 7 + + + + + + + + + + + + + Ограничения динамических IP-адресов для IIS 7 - бета-версия + Ограничения динамических IP-адресов для IIS 7 - бета-версия 2 + Ограничения динамических IP-адресов для IIS 7 - бета-версия 3 + + Ограничения динамических IP-адресов для IIS 7 - версия-кандидат + Ограничения динамических IP-адресов для IIS 7 - версия-кандидат 2 + Ограничения динамических IP-адресов для IIS 7 - версия-кандидат 3 + + Ограничения динамических IP-адресов для IIS 7 - рабочий выпуск + + Ограничения динамических IP-адресов для IIS 7 + Пользовательский интерфейс ограничения динамических IP-адресов для IIS 7 + + Ограничения динамического IP-адреса для IIS 7 - на компьютере обнаружена бета-версия. Удалите ее и повторите попытку + + + WebDAV 7.5 для IIS 7.0 + Для использования этого продукта необходимо установить компоненты IIS 7.0 CoreWebEngine и W3SVC. + Серверный модуль WebDAV + Пользовательский интерфейс администрирования WebDAV + + + Инструменты оптимизации IIS Search Engine 1.0 + Инструменты оптимизации IIS Search Engine 1.0 + Инструменты оптимизации Search Engine (SEO) 1.0 + Эта база данных установщика содержит логику и данные, необходимые для установки инструментов оптимизации IIS Search Engine 1.0. + + + Редактор IIS + + + Отчеты IIS + Программа Log Parser не установлена на этом компьютере. Установите программу Log Parser 2.2 с сайта http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07, затем установите отчеты IIS. + + + Необходимые компоненты не найдены. Запустите setup.exe, чтобы установить необходимые зависимые компоненты и установить эту программу. + Управляющие объекты Microsoft SQL Server 2008 являются необходимым условием для установки диспетчера базы данных IIS. Управляющие объекты Micrsoft SQL Server 2008 можно установить на странице http://go.microsoft.com/fwlink/?LinkID=150946. + Системные типы Microsoft SQL Server System CLR Types являются необходимым условием для установки диспетчера базы данных IIS. Системные типы Microsoft SQL Server System CLR Types можно установить на странице http://go.microsoft.com/fwlink/?LinkID=150949. + + + Microsoft Web Farm Framework + Microsoft External Cache + Для установки маршрутизации запросов приложений требуется установить платформу веб-фермы. Установите платформу веб-фермы. + Microsoft Application Request Routing 2.5 + Среда выполнения + Добавляет функции маршрутизации запросов приложений в IIS. + Пользовательский интерфейс + Настраивает функцию маршрутизации запросов приложений в диспетчере IIS. + + + Оснастка Microsoft Windows PowerShell для IIS 7.0 + + + Установщик веб-платформы Майкрософт 4.0 + Установщик веб-платформы Майкрософт + Для [ProductName] требуется Windows XP SP2, Windows 2003 SP1, Windows Vista или более поздняя версия. + Для [ProductName] требуется Windows XP с пакетом обновления 3, Windows Server 2003 с пакетом обновления 2, или более поздние версии. + + + Установщик служб Microsoft Windows Azure + Установщик служб Microsoft Windows Azure + + + Диспетчер служб IIS 7+ + Клиент диспетчера IIS + Поддержка удаленной работы + Для этого продукта требуется Windows XP с пакетом обновления 2 (SP2), Windows 2003 с пакетом обновления 1 (SP1), Windows Vista с пакетом обновления 1 (SP1), Windows 7 или более новая система + Консоль управления IIS не установлена, но она необходима для управления удаленными серверами IIS. Установите консоль управления IIS перед установкой поддержки удаленного управления. Для этого в панели управления откройте "Программы", "Включение или отключение компонентов Windows", и выберите консоль управления IIS среди компонентов IIS. + Этот продукт не требуется при использовании Windows Server 2008, Windows Server 2008 R2 и более новых систем. Установите консоль управления IIS, открыв диспетчер сервера и выбрав консоль управления IIS в службах ролей для роли веб-сервера. + + + Публикация диспетчера IIS 7.0 + Пользовательский интерфейс публикации + + + Application Warm-Up 1.0 для IIS 7.5 + + + + На компьютере установлен несовместимый продукт: [CONFLICTING_PRODUCT_NAME]. Установку [ProductName] продолжить невозможно. Чтобы установить этот продукт, удалите CONFLICTING_PRODUCT_NAME] в разделе "Добавление и удаление программ" в панели управления. + Для установки [ProductName] требуются права администратора. + Для использования [ProductName] требуется IIS версии 7.0. + Для установки [ProductName] требуется IIS версии 7.0 или более поздней. + Для установки [ProductName] требуется IIS версии 7.5 или более поздней. + Для установки [ProductName] требуется IIS версии 7 или 7.5. + На компьютере обнаружена бета-версия [ProductName]. + На компьютере обнаружена более поздняя версия [ProductName]. + Программа установки не может продолжить работу, поскольку на компьютере уже установлен другой экземпляр [ProductName]. Удалите его, затем заново запустите эту установку. + Для использования [ProductName] необходимо установить компоненты IIS 7.0 CoreWebEngine и W3SVC. + Для использования [ProductName] требуется установить консоль управления IIS. + Перед установкой [ProductName] остановите службу активации Windows (WAS) и службу веб-управления (WMSvc). Эти службы нужно будет запустить после установки [ProductName]. + Для установки [ProductName] требуется метабаза IIS. + 64-разрядную версию [ProductName] нельзя установить на 32-разрядный выпуск Microsoft Windows. + 32-разрядную версию [ProductName] нельзя установить на 64-разрядный выпуск Microsoft Windows. + Для установки [ProductName] требуется Microsoft .NET Framework версии 2.0 или более поздней. + Для установки [ProductName] требуется Microsoft .NET Framework версии 3.5 или более поздней. Воспользуйтесь функцией диспетчера сервера "Добавить функции", чтобы установить Microsoft .Net версии 3.5. + Для установки [ProductName] требуется Microsoft .NET Framework версии 4.0 или более поздней. + Перед установкой [ProductName] установите Microsoft .NET Framework версии 2.0 с пакетом обновления 1 (SP1)или более поздним. + Службу Windows Update (wuauserv) невозможно отключить, она необходима для установки [ProductName]. + Оснастка PowerShell является частью операционной системы Windows. Установите ее с помощью элемента панели управления "Программы и компоненты" или диспетчера сервера. + Для установки [ProductName] требуется установщик веб-платформы Майкрософт, версии 3.0 или более поздней. + + Программа установки не обнаружила общую конфигурацию. + Для IIS включена общая конфигурация. Установка [ProductName] не поддерживается при использовании общей конфигурации. Отключите общую конфигурацию перед установкой этого компонента. + + Перед установкой [ProductName] необходимо остановить службу веб-публикаций (W3SVC). Эту службу нужно будет включить после установки. + Консоль управления IIS PowerShell + Оснастка IIS PowerShell + Для оснастки IIS PowerShell требуется PowerShell v1.0 или v2.0 + Для оснастки IIS PowerShell требуется установить WAS и конфигурацию + Пустая строка. + + + Платформа веб-ферм Майкрософт 2.2 + Агент веб-ферм Майкрософт 2.2 + Служба Web Farm Service + Служба Web Farm Service + Служба Web Farm Controller Service + Служба Web Farm Controller Service + Служба Web Farm Agent Service + Служба Web Farm Agent Service + Установщик веб-платформы является необходимым компонентом для установки платформы веб-ферм. Установите установщик веб-платформы с сайта http://www.microsoft.com/web/downloads/platform.aspx. + Инструмент веб-развертывания является необходимым компонентом для установки платформы веб-ферм. Установите инструмент веб-развертывания с сайта http://www.iis.net/download/WebDeploy. + + + Платформа веб-размещения Майкрософт + Платформа веб-размещения + Роли и компоненты веб-размещения. + Платформа размещения + Платформа размещения предоставляет API и команды PowerShell для управления веб-размещением. + Веб-роль + Веб-роль устанавливает динамическую службу WAS и поставщик переопределения URL-адресов для веб-размещения. + Antares Express + Развертывание панели управления в конфигурации, оптимизированной для установки на одном компьютере. + Роль подсистемы балансировки нагрузки + Роль подсистемы балансировки нагрузки позволяет настроить в маршрутизаторе запросов приложений маршрутизацию на основе правил веб-размещения. + Контроллер размещения + Контроллер размещения расширяет платформу веб-ферм 2.0, позволяя ей работать с веб-размещением. + Публикация — роль + Установка средств поддержки веб-развертывания и FTP-публикации. + Эта оснастка PowerShell, которая содержит командлеты для управления инфраструктурой Microsoft Web Hosting. + Динамическая служба WAS + Служба активации Windows, оптимизированная для веб-размещения высокой плотности. + Служба контроля ресурсов + Установка службы контроля ресурсов, которая позволяет собирать и публиковать сведения о среде выполнения и работоспособности. + Resource Metering + Позволяет собирать с веб-роли сведения о среде выполнения и работоспособности и публиковать их. + Применение квот размещения + Служит для отслеживания использования ресурсов веб-сайтами и выполнения настраиваемых действий при превышении квот. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/TRK/misc/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/TRK/misc/setupstrings.wxl new file mode 100644 index 0000000000..83599c3b1c --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/loc/TRK/misc/setupstrings.wxl @@ -0,0 +1,351 @@ + + + + + + + 1055 + + + + Paylaşılan Yapılandırma Yükleme Seçenekleri + IIS paylaşılan yapılandırmasına yükleme seçeneğini belirtin + Yüklerken paylaşılan yapılandırmayı güncelleştir + Bu modülü paylaşılan yapılandırma kullanan bir IIS sunucusuna yüklüyorsunuz. Bu paylaşılan yapılandırmayı kullanan ek IIS sunucuları varsa, bu modülü söz konusu makinelerin tümüne yüklemeniz gerekir. Web sunucularında oluşabilecek kesintileri en az indirmek için bu modülü şu adımları kullanarak yüklemeniz gerekir: İlk olarak, sonuncu hariç tüm makinelerde paylaşılan yapılandırmayı güncelleştirmeden modülü yüklemeniz gerekir. Bunu, aşağıdaki onay kutusunu seçmeden yapın. +Bu işlem, paylaşılan yapılandırmada hiçbir değişiklik yapmadan modül için gereken tüm ikili ve diğer dosyaları her bir makineye yükler. İkinci olarak, sonuncu makinede, altında çalıştığınız kullanıcı kimliğinin UNC paylaşımındaki applicationhost.config dosyasında okuma ve yazma erişimi olduğunu doğrulamalısınız. Sonra, modülü yüklemeli ve aşağıdaki paylaşılan yapılandırmayı güncelleştirme seçeneğini seçmeniz gerekir. + + + WebConfig özel eylemi başlatılıyor + web.config güncelleştiriliyor + + + + IIS Gelişmiş Günlüğü + IIS ardışık düzen verileri için gelişmiş günlüğü etkinleştirir. + IIS Gelişmiş Günlüğü + Genişletilebilir alan seçimi olan özel günlük dosyaları oluşturmaya olanak tanır. + IIS Gelişmiş Günlüğü Güncelleştirmesi + + + + IIS Dönüşüm Yöneticisi + Beta + Dönüşüm Yöneticisi IIS Medya Hizmetleri'ni etkinleştirir. + IIS Dönüşüm Yöneticisi + Medya dönüşümleri oluşturmayı etkinleştirir. + IIS Dönüşüm Yöneticisi Ana Bilgisayarı + [ProductName] için hizmet ana bilgisayarı. + IIS Dönüşüm Yöneticisi + İsteğe bağlı medya dosyalarını alternatif dosya ve kapsayıcı biçimlerine toplu olarak dönüştürün. + Bir IIS Transform Manager 1.0 Expression Encoder SP Task paketi bilgisayarda yüklü. [ProductName] ürününü yüklemeden önce bunu kaldırmalısınız. + + [ProductName] ürününü yüklemek için Microsoft .NET Framework 3.5 gereklidir. Sunucu Yöneticisi'ndeki 'Özellik Ekleme Sihirbazı'nı kullanarak .NET Framework 3.5.1 Özellikleri'ni yükleyin veya 'Windows özelliklerini aç veya kapat'ı kullanarak Microsoft .NET Framework 3.5'i açın. + + + + IIS Dijital Hak Yönetimi + Beta + Kesintisiz Akış sunularında Dijital Hak Yönetimini etkinleştirir. + + + ASP.NET Yüklü Değil + + + + + + + + + Bu bilgisayarda IIS Kesintisiz Akış - Beta bulundu. [ProductName] yüklemesi devam edemez. Bu ürünü yüklemek için, Denetim Masası'ndaki Program Ekle/Kaldır'ı kullanarak IIS Kesintisiz Akış - Beta'yı kaldırın. + Bu bilgisayarda IIS Medya Hizmetleri'nin uyumsuz bir sürümü var. [ProductName] yüklemesi devam edemez. Bu ürünü yüklemek için, Denetim Masası'ndaki Program Ekle/Kaldır'ı kullanarak IIS Medya Hizmetleri'ni kaldırın. + Bu ürünün daha yeni bir sürümü bu bilgisayarda yüklü veya bu bilgisayara yüklenebilir durumda. [ProductName] yüklemesi devam edemiyor. Bu ürünün yeni sürümünü yüklemek için, Denetim Masası'ndaki Program Ekle/Kaldır'ı kullanarak IIS Medya Hizmetleri'ni güncelleştirin. + Çalma Listesi Dosyasının Dönüştürülmesi Gerekiyor + + + + + Eski IIS Medya Hizmetleri Dosyaları Bulundu + + + + + Beta IIS Medya Hizmetleri Dosyaları Bulundu + + + + + + IIS Medya Paketi 1.0 + IIS Medya Paketi 1.0 Güncelleştirmesi + IIS Medya Hizmetleri 2.0 + IIS Medya Paketi 2.0 Güncelleştirmesi + IIS Medya Hizmetleri 3.0 + IIS Medya Hizmetleri 3.0 TAP 2 + IIS Medya Paketi 3.0 Güncelleştirmesi + IIS Medya Paketi özellikleri ve araçları. + IIS Media Services 5 Premium özellikleri ve araçları. + IIS Medya Hizmetleri 4.0 Beta 1 + IIS Medya Hizmetleri 4.0 + IIS Medya Hizmetleri 4.5 Beta 1 + IIS Media Services 5 Premium + + Web Çalma Listeleri + İstemcinin, çalma listelerinde başvurulan medya listelerini kayıttan yürütmesini denetler. + Oturum Yardımcısı + ASP.NET oturum durumu kalıcılığını etkinleştirir. (Web Sunucusu (IIS) için ASP.NET rol hizmetini gerektirir.) + Kullanıcı Arabirimi + IIS Yöneticisi'nde Web Çalma Listeleri özelliğini yapılandırır. + + Bit Hızı Azaltma + İstemcilerin karşıdan yüklediği dosyaların teslimini yavaşlatarak bant genişliğinden tasarruf sağlar. + Kullanıcı Arabirimi + IIS Yöneticisi'nde Bit Hızı Azaltma özelliğini yapılandırır. + + Varlıklar + İsteğe bağlı varlıkların istemcilere HTTP ile uyarlamalı akışını etkinleştirir. + Kullanıcı Arabirimi + IIS Yöneticisi'nde Kesintisiz Akış özelliğini yapılandırır. + + Kanallar + Kanal yayınlarının istemcilere HTTP ile uyarlamalı akışını etkinleştirir. + Kullanıcı Arabirimi + IIS Yöneticisi'nde Canlı Kesintisiz Akış özelliğini yapılandırır. + + Dijital Hak Yönetimi + Kesintisiz Akış medyası için şifreleme ve lisanslama sağlar. + Kullanıcı Arabirimi + IIS Yöneticisi'nde Dijital Hak Yönetimi özelliğini yapılandırır. + + [ProductName] için Microsoft Windows Vista Service Pack 1 veya üstü gereklidir. + [ProductName], Vista Home Basic üzerine yüklenemez. + [ProductName] için Microsoft Windows 7 Service Pack 1 veya üstü gereklidir. + + + IIS Veritabanı Yöneticisi + IIS Veritabanı Yöneticisi + + + Microsoft Web Yönetimi Hizmeti 2 + Microsoft Web Yönetimi Hizmeti + [ProductName] ürününün temel özelliklerini yükler. + Microsoft Web Yönetimi Hizmeti 2 + Web Yönetimi Hizmeti, yöneticilerin bu makinede bulunan Web sunucularını, siteleri ve uygulamaları yönetmeleri için uzaktan ve temsilci seçilmiş yönetim becerileri sağlar. + + + IIS 7 için Microsoft URL Yeniden Yazma Modülü 1.1 + IIS 7 için URL Yeniden Yazma Modülü 1.1 Güncelleştirmesi + URL Yeniden Yazma + IIS 7'nin URL ve içerik yeniden yazma yeteneklerini etkinleştirir. + Kullanıcı Arabirimi + IIS Yöneticisi'nde URL Yeniden Yazma Modülü özelliğini yapılandırır. + + + IIS URL Yeniden Yazma Modülü 2 + IIS URL Yeniden Yazma Modülü 2 Güncelleştirmesi + URL Yeniden Yazma + IIS 7'nin URL ve içerik yeniden yazma yeteneklerini etkinleştirir. + Kullanıcı Arabirimi + IIS Yöneticisi'nde URL Yeniden Yazma Modülü özelliğini yapılandırır. + + + IIS 7.0 için Yönetim Paketi + [ProductName] ürününün temel özelliklerini yükler. + 1254 + IIS 7.0 için Yönetim Paketi + Microsoft Corporation + İşletim sisteminin bu sürümü desteklenmiyor. [ProductName] yalnızca Windows Server 2008 ya da Windows Vista Service Pack 1 ve üstü üzerine yüklenebilir. + ASP.Net Özellikleri + ASP.NET, yetkilendirme ve özel hata ayarlarınızı yönetmenizi sağlayan Yetkilendirme ve Hata Sayfaları özelliklerini içerir. + Kimlik Doğrulaması + ASP.Net Kimlik Doğrulaması Açıklaması. + Yetkilendirme + ASP.NET Yetkilendirme, kullanıcılara Web sitelerinize ve uygulamalarınıza erişme yetkisi verme kurallarını yapılandırmanızı sağlar. + Hata Sayfaları + ASP.NET Hata Sayfaları, hata oluştuğunda döndürülen HTTP hata yanıtlarını yapılandırmanızı sağlar. + Modüller + ASP.Net Modülleri Açıklaması. + İşleyiciler + ASP.Net İşleyiciler Açıklaması. + Yapılandırma Düzenleyicisi + Yapılandırma Düzenleyicisi, IIS Yöneticisi'nde yapılandırma dosyalarındaki bölümleri, öznitelikleri, öğeleri ve koleksiyonları düzenlemenize olanak tanıyarak yapılandırma dosyalarınızı yönetmenizi sağlar. + İstek Filtreleme + İstek Filtreleme, Web siteniz için filtreleme kurallarını yapılandırmanızı, protokol ve içerik davranışını kısıtlamanızı sağlar. + FastCGI + FastCGI, Web sunucunuzdaki FastCGI uygulamaları için işlem havuzu ayarlarını yapılandırmanızı sağlar. + + + IIS 7 için Dinamik IP Kısıtlamaları Kurulumu + + + + + + + + + + + + + IIS 7 için Dinamik IP Kısıtlamaları - Beta + IIS 7 için Dinamik IP Kısıtlamaları - Beta 2 + IIS 7 için Dinamik IP Kısıtlamaları - Beta 3 + + IIS 7 için Dinamik IP Kısıtlamaları - Sürüm Adayı + IIS 7 için Dinamik IP Kısıtlamaları - Sürüm Adayı 2 + IIS 7 için Dinamik IP Kısıtlamaları - Sürüm Adayı 3 + + IIS 7 için Dinamik IP Kısıtlamaları - RTW + + IIS 7 için Dinamik IP Kısıtlamaları + IIS 7 için Dinamik IP Kısıtlamaları Kullanıcı Arabirimi + + Bu makinede IIS 7 - Beta için Dinamik IP Kısıtlamaları bulundu. Lütfen kaldırın ve yeniden deneyin + + + IIS 7.0 için WebDAV 7.5 + Bu ürünü kullanmak için IIS 7.0 CoreWebEngine ve W3SVC özellikleri yüklenmelidir. + WebDAV Sunucu Modülü + WebDAV Yönetimi Kullanıcı Arabirimi + + + IIS Arama Alt Yapısı İyileştirme Araç Seti 1.0 + IIS Arama Alt Yapısı İyileştirme Araç Seti 1.0 + Arama Alt Yapısı İyileştirme (SEO) Araç Seti 1.0 + Bu yükleyici veritabanı IIS Arama Alt Yapısı İyileştirme Araç Seti 1.0'ı yüklemek için gereken mantığı ve verileri içermektedir. + + + IIS Düzenleyicisi + + + IIS Raporları + Bu makinede Günlük Ayrıştırıcısı yüklü değil. Lütfen http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07 adresinden Günlük Ayrıştırıcısı 2.2 sürümünü yükleyin ve sonra IIS Raporları yüklemesine devam edin + + + Önkoşul paketler bulunamadı. Bağımlılıkları çözümlemek ve bu programı yüklemek için lütfen setup.exe'yi çalıştırın. + Microsoft SQL Server 2008 Yönetim Nesneleri, IIS Veritabanı Yöneticisi'ni yüklemek için bir önkoşuldur. Microsoft SQL Server 2008 Yönetim Nesneleri'ni http://go.microsoft.com/fwlink/?LinkID=150946 adresinden yükleyebilirsiniz. + Microsoft SQL Server Sistem CLR Türleri, IIS Veritabanı Yöneticisi'ni yüklemek için bir önkoşuldur. Microsoft SQL Server Sistem CLR Türleri'ni http://go.microsoft.com/fwlink/?LinkID=150949 adresinden yükleyebilirsiniz. + + + Microsoft Web Grubu Çerçevesi + Microsoft Dış Önbellek + Web Grubu Çerçevesi, Uygulama İsteği Yönlendirme için bir önkoşuldur. Lütfen Web Grubu Çerçevesi'ni yükleyin. + Microsoft Uygulama İsteği Yönlendirme 2.5 + Çalışma Zamanı + IIS'ye Uygulama İsteği Yönlendirme özellikleri ekler. + Kullanıcı Arabirimi + IIS Yöneticisi'nde Uygulama İsteği Yönlendirme özelliğini yapılandırır. + + + IIS 7.0 için Microsoft Windows PowerShell ek bileşeni + + + Microsoft Web Platformu Yükleyicisi 4.0 + Microsoft Web Platformu Yükleyicisi + [ProductName] için Windows XP SP2, Windows 2003 SP1, Windows Vista veya üstü gereklidir. + [ProductName] için Windows XP Service Pack 3, Windows Server 2003 Service Pack 2 veya üstü gereklidir. + + + Microsoft Windows Azure Hizmetleri Yükleyicisi + Microsoft Windows Azure Hizmetleri Yükleyicisi + + + Internet Information Services (IIS) 7+ Yöneticisi + IIS Yöneticisi İstemcisi + Uzaktan İletişim Desteği + Bu ürün için Windows XP SP2, Windows 2003 SP1, Windows Vista SP1, Windows 7 veya daha üstü gereklidir + IIS Yönetim Konsolu yüklenmedi ancak uzak IIS Sunucularını yönetmek için gerekiyor. Uzaktan yönetim desteğini yüklemeden önce lütfen 'Denetim Masası -> Programlar -> Windows Özelliklerini Aç veya Kapat'ı açın ve Internet Information Services özelliğinde IIS Yönetimi Konsolu'nu seçin. + Bu ürün Windows Server 2008, Windows Server 2008 R2 veya daha üstünde gerekli değildir. IIS Yönetim Konsolu'nu yüklemek üzere lütfen Sunucu Yöneticisi'ni açın ve Web Sunucusu Rolü için Rol Hizmetleri'nde IIS Yönetim Konsolu'nu seçin. + + + IIS 7.0 için IIS Yöneticisi Yayımlama + Yayımlama Kullanıcı Arabirimi + + + IIS 7.5 için Application Warm-Up 1.0 + + + + Bu bilgisayarda uyumsuz bir ürün ([CONFLICTING_PRODUCT_NAME]) mevcut. [ProductName] ürününün yüklemesi devam edemiyor. Bu ürünü yüklemek için [CONFLICTING_PRODUCT_NAME] ürününü kaldırmak amacıyla Denetim Masası'ndaki Program Ekle/Kaldır'ı kullanın. + [ProductName] ürününü yüklemek için yönetici ayrıcalıkları gereklidir. + [ProductName] ürününü kullanmak için IIS Sürüm 7.0 gereklidir. + [ProductName] ürününü yüklemek için IIS Sürüm 7.0 veya üstü gereklidir. + [ProductName] ürününü yüklemek için IIS Sürüm 7.5 veya üstü gereklidir. + [ProductName] ürününü yüklemek için IIS Sürüm 7 veya 7.5 gereklidir. + Bu makinede [ProductName] ürününün beta sürümü bulundu. + Bu makinede [ProductName] ürününün daha yeni bir sürümü bulundu. + Bu bilgisayara başka bir [ProductName] örneği önceden yüklendiğinden Kurulum devam edemiyor. Lütfen önce onu kaldırın ve sonra bu yükleme işlemini yeniden başlatın. + [ProductName] ürününü kullanmak için IIS 7.0 CoreWebEngine ve W3SVC özellikleri yüklenmelidir. + [ProductName] ürününü kullanmak için IIS Yönetim Konsolu yüklenmelidir. + [ProductName] ürününü yüklemeden önce lütfen Windows İşlem Etkinleştirme Hizmeti (WAS) ve Web Yönetimi Hizmeti (WMSvc) hizmetlerinin ikisini de durdurun. [ProductName] yüklendikten sonra hizmetleri yeniden başlatmanız gerekir. + [ProductName] ürününü yüklemek için IIS Metatabanı gereklidir. + [ProductName] ürünün 64-bit sürümü Microsoft Windows'un 32-bit bir sürümüne yüklenemez. + [ProductName] ürünün 32-bit sürümü Microsoft Windows'un 64-bit bir sürümüne yüklenemez. + [ProductName] ürününü yüklemek için Microsoft .NET Framework Sürüm 2.0 veya üstü gereklidir. + [ProductName] ürününü yüklemek için Microsoft .NET Framework Sürüm 3.5 veya üstü gereklidir. Microsoft .Net Sürüm 3.5'i yüklemek için Sunucu Yöneticisi altındaki 'Özellik Ekle' seçeneğini kullanın. + [ProductName] ürününü yüklemek için Microsoft .NET Framework Sürüm 4.0 veya üstü gereklidir. + [ProductName] ürününü yüklemeden önce lütfen Microsoft .NET Framework Sürüm 2.0 Service Pack 1'i (veya daha yeni bir hizmet paketini) yükleyin. + Windows Update (wuauserv) hizmeti devre dışı bırakılamaz; [ProductName] ürününü yüklemek için gereklidir. + PowerShell ek bileşeni Windows İşletim Sisteminin bir parçasıdır. Lütfen 'Programlar ve Özellikler' veya 'Sunucu Yöneticisi' aracılığıyla yükleyin. + [ProductName] ürününü yüklemek için Microsoft Web Platformu Yükleyicisi 3.0 veya üstü gereklidir. + + Kurulum paylaşılan yapılandırmayı silemedi. + IIS için paylaşılan yapılandırma etkin. Paylaşılan yapılandırma kullanılırken [ProductName] ürününün yüklenmesi desteklenmiyor. Bu özelliği yüklemeden önce lütfen paylaşılan yapılandırmayı devre dışı bırakın. + + [ProductName] ürününü yüklemeden önce lütfen World Wide Web Yayımlama Hizmeti'ni (W3SVC) durdurun. Yükleme işleminden sonra hizmeti yeniden başlatmanız gerekir. + IIS PowerShell Yönetim Konsolu + IIS PowerShell ek bileşeni + IIS PowerShell ek bileşeni için PowerShell v1.0 veya v2.0 yüklü olmalıdır + IIS PowerShell ek bileşeni için WAS ve yapılandırma yüklü olmalıdır + Bu hatalı bir dizedir. + + + Microsoft Web Grubu Çerçevesi Sürüm 2.2 + Microsoft Web Grubu Aracısı Sürüm 2.2 + Web Grubu Hizmeti + Web Grubu Hizmeti + Web Grubu Denetleyicisi Hizmeti + Web Grubu Denetleyicisi Hizmeti + Web Grubu Aracısı Hizmeti + Web Grubu Aracısı Hizmeti + Web Grubu Çerçevesi'ni yüklemek için Web Platformu Yükleyicisi bir önkoşuldur. Lütfen http://www.microsoft.com/web/downloads/platform.aspx adresinden Web Platformu Yükleyicisi'ni yükleyin. + Web Grubu Çerçevesi'ni yüklemek için Web Dağıtım Aracı bir önkoşuldur. Lütfen http://www.iis.net/download/WebDeploy adresinden Web Dağıtımı Aracı'nı yükleyin. + + + Microsoft Web Barındırma Çerçevesi + Web Barındırma Çerçevesi + Web Barındırma rolleri ve özellikleri. + Barındırma Çerçevesi + Barındırma Çerçevesi, Web Barındırma'yı yönetmek için API'ler ve PowerShell komutları sağlar. + Web Rolü + Web Rolü, Web Barındırma için Dinamik WAS hizmetini ve URL Yeniden Yazma sağlayıcısını yükler. + Antares Express + Tek makineli kurulum için en iyi duruma getirilen bir Denetim Masası yapılandırmasını dağıtır. + Yük Dengeleyici Rolü + Yük Dengeleyici Rolü, Uygulama İstek Yönlendiricisini Web Barındırma kurallarına göre yönlendirecek şekilde yapılandırır. + Barındırma Denetleyicisi + Barındırma Denetleyicisi, Web Grubu Çerçevesi 2.0'ı Web Barındırma ile çalışacak şekilde genişletir. + Yayımlama Rolü + Web Dağıtımı ve FTP yayımlama için desteği yükler. + Bu, Microsoft Web Barındırma altyapısını yönetmeyi sağlayan cmdlet'ler içeren bir PowerShell ek bileşenidir. + Dinamik WAS Hizmeti + Yüksek yoğunluklu Web Barındırma için en iyi duruma getirilmiş Windows İşlem Etkinleştirme hizmeti. + Kaynak Ölçümü Hizmeti + Çalışma zamanı ve sistem bilgisi toplamayı ve yayımlamayı sağlayan Kaynak Ölçümü hizmetini yükler. + Kaynak Ölçümü + Web Rolünden çalışma zamanı ve sistem bilgisi toplamayı ve yayımlamayı sağlar. + Barındırma Kota Uygulama + Web sitesi kaynak kullanımını izler ve kullanım kotası aşıldığında özel eylemler uygular. + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/dutil.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/dutil.h new file mode 100644 index 0000000000..2a830b7c83 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/dutil.h @@ -0,0 +1,181 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once +//------------------------------------------------------------------------------------------------- +// +// Header for utility layer that provides standard support for asserts, exit macros +// +//------------------------------------------------------------------------------------------------- + +#define DAPI __stdcall +#define DAPIV __cdecl // used only for functions taking variable length arguments + +#define DAPI_(type) EXTERN_C type DAPI +#define DAPIV_(type) EXTERN_C type DAPIV + + +// enums +enum REPORT_LEVEL { + REPORT_NONE, // turns off report (only valid for XXXSetLevel()) + REPORT_STANDARD, // written if reporting is on + REPORT_VERBOSE, // written only if verbose reporting is on + REPORT_DEBUG, // reporting useful when debugging code + REPORT_ERROR, // always gets reported, but can never be specified + }; + +// asserts and traces +#ifdef DEBUG + +typedef BOOL (DAPI *DUTIL_ASSERTDISPLAYFUNCTION)(LPCSTR sz); + +extern "C" void DAPI Dutil_SetAssertModule(__in HMODULE hAssertModule); +extern "C" void DAPI Dutil_SetAssertDisplayFunction(__in DUTIL_ASSERTDISPLAYFUNCTION pfn); +extern "C" void DAPI Dutil_Assert(const CHAR* szFile, int iLine); +extern "C" void DAPI Dutil_AssertSz(const CHAR* szFile, int iLine, const CHAR *szMsg); + +extern "C" void DAPI Dutil_TraceSetLevel(__in REPORT_LEVEL ll, __in BOOL fTraceFilenames); +extern "C" REPORT_LEVEL DAPI Dutil_TraceGetLevel(); +extern "C" void __cdecl Dutil_Trace(__in LPCSTR szFile, __in int iLine, __in REPORT_LEVEL rl, __in LPCSTR szMessage, ...); +extern "C" void __cdecl Dutil_TraceError(__in LPCSTR szFile, __in int iLine, __in REPORT_LEVEL rl, __in HRESULT hr, __in LPCSTR szMessage, ...); + +#endif + +#if defined DEBUG + +#define AssertSetModule(m) (void)Dutil_SetAssertModule(m) +#define AssertSetDisplayFunction(pfn) (void)Dutil_SetAssertDisplayFunction(pfn) +#define Assert(f) ((f) ? (void)0 : (void)Dutil_Assert(__FILE__, __LINE__)) +#define AssertSz(f, sz) ((f) ? (void)0 : (void)Dutil_AssertSz(__FILE__, __LINE__, sz)) + +#define TraceSetLevel(l, f) (void)Dutil_TraceSetLevel(l, f) +#define TraceGetLevel() (REPORT_LEVEL)Dutil_TraceGetLevel() +#define Trace(l, f) (void)Dutil_Trace(__FILE__, __LINE__, l, f, NULL) +#define Trace1(l, f, s) (void)Dutil_Trace(__FILE__, __LINE__, l, f, s) +#define Trace2(l, f, s, t) (void)Dutil_Trace(__FILE__, __LINE__, l, f, s, t) +#define Trace3(l, f, s, t, u) (void)Dutil_Trace(__FILE__, __LINE__, l, f, s, t, u) + +#define TraceError(x, f) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_ERROR, x, f, NULL) +#define TraceError1(x, f, s) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_ERROR, x, f, s) +#define TraceError2(x, f, s, t) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_ERROR, x, f, s, t) +#define TraceError3(x, f, s, t, u) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_ERROR, x, f, s, t, u) + +#define TraceErrorDebug(x, f) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_DEBUG, x, f, NULL) +#define TraceErrorDebug1(x, f, s) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_DEBUG, x, f, s) +#define TraceErrorDebug2(x, f, s, t) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_DEBUG, x, f, s, t) +#define TraceErrorDebug3(x, f, s, t, u) (void)Dutil_TraceError(__FILE__, __LINE__, REPORT_DEBUG, x, f, s, t, u) + +#else // !DEBUG + +#define AssertSetModule(m) +#define AssertSetDisplayFunction(pfn) +#define Assert(f) +#define AssertSz(f, sz) + +#define TraceSetLevel(l, f) +#define Trace(l, f) +#define Trace1(l, f, s) +#define Trace2(l, f, s, t) +#define Trace3(l, f, s, t, u) + +#define TraceError(x, f) +#define TraceError1(x, f, s) +#define TraceError2(x, f, s, t) +#define TraceError3(x, f, s, t, u) + +#define TraceErrorDebug(x, f) +#define TraceErrorDebug1(x, f, s) +#define TraceErrorDebug2(x, f, s, t) +#define TraceErrorDebug3(x, f, s, t, u) + +#endif // DEBUG + + +// ExitTrace can be overriden +#ifndef ExitTrace +#define ExitTrace TraceError +#endif +#ifndef ExitTrace1 +#define ExitTrace1 TraceError1 +#endif +#ifndef ExitTrace2 +#define ExitTrace2 TraceError2 +#endif +#ifndef ExitTrace3 +#define ExitTrace3 TraceError3 +#endif + +// Exit macros +#define ExitFunction() { goto LExit; } +#define ExitFunction1(x) { x; goto LExit; } + +#define ExitOnLastError(x, s) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { ExitTrace(x, s); goto LExit; } } +#define ExitOnLastError1(x, f, s) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { ExitTrace1(x, f, s); goto LExit; } } +#define ExitOnLastError2(x, f, s, t) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { ExitTrace2(x, f, s, t); goto LExit; } } + +#define ExitOnLastErrorDebugTrace(x, s) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { TraceErrorDebug(x, s); goto LExit; } } +#define ExitOnLastErrorDebugTrace1(x, f, s) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { TraceErrorDebug1(x, f, s); goto LExit; } } +#define ExitOnLastErrorDebugTrace2(x, f, s, t) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { TraceErrorDebug2(x, f, s, t); goto LExit; } } + +#define ExitWithLastError(x, s) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTrace(x, s); goto LExit; } +#define ExitWithLastError1(x, f, s) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTrace1(x, f, s); goto LExit; } +#define ExitWithLastError2(x, f, s, t) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTrace2(x, f, s, t); goto LExit; } + +#define ExitOnFailure(x, s) if (FAILED(x)) { ExitTrace(x, s); goto LExit; } +#define ExitOnFailure1(x, f, s) if (FAILED(x)) { ExitTrace1(x, f, s); goto LExit; } +#define ExitOnFailure2(x, f, s, t) if (FAILED(x)) { ExitTrace2(x, f, s, t); goto LExit; } +#define ExitOnFailure3(x, f, s, t, u) if (FAILED(x)) { ExitTrace3(x, f, s, t, u); goto LExit; } + +#define ExitOnFailureDebugTrace(x, s) if (FAILED(x)) { TraceErrorDebug(x, s); goto LExit; } +#define ExitOnFailureDebugTrace1(x, f, s) if (FAILED(x)) { TraceErrorDebug1(x, f, s); goto LExit; } +#define ExitOnFailureDebugTrace2(x, f, s, t) if (FAILED(x)) { TraceErrorDebug2(x, f, s, t); goto LExit; } +#define ExitOnFailureDebugTrace3(x, f, s, t, u) if (FAILED(x)) { TraceErrorDebug3(x, f, s, t, u); goto LExit; } + +#define ExitOnNull(p, x, e, s) if (NULL == p) { x = e; ExitTrace(x, s); goto LExit; } +#define ExitOnNull1(p, x, e, f, s) if (NULL == p) { x = e; ExitTrace1(x, f, s); goto LExit; } +#define ExitOnNull2(p, x, e, f, s, t) if (NULL == p) { x = e; ExitTrace2(x, f, s, t); goto LExit; } + +#define ExitOnNullWithLastError(p, x, s) if (NULL == p) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTrace(x, s); goto LExit; } +#define ExitOnNullWithLastError1(p, x, f, s) if (NULL == p) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTrace1(x, f, s); goto LExit; } + +#define ExitOnNullDebugTrace(p, x, e, s) if (NULL == p) { x = e; TraceErrorDebug(x, s); goto LExit; } +#define ExitOnNullDebugTrace1(p, x, e, f, s) if (NULL == p) { x = e; TraceErrorDebug1(x, f, s); goto LExit; } + +#define ExitOnNtError(x, s) if (NT_ERROR(x)) { ExitTrace(x, s); goto LExit; } +#define ExitOnNtError1(x, f, s) if (NT_ERROR(x)) { ExitTrace1(x, f, s); goto LExit; } + + +// release macros +#define ReleaseObject(x) if (x) { x->Release(); } +#define ReleaseVariant(x) { ::VariantClear(&x); } +#define ReleaseNullObject(x) if (x) { (x)->Release(); x = NULL; } +#define ReleaseCertificate(x) if (x) { ::CertFreeCertificateContext(x); x=NULL; } + + +// useful defines and macros +#define Unused(x) ((void)x) + +#ifndef MAXSIZE_T +#define MAXSIZE_T ((SIZE_T)~((SIZE_T)0)) +#endif + + +#if 1 +#define countof(ary) (sizeof(ary) / sizeof(ary[0])) +#else +#ifndef __cplusplus +#define countof(ary) (sizeof(ary) / sizeof(ary[0])) +#else +template static char countofVerify(void const *, T) throw() { return 0; } +template static void countofVerify(T *const, T *const *) throw() {}; +#define countof(arr) (sizeof(countofVerify(arr,&(arr))) * sizeof(arr)/sizeof(*(arr))) +#endif +#endif + + +#ifndef MAXSIZE_T +#define MAXSIZE_T ((SIZE_T)~((SIZE_T)0)) +#endif + +#define E_NOMOREITEMS HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) +#define AddRefAndRelease(x) { x->AddRef(); x->Release(); } diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/memutil.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/memutil.h new file mode 100644 index 0000000000..36077b0fc6 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/memutil.h @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once +//------------------------------------------------------------------------------------------------- +// +// Header for memory helper functions. +// +//------------------------------------------------------------------------------------------------- + +#ifdef __cplusplus +extern "C" { +#endif + +#define ReleaseMem(p) if (p) { MemFree(p); } +#define ReleaseNullMem(p) if (p) { MemFree(p); p = NULL; } + + +HRESULT DAPI MemInitialize(); +void DAPI MemUninitialize(); + +LPVOID DAPI MemAlloc( + __in SIZE_T cbSize, + __in BOOL fZero + ); +LPVOID DAPI MemReAlloc( + __in LPVOID pv, + __in SIZE_T cbSize, + __in BOOL fZero + ); + +HRESULT DAPI MemFree( + __in LPVOID pv + ); +SIZE_T DAPI MemSize( + __in LPVOID pv + ); + +#ifdef __cplusplus +} +#endif + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/precomp.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/precomp.h new file mode 100644 index 0000000000..e41eecd4e4 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/precomp.h @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once + +#include +#include +#include +#include + +const WCHAR MAGIC_MULTISZ_DELIM = 128; + +#include "wcautil.h" +#include "memutil.h" +#include "strutil.h" diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/qtexec.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/qtexec.cpp new file mode 100644 index 0000000000..45d0945f62 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/qtexec.cpp @@ -0,0 +1,276 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +//------------------------------------------------------------------------------------------------- +// +// Executes command line instructions without popping up a shell. +// +//------------------------------------------------------------------------------------------------- + +#include "precomp.h" + +#define OUTPUT_BUFFER 1024 + + +#define ONEMINUTE 60000 + +static HRESULT CreatePipes( + __out HANDLE *phOutRead, + __out HANDLE *phOutWrite, + __out HANDLE *phErrWrite, + __out HANDLE *phInRead, + __out HANDLE *phInWrite + ) +{ + Assert(phOutRead); + Assert(phOutWrite); + Assert(phErrWrite); + Assert(phInRead); + Assert(phInWrite); + + HRESULT hr = S_OK; + SECURITY_ATTRIBUTES sa; + HANDLE hOutTemp = INVALID_HANDLE_VALUE; + HANDLE hInTemp = INVALID_HANDLE_VALUE; + + HANDLE hOutRead = INVALID_HANDLE_VALUE; + HANDLE hOutWrite = INVALID_HANDLE_VALUE; + HANDLE hErrWrite = INVALID_HANDLE_VALUE; + HANDLE hInRead = INVALID_HANDLE_VALUE; + HANDLE hInWrite = INVALID_HANDLE_VALUE; + + // Fill out security structure so we can inherit handles + ::ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + + // Create pipes + if (!::CreatePipe(&hOutTemp, &hOutWrite, &sa, 0)) + ExitOnLastError(hr, "failed to create output pipe"); + + if (!::CreatePipe(&hInRead, &hInTemp, &sa, 0)) + ExitOnLastError(hr, "failed to create input pipe"); + + + // Duplicate output pipe so standard error and standard output write to + // the same pipe + if (!::DuplicateHandle(::GetCurrentProcess(), hOutWrite, ::GetCurrentProcess(), &hErrWrite, 0, TRUE, DUPLICATE_SAME_ACCESS)) + ExitOnLastError(hr, "failed to duplicate write handle"); + + // We need to create new output read and input write handles that are + // non inheritable. Otherwise it creates handles that can't be closed. + if (!::DuplicateHandle(::GetCurrentProcess(), hOutTemp, ::GetCurrentProcess(), &hOutRead, 0, FALSE, DUPLICATE_SAME_ACCESS)) + ExitOnLastError(hr, "failed to duplicate output pipe"); + + if (!::DuplicateHandle(::GetCurrentProcess(), hInTemp, ::GetCurrentProcess(), &hInWrite, 0, FALSE, DUPLICATE_SAME_ACCESS)) + ExitOnLastError(hr, "failed to duplicate input pipe"); + + // now that everything has succeeded, assign to the outputs + *phOutRead = hOutRead; + hOutRead = INVALID_HANDLE_VALUE; + + *phOutWrite = hOutWrite; + hOutWrite = INVALID_HANDLE_VALUE; + + *phErrWrite = hErrWrite; + hErrWrite = INVALID_HANDLE_VALUE; + + *phInRead = hInRead; + hInRead = INVALID_HANDLE_VALUE; + + *phInWrite = hInWrite; + hInWrite = INVALID_HANDLE_VALUE; + +LExit: + if (INVALID_HANDLE_VALUE != hOutRead) + ::CloseHandle(hOutRead); + if (INVALID_HANDLE_VALUE != hOutWrite) + ::CloseHandle(hOutWrite); + if (INVALID_HANDLE_VALUE != hErrWrite) + ::CloseHandle(hErrWrite); + if (INVALID_HANDLE_VALUE != hInRead) + ::CloseHandle(hInRead); + if (INVALID_HANDLE_VALUE != hInWrite) + ::CloseHandle(hInWrite); + if (INVALID_HANDLE_VALUE != hOutTemp) + ::CloseHandle(hOutTemp); + if (INVALID_HANDLE_VALUE != hInTemp) + ::CloseHandle(hInTemp); + + return hr; +} + +static HRESULT LogOutput( + __in HANDLE hRead + ) +{ + BYTE *pBuffer = NULL; + LPWSTR szLog = NULL; + LPWSTR szTemp = NULL; + LPWSTR pEnd = NULL; + LPWSTR pNext = NULL; + LPSTR szWrite = NULL; + DWORD dwBytes = OUTPUT_BUFFER; + BOOL bFirst = TRUE; + BOOL bUnicode = TRUE; + HRESULT hr = S_OK; + + // Get buffer for output + pBuffer = (BYTE *)MemAlloc(OUTPUT_BUFFER, FALSE); + ExitOnNull(pBuffer, hr, E_OUTOFMEMORY, "Failed to allocate buffer for output."); + + while (0 != dwBytes) + { + ::ZeroMemory(pBuffer, OUTPUT_BUFFER); + if(!::ReadFile(hRead, pBuffer, OUTPUT_BUFFER - 1, &dwBytes, NULL) && GetLastError() != ERROR_BROKEN_PIPE) + { + ExitOnLastError(hr, "Failed to read from handle."); + } + + // Check for UNICODE or ANSI output + if (bFirst) + { + if ((isgraph(pBuffer[0]) && isgraph(pBuffer[1])) || + (isgraph(pBuffer[0]) && isspace(pBuffer[1])) || + (isspace(pBuffer[0]) && isgraph(pBuffer[1])) || + (isspace(pBuffer[0]) && isspace(pBuffer[1]))) + bUnicode = FALSE; + bFirst = FALSE; + } + + // Keep track of output + if (bUnicode) + { + hr = StrAllocConcat(&szLog, (LPWSTR)pBuffer, 0); + ExitOnFailure(hr, "failed to concatenate output strings"); + } + else + { + hr = StrAllocStringAnsi(&szTemp, (LPSTR)pBuffer, 0, CP_OEMCP); + ExitOnFailure(hr, "failed to allocate output string"); + hr = StrAllocConcat(&szLog, szTemp, 0); + ExitOnFailure(hr, "failed to concatenate output strings"); + } + + // Log each line of the output + pNext = szLog; + pEnd = wcschr(szLog, L'\r'); + if (NULL == pEnd) + pEnd = wcschr(szLog, L'\n'); + while (pEnd && *pEnd) + { + // Find beginning of next line + pEnd[0] = 0; + pEnd++; + if ((pEnd[0] == L'\r') || (pEnd[0] == L'\n')) + pEnd++; + + // Log output + hr = StrAnsiAllocString(&szWrite, pNext, 0, CP_OEMCP); + ExitOnFailure(hr, "failed to convert output to ANSI"); + WcaLog(LOGMSG_STANDARD, szWrite); + + // Next line + pNext = pEnd; + pEnd = wcschr(pNext, L'\r'); + if (NULL == pEnd) + pEnd = wcschr(pNext, L'\n'); + } + + hr = StrAllocString(&szTemp, pNext, 0); + ExitOnFailure(hr, "failed to allocate string"); + + hr = StrAllocString(&szLog, szTemp, 0); + ExitOnFailure(hr, "failed to allocate string"); + } + + // Print any text that didn't end with a new line + if (szLog && *szLog) + { + hr = StrAnsiAllocString(&szWrite, szLog, 0, CP_OEMCP); + ExitOnFailure(hr, "failed to convert output to ANSI"); + WcaLog(LOGMSG_VERBOSE, szWrite); + } + +LExit: + if (NULL != pBuffer) + MemFree(pBuffer); + + ReleaseNullStr(szLog); + ReleaseNullStr(szTemp); + ReleaseNullStr(szWrite); + + return hr; +} + +HRESULT QuietExec( + __in LPWSTR wzCommand, + __in DWORD dwTimeout + ) +{ + HRESULT hr = S_OK; + PROCESS_INFORMATION oProcInfo; + STARTUPINFOW oStartInfo; + DWORD dwExitCode = ERROR_SUCCESS; + HANDLE hOutRead = INVALID_HANDLE_VALUE; + HANDLE hOutWrite = INVALID_HANDLE_VALUE; + HANDLE hErrWrite = INVALID_HANDLE_VALUE; + HANDLE hInRead = INVALID_HANDLE_VALUE; + HANDLE hInWrite = INVALID_HANDLE_VALUE; + + memset(&oProcInfo, 0, sizeof(oProcInfo)); + memset(&oStartInfo, 0, sizeof(oStartInfo)); + + // Create output redirect pipes + hr = CreatePipes(&hOutRead, &hOutWrite, &hErrWrite, &hInRead, &hInWrite); + ExitOnFailure(hr, "failed to create output pipes"); + + // Set up startup structure + oStartInfo.cb = sizeof(STARTUPINFOW); + oStartInfo.dwFlags = STARTF_USESTDHANDLES; + oStartInfo.hStdInput = hInRead; + oStartInfo.hStdOutput = hOutWrite; + oStartInfo.hStdError = hErrWrite; + + WcaLog(LOGMSG_VERBOSE, "%S", wzCommand); + + if (::CreateProcessW(NULL, + wzCommand, // command line + NULL, // security info + NULL, // thread info + TRUE, // inherit handles + ::GetPriorityClass(::GetCurrentProcess()) | CREATE_NO_WINDOW, // creation flags + NULL, // environment + NULL, // cur dir + &oStartInfo, + &oProcInfo)) + { + ::CloseHandle(oProcInfo.hThread); + + // Close child output/input handles so it doesn't hang + ::CloseHandle(hOutWrite); + ::CloseHandle(hErrWrite); + ::CloseHandle(hInRead); + + // Log output + LogOutput(hOutRead); + + // Wait for everything to finish + ::WaitForSingleObject(oProcInfo.hProcess, dwTimeout); + if (!::GetExitCodeProcess(oProcInfo.hProcess, &dwExitCode)) + dwExitCode = ERROR_SEM_IS_SET; + ::CloseHandle(hOutRead); + ::CloseHandle(hInWrite); + ::CloseHandle(oProcInfo.hProcess); + } + else + ExitOnLastError(hr, "Command failed to execute."); + + hr = HRESULT_FROM_WIN32(dwExitCode); + ExitOnFailure(hr, "Command line returned an error."); + +LExit: + return hr; +} + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/strutil.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/strutil.h new file mode 100644 index 0000000000..151003329e --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/strutil.h @@ -0,0 +1,165 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once +//------------------------------------------------------------------------------------------------- +// +// Header for string helper functions. +// +//------------------------------------------------------------------------------------------------- + +#ifdef __cplusplus +extern "C" { +#endif + +#define ReleaseStr(pwz) if (pwz) { StrFree(pwz); } +#define ReleaseNullStr(pwz) if (pwz) { StrFree(pwz); pwz = NULL; } +#define ReleaseBSTR(bstr) if (bstr) { ::SysFreeString(bstr); } +#define ReleaseNullBSTR(bstr) if (bstr) { ::SysFreeString(bstr); bstr = NULL; } + +HRESULT DAPI StrAlloc( + __inout LPWSTR* ppwz, + __in DWORD_PTR cch + ); +HRESULT DAPI StrAnsiAlloc( + __inout LPSTR* ppz, + __in DWORD_PTR cch + ); +HRESULT DAPI StrAllocString( + __inout LPWSTR* ppwz, + __in LPCWSTR wzSource, + __in DWORD_PTR cchSource + ); +HRESULT DAPI StrAnsiAllocString( + __inout LPSTR* ppsz, + __in LPCWSTR wzSource, + __in DWORD_PTR cchSource, + __in UINT uiCodepage + ); +HRESULT DAPI StrAllocStringAnsi( + __inout LPWSTR* ppwz, + __in LPCSTR szSource, + __in DWORD_PTR cchSource, + __in UINT uiCodepage + ); +HRESULT DAPI StrAllocPrefix( + __inout LPWSTR* ppwz, + __in LPCWSTR wzPrefix, + __in DWORD_PTR cchPrefix + ); +HRESULT DAPI StrAllocConcat( + __inout LPWSTR* ppwz, + __in LPCWSTR wzSource, + __in DWORD_PTR cchSource + ); +HRESULT __cdecl StrAllocFormatted( + __inout LPWSTR* ppwz, + __in LPCWSTR wzFormat, + ... + ); +HRESULT __cdecl StrAnsiAllocFormatted( + __inout LPSTR* ppsz, + __in LPCSTR szFormat, + ... + ); +HRESULT DAPI StrAllocFormattedArgs( + __inout LPWSTR* ppwz, + __in LPCWSTR wzFormat, + __in va_list args + ); +HRESULT DAPI StrAnsiAllocFormattedArgs( + __inout LPSTR* ppsz, + __in LPCSTR szFormat, + __in va_list args + ); + +HRESULT DAPI StrMaxLength( + __in LPVOID p, + __out DWORD_PTR* pcch + ); +HRESULT DAPI StrSize( + __in LPVOID p, + __out DWORD_PTR* pcb + ); + +HRESULT DAPI StrFree( + __in LPVOID p + ); + +HRESULT DAPI StrCurrentTime( + __inout LPWSTR* ppwz, + __in BOOL fGMT + ); +HRESULT DAPI StrCurrentDateTime( + __inout LPWSTR* ppwz, + __in BOOL fGMT + ); + +HRESULT DAPI StrHexEncode( + __in_ecount(cbSource) const BYTE* pbSource, + __in DWORD_PTR cbSource, + __out_ecount(cchDest) LPWSTR wzDest, + __in DWORD_PTR cchDest + ); +HRESULT DAPI StrHexDecode( + __in LPCWSTR wzSource, + __out_bcount(cbDest) BYTE* pbDest, + __in DWORD_PTR cbDest + ); + +HRESULT DAPI StrAllocBase85Encode( + __in_bcount(cbSource) const BYTE* pbSource, + __in DWORD_PTR cbSource, + __inout LPWSTR* pwzDest + ); +HRESULT DAPI StrAllocBase85Decode( + __in LPCWSTR wzSource, + __out BYTE** hbDest, + __out DWORD_PTR* pcbDest + ); + +HRESULT DAPI MultiSzLen( + __in LPCWSTR pwzMultiSz, + __out DWORD_PTR* pcch + ); +HRESULT DAPI MultiSzPrepend( + __inout LPWSTR* ppwzMultiSz, + __inout_opt DWORD_PTR *pcchMultiSz, + __in LPCWSTR pwzInsert + ); +HRESULT DAPI MultiSzFindSubstring( + __in LPCWSTR pwzMultiSz, + __in LPCWSTR pwzSubstring, + __out_opt DWORD_PTR* pdwIndex, + __out_opt LPCWSTR* ppwzFoundIn + ); +HRESULT DAPI MultiSzFindString( + __in LPCWSTR pwzMultiSz, + __in LPCWSTR pwzString, + __out DWORD_PTR* pdwIndex, + __out LPCWSTR* ppwzFound + ); +HRESULT DAPI MultiSzRemoveString( + __inout LPWSTR* ppwzMultiSz, + __in DWORD_PTR dwIndex + ); +HRESULT DAPI MultiSzInsertString( + __inout LPWSTR* ppwzMultiSz, + __inout_opt DWORD_PTR *pcchMultiSz, + __in DWORD_PTR dwIndex, + __in LPCWSTR pwzInsert + ); +HRESULT DAPI MultiSzReplaceString( + __inout LPWSTR* ppwzMultiSz, + __in DWORD_PTR dwIndex, + __in LPCWSTR pwzString + ); + +LPCWSTR wcsistr( + IN LPCWSTR wzString, + IN LPCWSTR wzCharSet + ); + +#ifdef __cplusplus +} +#endif diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcalog.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcalog.cpp new file mode 100644 index 0000000000..b162bd6152 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcalog.cpp @@ -0,0 +1,150 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +//------------------------------------------------------------------------------------------------- +// +// Windows Installer XML CustomAction utility library logging functions +// +//------------------------------------------------------------------------------------------------- + +#include "precomp.h" + + +/******************************************************************** + IsVerboseLogging() - internal helper function to detect if doing + verbose logging + +********************************************************************/ +static BOOL IsVerboseLogging() +{ + static int iVerbose = -1; + + if (0 > iVerbose) + { + iVerbose = WcaIsPropertySet("LOGVERBOSE"); + if (0 == iVerbose) // if the property wasn't set, check the registry to see if the logging policy was turned on + { + HKEY hkey = NULL; + WCHAR rgwc[16] = { 0 }; + DWORD cb = sizeof(rgwc); + if (ERROR_SUCCESS == ::RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Policies\\Microsoft\\Windows\\Installer", 0, KEY_QUERY_VALUE, &hkey)) + { + if (ERROR_SUCCESS == ::RegQueryValueExW(hkey, L"Logging", 0, NULL, reinterpret_cast(rgwc), &cb)) + { + for (LPCWSTR pwc = rgwc; (cb / sizeof(WCHAR)) > static_cast(pwc - rgwc) && *pwc; pwc++) + { + if (L'v' == *pwc || L'V' == *pwc) + { + iVerbose = 1; + break; + } + } + } + + ::RegCloseKey(hkey); + } + } + } + + Assert(iVerbose >= 0); + return (BOOL)iVerbose; +} + + +/******************************************************************** + WcaLog() - outputs trace and log info + +*******************************************************************/ +extern "C" void WcaLog( + __in LOGLEVEL llv, + __in const char* fmt, ... + ) +{ + static char szFmt[LOG_BUFFER]; + static char szBuf[LOG_BUFFER]; + static bool fInLogPrint = false; + + // prevent re-entrant logprints. (recursion issues between assert/logging code) + if (fInLogPrint) + return; + fInLogPrint = true; + + if (LOGMSG_STANDARD == llv || + (LOGMSG_VERBOSE == llv && IsVerboseLogging()) +#ifdef DEBUG + || LOGMSG_TRACEONLY == llv +#endif + ) + { + va_list args; + va_start(args, fmt); + + LPCSTR szLogName = WcaGetLogName(); + if (szLogName[0] != 0) + StringCchPrintfA(szFmt, countof(szFmt), "%s: %s", szLogName, fmt); + else + StringCchCopyA(szFmt, countof(szFmt), fmt); + + StringCchVPrintfA(szBuf, countof(szBuf), szFmt, args); + va_end(args); + +#ifdef DEBUG + // always write to the log in debug +#else + if (llv == LOGMSG_STANDARD || (llv == LOGMSG_VERBOSE && IsVerboseLogging())) +#endif + { + PMSIHANDLE hrec = MsiCreateRecord(1); + + ::MsiRecordSetStringA(hrec, 0, szBuf); + // TODO: Recursion on failure. May not be safe to assert from here. + WcaProcessMessage(INSTALLMESSAGE_INFO, hrec); + } + +#if DEBUG + StringCchCatA(szBuf, countof(szBuf), "\n"); + OutputDebugStringA(szBuf); +#endif + } + + fInLogPrint = false; + return; +} + + +/******************************************************************** + WcaDisplayAssert() - called before Assert() dialog shows + + NOTE: writes the assert string to the MSI log +********************************************************************/ +extern "C" BOOL WcaDisplayAssert( + __in LPCSTR sz + ) +{ + WcaLog(LOGMSG_STANDARD, "Debug Assert Message: %s", sz); + return TRUE; +} + + +/******************************************************************** + WcaLogError() - called before ExitOnXXX() macro exists the function + + NOTE: writes the hresult and error string to the MSI log +********************************************************************/ +extern "C" void WcaLogError( + __in HRESULT hr, + __in LPCSTR szMessage, + ... + ) +{ + char szBuffer[LOG_BUFFER]; + va_list dots; + + va_start(dots, szMessage); + StringCchVPrintfA(szBuffer, countof(szBuffer), szMessage, dots); + va_end(dots); + + // log the message if using Wca common layer + if (WcaIsInitialized()) + WcaLog(LOGMSG_STANDARD, "Error 0x%x: %s", hr, szBuffer); +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcascript.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcascript.cpp new file mode 100644 index 0000000000..b0a55946f9 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcascript.cpp @@ -0,0 +1,447 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +//------------------------------------------------------------------------------------------------- +// +// Windows Installer XML CustomAction utility library CaScript functions +// +//------------------------------------------------------------------------------------------------- + +#include "precomp.h" + + +static HRESULT CaScriptFileName( + __in WCA_ACTION action, + __in WCA_CASCRIPT script, + __in BOOL fImpersonated, + __in LPCWSTR wzScriptKey, + __out LPWSTR* pwzScriptName + ); + + +/******************************************************************** + WcaCaScriptCreateKey() - creates a unique script key for this + CustomAction. + +********************************************************************/ +extern "C" HRESULT WIXAPI WcaCaScriptCreateKey( + __out LPWSTR* ppwzScriptKey + ) +{ + AssertSz(WcaIsInitialized(), "WcaInitialize() should have been called before calling this function."); + HRESULT hr = S_OK; + + hr = StrAllocStringAnsi(ppwzScriptKey, WcaGetLogName(), 0, CP_ACP); + ExitOnFailure(hr, "Failed to create script key."); + +LExit: + return hr; +} + + +/******************************************************************** + WcaCaScriptCreate() - creates the appropriate script for this + CustomAction Script Key. + +********************************************************************/ +extern "C" HRESULT WIXAPI WcaCaScriptCreate( + __in WCA_ACTION action, + __in WCA_CASCRIPT script, + __in BOOL fImpersonated, + __in LPCWSTR wzScriptKey, + __in BOOL fAppend, + __in WCA_CASCRIPT_HANDLE* phScript + ) +{ + HRESULT hr = S_OK; + LPWSTR pwzScriptPath = NULL; + HANDLE hScriptFile = INVALID_HANDLE_VALUE; + + hr = CaScriptFileName(action, script, fImpersonated, wzScriptKey, &pwzScriptPath); + ExitOnFailure(hr, "Failed to calculate script file name."); + + hScriptFile = ::CreateFileW(pwzScriptPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, fAppend ? OPEN_ALWAYS : CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (INVALID_HANDLE_VALUE == hScriptFile) + { + ExitWithLastError1(hr, "Failed to open CaScript: %S", pwzScriptPath); + } + + if (fAppend && INVALID_SET_FILE_POINTER == ::SetFilePointer(hScriptFile, 0, NULL, FILE_END)) + { + ExitWithLastError(hr, "Failed to seek to end of file."); + } + + *phScript = reinterpret_cast(MemAlloc(sizeof(WCA_CASCRIPT_STRUCT), TRUE)); + ExitOnNull(*phScript, hr, E_OUTOFMEMORY, "Failed to allocate space for cascript handle."); + + (*phScript)->pwzScriptPath = pwzScriptPath; + pwzScriptPath = NULL; + (*phScript)->hScriptFile = hScriptFile; + hScriptFile = INVALID_HANDLE_VALUE; + +LExit: + if (INVALID_HANDLE_VALUE != hScriptFile) + { + ::CloseHandle(hScriptFile); + } + + ReleaseStr(pwzScriptPath); + return hr; +} + + +/******************************************************************** + WcaCaScriptOpen() - opens the appropriate script for this CustomAction + Script Key. + +********************************************************************/ +extern "C" HRESULT WIXAPI WcaCaScriptOpen( + __in WCA_ACTION action, + __in WCA_CASCRIPT script, + __in BOOL fImpersonated, + __in LPCWSTR wzScriptKey, + __in WCA_CASCRIPT_HANDLE* phScript + ) +{ + HRESULT hr = S_OK; + LPWSTR pwzScriptPath = NULL; + HANDLE hScriptFile = INVALID_HANDLE_VALUE; + + hr = CaScriptFileName(action, script, fImpersonated, wzScriptKey, &pwzScriptPath); + ExitOnFailure(hr, "Failed to calculate script file name."); + + hScriptFile = ::CreateFileW(pwzScriptPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (INVALID_HANDLE_VALUE == hScriptFile) + { + ExitWithLastError1(hr, "Failed to open CaScript: %S", pwzScriptPath); + } + + *phScript = reinterpret_cast(MemAlloc(sizeof(WCA_CASCRIPT_STRUCT), TRUE)); + ExitOnNull(*phScript, hr, E_OUTOFMEMORY, "Failed to allocate space for cascript handle."); + + (*phScript)->pwzScriptPath = pwzScriptPath; + pwzScriptPath = NULL; + (*phScript)->hScriptFile = hScriptFile; + hScriptFile = INVALID_HANDLE_VALUE; + +LExit: + if (INVALID_HANDLE_VALUE != hScriptFile) + { + ::CloseHandle(hScriptFile); + } + + ReleaseStr(pwzScriptPath); + return hr; +} + + +/******************************************************************** + WcaCaScriptClose() - closes an open script handle. + +********************************************************************/ +extern "C" void WIXAPI WcaCaScriptClose( + __in WCA_CASCRIPT_HANDLE hScript, + __in WCA_CASCRIPT_CLOSE closeOperation + ) +{ + if (hScript) + { + if (INVALID_HANDLE_VALUE != hScript->hScriptFile) + { + ::CloseHandle(hScript->hScriptFile); + } + + if (hScript->pwzScriptPath) + { + if (WCA_CASCRIPT_CLOSE_DELETE == closeOperation) + { + ::DeleteFileW(hScript->pwzScriptPath); + } + + StrFree(hScript->pwzScriptPath); + } + + MemFree(hScript); + } +} + + +/******************************************************************** + WcaCaScriptReadAsCustomActionData() - read the ca script into a format + that is useable by other CA data + functions. + +********************************************************************/ +extern "C" HRESULT WIXAPI WcaCaScriptReadAsCustomActionData( + __in WCA_CASCRIPT_HANDLE hScript, + __out LPWSTR* ppwzCustomActionData + ) +{ + HRESULT hr = S_OK; + LARGE_INTEGER liScriptSize = { 0 }; + BYTE* pbData = NULL; + DWORD cbData = 0; + + if (!::GetFileSizeEx(hScript->hScriptFile, &liScriptSize)) + { + ExitWithLastError(hr, "Failed to get size of ca script file."); + } + + if (0 != liScriptSize.HighPart || 0 != (liScriptSize.LowPart % sizeof(WCHAR))) + { + hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + ExitOnFailure(hr, "Invalid data read from ca script."); + } + + cbData = liScriptSize.LowPart; + pbData = static_cast(MemAlloc(cbData, TRUE)); + ExitOnNull(pbData, hr, E_OUTOFMEMORY, "Failed to allocate memory to read in ca script."); + + if (INVALID_SET_FILE_POINTER == ::SetFilePointer(hScript->hScriptFile, 0, NULL, FILE_BEGIN)) + { + ExitWithLastError(hr, "Failed to reset to beginning of ca script."); + } + + DWORD cbTotalRead = 0; + DWORD cbRead = 0; + do + { + if (!::ReadFile(hScript->hScriptFile, pbData + cbTotalRead, cbData - cbTotalRead, &cbRead, NULL)) + { + ExitWithLastError(hr, "Failed to read from ca script."); + } + + cbTotalRead += cbRead; + } while (cbRead && cbTotalRead < cbData); + + if (cbTotalRead != cbData) + { + hr = E_UNEXPECTED; + ExitOnFailure(hr, "Failed to completely read ca script."); + } + + // Add one to the allocated space because the data stored in the script is not + // null terminated. After copying the memory over, we'll ensure the string is + // null terminated. + DWORD cchData = cbData / sizeof(WCHAR) + 1; + hr = StrAlloc(ppwzCustomActionData, cchData); + ExitOnFailure(hr, "Failed to copy ca script."); + + CopyMemory(*ppwzCustomActionData, pbData, cbData); + (*ppwzCustomActionData)[cchData - 1] = L'\0'; + +LExit: + ReleaseMem(pbData); + return hr; +} + + +/******************************************************************** + WcaCaScriptWriteString() - writes a string to the ca script. + +********************************************************************/ +extern "C" HRESULT WIXAPI WcaCaScriptWriteString( + __in WCA_CASCRIPT_HANDLE hScript, + __in LPCWSTR wzValue + ) +{ + HRESULT hr = S_OK; + DWORD cbFile = 0; + DWORD cbWrite = 0; + DWORD cbTotalWritten = 0; + WCHAR delim[] = { MAGIC_MULTISZ_DELIM }; // magic char followed by NULL terminator + + cbFile = ::SetFilePointer(hScript->hScriptFile, 0, NULL, FILE_END); + if (INVALID_SET_FILE_POINTER == cbFile) + { + ExitWithLastError(hr, "Failed to move file pointer to end of file."); + } + + // If there is existing data in the file, append on the magic delimeter + // before adding our new data on the end of the file. + if (0 < cbFile) + { + cbWrite = sizeof(delim); + cbTotalWritten = 0; + while (cbTotalWritten < cbWrite) + { + DWORD cbWritten = 0; + if (!::WriteFile(hScript->hScriptFile, reinterpret_cast(delim) + cbTotalWritten, cbWrite - cbTotalWritten, &cbWritten, NULL)) + { + ExitWithLastError(hr, "Failed to write data to ca script."); + } + + cbTotalWritten += cbWritten; + } + } + + cbWrite = lstrlenW(wzValue) * sizeof(WCHAR); + cbTotalWritten = 0; + while (cbTotalWritten < cbWrite) + { + DWORD cbWritten = 0; + if (!::WriteFile(hScript->hScriptFile, reinterpret_cast(wzValue) + cbTotalWritten, cbWrite - cbTotalWritten, &cbWritten, NULL)) + { + ExitWithLastError(hr, "Failed to write data to ca script."); + } + + cbTotalWritten += cbWritten; + } + +LExit: + return hr; +} + + +/******************************************************************** + WcaCaScriptWriteNumber() - writes a number to the ca script. + +********************************************************************/ +extern "C" HRESULT WIXAPI WcaCaScriptWriteNumber( + __in WCA_CASCRIPT_HANDLE hScript, + __in DWORD dwValue + ) +{ + HRESULT hr = S_OK; + WCHAR wzBuffer[13] = { 0 }; + + hr = ::StringCchPrintfW(wzBuffer, countof(wzBuffer), L"%u", dwValue); + ExitOnFailure(hr, "Failed to convert number into string."); + + hr = WcaCaScriptWriteString(hScript, wzBuffer); + ExitOnFailure(hr, "Failed to write number to script."); + +LExit: + return hr; +} + + +/******************************************************************** + WcaCaScriptFlush() - best effort function to get script written to + disk. + +********************************************************************/ +extern "C" void WIXAPI WcaCaScriptFlush( + __in WCA_CASCRIPT_HANDLE hScript + ) +{ + ::FlushFileBuffers(hScript->hScriptFile); +} + + +/******************************************************************** + WcaCaScriptCleanup() - best effort clean-up of any cascripts left + over from this install/uninstall. + +********************************************************************/ +extern "C" void WIXAPI WcaCaScriptCleanup( + __in LPCWSTR wzProductCode, + __in BOOL fImpersonated + ) +{ + HRESULT hr = S_OK; + WCHAR wzTempPath[MAX_PATH]; + LPWSTR pwzWildCardPath = NULL; + WIN32_FIND_DATAW fd = { 0 }; + HANDLE hff = INVALID_HANDLE_VALUE; + LPWSTR pwzDeletePath = NULL; + + if (fImpersonated) + { + if (!::GetTempPathW(countof(wzTempPath), wzTempPath)) + { + ExitWithLastError(hr, "Failed to get temp path."); + } + } + else + { + if (!::GetWindowsDirectoryW(wzTempPath, countof(wzTempPath))) + { + ExitWithLastError(hr, "Failed to get windows path."); + } + + hr = ::StringCchCatW(wzTempPath, countof(wzTempPath), L"\\Installer\\"); + ExitOnFailure(hr, "Failed to concat Installer directory on windows path string."); + } + + hr = StrAllocFormatted(&pwzWildCardPath, L"%swix%s.*.???", wzTempPath, wzProductCode); + ExitOnFailure(hr, "Failed to allocate wildcard path to ca scripts."); + + hff = ::FindFirstFileW(pwzWildCardPath, &fd); + if (INVALID_HANDLE_VALUE == hff) + { + ExitWithLastError1(hr, "Failed to find files with pattern: %S", pwzWildCardPath); + } + + do + { + hr = StrAllocFormatted(&pwzDeletePath, L"%s%s", wzTempPath, fd.cFileName); + if (SUCCEEDED(hr)) + { + if (!::DeleteFileW(pwzDeletePath)) + { + DWORD er = ::GetLastError(); + WcaLog(LOGMSG_VERBOSE, "Failed to clean up CAScript file: %S, er: %d", fd.cFileName, er); + } + } + else + { + WcaLog(LOGMSG_VERBOSE, "Failed to allocate path to clean up CAScript file: %S, hr: 0x%x", fd.cFileName, hr); + } + } while(::FindNextFileW(hff, &fd)); + +LExit: + if (INVALID_HANDLE_VALUE == hff) + { + ::FindClose(hff); + } + + ReleaseStr(pwzDeletePath); + ReleaseStr(pwzWildCardPath); + return; +} + + +static HRESULT CaScriptFileName( + __in WCA_ACTION action, + __in WCA_CASCRIPT script, + __in BOOL fImpersonated, + __in LPCWSTR wzScriptKey, + __out LPWSTR* ppwzScriptName + ) +{ + HRESULT hr = S_OK; + WCHAR wzTempPath[MAX_PATH]; + LPWSTR pwzProductCode = NULL; + WCHAR chInstallOrUninstall = action == WCA_ACTION_INSTALL ? L'i' : L'u'; + WCHAR chScheduledOrRollback = script == WCA_CASCRIPT_SCHEDULED ? L's' : L'r'; + WCHAR chUserOrMachine = fImpersonated ? L'u' : L'm'; + + if (fImpersonated) + { + if (!::GetTempPathW(countof(wzTempPath), wzTempPath)) + { + ExitWithLastError(hr, "Failed to get temp path."); + } + } + else + { + if (!::GetWindowsDirectoryW(wzTempPath, countof(wzTempPath))) + { + ExitWithLastError(hr, "Failed to get windows path."); + } + + hr = ::StringCchCatW(wzTempPath, countof(wzTempPath), L"\\Installer\\"); + ExitOnFailure(hr, "Failed to concat Installer directory on windows path string."); + } + + hr = WcaGetProperty(L"ProductCode", &pwzProductCode); + ExitOnFailure(hr, "Failed to get ProductCode."); + + hr = StrAllocFormatted(ppwzScriptName, L"%swix%s.%s.%c%c%c", wzTempPath, pwzProductCode, wzScriptKey, chScheduledOrRollback, chUserOrMachine, chInstallOrUninstall); + ExitOnFailure(hr, "Failed to allocate path to ca script."); + +LExit: + ReleaseStr(pwzProductCode); + return hr; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcautil.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcautil.cpp new file mode 100644 index 0000000000..5f7bbda74d --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcautil.cpp @@ -0,0 +1,201 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +//------------------------------------------------------------------------------------------------- +// +// Windows Installer XML CustomAction utility library. +// +//------------------------------------------------------------------------------------------------- + +#include "precomp.h" + +// globals +HMODULE g_hInstCADLL; + +// statics +static BOOL s_fInitialized; +static MSIHANDLE s_hInstall; +static MSIHANDLE s_hDatabase; +static char s_szCustomActionLogName[32]; +static UINT s_iRetVal; + + +/******************************************************************** + WcaGlobalInitialize() - initializes the Wca library, should be + called once per custom action Dll during + DllMain on DLL_PROCESS_ATTACH + +********************************************************************/ +extern "C" void WcaGlobalInitialize( + __in HINSTANCE hInst + ) +{ + g_hInstCADLL = hInst; + MemInitialize(); + + AssertSetModule(g_hInstCADLL); + AssertSetDisplayFunction(WcaDisplayAssert); +} + + +/******************************************************************** + WcaGlobalFinalize() - finalizes the Wca library, should be the + called once per custom action Dll during + DllMain on DLL_PROCESS_DETACH + +********************************************************************/ +extern "C" void WcaGlobalFinalize() +{ +#ifdef DEBUG + if (WcaIsInitialized()) + { + CHAR szBuf[2048]; + StringCchPrintfA(szBuf, countof(szBuf), "CustomAction %s called WcaInitialize() but not WcaTerminate()", WcaGetLogName()); + + AssertSz(FALSE, szBuf); + } +#endif + MemUninitialize(); + g_hInstCADLL = NULL; +} + + +/******************************************************************** + WcaInitialize() - initializes the Wca framework, should be the first + thing called by all CustomActions + +********************************************************************/ +extern "C" HRESULT WcaInitialize( + __in MSIHANDLE hInstall, + __in const char* szCustomActionLogName + ) +{ + // these statics should be called once per CustomAction invocation. + // Darwin does doesn't preserve DLL state across CustomAction calls so + // these should always be initialized to NULL. If that behavior changes + // we would need to do a careful review of all of our module/global data. + AssertSz(!s_fInitialized, "WcaInitialize() should only be called once per CustomAction"); + Assert(NULL == s_hInstall); + Assert(NULL == s_hDatabase); + Assert(0 == *s_szCustomActionLogName); + + HRESULT hr = S_OK; + + s_fInitialized = TRUE; + s_iRetVal = ERROR_SUCCESS; // assume all will go well + + s_hInstall = hInstall; + s_hDatabase = ::MsiGetActiveDatabase(s_hInstall); // may return null if deferred CustomAction + + hr = ::StringCchCopyA(s_szCustomActionLogName, countof(s_szCustomActionLogName), szCustomActionLogName); + ExitOnFailure1(hr, "Failed to copy CustomAction log name: %s", szCustomActionLogName); + + Assert(s_hInstall); +LExit: + if (FAILED(hr)) + { + if (s_hDatabase) + { + ::MsiCloseHandle(s_hDatabase); + s_hDatabase = NULL; + } + + s_hInstall = NULL; + s_fInitialized = FALSE; + } + + return hr; +} + + +/******************************************************************** + WcaFinalize() - cleans up after the Wca framework, should be the last + thing called by all CustomActions + +********************************************************************/ +extern "C" UINT WcaFinalize( + __in UINT iReturnValue + ) +{ + // clean up after our initialization + if (s_hDatabase) + { + ::MsiCloseHandle(s_hDatabase); + s_hDatabase = NULL; + } + + s_hInstall = NULL; + s_fInitialized = FALSE; + + // if no error occurred during the processing of the CusotmAction return the passed in return value + // otherwise return the previous failure + return (ERROR_SUCCESS == s_iRetVal) ? iReturnValue : s_iRetVal; +} + + +/******************************************************************** + WcaIsInitialized() - determines if WcaInitialize() has been called + +********************************************************************/ +extern "C" BOOL WcaIsInitialized() +{ + return s_fInitialized; +} + + +/******************************************************************** + WcaGetInstallHandle() - gets the handle to the active install session + +********************************************************************/ +extern "C" MSIHANDLE WcaGetInstallHandle() +{ + AssertSz(s_hInstall, "WcaInitialize() should be called before attempting to access the install handle."); + return s_hInstall; +} + + +/******************************************************************** + WcaGetDatabaseHandle() - gets the handle to the active database + + NOTE: this function can only be used in immediate CustomActions. + Deferred CustomActions do not have access to the active + database. +********************************************************************/ +extern "C" MSIHANDLE WcaGetDatabaseHandle() +{ + AssertSz(s_hDatabase, "WcaInitialize() should be called before attempting to access the install handle. Also note that deferred CustomActions do not have access to the active database."); + return s_hDatabase; +} + + +/******************************************************************** + WcaGetLogName() - gets the name of the CustomAction used in logging + +********************************************************************/ +extern "C" const char* WcaGetLogName() +{ + return s_szCustomActionLogName; +} + + +/******************************************************************** + WcaSetReturnValue() - sets the value to return from the CustomAction + +********************************************************************/ +extern "C" void WcaSetReturnValue( + __in UINT iReturnValue + ) +{ + s_iRetVal = iReturnValue; +} + + +/******************************************************************** + WcaCancelDetected() - determines if the user has canceled yet + + NOTE: returns true when WcaSetReturnValue() is set to ERROR_INSTALL_USEREXIT +********************************************************************/ +extern "C" BOOL WcaCancelDetected() +{ + return ERROR_INSTALL_USEREXIT == s_iRetVal; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcautil.h b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcautil.h new file mode 100644 index 0000000000..8265e27735 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcautil.h @@ -0,0 +1,344 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +#pragma once +//------------------------------------------------------------------------------------------------- +// +// Windows Installer XML CustomAction utility library. +// +//------------------------------------------------------------------------------------------------- + +#ifdef __cplusplus +extern "C" { +#endif + +#define WIXAPI __stdcall +#define ExitTrace WcaLogError +#define ExitTrace1 WcaLogError +#define ExitTrace2 WcaLogError +#define ExitTrace3 WcaLogError + +#include "dutil.h" + +#define MessageExitOnLastError(x, e, s) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { ExitTrace(x, "%s", s); WcaErrorMessage(e, x, MB_OK, 0); goto LExit; } } +#define MessageExitOnLastError1(x, e, f, s) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { ExitTrace1(x, f, s); WcaErrorMessage(e, x, MB_OK, 1, s); goto LExit; } } + +#define MessageExitOnFailure(x, e, s) if (FAILED(x)) { ExitTrace(x, "%s", s); WcaErrorMessage(e, x, INSTALLMESSAGE_ERROR | MB_OK, 0); goto LExit; } +#define MessageExitOnFailure1(x, e, f, s) if (FAILED(x)) { ExitTrace1(x, f, s); WcaErrorMessage(e, x, INSTALLMESSAGE_ERROR | MB_OK, 1, s); goto LExit; } +#define MessageExitOnFailure2(x, e, f, s, t) if (FAILED(x)) { ExitTrace2(x, f, s, t); WcaErrorMessage(e, x, INSTALLMESSAGE_ERROR | MB_OK, 2, s, t); goto LExit; } +#define MessageExitOnFailure3(x, e, f, s, t, u) if (FAILED(x)) { ExitTrace2(x, f, s, t, u); WcaErrorMessage(e, x, INSTALLMESSAGE_ERROR | MB_OK, 3, s, t, u); goto LExit; } + +#define MessageExitOnNullWithLastError(p, x, e, s) if (NULL == p) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTrace(x, "%s", s); WcaErrorMessage(e, x, MB_OK, 0); goto LExit; } +#define MessageExitOnNullWithLastError1(p, x, e, f, s) if (NULL == p) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTrace(x, f, s); WcaErrorMessage(e, x, MB_OK, 1, s); goto LExit; } +#define MessageExitOnNullWithLastError2(p, x, e, f, s, t) if (NULL == p) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTrace(x, f, s, t); WcaErrorMessage(e, x, MB_OK, 2, s, t); goto LExit; } + +#define MAX_DARWIN_KEY 73 +#define MAX_DARWIN_COLUMN 255 + +// Generic action enum. +enum WCA_ACTION +{ + WCA_ACTION_NONE, + WCA_ACTION_INSTALL, + WCA_ACTION_UNINSTALL, +}; + +enum WCA_CASCRIPT +{ + WCA_CASCRIPT_SCHEDULED, + WCA_CASCRIPT_ROLLBACK, +}; + +enum WCA_CASCRIPT_CLOSE +{ + WCA_CASCRIPT_CLOSE_PRESERVE, + WCA_CASCRIPT_CLOSE_DELETE, +}; + +typedef struct WCA_CASCRIPT_STRUCT +{ + LPWSTR pwzScriptPath; + HANDLE hScriptFile; +} *WCA_CASCRIPT_HANDLE; + +void WIXAPI WcaGlobalInitialize( + __in HINSTANCE hInst + ); +void WIXAPI WcaGlobalFinalize(); + +HRESULT WIXAPI WcaInitialize( + __in MSIHANDLE hInstall, + __in const char* szCustomActionLogName + ); +UINT WIXAPI WcaFinalize( + __in UINT iReturnValue + ); +BOOL WIXAPI WcaIsInitialized(); + +MSIHANDLE WIXAPI WcaGetInstallHandle(); +MSIHANDLE WIXAPI WcaGetDatabaseHandle(); + +const char* WIXAPI WcaGetLogName(); + +void WIXAPI WcaSetReturnValue( + __in UINT iReturnValue + ); +BOOL WIXAPI WcaCancelDetected(); + +const int LOG_BUFFER = 2048; +enum LOGLEVEL +{ + LOGMSG_TRACEONLY, // Never written to the log file (except in DEBUG builds) + LOGMSG_VERBOSE, // Written to log when LOGVERBOSE + LOGMSG_STANDARD // Written to log whenever informational logging is enabled +}; + +void __cdecl WcaLog( + __in LOGLEVEL llv, + __in const char* fmt, ... + ); +BOOL WIXAPI WcaDisplayAssert( + __in LPCSTR sz + ); +void __cdecl WcaLogError( + __in HRESULT hr, + __in LPCSTR szMessage, + ... + ); + + +UINT WIXAPI WcaProcessMessage( + __in INSTALLMESSAGE eMessageType, + __in MSIHANDLE hRecord + ); +UINT __cdecl WcaErrorMessage( + __in int iError, + __in HRESULT hrError, + __in UINT uiType, + __in DWORD cArgs, + ... + ); +HRESULT WIXAPI WcaProgressMessage( + __in UINT uiCost, + __in BOOL fExtendProgressBar + ); + +BOOL WIXAPI WcaIsInstalling( + __in INSTALLSTATE isInstalled, + __in INSTALLSTATE isAction + ); +BOOL WIXAPI WcaIsReInstalling( + __in INSTALLSTATE isInstalled, + __in INSTALLSTATE isAction + ); +BOOL WIXAPI WcaIsUninstalling( + __in INSTALLSTATE isInstalled, + __in INSTALLSTATE isAction + ); + +HRESULT WIXAPI WcaSetComponentState( + __in LPCWSTR wzComponent, + __in INSTALLSTATE isState + ); + +HRESULT WIXAPI WcaTableExists( + __in LPCWSTR wzTable + ); + +HRESULT WIXAPI WcaOpenView( + __in LPCWSTR wzSql, + __out MSIHANDLE* phView + ); +HRESULT WIXAPI WcaExecuteView( + __in MSIHANDLE hView, + __in MSIHANDLE hRec + ); +HRESULT WIXAPI WcaOpenExecuteView( + __in LPCWSTR wzSql, + __out MSIHANDLE* phView + ); +HRESULT WIXAPI WcaFetchRecord( + __in MSIHANDLE hView, + __out MSIHANDLE* phRec + ); +HRESULT WIXAPI WcaFetchSingleRecord( + __in MSIHANDLE hView, + __out MSIHANDLE* phRec + ); + +HRESULT WIXAPI WcaGetProperty( + __in LPCWSTR wzProperty, + __inout LPWSTR* ppwzData + ); +HRESULT WIXAPI WcaGetFormattedProperty( + __in LPCWSTR wzProperty, + __out LPWSTR* ppwzData + ); +HRESULT WIXAPI WcaGetFormattedString( + __in LPCWSTR wzString, + __out LPWSTR* ppwzData + ); +HRESULT WIXAPI WcaGetIntProperty( + __in LPCWSTR wzProperty, + __inout int* piData + ); +HRESULT WIXAPI WcaGetTargetPath( + __in LPCWSTR wzFolder, + __out LPWSTR* ppwzData + ); +HRESULT WIXAPI WcaSetProperty( + __in LPCWSTR wzPropertyName, + __in LPCWSTR wzPropertyValue + ); +HRESULT WIXAPI WcaSetIntProperty( + __in LPCWSTR wzPropertyName, + __in int nPropertyValue + ); +BOOL WIXAPI WcaIsPropertySet( + __in LPCSTR szProperty + ); + +HRESULT WIXAPI WcaGetRecordInteger( + __in MSIHANDLE hRec, + __in UINT uiField, + __inout int* piData + ); +HRESULT WIXAPI WcaGetRecordString( + __in MSIHANDLE hRec, + __in UINT uiField, + __inout LPWSTR* ppwzData + ); +HRESULT WIXAPI WcaGetRecordFormattedString( + __in MSIHANDLE hRec, + __in UINT uiField, + __inout LPWSTR* ppwzData + ); + +HRESULT WIXAPI WcaAllocStream(__inout BYTE** ppbData, __in DWORD cbData); +HRESULT WIXAPI WcaFreeStream(__in BYTE* pbData); + +HRESULT WIXAPI WcaGetRecordStream( + __in MSIHANDLE hRecBinary, + __in UINT uiField, + __inout BYTE** ppbData, + __inout DWORD* pcbData + ); +HRESULT WIXAPI WcaSetRecordString( + __in MSIHANDLE hRec, + __in UINT uiField, + __in LPCWSTR wzData + ); +HRESULT WIXAPI WcaSetRecordInteger( + __in MSIHANDLE hRec, + __in UINT uiField, + __in int iValue + ); + +HRESULT WIXAPI WcaDoDeferredAction( + __in LPCWSTR wzAction, + __in LPCWSTR wzCustomActionData, + __in UINT uiCost + ); +DWORD WIXAPI WcaCountOfCustomActionDataRecords( + __in LPCWSTR wzData + ); +HRESULT WIXAPI WcaReadStringFromCaData( + __inout LPWSTR* ppwzCustomActionData, + __inout LPWSTR* ppwzString + ); +HRESULT WIXAPI WcaReadIntegerFromCaData( + __inout LPWSTR* ppwzCustomActionData, + __inout int* piResult + ); +HRESULT WIXAPI WcaReadStreamFromCaData( + __inout LPWSTR* ppwzCustomActionData, + __out BYTE** ppbData, + __out DWORD_PTR* pcbData + ); +HRESULT WIXAPI WcaWriteStringToCaData( + __in LPCWSTR wzString, + __inout LPWSTR* ppwzCustomActionData + ); +HRESULT WIXAPI WcaWriteIntegerToCaData( + __in int i, + __inout LPWSTR* ppwzCustomActionData + ); +HRESULT WIXAPI WcaWriteStreamToCaData( + __in_bcount(cbData) const BYTE* pbData, + __in DWORD cbData, + __inout LPWSTR* ppwzCustomActionData + ); + +HRESULT __cdecl WcaAddTempRecord( + __inout MSIHANDLE* phTableView, + __inout MSIHANDLE* phColumns, + __in LPCWSTR wzTable, + __in UINT uiUniquifyColumn, + __in UINT cColumns, + ... + ); + +HRESULT WIXAPI WcaDumpTable( + __in LPCWSTR wzTable + ); + + +HRESULT WIXAPI WcaCaScriptCreateKey( + __out LPWSTR* ppwzScriptKey + ); + +HRESULT WIXAPI WcaCaScriptCreate( + __in WCA_ACTION action, + __in WCA_CASCRIPT script, + __in BOOL fImpersonated, + __in LPCWSTR wzScriptKey, + __in BOOL fAppend, + __out WCA_CASCRIPT_HANDLE* phScript + ); + +HRESULT WIXAPI WcaCaScriptOpen( + __in WCA_ACTION action, + __in WCA_CASCRIPT script, + __in BOOL fImpersonated, + __in LPCWSTR wzScriptKey, + __out WCA_CASCRIPT_HANDLE* phScript + ); + +void WIXAPI WcaCaScriptClose( + __in WCA_CASCRIPT_HANDLE hScript, + __in WCA_CASCRIPT_CLOSE closeOperation + ); + +HRESULT WIXAPI WcaCaScriptReadAsCustomActionData( + __in WCA_CASCRIPT_HANDLE hScript, + __out LPWSTR* ppwzCustomActionData + ); + +HRESULT WIXAPI WcaCaScriptWriteString( + __in WCA_CASCRIPT_HANDLE hScript, + __in LPCWSTR wzValue + ); + +HRESULT WIXAPI WcaCaScriptWriteNumber( + __in WCA_CASCRIPT_HANDLE hScript, + __in DWORD dwValue + ); + +void WIXAPI WcaCaScriptFlush( + __in WCA_CASCRIPT_HANDLE hScript + ); + +void WIXAPI WcaCaScriptCleanup( + __in LPCWSTR wzProductCode, + __in BOOL fImpersonated + ); + + +HRESULT QuietExec( + __in LPWSTR wzCommand, + __in DWORD dwTimeout + ); + +#ifdef __cplusplus +} +#endif diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcawrap.cpp b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcawrap.cpp new file mode 100644 index 0000000000..490a5d6713 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/wcautil/wcawrap.cpp @@ -0,0 +1,1419 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +//------------------------------------------------------------------------------------------------- +// +// Windows Installer XML CustomAction utility library wrappers for MSI API +// +//------------------------------------------------------------------------------------------------- + +#include "precomp.h" + + +/******************************************************************** + WcaProcessMessage() - sends a message from the CustomAction + +********************************************************************/ +extern "C" UINT WcaProcessMessage( + __in INSTALLMESSAGE eMessageType, + __in MSIHANDLE hRecord + ) +{ + UINT er = ::MsiProcessMessage(WcaGetInstallHandle(), eMessageType, hRecord); + if (ERROR_INSTALL_USEREXIT == er || IDCANCEL == er) + WcaSetReturnValue(ERROR_INSTALL_USEREXIT); + + return er; +} + + +/******************************************************************** + WcaErrorMessage() - sends an error message from the CustomAction using + the Error table + + NOTE: Any and all var_args (...) must be WCHAR* +********************************************************************/ +extern "C" UINT WcaErrorMessage( + __in int iError, + __in HRESULT hrError, + __in UINT uiType, + __in DWORD cArgs, + ... + ) +{ + UINT er; + MSIHANDLE hRec = NULL; + va_list args; + + uiType |= INSTALLMESSAGE_ERROR; // ensure error type is set + hRec = ::MsiCreateRecord(cArgs + 2); + if (!hRec) + { + er = ERROR_OUTOFMEMORY; + ExitOnFailure(HRESULT_FROM_WIN32(er), "failed to create record when sending error message"); + } + + er = ::MsiRecordSetInteger(hRec, 1, iError); + ExitOnFailure(HRESULT_FROM_WIN32(er), "failed to set error code into error message"); + + er = ::MsiRecordSetInteger(hRec, 2, hrError); + ExitOnFailure(HRESULT_FROM_WIN32(er), "failed to set hresult code into error message"); + + va_start(args, cArgs); + for (DWORD i = 0; i < cArgs; i++) + { + er = ::MsiRecordSetStringW(hRec, i + 3, va_arg(args, WCHAR*)); + ExitOnFailure(HRESULT_FROM_WIN32(er), "failed to set string string into error message"); + } + va_end(args); + + er = WcaProcessMessage(static_cast(uiType), hRec); +LExit: + if (hRec) + ::MsiCloseHandle(hRec); + + return er; +} + + +/******************************************************************** + WcaProgressMessage() - extends the progress bar or sends a progress + update from the CustomAction + +********************************************************************/ +extern "C" HRESULT WcaProgressMessage( + __in UINT uiCost, + __in BOOL fExtendProgressBar + ) +{ + static BOOL fExplicitProgressMessages = FALSE; + + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + MSIHANDLE hRec = ::MsiCreateRecord(3); + + // if aren't extending the progress bar and we haven't switched into explicit message mode + if (!fExtendProgressBar && !fExplicitProgressMessages) + { + AssertSz(::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_SCHEDULED) || + ::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_COMMIT) || + ::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK), "can only send progress bar messages in a deferred CustomAction"); + + // tell Darwin to use explicit progress messages + ::MsiRecordSetInteger(hRec, 1, 1); + ::MsiRecordSetInteger(hRec, 2, 1); + ::MsiRecordSetInteger(hRec, 3, 0); + + er = WcaProcessMessage(INSTALLMESSAGE_PROGRESS, hRec); + if (0 == er || IDOK == er || IDYES == er) + hr = S_OK; + else if (IDABORT == er || IDCANCEL == er) + { + WcaSetReturnValue(ERROR_INSTALL_USEREXIT); // note that the user said exit + ExitFunction1(hr = S_FALSE); + } + else + hr = E_UNEXPECTED; + ExitOnFailure(hr, "failed to tell Darwin to use explicit progress messages"); + + fExplicitProgressMessages = TRUE; + } +#if DEBUG + else if (fExtendProgressBar) // if we are extending the progress bar, make sure we're not deferred + { + AssertSz(!::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_SCHEDULED), "cannot add ticks to progress bar length from deferred CustomAction"); + } +#endif + + // send the progress message + ::MsiRecordSetInteger(hRec, 1, (fExtendProgressBar) ? 3 : 2); + ::MsiRecordSetInteger(hRec, 2, uiCost); + ::MsiRecordSetInteger(hRec, 3, 0); + + er = WcaProcessMessage(INSTALLMESSAGE_PROGRESS, hRec); + if (0 == er || IDOK == er || IDYES == er) + { + hr = S_OK; + } + else if (IDABORT == er || IDCANCEL == er) + { + WcaSetReturnValue(ERROR_INSTALL_USEREXIT); // note that the user said exit + hr = S_FALSE; + } + else + hr = E_UNEXPECTED; + +LExit: + if (hRec) + ::MsiCloseHandle(hRec); + + return hr; +} + + +/******************************************************************** + WcaIsInstalling() - determines if a pair of installstates means install + +********************************************************************/ +extern "C" BOOL WcaIsInstalling( + __in INSTALLSTATE isInstalled, + __in INSTALLSTATE isAction + ) +{ + return (INSTALLSTATE_LOCAL == isAction || + INSTALLSTATE_SOURCE == isAction || + (INSTALLSTATE_DEFAULT == isAction && + (INSTALLSTATE_LOCAL == isInstalled || + INSTALLSTATE_SOURCE == isInstalled))); +} + +/******************************************************************** + WcaIsReInstalling() - determines if a pair of installstates means install + +********************************************************************/ +extern "C" BOOL WcaIsReInstalling( + __in INSTALLSTATE isInstalled, + __in INSTALLSTATE isAction + ) +{ + return ((INSTALLSTATE_LOCAL == isAction || + INSTALLSTATE_SOURCE == isAction || + INSTALLSTATE_DEFAULT == isAction) && + (INSTALLSTATE_LOCAL == isInstalled || + INSTALLSTATE_SOURCE == isInstalled)); +} + + +/******************************************************************** + WcaIsUninstalling() - determines if a pair of installstates means uninstall + +********************************************************************/ +extern "C" BOOL WcaIsUninstalling( + __in INSTALLSTATE isInstalled, + __in INSTALLSTATE isAction + ) +{ + return ((INSTALLSTATE_ABSENT == isAction || + INSTALLSTATE_REMOVED == isAction) && + (INSTALLSTATE_LOCAL == isInstalled || + INSTALLSTATE_SOURCE == isInstalled)); +} + + +/******************************************************************** + WcaSetComponentState() - sets the install state of a Component + +********************************************************************/ +extern "C" HRESULT WcaSetComponentState( + __in LPCWSTR wzComponent, + __in INSTALLSTATE isState + ) +{ + UINT er = ::MsiSetComponentStateW(WcaGetInstallHandle(), wzComponent, isState); + if (ERROR_INSTALL_USEREXIT == er) + WcaSetReturnValue(er); + + return HRESULT_FROM_WIN32(er); +} + + +/******************************************************************** + WcaTableExists() - determines if installing database contains a table + +********************************************************************/ +extern "C" HRESULT WcaTableExists( + __in LPCWSTR wzTable + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + +// NOTE: The following line of commented out code should work in a +// CustomAction but does not in Windows Installer v1.1 + // er = ::MsiDatabaseIsTablePersistentW(hDatabase, wzTable); + + // a "most elegant" workaround a Darwin v1.1 bug + PMSIHANDLE hRec; + er = ::MsiDatabaseGetPrimaryKeysW(WcaGetDatabaseHandle(), wzTable, &hRec); + + if (ERROR_SUCCESS == er) + hr = S_OK; + else if (ERROR_INVALID_TABLE == er) + hr = S_FALSE; + else + hr = E_FAIL; + Assert(SUCCEEDED(hr)); + + return hr; +} + + +/******************************************************************** + WcaOpenView() - opens a view on the installing database + +********************************************************************/ +extern "C" HRESULT WcaOpenView( + __in LPCWSTR wzSql, + __out MSIHANDLE* phView + ) +{ + if (!wzSql || !*wzSql|| !phView) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er = ::MsiDatabaseOpenViewW(WcaGetDatabaseHandle(), wzSql, phView); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "failed to open view on database with SQL: %S", wzSql); + +LExit: + return hr; +} + + +/******************************************************************** + WcaExecuteView() - executes a parameterized open view on the installing database + +********************************************************************/ +extern "C" HRESULT WcaExecuteView( + __in MSIHANDLE hView, + __in MSIHANDLE hRec + ) +{ + if (!hView) + return E_INVALIDARG; + AssertSz(hRec, "Use WcaOpenExecuteView() if you don't need to pass in a record"); + + HRESULT hr = S_OK; + UINT er = ::MsiViewExecute(hView, hRec); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to execute view"); + +LExit: + return hr; +} + + +/******************************************************************** + WcaOpenExecuteView() - opens and executes a view on the installing database + +********************************************************************/ +extern "C" HRESULT WcaOpenExecuteView( + __in LPCWSTR wzSql, + __out MSIHANDLE* phView + ) +{ + if (!wzSql || !*wzSql|| !phView) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er = ::MsiDatabaseOpenViewW(WcaGetDatabaseHandle(), wzSql, phView); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to open view on database"); + + er = ::MsiViewExecute(*phView, NULL); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to execute view"); + +LExit: + return hr; +} + + +/******************************************************************** + WcaFetchRecord() - gets the next record from a view on the installing database + +********************************************************************/ +extern "C" HRESULT WcaFetchRecord( + __in MSIHANDLE hView, + __out MSIHANDLE* phRec + ) +{ + if (!hView|| !phRec) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er = ::MsiViewFetch(hView, phRec); + hr = HRESULT_FROM_WIN32(er); + if (FAILED(hr) && E_NOMOREITEMS != hr) + ExitOnFailure(hr, "failed to fetch record from view"); + +LExit: + return hr; +} + + +/******************************************************************** + WcaFetchSingleRecord() - gets a single record from a view on the installing database + +********************************************************************/ +extern "C" HRESULT WcaFetchSingleRecord( + __in MSIHANDLE hView, + __out MSIHANDLE* phRec + ) +{ + if (!hView|| !phRec) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er = ::MsiViewFetch(hView, phRec); + if (ERROR_NO_MORE_ITEMS == er) + hr = S_FALSE; + else + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to fetch single record from view"); + +#ifdef DEBUG // only do this in debug to verify that a single record was returned + MSIHANDLE hRecTest; + er = ::MsiViewFetch(hView, &hRecTest); + AssertSz(ERROR_NO_MORE_ITEMS == er && NULL == hRecTest, "WcaSingleFetch() did not fetch a single record"); + ::MsiCloseHandle(hRecTest); +#endif + +LExit: + return hr; +} + + +/******************************************************************** + WcaGetProperty - gets a string property value from the active install + +********************************************************************/ +extern "C" HRESULT WcaGetProperty( + __in LPCWSTR wzProperty, + __inout LPWSTR* ppwzData + ) +{ + if (!wzProperty || !*wzProperty || !ppwzData) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + DWORD_PTR cch = 0; + + if (!*ppwzData) + { + er = ::MsiGetPropertyW(WcaGetInstallHandle(), wzProperty, L"", (DWORD *)&cch); + if (ERROR_MORE_DATA == er || ERROR_SUCCESS == er) + { + hr = StrAlloc(ppwzData, ++cch); + } + else + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "Failed to allocate string for Property '%S'", wzProperty); + } + else + { + hr = StrMaxLength(*ppwzData, &cch); + ExitOnFailure(hr, "Failed to get previous size of property data string."); + } + + er = ::MsiGetPropertyW(WcaGetInstallHandle(), wzProperty, *ppwzData, (DWORD *)&cch); + if (ERROR_MORE_DATA == er) + { + Assert(*ppwzData); + hr = StrAlloc(ppwzData, ++cch); + ExitOnFailure1(hr, "Failed to allocate string for Property '%S'", wzProperty); + + er = ::MsiGetPropertyW(WcaGetInstallHandle(), wzProperty, *ppwzData, (DWORD *)&cch); + } + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "Failed to get data for property '%S'", wzProperty); + +LExit: + return hr; +} + + +/******************************************************************** + WcaGetFormattedProperty - gets a formatted string property value from + the active install + +********************************************************************/ +extern "C" HRESULT WcaGetFormattedProperty( + __in LPCWSTR wzProperty, + __out LPWSTR* ppwzData + ) +{ + if (!wzProperty || !*wzProperty || !ppwzData) + return E_INVALIDARG; + + HRESULT hr = S_OK; + LPWSTR pwzPropertyValue = NULL; + + + hr = WcaGetProperty(wzProperty, &pwzPropertyValue); + ExitOnFailure1(hr, "failed to get %S", wzProperty); + + hr = WcaGetFormattedString(pwzPropertyValue, ppwzData); + ExitOnFailure2(hr, "failed to get formatted value for property: '%S' with value: '%S'", wzProperty, pwzPropertyValue); + +LExit: + ReleaseStr(pwzPropertyValue); + return hr; +} + + +/******************************************************************** + WcaGetFormattedString - gets a formatted string value from + the active install + +********************************************************************/ +extern "C" HRESULT WcaGetFormattedString( + __in LPCWSTR wzString, + __out LPWSTR* ppwzData + ) +{ + if (!wzString || !*wzString || !ppwzData) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + PMSIHANDLE hRecord = ::MsiCreateRecord(1); + DWORD_PTR cch = 0; + + er = ::MsiRecordSetStringW(hRecord, 0, wzString); + ExitOnFailure1(hr = HRESULT_FROM_WIN32(er), "Failed to set record field 0 with '%S'", wzString); + + if (!*ppwzData) + { + er = ::MsiFormatRecordW(WcaGetInstallHandle(), hRecord, L"", (DWORD *)&cch); + if (ERROR_MORE_DATA == er || ERROR_SUCCESS == er) + { + hr = StrAlloc(ppwzData, ++cch); + } + else + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "Failed to allocate string for formatted string: '%S'", wzString); + } + else + { + hr = StrMaxLength(*ppwzData, &cch); + ExitOnFailure(hr, "Failed to get previous size of property data string"); + } + + er = ::MsiFormatRecordW(WcaGetInstallHandle(), hRecord, *ppwzData, (DWORD *)&cch); + if (ERROR_MORE_DATA == er) + { + hr = StrAlloc(ppwzData, ++cch); + ExitOnFailure1(hr, "Failed to allocate string for formatted string: '%S'", wzString); + + er = ::MsiFormatRecordW(WcaGetInstallHandle(), hRecord, *ppwzData, (DWORD *)&cch); + } + ExitOnFailure1(hr = HRESULT_FROM_WIN32(er), "Failed to get formatted string: '%S'", wzString); + +LExit: + return hr; +} + + +/******************************************************************** + WcaGetIntProperty - gets an integer property value from the active install + +********************************************************************/ +extern "C" HRESULT WcaGetIntProperty( + __in LPCWSTR wzProperty, + __inout int* piData + ) +{ + if (!piData) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er; + + WCHAR wzValue[32]; + DWORD cch = countof(wzValue) - 1; + + er = ::MsiGetPropertyW(WcaGetInstallHandle(), wzProperty, wzValue, &cch); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "Failed to get data for property '%S'", wzProperty); + + *piData = wcstol(wzValue, NULL, 10); + +LExit: + return hr; +} + + +/******************************************************************** + WcaGetTargetPath - gets the target path for a specified folder + +********************************************************************/ +extern "C" HRESULT WcaGetTargetPath( + __in LPCWSTR wzFolder, + __out LPWSTR* ppwzData + ) +{ + if (!wzFolder || !*wzFolder || !ppwzData) + return E_INVALIDARG; + + HRESULT hr = S_OK; + + UINT er = ERROR_SUCCESS; + DWORD_PTR cch = 0; + + if (!*ppwzData) + { + er = ::MsiGetTargetPathW(WcaGetInstallHandle(), wzFolder, L"", (DWORD*)&cch); + if (ERROR_MORE_DATA == er || ERROR_SUCCESS == er) + { + cch++; //Add one for the null terminator + hr = StrAlloc(ppwzData, cch); + } + else + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "Failed to allocate string for target path of folder: '%S'", wzFolder); + } + else + { + hr = StrMaxLength(*ppwzData, &cch); + ExitOnFailure(hr, "Failed to get previous size of string"); + } + + er = ::MsiGetTargetPathW(WcaGetInstallHandle(), wzFolder, *ppwzData, (DWORD*)&cch); + if (ERROR_MORE_DATA == er) + { + cch++; + hr = StrAlloc(ppwzData, cch); + ExitOnFailure1(hr, "Failed to allocate string for target path of folder: '%S'", wzFolder); + + er = ::MsiGetTargetPathW(WcaGetInstallHandle(), wzFolder, *ppwzData, (DWORD*)&cch); + } + ExitOnFailure1(hr = HRESULT_FROM_WIN32(er), "Failed to get target path for folder '%S'", wzFolder); + +LExit: + return hr; +} + + +/******************************************************************** + WcaSetProperty - sets a string property value in the active install + +********************************************************************/ +extern "C" HRESULT WcaSetProperty( + __in LPCWSTR wzPropertyName, + __in LPCWSTR wzPropertyValue + ) +{ + if (!wzPropertyName || !*wzPropertyName || !wzPropertyValue) + return E_INVALIDARG; + + UINT er = ::MsiSetPropertyW(WcaGetInstallHandle(), wzPropertyName, wzPropertyValue); + HRESULT hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "failed to set property: %S", wzPropertyName); + +LExit: + return hr; +} + + +/******************************************************************** + WcaSetIntProperty - sets a integer property value in the active install + +********************************************************************/ +extern "C" HRESULT WcaSetIntProperty( + __in LPCWSTR wzPropertyName, + __in int nPropertyValue + ) +{ + if (!wzPropertyName || !*wzPropertyName) + return E_INVALIDARG; + + // 12 characters should be enough for a 32-bit int: 10 digits, 1 sign, 1 null + WCHAR wzPropertyValue[13]; + HRESULT hr = StringCchPrintfW(wzPropertyValue, countof(wzPropertyValue), L"%d", nPropertyValue); + ExitOnFailure1(hr, "failed to convert into string property value: %d", nPropertyValue); + + UINT er = ::MsiSetPropertyW(WcaGetInstallHandle(), wzPropertyName, wzPropertyValue); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "failed to set property: %S", wzPropertyName); + +LExit: + return hr; +} + + +/******************************************************************** + WcaIsPropertySet() - returns TRUE if property is set + +********************************************************************/ +extern "C" BOOL WcaIsPropertySet( + __in LPCSTR szProperty + ) +{ + DWORD cchProperty = 0; + UINT er = ::MsiGetPropertyA(WcaGetInstallHandle(), szProperty, "", &cchProperty); + AssertSz(ERROR_INVALID_PARAMETER != er && ERROR_INVALID_HANDLE != er, "Unexpected return value from ::MsiGetProperty()"); + + return 0 < cchProperty; // property is set if the length is greater than zero +} + + +/******************************************************************** + WcaGetRecordInteger() - gets an integer field out of a record + + NOTE: returns S_FALSE if the field was null +********************************************************************/ +extern "C" HRESULT WcaGetRecordInteger( + __in MSIHANDLE hRec, + __in UINT uiField, + __inout int* piData + ) +{ + if (!hRec || !piData) + return E_INVALIDARG; + + HRESULT hr = S_OK; + *piData = ::MsiRecordGetInteger(hRec, uiField); + if (MSI_NULL_INTEGER == *piData) + hr = S_FALSE; + +//LExit: + return hr; +} + + +/******************************************************************** + WcaGetRecordString() - gets a string field out of a record + +********************************************************************/ +extern "C" HRESULT WcaGetRecordString( + __in MSIHANDLE hRec, + __in UINT uiField, + __inout LPWSTR* ppwzData + ) +{ + if (!hRec || !ppwzData) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er; + DWORD_PTR cch = 0; + + if (!*ppwzData) + { + er = ::MsiRecordGetStringW(hRec, uiField, L"", (DWORD*)&cch); + if (ERROR_MORE_DATA == er || ERROR_SUCCESS == er) + { + hr = StrAlloc(ppwzData, ++cch); + } + else + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed to allocate memory for record string"); + } + else + { + hr = StrMaxLength(*ppwzData, &cch); + ExitOnFailure(hr, "Failed to get previous size of string"); + } + + er = ::MsiRecordGetStringW(hRec, uiField, *ppwzData, (DWORD*)&cch); + if (ERROR_MORE_DATA == er) + { + hr = StrAlloc(ppwzData, ++cch); + ExitOnFailure(hr, "Failed to allocate memory for record string"); + + er = ::MsiRecordGetStringW(hRec, uiField, *ppwzData, (DWORD*)&cch); + } + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed to get string from record"); + +LExit: + return hr; +} + + +/******************************************************************** + HideNulls() - internal helper function to escape [~] in formatted strings + +********************************************************************/ +static void HideNulls( + __in LPWSTR wzData + ) +{ + LPWSTR pwz = wzData; + + while(*pwz) + { + if (pwz[0] == L'[' && pwz[1] == L'~' && pwz[2] == L']') // found a null [~] + { + pwz[0] = L'!'; // turn it into !$! + pwz[1] = L'$'; + pwz[2] = L'!'; + pwz += 3; + } + else + pwz++; + } +} + + +/******************************************************************** + RevealNulls() - internal helper function to unescape !$! in formatted strings + +********************************************************************/ +static void RevealNulls( + __in LPWSTR wzData + ) +{ + LPWSTR pwz = wzData; + + while(*pwz) + { + if (pwz[0] == L'!' && pwz[1] == L'$' && pwz[2] == L'!') // found the fake null !$! + { + pwz[0] = L'['; // turn it back into [~] + pwz[1] = L'~'; + pwz[2] = L']'; + pwz += 3; + } + else + pwz++; + } +} + + +/******************************************************************** + WcaGetRecordFormattedString() - gets formatted string filed from record + +********************************************************************/ +extern "C" HRESULT WcaGetRecordFormattedString( + __in MSIHANDLE hRec, + __in UINT uiField, + __inout LPWSTR* ppwzData + ) +{ + if (!hRec || !ppwzData) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er; + DWORD_PTR cch = 0; + PMSIHANDLE hRecFormat; + + // get the format string + hr = WcaGetRecordString(hRec, uiField, ppwzData); + ExitOnFailure(hr, "failed to get string from record"); + + if (!**ppwzData) + ExitFunction(); + + // hide the nulls '[~]' so we can get them back after formatting + HideNulls(*ppwzData); + + // set up the format record + hRecFormat = ::MsiCreateRecord(1); + ExitOnNull(hRecFormat, hr, E_UNEXPECTED, "Failed to create record to format string"); + hr = WcaSetRecordString(hRecFormat, 0, *ppwzData); + ExitOnFailure(hr, "failed to set string to format record"); + + // format the string + hr = StrMaxLength(*ppwzData, &cch); + ExitOnFailure(hr, "failed to get max length of string"); + + er = ::MsiFormatRecordW(WcaGetInstallHandle(), hRecFormat, *ppwzData, (DWORD*)&cch); + if (ERROR_MORE_DATA == er) + { + hr = StrAlloc(ppwzData, ++cch); + ExitOnFailure(hr, "Failed to allocate memory for record string"); + + er = ::MsiFormatRecordW(WcaGetInstallHandle(), hRecFormat, *ppwzData, (DWORD*)&cch); + } + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed to format string"); + + // put the nulls back + RevealNulls(*ppwzData); + +LExit: + return hr; +} + + +/******************************************************************** + WcaAllocStream() - creates a byte stream of the specified size + + NOTE: Use WcaFreeStream() to release the byte stream +********************************************************************/ +extern "C" HRESULT WcaAllocStream( + __inout BYTE** ppbData, + __in DWORD cbData + ) +{ + Assert(ppbData); + HRESULT hr; + BYTE* pbNewData; + + if (*ppbData) + pbNewData = (BYTE*)MemReAlloc(*ppbData, cbData, TRUE); + else + pbNewData = (BYTE*)MemAlloc(cbData, TRUE); + + if (!pbNewData) + ExitOnLastError(hr, "Failed to allocate string"); + *ppbData = pbNewData; + pbNewData = NULL; + + hr = S_OK; +LExit: + if (pbNewData) + MemFree(pbNewData); + + return hr; +} + + +/******************************************************************** + WcaFreeStream() - frees a byte stream + +********************************************************************/ +extern "C" HRESULT WcaFreeStream( + __in BYTE* pbData + ) +{ + if (!pbData) + return E_INVALIDARG; + + HRESULT hr = MemFree(pbData); + return hr; +} + + +/******************************************************************** + WcaReadRecordStream() - gets a byte stream field from record + +********************************************************************/ +extern "C" HRESULT WcaGetRecordStream( + __in MSIHANDLE hRecBinary, + __in UINT uiField, + __inout BYTE** ppbData, + __inout DWORD* pcbData + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + if (!hRecBinary || !ppbData || !pcbData) + return E_INVALIDARG; + + *pcbData = 0; + er = ::MsiRecordReadStream(hRecBinary, uiField, NULL, pcbData); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to get size of stream"); + + hr = WcaAllocStream(ppbData, *pcbData); + ExitOnFailure(hr, "failed to allocate data for stream"); + + er = ::MsiRecordReadStream(hRecBinary, uiField, (char*)*ppbData, pcbData); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to read from stream"); + +LExit: + return hr; +} + + +/******************************************************************** + WcaSetRecordString() - set a string field in record + +********************************************************************/ +extern "C" HRESULT WcaSetRecordString( + __in MSIHANDLE hRec, + __in UINT uiField, + __in LPCWSTR wzData + ) +{ + if (!hRec || !wzData) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er = ::MsiRecordSetStringW(hRec, uiField, wzData); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to set string in record"); + +LExit: + return hr; +} + + +/******************************************************************** + WcaSetRecordInteger() - set a integer field in record + +********************************************************************/ +extern "C" HRESULT WcaSetRecordInteger( + __in MSIHANDLE hRec, + __in UINT uiField, + __in int iValue + ) +{ + if (!hRec) + return E_INVALIDARG; + + HRESULT hr = S_OK; + UINT er = ::MsiRecordSetInteger(hRec, uiField, iValue); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to set integer in record"); + +LExit: + return hr; +} + + +/******************************************************************** + + WcaDoDeferredAction() - schedules an action at this point in the script + +********************************************************************/ +extern "C" HRESULT WcaDoDeferredAction( + __in LPCWSTR wzAction, + __in LPCWSTR wzCustomActionData, + __in UINT uiCost + ) +{ + HRESULT hr = S_OK; + UINT er; + + if (wzCustomActionData && *wzCustomActionData) + { + er = ::MsiSetPropertyW(WcaGetInstallHandle(), wzAction, wzCustomActionData); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed to set CustomActionData for deferred action"); + } + + if (0 < uiCost) + { + hr = WcaProgressMessage(uiCost, TRUE); // add ticks to the progress bar + // TODO: handle the return codes correctly + } + + er = ::MsiDoActionW(WcaGetInstallHandle(), wzAction); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed MsiDoAction on deferred action"); + +LExit: + return hr; +} + + +/******************************************************************** + WcaCountOfCustomActionDataRecords() - counts the number of records + passed to a deferred CustomAction + +********************************************************************/ +extern "C" DWORD WcaCountOfCustomActionDataRecords( + __in LPCWSTR wzData + ) +{ + if (!wzData) + return E_INVALIDARG; + + WCHAR delim[] = {MAGIC_MULTISZ_DELIM, 0}; // magic char followed by NULL terminator + DWORD dwCount = 0; + + // Loop through until there are no delimiters, we are at the end of the string, or the delimiter is the last character in the string + for (LPCWSTR pwzCurrent = wzData; pwzCurrent && *pwzCurrent && *(pwzCurrent + 1); pwzCurrent = wcsstr(pwzCurrent, delim)) + { + dwCount++; + pwzCurrent++; + } + + return dwCount; +} + + +/******************************************************************** + BreakDownCustomActionData() - internal helper to chop up CustomActionData + + NOTE: this modifies the passed in data +********************************************************************/ +static LPWSTR BreakDownCustomActionData( + __inout LPWSTR* ppwzData + ) +{ + if (!ppwzData) + return NULL; + if (0 == *ppwzData) + return NULL; + + WCHAR delim[] = {MAGIC_MULTISZ_DELIM, 0}; // magic char followed by Null terminator + + LPWSTR pwzReturn = *ppwzData; + LPWSTR pwz = wcsstr(pwzReturn, delim); + if (pwz) + { + *pwz = 0; + *ppwzData = pwz + 1; + } + else + *ppwzData = 0; + + return pwzReturn; +} + + +/******************************************************************** + WcaReadStringFromCaData() - reads a string out of the CustomActionData + + NOTE: this modifies the passed in ppwzCustomActionData variable +********************************************************************/ +extern "C" HRESULT WcaReadStringFromCaData( + __inout LPWSTR* ppwzCustomActionData, + __inout LPWSTR* ppwzString + ) +{ + HRESULT hr = S_OK; + + LPCWSTR pwz = BreakDownCustomActionData(ppwzCustomActionData); + if (!pwz) + return E_NOMOREITEMS; + + hr = StrAllocString(ppwzString, pwz, 0); + ExitOnFailure(hr, "failed to allocate memory for string"); + + hr = S_OK; +LExit: + return hr; +} + + +/******************************************************************** + WcaReadIntegerFromCaData() - reads an integer out of the CustomActionData + + NOTE: this modifies the passed in ppwzCustomActionData variable +********************************************************************/ +extern "C" HRESULT WcaReadIntegerFromCaData( + __inout LPWSTR* ppwzCustomActionData, + __inout int* piResult + ) +{ + LPCWSTR pwz = BreakDownCustomActionData(ppwzCustomActionData); + if (!pwz) + return E_NOMOREITEMS; + + *piResult = wcstol(pwz, NULL, 10); + return S_OK; +} + + +/******************************************************************** + WcaReadStreamFromCaData() - reads a stream out of the CustomActionData + + NOTE: this modifies the passed in ppwzCustomActionData variable + NOTE: returned stream should be freed with WcaFreeStream() +********************************************************************/ +extern "C" HRESULT WcaReadStreamFromCaData( + __inout LPWSTR* ppwzCustomActionData, + __out BYTE** ppbData, + __out DWORD_PTR* pcbData + ) +{ + HRESULT hr; + + LPCWSTR pwz = BreakDownCustomActionData(ppwzCustomActionData); + if (!pwz) + return E_NOMOREITEMS; + + hr = StrAllocBase85Decode(pwz, ppbData, pcbData); + ExitOnFailure(hr, "failed to decode string into stream"); + +LExit: + return hr; +} + + +/******************************************************************** + WcaWriteStringToCaData() - adds a string to the CustomActionData to + feed a deferred CustomAction + +********************************************************************/ +extern "C" HRESULT WcaWriteStringToCaData( + __in LPCWSTR wzString, + __inout LPWSTR* ppwzCustomActionData + ) +{ + HRESULT hr = S_OK; + WCHAR delim[] = {MAGIC_MULTISZ_DELIM, 0}; // magic char followed by NULL terminator + + if (!ppwzCustomActionData) + return E_INVALIDARG; + + DWORD cchString = lstrlenW(wzString) + 1; // assume we'll be adding the delim + DWORD_PTR cchCustomActionData = 0; + + if (*ppwzCustomActionData) + { + hr = StrMaxLength(*ppwzCustomActionData, &cchCustomActionData); + ExitOnFailure(hr, "failed to get length of custom action data"); + } + + if ((cchCustomActionData - lstrlenW(*ppwzCustomActionData)) < cchString + 1) + { + cchCustomActionData += cchString + 1 + 255; // add 255 for good measure + hr = StrAlloc(ppwzCustomActionData, cchCustomActionData); + ExitOnFailure(hr, "Failed to allocate memory for CustomActionData string"); + ExitOnNull(*ppwzCustomActionData, hr, E_OUTOFMEMORY, "Failed to allocate memory for CustomActionData string"); + } + + if (**ppwzCustomActionData) // if data exists toss the delimiter on before adding more to the end + StringCchCatW(*ppwzCustomActionData, cchCustomActionData, delim); + StringCchCatW(*ppwzCustomActionData, cchCustomActionData, wzString); + +LExit: + return hr; +} + + +/******************************************************************** + WcaWriteStringToCaData() - adds an integer to the CustomActionData to + feed a deferred CustomAction + +********************************************************************/ +extern "C" HRESULT WcaWriteIntegerToCaData( + __in int i, + __inout LPWSTR* ppwzCustomActionData + ) +{ + WCHAR wzBuffer[13]; + StringCchPrintfW(wzBuffer, countof(wzBuffer), L"%d", i); + + return WcaWriteStringToCaData(wzBuffer, ppwzCustomActionData); +} + + +/******************************************************************** + WcaWriteStringToCaData() - adds a byte stream to the CustomActionData to + feed a deferred CustomAction + +********************************************************************/ +extern "C" HRESULT WcaWriteStreamToCaData( + __in_bcount(cbData) const BYTE* pbData, + __in DWORD cbData, + __inout LPWSTR* ppwzCustomActionData + ) +{ + HRESULT hr; + LPWSTR pwzData = NULL; + + hr = StrAllocBase85Encode(pbData, cbData, &pwzData); + ExitOnFailure(hr, "failed to encode data into string"); + + hr = WcaWriteStringToCaData(pwzData, ppwzCustomActionData); + +LExit: + ReleaseStr(pwzData); + return hr; +} + + +/******************************************************************** +WcaAddTempRecord - adds a temporary record to the active database + +NOTE: you cannot use PMSIHANDLEs for the __in/__out parameters +NOTE: uiUniquifyColumn can be 0 if no column needs to be made unique +********************************************************************/ +extern "C" HRESULT WcaAddTempRecord( + __inout MSIHANDLE* phTableView, + __inout MSIHANDLE* phColumns, + __in LPCWSTR wzTable, + __in UINT uiUniquifyColumn, + __in UINT cColumns, + ... + ) +{ + Assert(phTableView && phColumns); + + static DWORD dwUniquifyValue = ::GetTickCount(); + + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + LPWSTR pwzQuery = NULL; + PMSIHANDLE hTempRec; + DWORD i; + va_list args; + + LPWSTR pwzData = NULL; + LPWSTR pwzUniquify = NULL; + + // + // if we don't have a table and it's columns already + // + if (NULL == *phTableView) + { + // set the query + hr = StrAllocFormatted(&pwzQuery, L"SELECT * FROM `%s`",wzTable); + ExitOnFailure(hr, "failed to allocate string for query"); + + // Open and Execute the temp View + hr = WcaOpenExecuteView(pwzQuery, phTableView); + ExitOnFailure1(hr, "failed to openexecute temp view with query %S", pwzQuery); + } + + if (NULL == *phColumns) + { + // use GetColumnInfo to populate the datatype record + er = ::MsiViewGetColumnInfo(*phTableView, MSICOLINFO_TYPES, phColumns); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "failed to columns for table: %S", wzTable); + } + AssertSz(::MsiRecordGetFieldCount(*phColumns) == cColumns, "passed in argument does not match number of columns in table"); + + // + // create the temp record + // + hTempRec = ::MsiCreateRecord(cColumns); + ExitOnNull1(hTempRec, hr, E_UNEXPECTED, "could not create temp record for table: %S", wzTable); + + // + // loop through all the columns filling in the data + // + va_start(args, cColumns); + for (i = 1; i <= cColumns; i++) + { + hr = WcaGetRecordString(*phColumns, i, &pwzData); + ExitOnFailure1(hr, "failed to get the data type for %d", i); + + // if data type is string write string + if (L's' == *pwzData || L'S' == *pwzData || L'g' == *pwzData || L'G' == *pwzData || L'l' == *pwzData || L'L' == *pwzData) + { + LPCWSTR wz = va_arg(args, WCHAR*); + + // if this is the column that is supposed to be unique add the time stamp on the end + if (uiUniquifyColumn == i) + { + hr = StrAllocFormatted(&pwzUniquify, L"%s%u", wz, ++dwUniquifyValue); // up the count so we have no collisions on the unique name + ExitOnFailure1(hr, "failed to allocate string for unique column: %d", uiUniquifyColumn); + + wz = pwzUniquify; + } + + er = ::MsiRecordSetStringW(hTempRec, i, wz); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "failed to set string value at position %d", i); + } + // if data type is integer write integer + else if (L'i' == *pwzData || L'I' == *pwzData || L'j' == *pwzData || L'J' == *pwzData) + { + AssertSz(uiUniquifyColumn != i, "Cannot uniquify an integer column"); + int iData = va_arg(args, int); + + er = ::MsiRecordSetInteger(hTempRec, i, iData); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "failed to set integer value at position %d", i); + } + else + { + // not supporting binary streams so error out + hr = HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH); + ExitOnFailure2(hr, "unsupported data type '%S' in column: %d", pwzData, i); + } + } + va_end(args); + + // + // add the temporary record to the MSI + // + er = ::MsiViewModify(*phTableView, MSIMODIFY_INSERT_TEMPORARY, hTempRec); + hr = HRESULT_FROM_WIN32(er); + if (FAILED(hr)) + { + MSIDBERROR dbErr; + WCHAR wzBuf[MAX_PATH]; + DWORD cchBuf = countof(wzBuf); + + dbErr = ::MsiViewGetErrorW(*phTableView, wzBuf, &cchBuf); + ExitOnFailure2(hr, "failed to add temporary row, dberr: %d, err: %S", dbErr, wzBuf); + } + +LExit: + ReleaseStr(pwzUniquify); + ReleaseStr(pwzData); + ReleaseStr(pwzQuery); + + return hr; +} + + +/******************************************************************** +WcaDumpTable - dumps a table to the log file + +********************************************************************/ +extern "C" HRESULT WIXAPI WcaDumpTable( + __in LPCWSTR wzTable + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + LPWSTR pwzQuery = NULL; + PMSIHANDLE hView; + PMSIHANDLE hColumns; + DWORD cColumns = 0; + PMSIHANDLE hRec; + + LPWSTR pwzData = NULL; + LPWSTR pwzPrint = NULL; + + hr = StrAllocFormatted(&pwzQuery, L"SELECT * FROM `%s`",wzTable); + ExitOnFailure(hr, "failed to allocate string for query"); + + // Open and Execute the temp View + hr = WcaOpenExecuteView(pwzQuery, &hView); + ExitOnFailure1(hr, "failed to openexecute temp view with query %S", pwzQuery); + + // Use GetColumnInfo to populate the names of the columns. + er = ::MsiViewGetColumnInfo(hView, MSICOLINFO_NAMES, &hColumns); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure1(hr, "failed to columns for table: %S", wzTable); + + cColumns = ::MsiRecordGetFieldCount(hColumns); + + WcaLog(LOGMSG_STANDARD, "--- Begin Table Dump %S ---", wzTable); + + // Loop through all the columns filling in the data. + for (DWORD i = 1; i <= cColumns; i++) + { + hr = WcaGetRecordString(hColumns, i, &pwzData); + ExitOnFailure1(hr, "failed to get the column name for %d", i); + + hr = StrAllocConcat(&pwzPrint, pwzData, 0); + ExitOnFailure(hr, "Failed to add column name."); + + hr = StrAllocConcat(&pwzPrint, L"\t", 1); + ExitOnFailure(hr, "Failed to add column name."); + } + + WcaLog(LOGMSG_STANDARD, "%S", pwzPrint); + + // Now dump the actual rows. + while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) + { + if (pwzPrint && *pwzPrint) + { + *pwzPrint = L'\0'; + } + + for (DWORD i = 1; i <= cColumns; i++) + { + hr = WcaGetRecordString(hRec, i, &pwzData); + ExitOnFailure1(hr, "failed to get the column name for %d", i); + + hr = StrAllocConcat(&pwzPrint, pwzData, 0); + ExitOnFailure(hr, "Failed to add column name."); + + hr = StrAllocConcat(&pwzPrint, L"\t", 1); + ExitOnFailure(hr, "Failed to add column name."); + } + + WcaLog(LOGMSG_STANDARD, "%S", pwzPrint); + } + + WcaLog(LOGMSG_STANDARD, "--- End Table Dump %S ---", wzTable); + +LExit: + ReleaseStr(pwzPrint); + ReleaseStr(pwzData); + ReleaseStr(pwzQuery); + + return hr; +} diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/bitmaps/AspNetCoreModule.ico b/src/Installers/Windows/AspNetCoreModule-Setup/bitmaps/AspNetCoreModule.ico new file mode 100644 index 0000000000000000000000000000000000000000..bcafd4a5b717c275d5faa24c71b494ce9696c4a9 GIT binary patch literal 894 zcmaKrOD{t~6vw9#dn>VHCAQ)Vh>e}ZUTh?2P*kewqN-YN78>toQPNggTGfZDt5hG@ zu%c4WD6L209ShDiHMzMObI+MMIp_C3GnvdqhzDO%5`sAel_nsRj1bBIhZIT!XY$O* zh8lPDDjPawwe3=2TcbchRYTI^ z+4WAd#=bOTS)7tf$~X*>LqI#NK6=@^Zgl_b;xNrAsB(N}Hb(kyZ8-e22@LN-TeWSC zm2r72@whis-Eu`!ZJm%W6${{QyPB&pA9wb8HXrXU!0v8C(Qxqg`lzo}gj;dWgOdU8 z_Ah@L4W9t7>Zp&)V|l>0qn;S*RLUAef)+~HEfDD-#T2Ej%RF01_L{ z0T1T)dFZuO$I7Bvuh!2FvT*KuW0(HMq&Ybc&kg^_Ma++3b%BZkm&DW`uzo@wE{&=2 K7$(Mlf%Y4T_a{vN literal 0 HcmV?d00001 diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/bitmaps/bannrbmp.bmp b/src/Installers/Windows/AspNetCoreModule-Setup/bitmaps/bannrbmp.bmp new file mode 100644 index 0000000000000000000000000000000000000000..8507592b05e61465063f395f77824e3f6b00a9a5 GIT binary patch literal 5950 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 JuAHcB zqbSKPU~maWQ_j@NWhH50nLeg z6mS8KNh+`%p|~P=`g|_g#4wOvgL63s>wUc?SZ#_6XZv=AdBphC;EJDG23Hiu#QgND ziY?ZubEgtbcisl`ZKLA%^0uj_zYH%}rfuh!F<%I+EJ+4zcHuuQM|+gDJZ#D->@Uj= zV_6%v>7eV9n8VlCI^UyQuYgDMz_A=anXTGuOTCwG;bxffrxp)->tRxEAZ3*-Q#d8V rC%{Kxpa5qSV_@Sryl917b|?a${wu4tw%-z8^82O*|G!A_oXP(NBma{m literal 0 HcmV?d00001 diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/bitmaps/dlgbmp.bmp b/src/Installers/Windows/AspNetCoreModule-Setup/bitmaps/dlgbmp.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c3810b4037ef343c5842ce36025c0dd06e26b6d1 GIT binary patch literal 20396 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 literal 0 HcmV?d00001 diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/build/copy-outputs.targets b/src/Installers/Windows/AspNetCoreModule-Setup/build/copy-outputs.targets new file mode 100644 index 0000000000..bdc59f4f6d --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/build/copy-outputs.targets @@ -0,0 +1,18 @@ + + + + + + + + $(Configuration)\$(PlatformShortname)\ + + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/build/exports.props b/src/Installers/Windows/AspNetCoreModule-Setup/build/exports.props new file mode 100644 index 0000000000..512b082102 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/build/exports.props @@ -0,0 +1,13 @@ + + + + + + $(MSBuildThisFileDirectory)..\ + + + + $(MSBuildThisFileDirectory)..\ + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/build/settings.props b/src/Installers/Windows/AspNetCoreModule-Setup/build/settings.props new file mode 100644 index 0000000000..ba1ca74632 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/build/settings.props @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/build/settings/common.props b/src/Installers/Windows/AspNetCoreModule-Setup/build/settings/common.props new file mode 100644 index 0000000000..0130b6e5ab --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/build/settings/common.props @@ -0,0 +1,53 @@ + + + + + + + x64 + x86 + + + + + + 10.0.15063.0 + $(IisOobWinSdkVersion) + Unicode + bin\$(Configuration)\$(PlatformShortname)\ + obj\$(Configuration)\$(PlatformShortname)\ + + + + + + + Level3 + + + + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + + + WIN32;%(PreprocessorDefinitions) + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/build/settings/debug.props b/src/Installers/Windows/AspNetCoreModule-Setup/build/settings/debug.props new file mode 100644 index 0000000000..710f5553d0 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/build/settings/debug.props @@ -0,0 +1,29 @@ + + + + + + true + true + false + + + + + + + true + Disabled + true + EnableFastChecks + MultiThreadedDebug + + + false + false + true + /JMC- + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/build/settings/release.props b/src/Installers/Windows/AspNetCoreModule-Setup/build/settings/release.props new file mode 100644 index 0000000000..d7eb8ffa35 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/build/settings/release.props @@ -0,0 +1,51 @@ + + + + + + + true + true + + + + + + + false + false + true + + + + + + + Full + Speed + false + MultiThreaded + true + + + true + true + UseLinkTimeCodeGeneration + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/build/submodule.props b/src/Installers/Windows/AspNetCoreModule-Setup/build/submodule.props new file mode 100644 index 0000000000..00046cf191 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/build/submodule.props @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/build/versions.props b/src/Installers/Windows/AspNetCoreModule-Setup/build/versions.props new file mode 100644 index 0000000000..3be2245e72 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/build/versions.props @@ -0,0 +1,38 @@ + + + + + 7 + 1 + + + $([MSBuild]::Multiply(12,$([MSBuild]::Subtract($([System.DateTime]::Now.Year), 2016)))) + $([MSBuild]::Add( $([MSBuild]::Subtract($([System.DateTime]::Now.Month), 10)), $(VersionDateMonths))) + $([System.DateTime]::Now.ToString("dd")) + $([System.String]::Concat($([System.Int32]::Parse('$(VersionDateTotalMonths)').ToString("D3")), $(VersionDateDays))) + $(VersionBuildMajor) + $([System.DateTime]::Now.ToString("HHmm")) + + + + + /DPRODUCT_MAJOR=$(PRODUCT_MAJOR) %(AdditionalOptions) + + + /DPRODUCT_MINOR=$(PRODUCT_MINOR) %(AdditionalOptions) + + + /DBUILD_MAJOR=$(BUILD_MAJOR) %(AdditionalOptions) + + + /DBUILD_MINOR=$(BUILD_MINOR) %(AdditionalOptions) + + + + + PRODUCT_MAJOR=$(PRODUCT_MAJOR);$(ResourceCompilePreprocessorDefinitions) + PRODUCT_MINOR=$(PRODUCT_MINOR);$(ResourceCompilePreprocessorDefinitions) + BUILD_MAJOR=$(BUILD_MAJOR);$(ResourceCompilePreprocessorDefinitions) + BUILD_MINOR=$(BUILD_MINOR);$(ResourceCompilePreprocessorDefinitions) + + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/license/license.rtf b/src/Installers/Windows/AspNetCoreModule-Setup/license/license.rtf new file mode 100644 index 0000000000..91c46e44c4 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/license/license.rtf @@ -0,0 +1,97 @@ +{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033\deflangfe2052{\fonttbl{\f0\fswiss\fprq2\fcharset0 Tahoma;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\froman\fprq2\fcharset0 Times New Roman;}{\f3\fswiss\fprq2\fcharset0 Calibri;}{\f4\fnil\fcharset2 Symbol;}} +{\colortbl ;\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;} +{\stylesheet{ Normal;}{\s1 heading 1;}} +{\*\generator Riched20 10.0.10586}\viewkind4\uc1 +\pard\nowidctlpar\sb120\sa120\b\f0\fs22 MICROSOFT SOFTWARE LICENSE TERMS\fs20\par + +\pard\brdrb\brdrs\brdrw10\brsp20 \nowidctlpar\sb120\sa120\fs22 MICROSOFT ASP.NET CORE MODULE\fs20\par + +\pard\widctlpar\sb120\sa120 These license terms are an agreement between Microsoft Corporation (or based on where you live, one of its affiliates) and you. Please read them. They apply to the software named above, which includes the media on which you received it, if any. The terms also apply to any Microsoft\b0\par + +\pard\nowidctlpar\fi-360\li360\sb120\sa120\tx360\f1\'b7\tab\f0 updates,\par +\f1\'b7\tab\f0 supplements,\par +\f1\'b7\tab\f0 Internet-based services, and\par +\f1\'b7\tab\f0 support services\par + +\pard\nowidctlpar\sb120\sa120 for this software, unless other terms accompany those items. If so, those terms apply.\par +\b BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. IF YOU DO NOT ACCEPT THEM, DO NOT USE THE SOFTWARE.\par + +\pard\brdrt\brdrs\brdrw10\brsp20 \nowidctlpar\sb120\sa120 IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS BELOW.\par + +\pard\nowidctlpar\s1\fi-357\li357\sb120\sa120\tx360 1.\tab INSTALLATION AND USE RIGHTS. \b0\f2\par + +\pard\widctlpar\fi-363\li720\sb120\sa120\b\f0 a.\~\~\~ Installation and Use.\b0 You may install and use any number of copies of the software to design, develop and test your programs.\b\par +b.\~\~\~ Third Party Programs.\b0 The software may include third party programs that Microsoft, not the third party, licenses to you under this agreement. Notices, if any, for the third party program are included for your information only.\b\par + +\pard\widctlpar\fi-357\li357\sb120\sa120\kerning36 2.\tab ADDITIONAL LICENSING REQUIREMENTS AND/OR USE RIGHTS.\par + +\pard\widctlpar\fi-363\li720\sb120\sa120\kerning0 a.\~\~\~ DISTRIBUTABLE CODE.\~ \b0 The software is comprised of Distributable Code. \ldblquote Distributable Code\rdblquote is code that you are permitted to distribute in programs you develop if you comply with the terms below.\b\par + +\pard\widctlpar\fi-357\li1077\sb120\sa120 i.\~\~\~\~\~ Right to Use and Distribute. \b0\par + +\pard{\pntext\f4\'B7\tab}{\*\pn\pnlvlblt\pnf4\pnindent0{\pntxtb\'B7}}\fi-360\li1797\sb120\sa120 You may copy and distribute the object code form of the software.\par +{\pntext\f4\'B7\tab}Third Party Distribution. You may permit distributors of your programs to copy and distribute the Distributable Code as part of those programs.\par + +\pard\widctlpar\fi-357\li1077\sb120\sa120\b ii.\~\~\~ Distribution Requirements.\b0 \b For any Distributable Code you distribute, you must\b0\par + +\pard{\pntext\f4\'B7\tab}{\*\pn\pnlvlblt\pnf4\pnindent0{\pntxtb\'B7}}\fi-360\li1797\sb120\sa120 add significant primary functionality to it in your programs;\par +{\pntext\f4\'B7\tab}require distributors and external end users to agree to terms that protect it at least as much as this agreement;\par +{\pntext\f4\'B7\tab}display your valid copyright notice on your programs; and\par +{\pntext\f4\'B7\tab}indemnify, defend, and hold harmless Microsoft from any claims, including attorneys\rquote fees, related to the distribution or use of your programs.\par + +\pard\widctlpar\fi-357\li1077\sb120\sa120\b iii.\~\~ Distribution Restrictions.\b0 \b You may not\b0\par + +\pard{\pntext\f4\'B7\tab}{\*\pn\pnlvlblt\pnf4\pnindent0{\pntxtb\'B7}}\fi-360\li1797\sb120\sa120 alter any copyright, trademark or patent notice in the Distributable Code;\par +{\pntext\f4\'B7\tab}use Microsoft\rquote s trademarks in your programs\rquote names or in a way that suggests your programs come from or are endorsed by Microsoft;\par +{\pntext\f4\'B7\tab}include Distributable Code in malicious, deceptive or unlawful programs; or\par +{\pntext\f4\'B7\tab}modify or distribute the source code of any Distributable Code so that any part of it becomes subject to an Excluded License. An Excluded License is one that requires, as a condition of use, modification or distribution, that\par +{\pntext\f4\'B7\tab}the code be disclosed or distributed in source code form; or\par +{\pntext\f4\'B7\tab}others have the right to modify it.\f2\par + +\pard\widctlpar\fi-357\li357\sb120\sa120\b\f0 3.\tab\kerning36 SCOPE OF LICENSE. \b0 The software is licensed, not sold. This agreement only gives you some rights to use the software. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you may use the software only as expressly permitted in this agreement. In doing so, you must comply with any technical limitations in the software that only allow you to use it in certain ways. You may not\b\par + +\pard{\pntext\f4\'B7\tab}{\*\pn\pnlvlblt\pnf4\pnindent0{\pntxtb\'B7}}\fi-360\li1797\sb120\sa120\kerning0\b0 work around any technical limitations in the software;\par +{\pntext\f4\'B7\tab}reverse engineer, decompile or disassemble the software, except and only to the extent that applicable law expressly permits, despite this limitation;\par +{\pntext\f4\'B7\tab}publish the software for others to copy;\par +{\pntext\f4\'B7\tab}rent, lease or lend the software;\par +{\pntext\f4\'B7\tab}transfer the software or this agreement to any third party; or\par +{\pntext\f4\'B7\tab}use the software for commercial software hosting services.\par + +\pard\widctlpar\fi-357\li357\sb120\sa120\b 4.\tab\cf1\highlight2 DATA.\cf0\highlight0\b0 The software may collect information about you and your use of the software, and send that to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may opt-out of many of these scenarios, but not all, as described in the product documentation. You can learn more about data collection and use in the help documentation and the privacy statement at {{\field{\*\fldinst{HYPERLINK https://privacy.microsoft.com/en-us/privacystatement }}{\fldrslt{https://privacy.microsoft.com/en-us/privacystatement\ul0\cf0}}}}\f0\fs20 . {\f3\fs22{\field{\*\fldinst{HYPERLINK http://go.microsoft.com/fwlink/?LinkID=528096Your }}{\fldrslt{http://go.microsoft.com/fwlink/?LinkID=528096\f0\fs20 Your\ul0\cf0}}}}\f0\fs20 use of the software operates as your consent to these practices.\par +\b 5.\tab\kerning36 BACKUP COPY. \b0 You may make one backup copy of the software. You may use it only to reinstall the software.\b\par +6.\tab DOCUMENTATION. \b0 Any person that has valid access to your computer or internal network may copy and use the documentation for your internal, reference purposes.\b\par +7.\tab EXPORT RESTRICTIONS. \b0 The software is subject to United States export laws and regulations. You must comply with all domestic and international export laws and regulations that apply to the software. These laws include restrictions on destinations, end users and end use. For additional information, see {{\field{\*\fldinst{HYPERLINK www.microsoft.com/exporting }}{\fldrslt{www.microsoft.com/exporting\ul0\cf0}}}}\f0\fs20 .\b\par +8.\tab SUPPORT SERVICES. \b0 Because this software is \ldblquote as is,\rdblquote we may not provide support services for it.\b\par +9.\tab ENTIRE AGREEMENT. \b0 This agreement, and the terms for supplements, updates, Internet-based services and support services that you use, are the entire agreement for the software and support services.\b\par +10.\tab APPLICABLE LAW.\par + +\pard\widctlpar\fi-363\li720\sb120\sa120\kerning0 a.\tab United States. \b0 If you acquired the software in the United States, Washington state law governs the interpretation of this agreement and applies to claims for breach of it, regardless of conflict of laws principles. The laws of the state where you live govern all other claims, including claims under state consumer protection laws, unfair competition laws, and in tort.\b\par +b.\~\~\~ Outside the United States. If you acquired the software in any other country, the laws of that country apply.\par + +\pard\widctlpar\fi-357\li357\sb120\sa120\kerning36 11.\tab LEGAL EFFECT. \b0 This agreement describes certain legal rights. You may have other rights under the laws of your country. You may also have rights with respect to the party from whom you acquired the software. This agreement does not change your rights under the laws of your country if the laws of your country do not permit it to do so.\b\par +12.\tab DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED \ldblquote AS-IS.\rdblquote YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES OR CONDITIONS. YOU MAY HAVE ADDITIONAL CONSUMER RIGHTS OR STATUTORY GUARANTEES UNDER YOUR LOCAL LAWS WHICH THIS AGREEMENT CANNOT CHANGE. TO THE EXTENT PERMITTED UNDER YOUR LOCAL LAWS, MICROSOFT EXCLUDES THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.\par + +\pard\widctlpar\li357\sb120\sa120\kerning0 FOR AUSTRALIA \endash YOU HAVE STATUTORY GUARANTEES UNDER THE AUSTRALIAN CONSUMER LAW AND NOTHING IN THESE TERMS IS INTENDED TO AFFECT THOSE RIGHTS.\b0\par + +\pard\widctlpar\fi-357\li357\sb120\sa120\kerning36\b 13.LIMITATION ON AND EXCLUSION OF REMEDIES AND DAMAGES. YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES.\par + +\pard\widctlpar\li357\sb120\sa120\kerning0\b0 This limitation applies to\par + +\pard{\pntext\f4\'B7\tab}{\*\pn\pnlvlblt\pnf4\pnindent0{\pntxtb\'B7}}\fi-270\li720\sb120\sa120 anything related to the software, services, content (including code) on third party Internet sites, or third party programs; and\par +{\pntext\f4\'B7\tab}claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law.\par + +\pard\widctlpar\sb120\sa120 It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your country may not allow the exclusion or limitation of incidental, consequential or other damages.\par +\lang9 Please note: As this software is distributed in Quebec, Canada, some of the clauses in this agreement are provided below in French.\lang1033\par +\lang9 Remarque : Ce logiciel \'e9tant distribu\'e9 au Qu\'e9bec, Canada, certaines des clauses dans ce contrat sont fournies ci-dessous en fran\'e7ais.\lang1033\par +\kerning36\b EXON\'c9RATION DE GARANTIE. \b0 Le logiciel vis\'e9 par une licence est offert \'ab tel quel \'bb. Toute utilisation de ce logiciel est \'e0 votre seule risque et p\'e9ril. Microsoft n\rquote accorde aucune autre garantie expresse. Vous pouvez b\'e9n\'e9ficier de droits additionnels en vertu du droit local sur la protection des consommateurs, que ce contrat ne peut modifier. La ou elles sont permises par le droit locale, les garanties implicites de qualit\'e9 marchande, d\rquote ad\'e9quation \'e0 un usage particulier et d\rquote absence de contrefa\'e7on sont exclues.\b\par +LIMITATION DES DOMMAGES-INT\'c9R\'caTS ET EXCLUSION DE RESPONSABILIT\'c9 POUR LES DOMMAGES. \b0 Vous pouvez obtenir de Microsoft et de ses fournisseurs une indemnisation en cas de dommages directs uniquement \'e0 hauteur de 5,00 $ US. Vous ne pouvez pr\'e9tendre \'e0 aucune indemnisation pour les autres dommages, y compris les dommages sp\'e9ciaux, indirects ou accessoires et pertes de b\'e9n\'e9fices.\b\par +\kerning0\b0\lang9 Cette limitation concerne :\lang1033\par + +\pard{\pntext\f4\'B7\tab}{\*\pn\pnlvlblt\pnf4\pnindent0{\pntxtb\'B7}}\fi-720\li720\sb120\sa120\lang9 tout ce qui est reli\'e9 au logiciel, aux services ou au contenu (y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers ; et\par +{\pntext\f4\'B7\tab}les r\'e9clamations au titre de violation de contrat ou de garantie, ou au titre de responsabilit\'e9 stricte, de n\'e9gligence ou d\rquote une autre faute dans la limite autoris\'e9e par la loi en vigueur.\lang1033\par + +\pard\widctlpar\sb120\sa120\lang9 Elle s\rquote applique \'e9galement, m\'eame si Microsoft connaissait ou devrait conna\'eetre l\rquote\'e9ventualit\'e9 d\rquote un tel dommage. Si votre pays n\rquote autorise pas l\rquote exclusion ou la limitation de responsabilit\'e9 pour les dommages indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou l\rquote exclusion ci-dessus ne s\rquote appliquera pas \'e0 votre \'e9gard.\lang1033\par +\kerning36\b\fs19 EFFET JURIDIQUE. \b0 Le pr\'e9sent contrat d\'e9crit certains droits juridiques. Vous pourriez avoir d\rquote autres droits pr\'e9vus par les lois de votre pays. Le pr\'e9sent contrat ne modifie pas les droits que vous conf\'e8rent les lois de votre pays si celles-ci ne le permettent pas.\b\par +\kerning0\b0\f2\fs20\par +} + \ No newline at end of file diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/setupstrings.wxl new file mode 100644 index 0000000000..5ac48523c5 --- /dev/null +++ b/src/Installers/Windows/AspNetCoreModule-Setup/setupstrings.wxl @@ -0,0 +1,52 @@ + + + + 1033 + + + Microsoft ASP.NET Core Module + Microsoft ASP.NET Core Module V2 + ASP.NET Core IIS Runtime + Adds the support of asp.net core application to IIS. + Microsoft ASP.NET Core Module for IIS Express + Microsoft ASP.NET Core Module V2 for IIS Express + IIS Express 8.0 or higher is not installed. + + + + Microsoft Corporation + An incompatible product, [CONFLICTING_PRODUCT_NAME], is on this computer. Installation of [ProductName] cannot continue. To install this product, use Add/Remove Programs on the Control Panel to remove [CONFLICTING_PRODUCT_NAME]. + Administrator privilege is required to install [ProductName]. + IIS Version 7.0 is required to use [ProductName]. + IIS Version 7.0 or greater is required to install [ProductName]. + IIS Version 7.5 or greater is required to install [ProductName]. + IIS Version 7 or 7.5 is required to install [ProductName]. + IIS Version 8.0 or greater is required to install [ProductName]. + The beta version of [ProductName] was found on this machine. + A newer version of [ProductName] was found on this machine. + Setup cannot continue because another instance of [ProductName] is already installed on this computer. Please uninstall it first and then re-launch this installation. + The IIS 7.0 CoreWebEngine and W3SVC features must be installed to use [ProductName]. + The IIS Management Console must be installed to use [ProductName]. + Please stop both services Windows Process Activation Service (WAS) and Web Management Service (WMSvc) before installing [ProductName]. You will need to start the services after installing [ProductName]. + IIS Metabase is required to install [ProductName]. + The 64-bit version of [ProductName] cannot be installed on a 32-bit edition of Microsoft Windows. + The 32-bit version of [ProductName] cannot be installed on a 64-bit edition of Microsoft Windows. + Microsoft .NET Framework Version 2.0 or greater is required to install [ProductName]. + Microsoft .NET Framework Version 3.5 or greater is required to install [ProductName]. Use 'Add Features' under the Server Manager to install Microsoft .Net Version 3.5. + Microsoft .NET Framework Version 4.0 or greater is required to install [ProductName]. + Please install Microsoft .NET Framework Version 2.0 Service Pack 1 (or a later service pack), before installing [ProductName]. + The Windows Update (wuauserv) service cannot be disabled, it is required to install [ProductName]. + The PowerShell snap-in is part of Windows Operating System. Please install it via 'Programs and Features' or 'Server Manager'. + Microsoft Web Platform Installer Version 3.0 or greater is required to install [ProductName]. + + Setup failed to detect shared configuration. + Shared configuration is enabled for IIS. Installing [ProductName] is not supported when using shared configuration. Please disable shared configuration before installing this feature. + + Please stop World Wide Web Publishing Service (W3SVC) before installing [ProductName]. You will need to start the service after installation. + IIS PowerShell Management Console + IIS PowerShell snap-in + IIS PowerShell snap-in requires PowerShell v1.0 or v2.0 installed + IIS PowerShell snap-in requires WAS and configuration installed + This is a bogus string. + + diff --git a/src/Installers/Windows/WindowsHostingBundle/ANCM.wxs b/src/Installers/Windows/WindowsHostingBundle/ANCM.wxs index 367daa45ed..71c6a3cc36 100644 --- a/src/Installers/Windows/WindowsHostingBundle/ANCM.wxs +++ b/src/Installers/Windows/WindowsHostingBundle/ANCM.wxs @@ -4,14 +4,14 @@ - - + + + + + + + + + + + + + @@ -15,6 +28,7 @@ + diff --git a/src/Installers/Windows/Wix.props b/src/Installers/Windows/Wix.props index 61c4ca9f6c..f2737edad2 100644 --- a/src/Installers/Windows/Wix.props +++ b/src/Installers/Windows/Wix.props @@ -2,7 +2,6 @@ $(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).$(AspNetCorePatchVersion).0 - Release x64 ENU diff --git a/src/Installers/Windows/Wix.targets b/src/Installers/Windows/Wix.targets index a40275cd06..85eecfa243 100644 --- a/src/Installers/Windows/Wix.targets +++ b/src/Installers/Windows/Wix.targets @@ -12,7 +12,7 @@ - + @@ -39,4 +39,5 @@ $(DefineConstants);BundleProviderKey=$(BundleProviderKey);BundleUpgradeCode=$(BundleUpgradeCode) + diff --git a/src/Installers/Windows/clone_and_build_ancm.ps1 b/src/Installers/Windows/clone_and_build_ancm.ps1 deleted file mode 100644 index cc76a869d9..0000000000 --- a/src/Installers/Windows/clone_and_build_ancm.ps1 +++ /dev/null @@ -1,105 +0,0 @@ -# -# This builds installers for AspNetCoreModule. -# This script requires internal-only access to the code which generates ANCM installers. -# -#requires -version 5 -[cmdletbinding()] -param( - [string]$GitCredential, - [string]$Configuration = 'Release', - [string]$BuildNumber = 't000', - [string]$AncmSourceBranch = 'release/2.1', - [string]$SignType = '' -) - -$ErrorActionPreference = 'Stop' - -$repoRoot = Resolve-Path "$PSScriptRoot/../../../" - -Import-Module -Scope Local "$repoRoot/scripts/common.psm1" -Force - -$msbuild = Get-MSBuildPath -Prerelease -requires 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64' - -# get wix -[version] $wixVer = '3.11.1' -$wixToolSetRoot = "$repoRoot/obj/tools/wix/$wixVer/" -$downloadFile = "$wixToolSetRoot/wix-binaries.zip" -if (-not (Test-Path $downloadFile)) { - [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 - $downloadUrl = "https://github.com/wixtoolset/wix3/releases/download/wix$($wixVer.Major)$($wixVer.Minor)$($wixVer.Build)rtm/wix$($wixVer.Major)$($wixVer.Minor)-binaries.zip" - Write-Host "Downloading fix $wixVer from $downloadUrl" - New-Item -Type Directory $wixToolSetRoot -ErrorAction Ignore | Out-Null - Invoke-WebRequest -UseBasicParsing -Uri $downloadUrl -OutFile $downloadFile - Expand-Archive $downloadFile -DestinationPath $wixToolSetRoot -} - -# get nuget.exe -$nuget = "$repoRoot/obj/tools/nuget.exe" -if (-not (Test-Path $nuget)) { - Invoke-WebRequest -UseBasicParsing -Uri 'https://dist.nuget.org/win-x86-commandline/latest/nuget.exe' -OutFile $nuget -} - -Push-Location $PSScriptRoot - -try { - if ($GitCredential) { - # Disable prompts for passwords - $env:GIT_TERMINAL_PROMPT = 0 - } - - if (-not (Test-Path ancm/)) { - Invoke-Block { - & git clone "https://${GitCredential}@devdiv.visualstudio.com/DefaultCollection/DevDiv/_git/AspNetCoreModule-Setup" ` - --branch $AncmSourceBranch ` - --recursive ` - ancm/ - } - } - - Invoke-Block -WorkingDir ancm/ { - & git submodule update --init --recursive - } - - Invoke-Block -WorkingDir ancm/ { - New-Item .deps -ItemType Directory -ErrorAction Ignore | Out-Null - Copy-Item "$repoRoot/obj/dependencies.g.props" .deps/dependencies.g.props - & $msbuild artifactfetcher/artifactfetcher.csproj ` - '-t:Restore' ` - "-p:RestoreAdditionalProjectSources=$repoRoot/artifacts/build" - } - - Invoke-Block -WorkingDir ancm/ { - & $nuget restore ANCM-Setup.sln - } - - Invoke-Block -WorkingDir ancm/IIS-Common/lib/ { - & $nuget restore packages.config - } - - Invoke-Block { & $msbuild ` - ancm/Setup.msbuild ` - -m ` - -v:m ` - -nodeReuse:false ` - -clp:Summary ` - "-t:BuildCustomAction;Build" ` - "-p:WixToolPath=$wixToolSetRoot" ` - "-p:WixTargetsPath=$wixToolSetRoot\Wix.targets" ` - "-p:WixTasksPath=$wixToolSetRoot\wixtasks.dll" ` - "-p:WixNativeCATargetsPath=$wixToolSetRoot\sdk\wix.nativeca.targets" ` - "-p:Configuration=$Configuration" ` - "-p:BuildNumber=$BuildNumber" ` - "-p:SignType=$SignType" ` - "-bl:$repoRoot/artifacts/logs/ancn.msbuild.binlog" - } - - $outputPath = "$repoRoot/artifacts/bin/$Configuration/installers/en-US/" - New-Item $outputPath -ItemType Directory -ErrorAction Ignore | Out-Null - Copy-Item -Recurse "ancm/bin/AspNetCoreModuleV1/$Configuration/x64/en-us/*" $outputPath - Copy-Item -Recurse "ancm/bin/AspNetCoreModuleV1/$Configuration/x86/en-us/*" $outputPath - Copy-Item -Recurse "ancm/bin/AspNetCoreModuleV2/$Configuration/x64/en-us/*" $outputPath - Copy-Item -Recurse "ancm/bin/AspNetCoreModuleV2/$Configuration/x86/en-us/*" $outputPath -} -finally { - Pop-Location -} From 4b4bd68fc78642e1f167cc11d58bd348fa00c6f2 Mon Sep 17 00:00:00 2001 From: Justin Kotalik Date: Fri, 9 Nov 2018 11:27:08 -0800 Subject: [PATCH 1001/1029] Downgrade stable package versions and remove duplicate test project (#3991) --- .../dependencies.overrides.props | 9 +- .../AppHostConfig/IIS.config | 740 ------------------ .../Common.FunctionalTests/AppOfflineTests.cs | 287 ------- .../Common.FunctionalTests/BasicAuthTests.cs | 70 -- .../ClientCertificateFixture.cs | 104 --- .../ClientCertificateTests.cs | 108 --- .../ClientDisconnectStress.cs | 65 -- .../CommonStartupTests.cs | 44 -- .../CompressionTests.cs | 58 -- .../ConfigurationChangeTests.cs | 126 --- .../Inprocess/ClientDisconnectTests.cs | 108 --- .../Inprocess/CompressionTests.cs | 96 --- .../Inprocess/EnvironmentVariableTests.cs | 51 -- .../Inprocess/ErrorPagesTests.cs | 131 ---- .../Inprocess/EventLogTests.cs | 46 -- .../Inprocess/FeatureCollectionTests.cs | 29 - .../Inprocess/FixtureLoggedTest.cs | 31 - .../Inprocess/FrebTests.cs | 181 ----- .../Inprocess/HelloWorldTests.cs | 30 - .../Inprocess/HostingEnvironmentTests.cs | 33 - .../InvalidReadWriteOperationTests.cs | 84 -- .../Inprocess/LargeResponseBodyTests.cs | 36 - .../Inprocess/LogPipeTests.cs | 83 -- .../Inprocess/ResponseHeaderTests.cs | 85 -- .../Inprocess/ResponseInvalidOrderingTests.cs | 29 - .../Inprocess/ServerVariablesTest.cs | 59 -- .../Inprocess/StartupExceptionTests.cs | 100 --- .../Inprocess/StartupTests.cs | 479 ------------ .../Inprocess/SynchronousReadAndWriteTests.cs | 197 ----- .../Common.FunctionalTests/LogFileTests.cs | 242 ------ .../MultiApplicationTests.cs | 144 ---- .../OutOfProcess/AspNetCorePortTests.cs | 125 --- .../OutOfProcess/GlobalVersionTests.cs | 252 ------ .../OutOfProcess/HelloWorldTest.cs | 81 -- .../PublishedSitesFixture.cs | 65 -- .../RequiresNewHandler.cs | 16 - .../Common.FunctionalTests/RequiresNewShim.cs | 16 - .../ServerAbortTests.cs | 65 -- .../SkipIfNotAdminAttribute.cs | 25 - .../SkipVSTSAttribute.cs | 17 - .../Utilities/AppVerifier.cs | 83 -- .../Utilities/EventLogHelpers.cs | 210 ----- .../Utilities/FunctionalTestsBase.cs | 59 -- .../Utilities/Helpers.cs | 241 ------ .../Utilities/IISCapability.cs | 22 - .../Utilities/IISCompressionSiteCollection.cs | 13 - .../Utilities/IISCompressionSiteFixture.cs | 44 -- .../Utilities/IISFunctionalTestBase.cs | 15 - .../Utilities/IISTestSiteCollection.cs | 29 - .../Utilities/IISTestSiteFixture.cs | 191 ----- .../Utilities/LogFileTestBase.cs | 34 - .../RequiresEnvironmentVariableAttribute.cs | 24 - .../Utilities/SkipIfDebugAttribute.cs | 22 - .../WindowsAuthTests.cs | 52 -- .../test/Common.Tests/Common.Tests.csproj | 22 - .../Common.Tests/Utilities/DisposableList.cs | 25 - .../Common.Tests/Utilities/TestConnections.cs | 252 ------ .../Utilities/TimeoutExtensions.cs | 26 - .../CommonLibTests/CommonLibTests.vcxproj | 196 ----- .../CommonLibTests/ConfigUtilityTests.cpp | 123 --- .../CommonLibTests/FileOutputManagerTests.cpp | 152 ---- .../CommonLibTests/GlobalVersionTests.cpp | 153 ---- .../test/CommonLibTests/Helpers.cpp | 41 - .../test/CommonLibTests/Helpers.h | 28 - .../test/CommonLibTests/NativeTests.targets | 8 - .../CommonLibTests/PipeOutputManagerTests.cpp | 162 ---- .../exception_handler_tests.cpp | 49 -- .../test/CommonLibTests/fakeclasses.h | 190 ----- .../CommonLibTests/hostfxr_utility_tests.cpp | 122 --- .../inprocess_application_tests.cpp | 85 -- .../test/CommonLibTests/main.cpp | 12 - .../test/CommonLibTests/stdafx.h | 59 -- .../test/CommonLibTests/utility_tests.cpp | 75 -- .../IISIntegration/test/Directory.Build.props | 16 - .../BackwardsCompatibilityTests.cs | 39 - .../DeployerSelector.cs | 14 - ...kwardsCompatibility.FunctionalTests.csproj | 46 -- .../DeployerSelector.cs | 14 - .../ForwardsCompatibilityTests.cs | 38 - ...rwardsCompatibility.FunctionalTests.csproj | 45 -- .../IIS.FunctionalTests/DeployerSelector.cs | 14 - .../IIS.FunctionalTests.csproj | 46 -- .../Inprocess/StdOutRedirectionTests.cs | 150 ---- .../MofFileTests.cs | 26 - .../Properties/AssemblyInfo.cs | 10 - .../RequiresIISAttribute.cs | 150 ---- .../ServicesTests.cs | 96 --- .../AppHostConfig/HostableWebCore.config | 198 ----- .../test/IIS.Tests/ClientDisconnectTests.cs | 302 ------- .../IIS.Tests/ConnectionIdFeatureTests.cs | 54 -- .../IIS.Tests/HttpBodyControlFeatureTests.cs | 31 - .../test/IIS.Tests/IIS.Tests.csproj | 32 - .../test/IIS.Tests/ResponseAbortTests.cs | 151 ---- .../test/IIS.Tests/StrictTestServerTests.cs | 24 - .../test/IIS.Tests/TestServerTest.cs | 35 - ...pIfHostableWebCoreNotAvailibleAttribute.cs | 17 - .../test/IIS.Tests/Utilities/TestServer.cs | 211 ----- .../DeployerSelector.cs | 14 - .../IISExpress.FunctionalTests/HttpsTests.cs | 60 -- .../IISExpress.FunctionalTests.csproj | 38 - .../InProcess/AuthenticationTests.cs | 70 -- .../InProcess/ShutdownTests.cs | 90 --- .../InProcess/WebSocketTests.cs | 79 -- .../OutOfProcess/MultipleAppTests.cs | 81 -- .../OutOfProcess/NtlmAuthentationTest.cs | 87 -- .../Properties/AssemblyInfo.cs | 10 - .../RequiresIISAttribute.cs | 24 - .../UpgradeFeatureDetectionTests.cs | 83 -- .../IISExtensionTests.cs | 33 - .../IISMiddlewareTests.cs | 420 ---------- ...NetCore.Server.IISIntegration.Tests.csproj | 18 - .../test/TestTasks/InjectRequestHandler.cs | 62 -- .../test/TestTasks/TestTasks.csproj | 12 - .../test/WebSites/Directory.Build.props | 7 - .../InProcessWebSite.csproj | 31 - .../Properties/launchSettings.json | 42 - .../WebSites/InProcessWebSite/DummyServer.cs | 30 - .../InProcessWebSite/InProcessWebSite.csproj | 33 - .../test/WebSites/InProcessWebSite/Program.cs | 114 --- .../Properties/launchSettings.json | 42 - .../InProcessWebSite/Startup.WebSockets.cs | 147 ---- .../test/WebSites/InProcessWebSite/Startup.cs | 699 ----------------- .../test/WebSites/InProcessWebSite/web.config | 16 - .../InProcessWebSite/wwwroot/static.txt | 0 .../OutOfProcessWebSite.csproj | 31 - .../WebSites/OutOfProcessWebSite/Program.cs | 45 -- .../Properties/launchSettings.json | 42 - .../WebSites/OutOfProcessWebSite/Startup.cs | 105 --- .../OutOfProcessWebSite/wwwroot/static.txt | 0 .../WebSites/StressTestWebSite/Program.cs | 26 - .../Properties/launchSettings.json | 42 - .../WebSites/StressTestWebSite/Startup.cs | 232 ------ .../StressTestWebSite.csproj | 25 - .../shared/SharedStartup/Startup.shared.cs | 117 --- .../WebSites/shared/WebSockets/Constants.cs | 17 - .../shared/WebSockets/HandshakeHelpers.cs | 41 - .../WebSites/shared/WebSockets/TestStartup.cs | 38 - .../IISIntegration/test/gtest/gtest.vcxproj | 180 ----- 138 files changed, 5 insertions(+), 12403 deletions(-) delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/AppHostConfig/IIS.config delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/AppOfflineTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/BasicAuthTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/ClientCertificateFixture.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/ClientCertificateTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/ClientDisconnectStress.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/CommonStartupTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/CompressionTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/ConfigurationChangeTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/ClientDisconnectTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/CompressionTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/EnvironmentVariableTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/ErrorPagesTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/EventLogTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/FeatureCollectionTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/FixtureLoggedTest.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/FrebTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/HelloWorldTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/HostingEnvironmentTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/InvalidReadWriteOperationTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/LargeResponseBodyTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/LogPipeTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/ResponseHeaderTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/ResponseInvalidOrderingTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/ServerVariablesTest.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/StartupExceptionTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/StartupTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/SynchronousReadAndWriteTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/LogFileTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/MultiApplicationTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/OutOfProcess/AspNetCorePortTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/OutOfProcess/GlobalVersionTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/OutOfProcess/HelloWorldTest.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/PublishedSitesFixture.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/RequiresNewHandler.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/RequiresNewShim.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/ServerAbortTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/SkipIfNotAdminAttribute.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/SkipVSTSAttribute.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/AppVerifier.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/EventLogHelpers.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/FunctionalTestsBase.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/Helpers.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISCapability.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISCompressionSiteCollection.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISCompressionSiteFixture.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISFunctionalTestBase.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISTestSiteCollection.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISTestSiteFixture.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/LogFileTestBase.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/RequiresEnvironmentVariableAttribute.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/SkipIfDebugAttribute.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/WindowsAuthTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.Tests/Common.Tests.csproj delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.Tests/Utilities/DisposableList.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.Tests/Utilities/TestConnections.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Common.Tests/Utilities/TimeoutExtensions.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/CommonLibTests/CommonLibTests.vcxproj delete mode 100644 src/IISIntegration/src/IISIntegration/test/CommonLibTests/ConfigUtilityTests.cpp delete mode 100644 src/IISIntegration/src/IISIntegration/test/CommonLibTests/FileOutputManagerTests.cpp delete mode 100644 src/IISIntegration/src/IISIntegration/test/CommonLibTests/GlobalVersionTests.cpp delete mode 100644 src/IISIntegration/src/IISIntegration/test/CommonLibTests/Helpers.cpp delete mode 100644 src/IISIntegration/src/IISIntegration/test/CommonLibTests/Helpers.h delete mode 100644 src/IISIntegration/src/IISIntegration/test/CommonLibTests/NativeTests.targets delete mode 100644 src/IISIntegration/src/IISIntegration/test/CommonLibTests/PipeOutputManagerTests.cpp delete mode 100644 src/IISIntegration/src/IISIntegration/test/CommonLibTests/exception_handler_tests.cpp delete mode 100644 src/IISIntegration/src/IISIntegration/test/CommonLibTests/fakeclasses.h delete mode 100644 src/IISIntegration/src/IISIntegration/test/CommonLibTests/hostfxr_utility_tests.cpp delete mode 100644 src/IISIntegration/src/IISIntegration/test/CommonLibTests/inprocess_application_tests.cpp delete mode 100644 src/IISIntegration/src/IISIntegration/test/CommonLibTests/main.cpp delete mode 100644 src/IISIntegration/src/IISIntegration/test/CommonLibTests/stdafx.h delete mode 100644 src/IISIntegration/src/IISIntegration/test/CommonLibTests/utility_tests.cpp delete mode 100644 src/IISIntegration/src/IISIntegration/test/Directory.Build.props delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.BackwardsCompatibility.FunctionalTests/BackwardsCompatibilityTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.BackwardsCompatibility.FunctionalTests/DeployerSelector.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.BackwardsCompatibility.FunctionalTests/IIS.BackwardsCompatibility.FunctionalTests.csproj delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.ForwardsCompatibility.FunctionalTests/DeployerSelector.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.ForwardsCompatibility.FunctionalTests/ForwardsCompatibilityTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.ForwardsCompatibility.FunctionalTests/IIS.ForwardsCompatibility.FunctionalTests.csproj delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.FunctionalTests/DeployerSelector.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.FunctionalTests/IIS.FunctionalTests.csproj delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.Shared.FunctionalTests/Inprocess/StdOutRedirectionTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.Shared.FunctionalTests/MofFileTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.Shared.FunctionalTests/Properties/AssemblyInfo.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.Shared.FunctionalTests/RequiresIISAttribute.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.Shared.FunctionalTests/ServicesTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.Tests/AppHostConfig/HostableWebCore.config delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.Tests/ClientDisconnectTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.Tests/ConnectionIdFeatureTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.Tests/HttpBodyControlFeatureTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.Tests/IIS.Tests.csproj delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.Tests/ResponseAbortTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.Tests/StrictTestServerTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.Tests/TestServerTest.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.Tests/Utilities/SkipIfHostableWebCoreNotAvailibleAttribute.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IIS.Tests/Utilities/TestServer.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/DeployerSelector.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/HttpsTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/IISExpress.FunctionalTests.csproj delete mode 100644 src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/InProcess/AuthenticationTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/InProcess/ShutdownTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/InProcess/WebSocketTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/OutOfProcess/MultipleAppTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/OutOfProcess/NtlmAuthentationTest.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/Properties/AssemblyInfo.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/RequiresIISAttribute.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/UpgradeFeatureDetectionTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Microsoft.AspNetCore.Server.IISIntegration.Tests/IISExtensionTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Microsoft.AspNetCore.Server.IISIntegration.Tests/IISMiddlewareTests.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/Microsoft.AspNetCore.Server.IISIntegration.Tests/Microsoft.AspNetCore.Server.IISIntegration.Tests.csproj delete mode 100644 src/IISIntegration/src/IISIntegration/test/TestTasks/InjectRequestHandler.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/TestTasks/TestTasks.csproj delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/Directory.Build.props delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/InProcessForwardsCompatWebSite/InProcessWebSite.csproj delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/InProcessForwardsCompatWebSite/Properties/launchSettings.json delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/DummyServer.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/InProcessWebSite.csproj delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/Program.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/Properties/launchSettings.json delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/Startup.WebSockets.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/Startup.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/web.config delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/wwwroot/static.txt delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/OutOfProcessWebSite/OutOfProcessWebSite.csproj delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/OutOfProcessWebSite/Program.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/OutOfProcessWebSite/Properties/launchSettings.json delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/OutOfProcessWebSite/Startup.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/OutOfProcessWebSite/wwwroot/static.txt delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/StressTestWebSite/Program.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/StressTestWebSite/Properties/launchSettings.json delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/StressTestWebSite/Startup.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/StressTestWebSite/StressTestWebSite.csproj delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/shared/SharedStartup/Startup.shared.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/shared/WebSockets/Constants.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/shared/WebSockets/HandshakeHelpers.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/WebSites/shared/WebSockets/TestStartup.cs delete mode 100644 src/IISIntegration/src/IISIntegration/test/gtest/gtest.vcxproj diff --git a/src/IISIntegration/dependencies.overrides.props b/src/IISIntegration/dependencies.overrides.props index 8fa5d9fc58..5fb926e6f8 100644 --- a/src/IISIntegration/dependencies.overrides.props +++ b/src/IISIntegration/dependencies.overrides.props @@ -2,11 +2,12 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 + + 2.2.0-preview3-35497 + 2.2.0-preview3-35497 + 2.2.0-preview3-35497 + 2.1.0 2.1.0 2.1.0 diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/AppHostConfig/IIS.config b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/AppHostConfig/IIS.config deleted file mode 100644 index bc24ef9639..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/AppHostConfig/IIS.config +++ /dev/null @@ -1,740 +0,0 @@ - - - - - - - - -
-
-
-
-
-
-
-
- - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
- -
-
-
-
-
-
- -
-
-
-
-
- -
-
-
- -
-
- -
-
- -
-
-
- -
-
- - -
-
-
-
- -
-
-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/AppOfflineTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/AppOfflineTests.cs deleted file mode 100644 index 7d8d661ef0..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/AppOfflineTests.cs +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Net; -using System.Net.Http; -using System.Net.Sockets; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Testing.xunit; -using Microsoft.Extensions.Logging; -using Xunit; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; - -namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class AppOfflineTests : IISFunctionalTestBase - { - private static readonly TimeSpan RetryDelay = TimeSpan.FromMilliseconds(100); - - private readonly PublishedSitesFixture _fixture; - - public AppOfflineTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - [ConditionalTheory] - [InlineData(HostingModel.InProcess)] - [InlineData(HostingModel.OutOfProcess)] - public async Task AppOfflineDroppedWhileSiteIsDown_SiteReturns503(HostingModel hostingModel) - { - var deploymentResult = await DeployApp(hostingModel); - - AddAppOffline(deploymentResult.ContentRoot); - - await AssertAppOffline(deploymentResult); - DeletePublishOutput(deploymentResult); - } - - [ConditionalTheory] - [InlineData(HostingModel.InProcess)] - [InlineData(HostingModel.OutOfProcess)] - public async Task LockedAppOfflineDroppedWhileSiteIsDown_SiteReturns503(HostingModel hostingModel) - { - var deploymentResult = await DeployApp(hostingModel); - - // Add app_offline without shared access - using (var stream = File.Open(Path.Combine(deploymentResult.ContentRoot, "app_offline.htm"), FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None)) - using (var writer = new StreamWriter(stream)) - { - await writer.WriteLineAsync("App if offline but you wouldn't see this message"); - await writer.FlushAsync(); - await AssertAppOffline(deploymentResult, ""); - } - - DeletePublishOutput(deploymentResult); - } - - [ConditionalTheory] - [InlineData(HostingModel.InProcess, 500, "500.0")] - [InlineData(HostingModel.OutOfProcess, 502, "502.5")] - public async Task AppOfflineDroppedWhileSiteFailedToStartInShim_AppOfflineServed(HostingModel hostingModel, int statusCode, string content) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(hostingModel: hostingModel, publish: true); - deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("processPath", "nonexistent")); - - var deploymentResult = await DeployAsync(deploymentParameters); - - var result = await deploymentResult.HttpClient.GetAsync("/"); - Assert.Equal(statusCode, (int)result.StatusCode); - Assert.Contains(content, await result.Content.ReadAsStringAsync()); - - AddAppOffline(deploymentResult.ContentRoot); - - await AssertAppOffline(deploymentResult); - DeletePublishOutput(deploymentResult); - } - - [ConditionalFact(Skip = "https://github.com/aspnet/IISIntegration/issues/933")] - public async Task AppOfflineDroppedWhileSiteFailedToStartInRequestHandler_SiteStops_InProcess() - { - var deploymentResult = await DeployApp(HostingModel.InProcess); - - // Set file content to empty so it fails at runtime - File.WriteAllText(Path.Combine(deploymentResult.ContentRoot, "Microsoft.AspNetCore.Server.IIS.dll"), ""); - - var result = await deploymentResult.HttpClient.GetAsync("/"); - Assert.Equal(500, (int)result.StatusCode); - Assert.Contains("500.30", await result.Content.ReadAsStringAsync()); - - AddAppOffline(deploymentResult.ContentRoot); - - await deploymentResult.AssertRecycledAsync(() => AssertAppOffline(deploymentResult)); - } - - [ConditionalFact] - [RequiresIIS(IISCapability.ShutdownToken)] - public async Task AppOfflineDroppedWhileSiteStarting_SiteShutsDown_InProcess() - { - // This test often hits a race between debug logging and stdout redirection closing the handle - // we are fine having this race - using (AppVerifier.Disable(DeployerSelector.ServerType, 0x300)) - { - var deploymentResult = await DeployApp(HostingModel.InProcess); - - for (int i = 0; i < 10; i++) - { - // send first request and add app_offline while app is starting - var runningTask = AssertAppOffline(deploymentResult); - - // This test tries to hit a race where we drop app_offline file while - // in process application is starting, application start takes at least 400ms - // so we back off for 100ms to allow request to reach request handler - // Test itself is racy and can result in two scenarios - // 1. ANCM detects app_offline before it starts the request - if AssertAppOffline succeeds we've hit it - // 2. Intended scenario where app starts and then shuts down - // In first case we remove app_offline and try again - await Task.Delay(RetryDelay); - - AddAppOffline(deploymentResult.ContentRoot); - - try - { - await runningTask.DefaultTimeout(); - - // if AssertAppOffline succeeded ANCM have picked up app_offline before starting the app - // try again - RemoveAppOffline(deploymentResult.ContentRoot); - } - catch - { - deploymentResult.AssertWorkerProcessStop(); - return; - } - } - - Assert.True(false); - - } - } - - [ConditionalFact] - public async Task AppOfflineDroppedWhileSiteRunning_SiteShutsDown_InProcess() - { - var deploymentResult = await AssertStarts(HostingModel.InProcess); - - AddAppOffline(deploymentResult.ContentRoot); - - await deploymentResult.AssertRecycledAsync(() => AssertAppOffline(deploymentResult)); - } - - [ConditionalFact] - public async Task AppOfflineDroppedWhileSiteRunning_SiteShutsDown_OutOfProcess() - { - var deploymentResult = await AssertStarts(HostingModel.OutOfProcess); - - // Repeat dropping file and restarting multiple times - for (int i = 0; i < 5; i++) - { - AddAppOffline(deploymentResult.ContentRoot); - await AssertAppOffline(deploymentResult); - RemoveAppOffline(deploymentResult.ContentRoot); - await AssertRunning(deploymentResult); - } - - AddAppOffline(deploymentResult.ContentRoot); - await AssertAppOffline(deploymentResult); - DeletePublishOutput(deploymentResult); - } - - [ConditionalTheory] - [InlineData(HostingModel.InProcess)] - [InlineData(HostingModel.OutOfProcess)] - public async Task AppOfflineDropped_CanRemoveAppOfflineAfterAddingAndSiteWorks(HostingModel hostingModel) - { - var deploymentResult = await DeployApp(hostingModel); - - AddAppOffline(deploymentResult.ContentRoot); - - await AssertAppOffline(deploymentResult); - - RemoveAppOffline(deploymentResult.ContentRoot); - - await AssertRunning(deploymentResult); - } - - [ConditionalTheory] - [InlineData(HostingModel.InProcess)] - [InlineData(HostingModel.OutOfProcess)] - public async Task AppOfflineAddedAndRemovedStress(HostingModel hostingModel) - { - var deploymentResult = await AssertStarts(hostingModel); - - var load = Helpers.StressLoad(deploymentResult.HttpClient, "/HelloWorld", response => { - var statusCode = (int)response.StatusCode; - Assert.True(statusCode == 200 || statusCode == 503, "Status code was " + statusCode); - }); - - for (int i = 0; i < 100; i++) - { - // AddAppOffline might fail if app_offline is being read by ANCM and deleted at the same time - RetryHelper.RetryOperation( - () => AddAppOffline(deploymentResult.ContentRoot), - e => Logger.LogError($"Failed to create app_offline : {e.Message}"), - retryCount: 3, - retryDelayMilliseconds: RetryDelay.Milliseconds); - RemoveAppOffline(deploymentResult.ContentRoot); - } - - try - { - await load; - } - catch (HttpRequestException ex) when (ex.InnerException is IOException | ex.InnerException is SocketException) - { - // IOException in InProcess is fine, just means process stopped - if (hostingModel != HostingModel.InProcess) - { - throw; - } - } - } - - private async Task DeployApp(HostingModel hostingModel = HostingModel.InProcess) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(hostingModel: hostingModel, publish: true); - - return await DeployAsync(deploymentParameters); - } - - private void AddAppOffline(string appPath, string content = "The app is offline.") - { - File.WriteAllText(Path.Combine(appPath, "app_offline.htm"), content); - } - - private void RemoveAppOffline(string appPath) - { - RetryHelper.RetryOperation( - () => File.Delete(Path.Combine(appPath, "app_offline.htm")), - e => Logger.LogError($"Failed to remove app_offline : {e.Message}"), - retryCount: 3, - retryDelayMilliseconds: RetryDelay.Milliseconds); - } - - private async Task AssertAppOffline(IISDeploymentResult deploymentResult, string expectedResponse = "The app is offline.") - { - var response = await deploymentResult.HttpClient.RetryRequestAsync("HelloWorld", r => r.StatusCode == HttpStatusCode.ServiceUnavailable); - Assert.Equal(expectedResponse, await response.Content.ReadAsStringAsync()); - } - - private async Task AssertStarts(HostingModel hostingModel) - { - var deploymentResult = await DeployApp(hostingModel); - - await AssertRunning(deploymentResult); - - return deploymentResult; - } - - private static async Task AssertRunning(IISDeploymentResult deploymentResult) - { - var response = await deploymentResult.HttpClient.RetryRequestAsync("HelloWorld", r => r.IsSuccessStatusCode); - var responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal("Hello World", responseText); - } - - private void DeletePublishOutput(IISDeploymentResult deploymentResult) - { - foreach (var file in Directory.GetFiles(deploymentResult.ContentRoot, "*", SearchOption.AllDirectories)) - { - // Out of process module dll is allowed to be locked - var name = Path.GetFileName(file); - if (name == "aspnetcore.dll" || name == "aspnetcorev2.dll" || name == "aspnetcorev2_outofprocess.dll") - { - continue; - } - File.Delete(file); - } - } - - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/BasicAuthTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/BasicAuthTests.cs deleted file mode 100644 index d8607db21e..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/BasicAuthTests.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Text; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class BasicAuthTests : IISFunctionalTestBase - { - private readonly PublishedSitesFixture _fixture; - - public BasicAuthTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - public static TestMatrix TestVariants - => TestMatrix.ForServers(DeployerSelector.ServerType) - .WithTfms(Tfm.NetCoreApp22) - .WithApplicationTypes(ApplicationType.Portable) - .WithAllAncmVersions() - .WithAllHostingModels(); - - [ConditionalTheory] - [RequiresEnvironmentVariable("ASPNETCORE_MODULE_TEST_USER")] - [RequiresIIS(IISCapability.BasicAuthentication)] - [MemberData(nameof(TestVariants))] - public async Task BasicAuthTest(TestVariant variant) - { - var username = Environment.GetEnvironmentVariable("ASPNETCORE_MODULE_TEST_USER"); - var password = Environment.GetEnvironmentVariable("ASPNETCORE_MODULE_TEST_PASSWORD"); - - var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant, publish: true); - deploymentParameters.SetAnonymousAuth(enabled: false); - deploymentParameters.SetWindowsAuth(enabled: false); - deploymentParameters.SetBasicAuth(enabled: true); - - // The default in hosting sets windows auth to true. - var deploymentResult = await DeployAsync(deploymentParameters); - var request = new HttpRequestMessage(HttpMethod.Get, "/Auth"); - var byteArray = new UTF8Encoding().GetBytes(username + ":" + password); - request.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray)); - - var response = await deploymentResult.HttpClient.SendAsync(request); - - var responseText = await response.Content.ReadAsStringAsync(); - - if (variant.HostingModel == HostingModel.InProcess) - { - Assert.StartsWith("Windows", responseText); - Assert.Contains(username, responseText); - } - else - { - // We expect out-of-proc not allowing basic auth - Assert.Equal("Windows", responseText); - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/ClientCertificateFixture.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/ClientCertificateFixture.cs deleted file mode 100644 index 40b6f2265e..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/ClientCertificateFixture.cs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - public class ClientCertificateFixture : IDisposable - { - private X509Certificate2 _certificate; - private const string _certIssuerPrefix = "CN=IISIntegrationTest_Root"; - - public X509Certificate2 GetOrCreateCertificate() - { - if (_certificate != null) - { - return _certificate; - } - - using (var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine)) - { - store.Open(OpenFlags.ReadWrite); - var parentKey = CreateKeyMaterial(2048); - - // Create a cert name with a random guid to avoid name conflicts - var parentRequest = new CertificateRequest( - _certIssuerPrefix + Guid.NewGuid().ToString(), - parentKey, HashAlgorithmName.SHA256, - RSASignaturePadding.Pkcs1); - - parentRequest.CertificateExtensions.Add( - new X509BasicConstraintsExtension( - certificateAuthority: true, - hasPathLengthConstraint: false, - pathLengthConstraint: 0, - critical: true)); - - parentRequest.CertificateExtensions.Add( - new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.NonRepudiation, critical: true)); - - parentRequest.CertificateExtensions.Add( - new X509SubjectKeyIdentifierExtension(parentRequest.PublicKey, false)); - - var notBefore = DateTimeOffset.Now.AddDays(-1); - var notAfter = DateTimeOffset.Now.AddYears(5); - - var parentCert = parentRequest.CreateSelfSigned(notBefore, notAfter); - - // Need to export/import the certificate to associate the private key with the cert. - var imported = parentCert; - - var export = parentCert.Export(X509ContentType.Pkcs12, ""); - imported = new X509Certificate2(export, "", X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); - Array.Clear(export, 0, export.Length); - - // Add the cert to the cert store - _certificate = imported; - - store.Add(certificate: imported); - store.Close(); - return imported; - } - } - - public void Dispose() - { - if (_certificate == null) - { - return; - } - - using (var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine)) - { - store.Open(OpenFlags.ReadWrite); - store.Remove(_certificate); - - // Remove any extra certs that were left by previous tests. - for (var i = store.Certificates.Count - 1; i >= 0; i--) - { - var cert = store.Certificates[i]; - if (cert.Issuer.StartsWith(_certIssuerPrefix)) - { - store.Remove(cert); - } - } - store.Close(); - } - } - - private RSA CreateKeyMaterial(int minimumKeySize) - { - var rsa = RSA.Create(minimumKeySize); - if (rsa.KeySize < minimumKeySize) - { - throw new InvalidOperationException($"Failed to create a key with a size of {minimumKeySize} bits"); - } - - return rsa; - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/ClientCertificateTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/ClientCertificateTests.cs deleted file mode 100644 index 43ccc83eff..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/ClientCertificateTests.cs +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Net.Http; -using System.Security.Cryptography.X509Certificates; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.Common; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.AspNetCore.Testing.xunit; -using Microsoft.Extensions.Logging; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - [SkipIfNotAdmin] - public class ClientCertificateTests : IISFunctionalTestBase - { - private readonly PublishedSitesFixture _fixture; - private readonly ClientCertificateFixture _certFixture; - - public ClientCertificateTests(PublishedSitesFixture fixture, ClientCertificateFixture certFixture) - { - _fixture = fixture; - _certFixture = certFixture; - } - - public static TestMatrix TestVariants - => TestMatrix.ForServers(DeployerSelector.ServerType) - .WithTfms(Tfm.NetCoreApp22, Tfm.Net461) - .WithAllApplicationTypes() - .WithAllAncmVersions() - .WithAllHostingModels(); - - [ConditionalTheory] - [MemberData(nameof(TestVariants))] - public Task HttpsNoClientCert_NoClientCert(TestVariant variant) - { - return ClientCertTest(variant, sendClientCert: false); - } - - [ConditionalTheory] - [MemberData(nameof(TestVariants))] - public Task HttpsClientCert_GetCertInformation(TestVariant variant) - { - return ClientCertTest(variant, sendClientCert: true); - } - - private async Task ClientCertTest(TestVariant variant, bool sendClientCert) - { - var port = TestPortHelper.GetNextSSLPort(); - var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant); - deploymentParameters.ApplicationBaseUriHint = $"https://localhost:{port}/"; - deploymentParameters.AddHttpsToServerConfig(); - - var handler = new HttpClientHandler - { - ServerCertificateCustomValidationCallback = (a, b, c, d) => true, - ClientCertificateOptions = ClientCertificateOption.Manual, - }; - - X509Certificate2 cert = null; - if (sendClientCert) - { - cert = _certFixture.GetOrCreateCertificate(); - handler.ClientCertificates.Add(cert); - } - - var deploymentResult = await DeployAsync(deploymentParameters); - - var client = deploymentResult.CreateClient(handler); - var response = await client.GetAsync("GetClientCert"); - - var responseText = await response.Content.ReadAsStringAsync(); - - try - { - if (sendClientCert) - { - Assert.Equal($"Enabled;{cert.GetCertHashString()}", responseText); - } - else - { - Assert.Equal("Disabled", responseText); - } - } - catch (Exception ex) - { - Logger.LogError($"Certificate is invalid. Issuer name: {cert.Issuer}"); - using (var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine)) - { - Logger.LogError($"List of current certificates in root store:"); - store.Open(OpenFlags.ReadWrite); - foreach (var otherCert in store.Certificates) - { - Logger.LogError(otherCert.Issuer); - } - store.Close(); - } - throw ex; - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/ClientDisconnectStress.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/ClientDisconnectStress.cs deleted file mode 100644 index 9deeae3f92..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/ClientDisconnectStress.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class ClientDisconnectStressTests: FunctionalTestsBase - { - private readonly PublishedSitesFixture _fixture; - - public ClientDisconnectStressTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - [ConditionalTheory] - [InlineData(HostingModel.InProcess)] - [InlineData(HostingModel.OutOfProcess)] - public async Task ClientDisconnectStress(HostingModel hostingModel) - { - var site = await StartAsync(_fixture.GetBaseDeploymentParameters(hostingModel)); - var maxRequestSize = 1000; - var blockSize = 40; - var random = new Random(); - async Task RunRequests() - { - using (var connection = new TestConnection(site.HttpClient.BaseAddress.Port)) - { - await connection.Send( - "POST /ReadAndFlushEcho HTTP/1.1", - $"Content-Length: {maxRequestSize}", - "Host: localhost", - "Connection: close", - "", - ""); - - var disconnectAfter = random.Next(maxRequestSize); - var data = new byte[blockSize]; - for (int i = 0; i < disconnectAfter / blockSize; i++) - { - await connection.Stream.WriteAsync(data); - } - } - } - - List tasks = new List(); - for (int i = 0; i < 100; i++) - { - tasks.Add(Task.Run(RunRequests)); - } - - await Task.WhenAll(tasks); - - StopServer(); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/CommonStartupTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/CommonStartupTests.cs deleted file mode 100644 index e2bcf2a8f9..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/CommonStartupTests.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Net; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class CommonStartupTests : IISFunctionalTestBase - { - private readonly PublishedSitesFixture _fixture; - - public CommonStartupTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - public static TestMatrix TestVariants - => TestMatrix.ForServers(DeployerSelector.ServerType) - .WithTfms(Tfm.NetCoreApp22) - .WithAllApplicationTypes() - .WithAllAncmVersions() - .WithAllHostingModels(); - - [ConditionalTheory] - [MemberData(nameof(TestVariants))] - public async Task StartupStress(TestVariant variant) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant, publish: true); - - var deploymentResult = await DeployAsync(deploymentParameters); - - await Helpers.StressLoad(deploymentResult.HttpClient, "/HelloWorld", response => { - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal("Hello World", response.Content.ReadAsStringAsync().GetAwaiter().GetResult()); - }); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/CompressionTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/CompressionTests.cs deleted file mode 100644 index c2d0277c4c..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/CompressionTests.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Linq; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISCompressionSiteCollection.Name)] - public abstract class CompressionTests : FixtureLoggedTest - { - private readonly IISTestSiteFixture _fixture; - - [Collection(IISTestSiteCollection.Name)] - public class InProc: CompressionTests - { - public InProc(IISTestSiteFixture fixture) : base(fixture) { } - } - - [Collection(OutOfProcessTestSiteCollection.Name)] - public class OutOfProcess: CompressionTests - { - public OutOfProcess(OutOfProcessTestSiteFixture fixture) : base(fixture) { } - } - - [Collection(OutOfProcessV1TestSiteCollection.Name)] - public class OutOfProcessV1: CompressionTests - { - public OutOfProcessV1(OutOfProcessV1TestSiteFixture fixture) : base(fixture) { } - } - - protected CompressionTests(IISTestSiteFixture fixture) : base(fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task PassesThroughCompression() - { - var request = new HttpRequestMessage(HttpMethod.Get, "/CompressedData"); - - request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip")); - - var response = await _fixture.Client.SendAsync(request); - Assert.Equal("gzip", response.Content.Headers.ContentEncoding.Single()); - Assert.Equal( - new byte[] { - 0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x0B, 0x63, 0x60, 0xA0, 0x3D, 0x00, 0x00, - 0xCA, 0xC6, 0x88, 0x99, 0x64, 0x00, 0x00, 0x00 }, - await response.Content.ReadAsByteArrayAsync()); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/ConfigurationChangeTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/ConfigurationChangeTests.cs deleted file mode 100644 index 099cefb97a..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/ConfigurationChangeTests.cs +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Net.Sockets; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.AspNetCore.Testing.xunit; -using Microsoft.Extensions.Logging; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class ConfigurationChangeTests : IISFunctionalTestBase - { - private static readonly TimeSpan RetryDelay = TimeSpan.FromMilliseconds(100); - private readonly PublishedSitesFixture _fixture; - - public ConfigurationChangeTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task ConfigurationChangeStopsInProcess() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(HostingModel.InProcess, publish: true); - - var deploymentResult = await DeployAsync(deploymentParameters); - - await deploymentResult.AssertStarts(); - - // Just "touching" web.config should be enough - deploymentResult.ModifyWebConfig(element => {}); - - await deploymentResult.AssertRecycledAsync(); - } - - [ConditionalTheory] - [InlineData(AncmVersion.AspNetCoreModule)] - [InlineData(AncmVersion.AspNetCoreModuleV2)] - public async Task ConfigurationChangeForcesChildProcessRestart(AncmVersion version) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(HostingModel.OutOfProcess, publish: true); - deploymentParameters.AncmVersion = version; - - var deploymentResult = await DeployAsync(deploymentParameters); - - var processBefore = await deploymentResult.HttpClient.GetStringAsync("/ProcessId"); - - // Just "touching" web.config should be enough - deploymentResult.ModifyWebConfig(element => {}); - - // Have to retry here to allow ANCM to receive notification and react to it - // Verify that worker process gets restarted with new process id - await deploymentResult.HttpClient.RetryRequestAsync("/ProcessId", async r => await r.Content.ReadAsStringAsync() != processBefore); - } - - [ConditionalFact] - public async Task OutOfProcessToInProcessHostingModelSwitchWorks() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(HostingModel.OutOfProcess, publish: true); - - var deploymentResult = await DeployAsync(deploymentParameters); - - await deploymentResult.AssertStarts(); - - deploymentResult.ModifyWebConfig(element => element - .Descendants("system.webServer") - .Single() - .GetOrAdd("aspNetCore") - .SetAttributeValue("hostingModel", "inprocess")); - - // Have to retry here to allow ANCM to receive notification and react to it - // Verify that inprocess application was created and tried to start - await deploymentResult.HttpClient.RetryRequestAsync("/HelloWorld", r => r.StatusCode == HttpStatusCode.InternalServerError); - - StopServer(); - EventLogHelpers.VerifyEventLogEvent(deploymentResult, "Could not find the assembly 'aspnetcorev2_inprocess.dll'", Logger); - } - - [ConditionalTheory] - [InlineData(HostingModel.InProcess)] - [InlineData(HostingModel.OutOfProcess)] - public async Task ConfigurationTouchedStress(HostingModel hostingModel) - { - var deploymentResult = await DeployAsync(_fixture.GetBaseDeploymentParameters(hostingModel, publish: true)); - - await deploymentResult.AssertStarts(); - var load = Helpers.StressLoad(deploymentResult.HttpClient, "/HelloWorld", response => { - var statusCode = (int)response.StatusCode; - Assert.True(statusCode == 200 || statusCode == 503, "Status code was " + statusCode); - }); - - for (int i = 0; i < 100; i++) - { - // ModifyWebConfig might fail if web.config is being read by IIS - RetryHelper.RetryOperation( - () => deploymentResult.ModifyWebConfig(element => {}), - e => Logger.LogError($"Failed to touch web.config : {e.Message}"), - retryCount: 3, - retryDelayMilliseconds: RetryDelay.Milliseconds); - } - - try - { - await load; - } - catch (HttpRequestException ex) when (ex.InnerException is IOException | ex.InnerException is SocketException) - { - // IOException in InProcess is fine, just means process stopped - if (hostingModel != HostingModel.InProcess) - { - throw; - } - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/ClientDisconnectTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/ClientDisconnectTests.cs deleted file mode 100644 index 6e2d1bc752..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/ClientDisconnectTests.cs +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Microsoft.Extensions.Logging; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class ClientDisconnectTests: FixtureLoggedTest - { - private readonly IISTestSiteFixture _fixture; - - public ClientDisconnectTests(IISTestSiteFixture fixture): base(fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task ServerWorksAfterClientDisconnect() - { - using (var connection = _fixture.CreateTestConnection()) - { - var message = "Hello"; - await connection.Send( - "POST /ReadAndWriteSynchronously HTTP/1.1", - $"Content-Length: {100000}", - "Host: localhost", - "Connection: close", - "", - ""); - - await connection.Send(message); - - await connection.Receive( - "HTTP/1.1 200 OK", - ""); - } - - var response = await _fixture.Client.GetAsync("HelloWorld"); - - var responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal("Hello World", responseText); - } - - [ConditionalFact] - public async Task RequestAbortedTokenFires() - { - using (var connection = _fixture.CreateTestConnection()) - { - await connection.Send( - "GET /WaitForAbort HTTP/1.1", - "Host: localhost", - "Connection: close", - "", - ""); - - await _fixture.Client.RetryRequestAsync("/WaitingRequestCount", async message => await message.Content.ReadAsStringAsync() == "1"); - } - - await _fixture.Client.RetryRequestAsync("/WaitingRequestCount", async message => await message.Content.ReadAsStringAsync() == "0"); - } - - [ConditionalFact] - public async Task ClientDisconnectCallbackStress() - { - // Fixture initialization fails if inside of the Task.Run, so send an - // initial request to initialize the fixture. - var response = await _fixture.Client.GetAsync("HelloWorld"); - var numTotalRequests = 0; - for (var j = 0; j < 20; j++) - { - // Windows has a max connection limit of 10 for the IIS server, - // so setting limit fairly low. - const int numRequests = 5; - async Task RunRequests() - { - using (var connection = _fixture.CreateTestConnection()) - { - await connection.Send( - "GET /WaitForAbort HTTP/1.1", - "Host: localhost", - "Connection: close", - "", - ""); - await _fixture.Client.RetryRequestAsync("/WaitingRequestCount", async message => await message.Content.ReadAsStringAsync() != "0"); - Interlocked.Increment(ref numTotalRequests); - } - } - - List tasks = new List(); - for (int i = 0; i < numRequests; i++) - { - tasks.Add(Task.Run(RunRequests)); - } - - await Task.WhenAll(tasks); - - await _fixture.Client.RetryRequestAsync("/WaitingRequestCount", async message => await message.Content.ReadAsStringAsync() == "0"); - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/CompressionTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/CompressionTests.cs deleted file mode 100644 index ce1c84e609..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/CompressionTests.cs +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISCompressionSiteCollection.Name)] - public class CompressionModuleTests : FixtureLoggedTest - { - private readonly IISCompressionSiteFixture _fixture; - - public CompressionModuleTests(IISCompressionSiteFixture fixture): base(fixture) - { - _fixture = fixture; - } - - [ConditionalTheory] - [RequiresIIS(IISCapability.DynamicCompression)] - [InlineData(true)] - [InlineData(false)] - public async Task BufferingDisabled(bool compression) - { - using (var connection = _fixture.CreateTestConnection()) - { - var requestLength = 0; - var messages = new List(); - for (var i = 1; i < 100; i++) - { - var message = i + Environment.NewLine; - requestLength += message.Length; - messages.Add(message); - } - - await connection.Send( - "POST /ReadAndWriteEchoLinesNoBuffering HTTP/1.1", - $"Content-Length: {requestLength}", - "Accept-Encoding: " + (compression ? "gzip": "identity"), - "Response-Content-Type: text/event-stream", - "Host: localhost", - "Connection: close", - "", - ""); - - await connection.Receive( - "HTTP/1.1 200 OK", - ""); - await connection.ReceiveHeaders(); - - foreach (var message in messages) - { - await connection.Send(message); - await connection.ReceiveChunk(message); - } - - await connection.Send("\r\n"); - await connection.ReceiveChunk(""); - await connection.WaitForConnectionClose(); - } - } - - [ConditionalFact] - [RequiresIIS(IISCapability.DynamicCompression)] - public async Task DynamicResponsesAreCompressed() - { - var handler = new HttpClientHandler - { - AutomaticDecompression = DecompressionMethods.GZip - }; - var client = new HttpClient(handler) - { - BaseAddress = _fixture.Client.BaseAddress, - }; - client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip")); - client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("identity", 0)); - client.DefaultRequestHeaders.Add("Response-Content-Type", "text/event-stream"); - var messages = "Message1\r\nMessage2\r\n"; - - // Send messages with terminator - var response = await client.PostAsync("ReadAndWriteEchoLines", new StringContent(messages + "\r\n")); - Assert.Equal(messages, await response.Content.ReadAsStringAsync()); - Assert.True(response.Content.Headers.TryGetValues("Content-Type", out var contentTypes)); - Assert.Single(contentTypes, "text/event-stream"); - // Not the cleanest check but I wasn't able to figure out other way to check - // that response was compressed - Assert.Contains("gzip", response.Content.GetType().FullName, StringComparison.OrdinalIgnoreCase); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/EnvironmentVariableTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/EnvironmentVariableTests.cs deleted file mode 100644 index ae8fde39ed..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/EnvironmentVariableTests.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class EnvironmentVariableTests: FixtureLoggedTest - { - private readonly IISTestSiteFixture _fixture; - - public EnvironmentVariableTests(IISTestSiteFixture fixture): base(fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task GetUniqueEnvironmentVariable() - { - Assert.Equal("foobar", await _fixture.Client.GetStringAsync("/CheckEnvironmentVariable")); - } - - [ConditionalFact] - public async Task GetLongEnvironmentVariable() - { - Assert.Equal( - "AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" + - "AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" + - "AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" + - "AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" + - "AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" + - "AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative", - await _fixture.Client.GetStringAsync("/CheckEnvironmentLongValueVariable")); - } - - [ConditionalFact] - public async Task GetExistingEnvironmentVariable() - { - Assert.Contains(";foobarbaz", await _fixture.Client.GetStringAsync("/CheckAppendedEnvironmentVariable")); - } - - [ConditionalFact] - public async Task AuthHeaderEnvironmentVariableRemoved() - { - Assert.DoesNotContain("shouldberemoved", await _fixture.Client.GetStringAsync("/CheckRemoveAuthEnvironmentVariable")); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/ErrorPagesTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/ErrorPagesTests.cs deleted file mode 100644 index bf45949491..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/ErrorPagesTests.cs +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class ErrorPagesTests : IISFunctionalTestBase - { - private readonly PublishedSitesFixture _fixture; - - public ErrorPagesTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - [RequiresIIS(IISCapability.PoolEnvironmentVariables)] - public async Task IncludesAdditionalErrorPageTextInProcessHandlerLoadFailure_CorrectString() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true); - var response = await DeployAppWithStartupFailure(deploymentParameters); - - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - - StopServer(); - - var responseString = await response.Content.ReadAsStringAsync(); - Assert.Contains("HTTP Error 500.0 - ANCM In-Process Handler Load Failure", responseString); - VerifyNoExtraTrailingBytes(responseString); - - await AssertLink(response); - } - - [ConditionalFact] - [RequiresIIS(IISCapability.PoolEnvironmentVariables)] - public async Task IncludesAdditionalErrorPageTextOutOfProcessStartupFailure_CorrectString() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(HostingModel.OutOfProcess, publish: true); - var response = await DeployAppWithStartupFailure(deploymentParameters); - - Assert.Equal(HttpStatusCode.BadGateway, response.StatusCode); - - StopServer(); - - var responseString = await response.Content.ReadAsStringAsync(); - Assert.Contains("HTTP Error 502.5 - ANCM Out-Of-Process Startup Failure", responseString); - VerifyNoExtraTrailingBytes(responseString); - - await AssertLink(response); - } - - [ConditionalFact] - [RequiresIIS(IISCapability.PoolEnvironmentVariables)] - public async Task IncludesAdditionalErrorPageTextOutOfProcessHandlerLoadFailure_CorrectString() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(HostingModel.OutOfProcess, publish: true); - deploymentParameters.HandlerSettings["handlerVersion"] = "88.93"; - deploymentParameters.EnvironmentVariables["ANCM_ADDITIONAL_ERROR_PAGE_LINK"] = "http://example"; - - var deploymentResult = await DeployAsync(deploymentParameters); - var response = await deploymentResult.HttpClient.GetAsync("HelloWorld"); - - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - - StopServer(); - - var responseString = await response.Content.ReadAsStringAsync(); - Assert.Contains("HTTP Error 500.0 - ANCM Out-Of-Process Handler Load Failure", responseString); - VerifyNoExtraTrailingBytes(responseString); - - await AssertLink(response); - } - - [ConditionalFact] - [RequiresIIS(IISCapability.PoolEnvironmentVariables)] - [RequiresNewHandler] - public async Task IncludesAdditionalErrorPageTextInProcessStartupFailure_CorrectString() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true); - deploymentParameters.TransformArguments((a, _) => $"{a} EarlyReturn"); - deploymentParameters.EnvironmentVariables["ANCM_ADDITIONAL_ERROR_PAGE_LINK"] = "http://example"; - - var deploymentResult = await DeployAsync(deploymentParameters); - var response = await deploymentResult.HttpClient.GetAsync("HelloWorld"); - - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - - StopServer(); - - var responseString = await response.Content.ReadAsStringAsync(); - Assert.Contains("HTTP Error 500.30 - ANCM In-Process Start Failure", responseString); - VerifyNoExtraTrailingBytes(responseString); - - await AssertLink(response); - } - - private static void VerifyNoExtraTrailingBytes(string responseString) - { - if (!DeployerSelector.IsBackwardsCompatiblityTest) - { - Assert.EndsWith("\r\n", responseString); - } - } - - private static async Task AssertLink(HttpResponseMessage response) - { - Assert.Contains(" http://example and ", await response.Content.ReadAsStringAsync()); - } - - private async Task DeployAppWithStartupFailure(IISDeploymentParameters deploymentParameters) - { - deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("processPath", "doesnot")); - deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("arguments", "start")); - - deploymentParameters.EnvironmentVariables["ANCM_ADDITIONAL_ERROR_PAGE_LINK"] = "http://example"; - - var deploymentResult = await DeployAsync(deploymentParameters); - - return await deploymentResult.HttpClient.GetAsync("HelloWorld"); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/EventLogTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/EventLogTests.cs deleted file mode 100644 index 1df7f3c077..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/EventLogTests.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class EventLogTests : IISFunctionalTestBase - { - private readonly PublishedSitesFixture _fixture; - - public EventLogTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task CheckStartupEventLogMessage() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true); - - var deploymentResult = await DeployAsync(deploymentParameters); - await deploymentResult.AssertStarts(); - - StopServer(); - - EventLogHelpers.VerifyEventLogEvent(deploymentResult, "Application '.+' started the coreclr in-process successfully."); - } - - [ConditionalFact] - public async Task CheckShutdownEventLogMessage() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true); - var deploymentResult = await DeployAsync(deploymentParameters); - await deploymentResult.AssertStarts(); - - StopServer(); - - EventLogHelpers.VerifyEventLogEvent(deploymentResult, "Application '.+' has shutdown."); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/FeatureCollectionTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/FeatureCollectionTests.cs deleted file mode 100644 index e31dc3dbaa..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/FeatureCollectionTests.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class FeatureCollectionTest - { - private readonly IISTestSiteFixture _fixture; - - public FeatureCollectionTest(IISTestSiteFixture fixture) - { - _fixture = fixture; - } - - [ConditionalTheory] - [InlineData("FeatureCollectionSetRequestFeatures")] - [InlineData("FeatureCollectionSetResponseFeatures")] - [InlineData("FeatureCollectionSetConnectionFeatures")] - public async Task FeatureCollectionTest_SetHttpContextFeatures(string path) - { - Assert.Equal("Success", await _fixture.Client.GetStringAsync(path + "/path" + "?query")); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/FixtureLoggedTest.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/FixtureLoggedTest.cs deleted file mode 100644 index 705af2b213..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/FixtureLoggedTest.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Reflection; -using Microsoft.Extensions.Logging.Testing; -using Xunit.Abstractions; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - public class FixtureLoggedTest: LoggedTest - { - private readonly IISTestSiteFixture _fixture; - - public FixtureLoggedTest(IISTestSiteFixture fixture) - { - _fixture = fixture; - } - - public override void Initialize(MethodInfo methodInfo, object[] testMethodArguments, ITestOutputHelper testOutputHelper) - { - base.Initialize(methodInfo, testMethodArguments, testOutputHelper); - _fixture.Attach(this); - } - - public override void Dispose() - { - _fixture.Detach(this); - base.Dispose(); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/FrebTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/FrebTests.cs deleted file mode 100644 index 12e2f6ae53..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/FrebTests.cs +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using System.Xml.Linq; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.AspNetCore.Testing.xunit; -using Microsoft.Extensions.Logging; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class FrebTests : LogFileTestBase - { - private readonly PublishedSitesFixture _fixture; - public FrebTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - public static IList FrebChecks() - { - var list = new List(); - list.Add(new FrebLogItem("ANCM_INPROC_EXECUTE_REQUEST_START")); - list.Add(new FrebLogItem("ANCM_INPROC_EXECUTE_REQUEST_COMPLETION", "1")); - list.Add(new FrebLogItem("ANCM_INPROC_ASYNC_COMPLETION_START")); - list.Add(new FrebLogItem("ANCM_INPROC_ASYNC_COMPLETION_COMPLETION", "0")); - list.Add(new FrebLogItem("ANCM_INPROC_MANAGED_REQUEST_COMPLETION")); - return list; - } - - [ConditionalFact] - [RequiresIIS(IISCapability.FailedRequestTracingModule)] - public async Task CheckCommonFrebEvents() - { - var result = await SetupFrebApp(); - - await result.HttpClient.GetAsync("HelloWorld"); - - StopServer(); - - AssertFrebLogs(result, FrebChecks()); - } - - [ConditionalFact] - [RequiresNewShim] - [RequiresIIS(IISCapability.FailedRequestTracingModule)] - public async Task FrebIncludesHResultFailures() - { - var parameters = _fixture.GetBaseDeploymentParameters(publish: true); - parameters.TransformArguments((args, _) => string.Empty); - var result = await SetupFrebApp(parameters); - - await result.HttpClient.GetAsync("HelloWorld"); - - StopServer(); - - AssertFrebLogs(result, new FrebLogItem("ANCM_HRESULT_FAILED"), new FrebLogItem("ANCM_EXCEPTION_CAUGHT")); - } - - [ConditionalFact] - [RequiresIIS(IISCapability.FailedRequestTracingModule)] - public async Task CheckFailedRequestEvents() - { - var result = await SetupFrebApp(); - - await result.HttpClient.GetAsync("Throw"); - - StopServer(); - - AssertFrebLogs(result, new FrebLogItem("ANCM_INPROC_ASYNC_COMPLETION_COMPLETION", "2")); - } - - [ConditionalFact] - [RequiresIIS(IISCapability.FailedRequestTracingModule)] - public async Task CheckFrebDisconnect() - { - var result = await SetupFrebApp(); - - using (var connection = new TestConnection(result.HttpClient.BaseAddress.Port)) - { - await connection.Send( - "GET /WaitForAbort HTTP/1.1", - "Host: localhost", - "Connection: close", - "", - ""); - await result.HttpClient.RetryRequestAsync("/WaitingRequestCount", async message => await message.Content.ReadAsStringAsync() == "1"); - } - - StopServer(); - - // The order of freb logs is based on when the requests are complete. - // This is non-deterministic here, so we need to check both freb files for a request that was disconnected. - AssertFrebLogs(result, new FrebLogItem("ANCM_INPROC_REQUEST_DISCONNECT"), new FrebLogItem("ANCM_INPROC_MANAGED_REQUEST_COMPLETION")); - } - - private async Task SetupFrebApp(IISDeploymentParameters parameters = null) - { - parameters = parameters ?? _fixture.GetBaseDeploymentParameters(publish: true); - parameters.EnableFreb("Verbose", _logFolderPath); - - Directory.CreateDirectory(_logFolderPath); - var result = await DeployAsync(parameters); - return result; - } - - private void AssertFrebLogs(IISDeploymentResult result, params FrebLogItem[] expectedFrebEvents) - { - AssertFrebLogs(result, (IEnumerable)expectedFrebEvents); - } - - private void AssertFrebLogs(IISDeploymentResult result, IEnumerable expectedFrebEvents) - { - var frebEvent = GetFrebLogItems(result); - foreach (var expectedEvent in expectedFrebEvents) - { - Assert.Contains(expectedEvent, frebEvent); - } - } - - private IEnumerable GetFrebLogItems(IISDeploymentResult result) - { - var folderPath = Helpers.GetFrebFolder(_logFolderPath, result); - var xmlFiles = Directory.GetFiles(folderPath).Where(f => f.EndsWith("xml")); - var frebEvents = new List(); - - foreach (var xmlFile in xmlFiles) - { - var xDocument = XDocument.Load(xmlFile).Root; - var nameSpace = (XNamespace)"http://schemas.microsoft.com/win/2004/08/events/event"; - var eventElements = xDocument.Descendants(nameSpace + "Event"); - foreach (var eventElement in eventElements) - { - var eventElementWithOpCode = eventElement.Descendants(nameSpace + "RenderingInfo").Single().Descendants(nameSpace + "Opcode").Single(); - var requestStatus = eventElement.Element(nameSpace + "EventData").Descendants().Where(el => el.Attribute("Name").Value == "requestStatus").SingleOrDefault(); - frebEvents.Add(new FrebLogItem(eventElementWithOpCode.Value, requestStatus?.Value)); - } - } - - return frebEvents; - } - - public class FrebLogItem - { - private string _opCode; - private string _requestStatus; - - public FrebLogItem(string opCode) - { - _opCode = opCode; - } - - public FrebLogItem(string opCode, string requestStatus) - { - _opCode = opCode; - _requestStatus = requestStatus; - } - - public override bool Equals(object obj) - { - var item = obj as FrebLogItem; - return item != null && - _opCode == item._opCode && - _requestStatus == item._requestStatus; - } - - public override int GetHashCode() - { - return HashCode.Combine(_opCode, _requestStatus); - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/HelloWorldTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/HelloWorldTests.cs deleted file mode 100644 index 1b2ad70600..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/HelloWorldTests.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class HelloWorldInProcessTests - { - private readonly IISTestSiteFixture _fixture; - - public HelloWorldInProcessTests(IISTestSiteFixture fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task HelloWorld_InProcess() - { - Assert.Equal("Hello World", await _fixture.Client.GetStringAsync("/HelloWorld")); - - Assert.Equal("/Path??", await _fixture.Client.GetStringAsync("/HelloWorld/Path%3F%3F?query")); - - Assert.Equal("?query", await _fixture.Client.GetStringAsync("/HelloWorld/Query%3F%3F?query")); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/HostingEnvironmentTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/HostingEnvironmentTests.cs deleted file mode 100644 index 061b828a6c..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/HostingEnvironmentTests.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class HostingEnvironmentTests: FixtureLoggedTest - { - private readonly IISTestSiteFixture _fixture; - - public HostingEnvironmentTests(IISTestSiteFixture fixture): base(fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - [RequiresIIS(IISCapability.ShutdownToken)] - public async Task HostingEnvironmentIsCorrect() - { - Assert.Equal( - $"ContentRootPath {_fixture.DeploymentResult.ContentRoot}" + Environment.NewLine + - $"WebRootPath {_fixture.DeploymentResult.ContentRoot}\\wwwroot" + Environment.NewLine + - $"CurrentDirectory {Path.GetDirectoryName(_fixture.DeploymentResult.HostProcess.MainModule.FileName)}", - await _fixture.Client.GetStringAsync("/HostingEnvironment")); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/InvalidReadWriteOperationTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/InvalidReadWriteOperationTests.cs deleted file mode 100644 index 95c05308bd..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/InvalidReadWriteOperationTests.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class InvalidReadWriteOperationTests - { - private readonly IISTestSiteFixture _fixture; - - public InvalidReadWriteOperationTests(IISTestSiteFixture fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task TestReadOffsetWorks() - { - var result = await _fixture.Client.PostAsync($"/TestReadOffsetWorks", new StringContent("Hello World")); - Assert.Equal("Hello World", await result.Content.ReadAsStringAsync()); - } - - [ConditionalTheory] - [InlineData("/InvalidOffsetSmall")] - [InlineData("/InvalidOffsetLarge")] - [InlineData("/InvalidCountSmall")] - [InlineData("/InvalidCountLarge")] - [InlineData("/InvalidCountWithOffset")] - public async Task TestInvalidReadOperations(string operation) - { - var result = await _fixture.Client.GetStringAsync($"/TestInvalidReadOperations{operation}"); - Assert.Equal("Success", result); - } - - [ConditionalTheory] - [InlineData("/NullBuffer")] - [InlineData("/InvalidCountZeroRead")] - public async Task TestValidReadOperations(string operation) - { - var result = await _fixture.Client.GetStringAsync($"/TestValidReadOperations{operation}"); - Assert.Equal("Success", result); - } - - [ConditionalTheory] - [InlineData("/NullBufferPost")] - [InlineData("/InvalidCountZeroReadPost")] - public async Task TestValidReadOperationsPost(string operation) - { - var result = await _fixture.Client.PostAsync($"/TestValidReadOperations{operation}", new StringContent("hello")); - Assert.Equal("Success", await result.Content.ReadAsStringAsync()); - } - - [ConditionalTheory] - [InlineData("/InvalidOffsetSmall")] - [InlineData("/InvalidOffsetLarge")] - [InlineData("/InvalidCountSmall")] - [InlineData("/InvalidCountLarge")] - [InlineData("/InvalidCountWithOffset")] - public async Task TestInvalidWriteOperations(string operation) - { - var result = await _fixture.Client.GetStringAsync($"/TestInvalidWriteOperations{operation}"); - Assert.Equal("Success", result); - } - - [ConditionalFact] - public async Task TestValidWriteOperations() - { - var result = await _fixture.Client.GetStringAsync($"/TestValidWriteOperations/NullBuffer"); - Assert.Equal("Success", result); - } - - [ConditionalFact] - public async Task TestValidWriteOperationsPost() - { - var result = await _fixture.Client.PostAsync($"/TestValidWriteOperations/NullBufferPost", new StringContent("hello")); - Assert.Equal("Success", await result.Content.ReadAsStringAsync()); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/LargeResponseBodyTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/LargeResponseBodyTests.cs deleted file mode 100644 index 40db2cfdb8..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/LargeResponseBodyTests.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class LargeResponseBodyTests - { - private readonly IISTestSiteFixture _fixture; - - public LargeResponseBodyTests(IISTestSiteFixture fixture) - { - _fixture = fixture; - } - - [ConditionalTheory] - [InlineData(65000)] - [InlineData(1000000)] - [InlineData(10000000)] - [InlineData(100000000)] - public async Task LargeResponseBodyTest_CheckAllResponseBodyBytesWritten(int query) - { - Assert.Equal(new string('a', query), await _fixture.Client.GetStringAsync($"/LargeResponseBody?length={query}")); - } - - [ConditionalFact] - public async Task LargeResponseBodyFromFile_CheckAllResponseBodyBytesWritten() - { - Assert.Equal(200000000, (await _fixture.Client.GetStringAsync($"/LargeResponseFile")).Length); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/LogPipeTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/LogPipeTests.cs deleted file mode 100644 index 4d34c3154f..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/LogPipeTests.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Net; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class LogPipeTests : IISFunctionalTestBase - { - private readonly PublishedSitesFixture _fixture; - - public LogPipeTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - [ConditionalTheory] - [InlineData("ConsoleErrorWrite")] - [InlineData("ConsoleWrite")] - public async Task CheckStdoutLoggingToPipe_DoesNotCrashProcess(string path) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true); - var deploymentResult = await DeployAsync(deploymentParameters); - - await Helpers.AssertStarts(deploymentResult, path); - - StopServer(); - - if (deploymentParameters.ServerType == ServerType.IISExpress) - { - Assert.Contains(TestSink.Writes, context => context.Message.Contains("TEST MESSAGE")); - } - } - - [ConditionalTheory] - [InlineData("ConsoleErrorWriteStartServer")] - [InlineData("ConsoleWriteStartServer")] - public async Task CheckStdoutLoggingToPipeWithFirstWrite(string path) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true); - - var firstWriteString = "TEST MESSAGE"; - - deploymentParameters.TransformArguments((a, _) => $"{a} {path}"); - - var deploymentResult = await DeployAsync(deploymentParameters); - - await Helpers.AssertStarts(deploymentResult); - - StopServer(); - - if (deploymentParameters.ServerType == ServerType.IISExpress) - { - // We can't read stdout logs from IIS as they aren't redirected. - Assert.Contains(TestSink.Writes, context => context.Message.Contains(firstWriteString)); - } - } - - [ConditionalFact] - public async Task CheckUnicodePipe() - { - var path = "CheckConsoleFunctions"; - var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true); - deploymentParameters.TransformArguments((a, _) => $"{a} {path}"); - - var deploymentResult = await DeployAsync(deploymentParameters); - - var response = await deploymentResult.HttpClient.GetAsync(path); - - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - - StopServer(); - EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.InProcessThreadExitStdOut(deploymentResult, "12", "(.*)彡⾔(.*)")); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/ResponseHeaderTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/ResponseHeaderTests.cs deleted file mode 100644 index fec5c227ec..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/ResponseHeaderTests.cs +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Microsoft.Net.Http.Headers; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class ResponseHeaders - { - private readonly IISTestSiteFixture _fixture; - - public ResponseHeaders(IISTestSiteFixture fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task AddResponseHeaders_HeaderValuesAreSetCorrectly() - { - var response = await _fixture.Client.GetAsync("ResponseHeaders"); - var responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal("Request Complete", responseText); - - Assert.True(response.Headers.TryGetValues("UnknownHeader", out var headerValues)); - Assert.Equal("test123=foo", headerValues.First()); - - Assert.True(response.Content.Headers.TryGetValues(HeaderNames.ContentType, out headerValues)); - Assert.Equal("text/plain", headerValues.First()); - - Assert.True(response.Headers.TryGetValues("MultiHeader", out headerValues)); - Assert.Equal(2, headerValues.Count()); - Assert.Equal("1", headerValues.First()); - Assert.Equal("2", headerValues.Last()); - } - - [ConditionalFact] - public async Task ErrorCodeIsSetForExceptionDuringRequest() - { - var response = await _fixture.Client.GetAsync("Throw"); - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - Assert.Equal("Internal Server Error", response.ReasonPhrase); - } - - [ConditionalTheory] - [InlineData(200, "custom", "custom", null)] - [InlineData(200, "custom", "custom", "Custom body")] - [InlineData(200, "custom", "custom", "")] - - - [InlineData(500, "", "Internal Server Error", null)] - [InlineData(500, "", "Internal Server Error", "Custom body")] - [InlineData(500, "", "Internal Server Error", "")] - - [InlineData(400, "custom", "custom", null)] - [InlineData(400, "", "Bad Request", "Custom body")] - [InlineData(400, "", "Bad Request", "")] - - [InlineData(999, "", "", null)] - [InlineData(999, "", "", "Custom body")] - [InlineData(999, "", "", "")] - public async Task CustomErrorCodeWorks(int code, string reason, string expectedReason, string body) - { - var response = await _fixture.Client.GetAsync($"SetCustomErorCode?code={code}&reason={reason}&writeBody={body != null}&body={body}"); - Assert.Equal((HttpStatusCode)code, response.StatusCode); - Assert.Equal(expectedReason, response.ReasonPhrase); - - // ReadAsStringAsync returns empty string for empty results - Assert.Equal(body ?? string.Empty, await response.Content.ReadAsStringAsync()); - } - - [ConditionalFact] - public async Task ServerHeaderIsOverriden() - { - var response = await _fixture.Client.GetAsync("OverrideServer"); - Assert.Equal("MyServer/7.8", response.Headers.Server.Single().Product.ToString()); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/ResponseInvalidOrderingTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/ResponseInvalidOrderingTests.cs deleted file mode 100644 index c39e155e77..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/ResponseInvalidOrderingTests.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class ResponseInvalidOrderingTest - { - private readonly IISTestSiteFixture _fixture; - - public ResponseInvalidOrderingTest(IISTestSiteFixture fixture) - { - _fixture = fixture; - } - - [ConditionalTheory] - [InlineData("SetStatusCodeAfterWrite")] - [InlineData("SetHeaderAfterWrite")] - public async Task ResponseInvalidOrderingTests_ExpectFailure(string path) - { - Assert.Equal($"Started_{path}Threw_Finished", await _fixture.Client.GetStringAsync("/ResponseInvalidOrdering/" + path)); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/ServerVariablesTest.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/ServerVariablesTest.cs deleted file mode 100644 index d18c4c7f09..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/ServerVariablesTest.cs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class ServerVariablesTest - { - private readonly IISTestSiteFixture _fixture; - - public ServerVariablesTest(IISTestSiteFixture fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task ProvidesAccessToServerVariables() - { - var port = _fixture.Client.BaseAddress.Port; - Assert.Equal("SERVER_PORT: " + port, await _fixture.Client.GetStringAsync("/ServerVariable?q=SERVER_PORT")); - Assert.Equal("QUERY_STRING: q=QUERY_STRING", await _fixture.Client.GetStringAsync("/ServerVariable?q=QUERY_STRING")); - } - - [ConditionalFact] - public async Task ReturnsNullForUndefinedServerVariable() - { - Assert.Equal("THIS_VAR_IS_UNDEFINED: (null)", await _fixture.Client.GetStringAsync("/ServerVariable?q=THIS_VAR_IS_UNDEFINED")); - } - - [ConditionalFact] - public async Task CanSetAndReadVariable() - { - Assert.Equal("ROUNDTRIP: 1", await _fixture.Client.GetStringAsync("/ServerVariable?v=1&q=ROUNDTRIP")); - } - - [ConditionalFact] - public async Task BasePathIsNotPrefixedBySlashSlashQuestionMark() - { - Assert.DoesNotContain(@"\\?\", await _fixture.Client.GetStringAsync("/BasePath")); - } - - [ConditionalFact] - public async Task GetServerVariableDoesNotCrash() - { - await Helpers.StressLoad(_fixture.Client, "/GetServerVariableStress", response => { - var text = response.Content.ReadAsStringAsync().Result; - Assert.StartsWith("Response Begin", text); - Assert.EndsWith("Response End", text); - }); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/StartupExceptionTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/StartupExceptionTests.cs deleted file mode 100644 index cadfed9781..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/StartupExceptionTests.cs +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Net; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class StartupExceptionTests : LogFileTestBase - { - private readonly PublishedSitesFixture _fixture; - - public StartupExceptionTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - [ConditionalTheory] - [InlineData("CheckLargeStdErrWrites")] - [InlineData("CheckLargeStdOutWrites")] - [InlineData("CheckOversizedStdErrWrites")] - [InlineData("CheckOversizedStdOutWrites")] - public async Task CheckStdoutWithLargeWrites_TestSink(string mode) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true); - deploymentParameters.TransformArguments((a, _) => $"{a} {mode}"); - var deploymentResult = await DeployAsync(deploymentParameters); - - await AssertFailsToStart(deploymentResult); - var expectedString = new string('a', 30000); - Assert.Contains(TestSink.Writes, context => context.Message.Contains(expectedString)); - EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.InProcessThreadExitStdOut(deploymentResult, "12", expectedString)); - } - - [ConditionalTheory] - [InlineData("CheckLargeStdErrWrites")] - [InlineData("CheckLargeStdOutWrites")] - [InlineData("CheckOversizedStdErrWrites")] - [InlineData("CheckOversizedStdOutWrites")] - public async Task CheckStdoutWithLargeWrites_LogFile(string mode) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true); - deploymentParameters.TransformArguments((a, _) => $"{a} {mode}"); - deploymentParameters.EnableLogging(_logFolderPath); - - var deploymentResult = await DeployAsync(deploymentParameters); - - await AssertFailsToStart(deploymentResult); - - var contents = GetLogFileContent(deploymentResult); - var expectedString = new string('a', 30000); - - Assert.Contains(expectedString, contents); - EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.InProcessThreadExitStdOut(deploymentResult, "12", expectedString)); - } - - [ConditionalFact] - public async Task CheckValidConsoleFunctions() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true); - deploymentParameters.TransformArguments((a, _) => $"{a} CheckConsoleFunctions"); - - var deploymentResult = await DeployAsync(deploymentParameters); - - await AssertFailsToStart(deploymentResult); - - Assert.Contains(TestSink.Writes, context => context.Message.Contains("Is Console redirection: True")); - } - - private async Task AssertFailsToStart(IISDeploymentResult deploymentResult) - { - var response = await deploymentResult.HttpClient.GetAsync("/HelloWorld"); - - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - - StopServer(); - } - - [ConditionalFact] - public async Task Gets500_30_ErrorPage() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true); - deploymentParameters.TransformArguments((a, _) => $"{a} EarlyReturn"); - - var deploymentResult = await DeployAsync(deploymentParameters); - - var response = await deploymentResult.HttpClient.GetAsync("/HelloWorld"); - Assert.False(response.IsSuccessStatusCode); - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - - var responseText = await response.Content.ReadAsStringAsync(); - Assert.Contains("500.30 - ANCM In-Process Start Failure", responseText); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/StartupTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/StartupTests.cs deleted file mode 100644 index 3bcc134cb2..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/StartupTests.cs +++ /dev/null @@ -1,479 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using System.Xml.Linq; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.AspNetCore.Testing.xunit; -using Newtonsoft.Json; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class StartupTests : IISFunctionalTestBase - { - private readonly PublishedSitesFixture _fixture; - - public StartupTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - private readonly string _dotnetLocation = DotNetCommands.GetDotNetExecutable(RuntimeArchitecture.x64); - - [ConditionalFact] - [RequiresIIS(IISCapability.PoolEnvironmentVariables)] - public async Task ExpandEnvironmentVariableInWebConfig() - { - // Point to dotnet installed in user profile. - var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true); - deploymentParameters.EnvironmentVariables["DotnetPath"] = _dotnetLocation; - deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("processPath", "%DotnetPath%")); - await StartAsync(deploymentParameters); - } - - [ConditionalTheory] - [InlineData("bogus", "", @"Executable was not found at '.*?\\bogus.exe")] - [InlineData("c:\\random files\\dotnet.exe", "something.dll", @"Could not find dotnet.exe at '.*?\\dotnet.exe'")] - [InlineData(".\\dotnet.exe", "something.dll", @"Could not find dotnet.exe at '.*?\\.\\dotnet.exe'")] - [InlineData("dotnet.exe", "", @"Application arguments are empty.")] - [InlineData("dotnet.zip", "", @"Process path 'dotnet.zip' doesn't have '.exe' extension.")] - public async Task InvalidProcessPath_ExpectServerError(string path, string arguments, string subError) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true); - deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("processPath", path)); - deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("arguments", arguments)); - - var deploymentResult = await DeployAsync(deploymentParameters); - - var response = await deploymentResult.HttpClient.GetAsync("HelloWorld"); - - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - - StopServer(); - - EventLogHelpers.VerifyEventLogEvent(deploymentResult, $@"Application '{Regex.Escape(deploymentResult.ContentRoot)}\\' wasn't able to start. {subError}"); - - Assert.Contains("HTTP Error 500.0 - ANCM In-Process Handler Load Failure", await response.Content.ReadAsStringAsync()); - } - - [ConditionalFact] - public async Task StartsWithDotnetLocationWithoutExe() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true); - - var dotnetLocationWithoutExtension = _dotnetLocation.Substring(0, _dotnetLocation.LastIndexOf(".")); - deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("processPath", dotnetLocationWithoutExtension)); - - await StartAsync(deploymentParameters); - } - - [ConditionalFact] - public async Task StartsWithDotnetLocationUppercase() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true); - - var dotnetLocationWithoutExtension = _dotnetLocation.Substring(0, _dotnetLocation.LastIndexOf(".")).ToUpperInvariant(); - deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("processPath", dotnetLocationWithoutExtension)); - - await StartAsync(deploymentParameters); - } - - [ConditionalTheory] - [InlineData("dotnet")] - [InlineData("dotnet.EXE")] - [RequiresIIS(IISCapability.PoolEnvironmentVariables)] - public async Task StartsWithDotnetOnThePath(string path) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true); - - deploymentParameters.EnvironmentVariables["PATH"] = Path.GetDirectoryName(_dotnetLocation); - deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("processPath", path)); - - var deploymentResult = await DeployAsync(deploymentParameters); - await deploymentResult.AssertStarts(); - - StopServer(); - // Verify that in this scenario where.exe was invoked only once by shim and request handler uses cached value - Assert.Equal(1, TestSink.Writes.Count(w => w.Message.Contains("Invoking where.exe to find dotnet.exe"))); - } - - public static TestMatrix TestVariants - => TestMatrix.ForServers(DeployerSelector.ServerType) - .WithTfms(Tfm.NetCoreApp22) - .WithAllApplicationTypes() - .WithAncmV2InProcess(); - - [ConditionalTheory] - [MemberData(nameof(TestVariants))] - public async Task HelloWorld(TestVariant variant) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant, publish: true); - await StartAsync(deploymentParameters); - } - - [ConditionalFact] - [RequiresIIS(IISCapability.PoolEnvironmentVariables)] - public async Task StartsWithPortableAndBootstraperExe() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true); - // We need the right dotnet on the path in IIS - deploymentParameters.EnvironmentVariables["PATH"] = Path.GetDirectoryName(DotNetCommands.GetDotNetExecutable(deploymentParameters.RuntimeArchitecture)); - - // rest publisher as it doesn't support additional parameters - deploymentParameters.ApplicationPublisher = null; - // ReferenceTestTasks is workaround for https://github.com/dotnet/sdk/issues/2482 - deploymentParameters.AdditionalPublishParameters = "-p:RuntimeIdentifier=win7-x64 -p:UseAppHost=true -p:SelfContained=false -p:ReferenceTestTasks=false"; - var deploymentResult = await DeployAsync(deploymentParameters); - - Assert.True(File.Exists(Path.Combine(deploymentResult.ContentRoot, "InProcessWebSite.exe"))); - Assert.False(File.Exists(Path.Combine(deploymentResult.ContentRoot, "hostfxr.dll"))); - Assert.Contains("InProcessWebSite.exe", Helpers.ReadAllTextFromFile(Path.Combine(deploymentResult.ContentRoot, "web.config"), Logger)); - - await deploymentResult.AssertStarts(); - } - - [ConditionalFact] - public async Task DetectsOverriddenServer() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true); - deploymentParameters.TransformArguments((a, _) => $"{a} OverriddenServer"); - - var deploymentResult = await DeployAsync(deploymentParameters); - var response = await deploymentResult.HttpClient.GetAsync("/"); - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - - StopServer(); - - EventLogHelpers.VerifyEventLogEvents(deploymentResult, - EventLogHelpers.InProcessFailedToStart(deploymentResult, "CLR worker thread exited prematurely"), - EventLogHelpers.InProcessThreadException(deploymentResult, ".*?Application is running inside IIS process but is not configured to use IIS server")); - } - - [ConditionalFact] - public async Task LogsStartupExceptionExitError() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true); - deploymentParameters.TransformArguments((a, _) => $"{a} Throw"); - - var deploymentResult = await DeployAsync(deploymentParameters); - - var response = await deploymentResult.HttpClient.GetAsync("/"); - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - - StopServer(); - - EventLogHelpers.VerifyEventLogEvents(deploymentResult, - EventLogHelpers.InProcessFailedToStart(deploymentResult, "CLR worker thread exited prematurely"), - EventLogHelpers.InProcessThreadException(deploymentResult, ", exception code = '0xe0434352'")); - } - - [ConditionalFact] - public async Task LogsUnexpectedThreadExitError() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true); - deploymentParameters.TransformArguments((a, _) => $"{a} EarlyReturn"); - var deploymentResult = await DeployAsync(deploymentParameters); - - var response = await deploymentResult.HttpClient.GetAsync("/HelloWorld"); - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - - StopServer(); - - EventLogHelpers.VerifyEventLogEvents(deploymentResult, - EventLogHelpers.InProcessFailedToStart(deploymentResult, "CLR worker thread exited prematurely"), - EventLogHelpers.InProcessThreadExit(deploymentResult, "12")); - } - - [ConditionalFact] - public async Task RemoveHostfxrFromApp_InProcessHostfxrInvalid() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true); - deploymentParameters.ApplicationType = ApplicationType.Standalone; - var deploymentResult = await DeployAsync(deploymentParameters); - - File.Copy( - Path.Combine(deploymentResult.ContentRoot, "aspnetcorev2_inprocess.dll"), - Path.Combine(deploymentResult.ContentRoot, "hostfxr.dll"), - true); - await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult); - - EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.InProcessHostfxrInvalid(deploymentResult), Logger); - } - - [ConditionalFact] - public async Task TargedDifferenceSharedFramework_FailedToFindNativeDependencies() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true); - var deploymentResult = await DeployAsync(deploymentParameters); - - Helpers.ModifyFrameworkVersionInRuntimeConfig(deploymentResult); - await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult); - - EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.InProcessFailedToFindNativeDependencies(deploymentResult), Logger); - } - - [ConditionalFact] - public async Task RemoveInProcessReference_FailedToFindRequestHandler() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true); - deploymentParameters.ApplicationType = ApplicationType.Standalone; - var deploymentResult = await DeployAsync(deploymentParameters); - - File.Delete(Path.Combine(deploymentResult.ContentRoot, "aspnetcorev2_inprocess.dll")); - - await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult); - - if (DeployerSelector.IsForwardsCompatibilityTest) - { - EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.InProcessFailedToFindNativeDependencies(deploymentResult), Logger); - } - else - { - EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.InProcessFailedToFindRequestHandler(deploymentResult), Logger); - } - } - - [ConditionalFact] - public async Task StartupTimeoutIsApplied() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true); - deploymentParameters.TransformArguments((a, _) => $"{a} Hang"); - deploymentParameters.WebConfigActionList.Add( - WebConfigHelpers.AddOrModifyAspNetCoreSection("startupTimeLimit", "1")); - - var deploymentResult = await DeployAsync(deploymentParameters); - - var response = await deploymentResult.HttpClient.GetAsync("/"); - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - - StopServer(); - - EventLogHelpers.VerifyEventLogEvents(deploymentResult, - EventLogHelpers.InProcessFailedToStart(deploymentResult, "Managed server didn't initialize after 1000 ms.") - ); - } - - [ConditionalFact] - public async Task ShutdownTimeoutIsApplied() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true); - deploymentParameters.TransformArguments((a, _) => $"{a} HangOnStop"); - deploymentParameters.WebConfigActionList.Add( - WebConfigHelpers.AddOrModifyAspNetCoreSection("shutdownTimeLimit", "1")); - - var deploymentResult = await DeployAsync(deploymentParameters); - - Assert.Equal("Hello World", await deploymentResult.HttpClient.GetStringAsync("/HelloWorld")); - - StopServer(); - - EventLogHelpers.VerifyEventLogEvents(deploymentResult, - EventLogHelpers.InProcessStarted(deploymentResult), - EventLogHelpers.InProcessFailedToStop(deploymentResult, "")); - } - - [ConditionalFact] - public async Task CheckInvalidHostingModelParameter() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true); - deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("hostingModel", "bogus")); - - var deploymentResult = await DeployAsync(deploymentParameters); - - var response = await deploymentResult.HttpClient.GetAsync("HelloWorld"); - - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - - StopServer(); - - EventLogHelpers.VerifyEventLogEvents(deploymentResult, - EventLogHelpers.ConfigurationLoadError(deploymentResult, "Unknown hosting model 'bogus'. Please specify either hostingModel=\"inprocess\" or hostingModel=\"outofprocess\" in the web.config file.") - ); - } - - private static Dictionary)> InvalidConfigTransformations = InitInvalidConfigTransformations(); - public static IEnumerable InvalidConfigTransformationsScenarios => InvalidConfigTransformations.ToTheoryData(); - - [ConditionalTheory] - [MemberData(nameof(InvalidConfigTransformationsScenarios))] - public async Task ReportsWebConfigAuthoringErrors(string scenario) - { - var (expectedError, action) = InvalidConfigTransformations[scenario]; - var iisDeploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true); - iisDeploymentParameters.WebConfigActionList.Add((element, _) => action(element)); - var deploymentResult = await DeployAsync(iisDeploymentParameters); - var result = await deploymentResult.HttpClient.GetAsync("/HelloWorld"); - Assert.Equal(HttpStatusCode.InternalServerError, result.StatusCode); - - // Config load errors might not allow us to initialize log file - deploymentResult.AllowNoLogs(); - - StopServer(); - - EventLogHelpers.VerifyEventLogEvents(deploymentResult, - EventLogHelpers.ConfigurationLoadError(deploymentResult, expectedError) - ); - } - - public static Dictionary)> InitInvalidConfigTransformations() - { - var dictionary = new Dictionary)>(); - dictionary.Add("Empty process path", - ( - "Attribute 'processPath' is required.", - element => element.Descendants("aspNetCore").Single().SetAttributeValue("processPath", "") - )); - dictionary.Add("Unknown hostingModel", - ( - "Unknown hosting model 'asdf'.", - element => element.Descendants("aspNetCore").Single().SetAttributeValue("hostingModel", "asdf") - )); - dictionary.Add("environmentVariables with add", - ( - "Unable to get required configuration section 'system.webServer/aspNetCore'. Possible reason is web.config authoring error.", - element => element.Descendants("aspNetCore").Single().GetOrAdd("environmentVariables").GetOrAdd("add") - )); - return dictionary; - } - - private static Dictionary> PortableConfigTransformations = InitPortableWebConfigTransformations(); - public static IEnumerable PortableConfigTransformationsScenarios => PortableConfigTransformations.ToTheoryData(); - - [ConditionalTheory] - [MemberData(nameof(PortableConfigTransformationsScenarios))] - public async Task StartsWithWebConfigVariationsPortable(string scenario) - { - var action = PortableConfigTransformations[scenario]; - var iisDeploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true); - var expectedArguments = action(iisDeploymentParameters); - var result = await DeployAsync(iisDeploymentParameters); - Assert.Equal(expectedArguments, await result.HttpClient.GetStringAsync("/CommandLineArgs")); - } - - public static Dictionary> InitPortableWebConfigTransformations() - { - var dictionary = new Dictionary>(); - var pathWithSpace = "\u03c0 \u2260 3\u00b714"; - - dictionary.Add("App in bin subdirectory full path to dll using exec and quotes", - parameters => { - MoveApplication(parameters, "bin"); - parameters.TransformArguments((arguments, root) => "exec " + Path.Combine(root, "bin", arguments)); - return ""; - }); - - dictionary.Add("App in subdirectory with space", - parameters => { - MoveApplication(parameters, pathWithSpace); - parameters.TransformArguments((arguments, root) => Path.Combine(pathWithSpace, arguments)); - return ""; - }); - - dictionary.Add("App in subdirectory with space and full path to dll", - parameters => { - MoveApplication(parameters, pathWithSpace); - parameters.TransformArguments((arguments, root) => Path.Combine(root, pathWithSpace, arguments)); - return ""; - }); - - dictionary.Add("App in bin subdirectory with space full path to dll using exec and quotes", - parameters => { - MoveApplication(parameters, pathWithSpace); - parameters.TransformArguments((arguments, root) => "exec \"" + Path.Combine(root, pathWithSpace, arguments) + "\" extra arguments"); - return "extra|arguments"; - }); - - dictionary.Add("App in bin subdirectory and quoted argument", - parameters => { - MoveApplication(parameters, "bin"); - parameters.TransformArguments((arguments, root) => Path.Combine("bin", arguments) + " \"extra argument\""); - return "extra argument"; - }); - - dictionary.Add("App in bin subdirectory full path to dll", - parameters => { - MoveApplication(parameters, "bin"); - parameters.TransformArguments((arguments, root) => Path.Combine(root, "bin", arguments) + " extra arguments"); - return "extra|arguments"; - }); - return dictionary; - } - - - private static Dictionary> StandaloneConfigTransformations = InitStandaloneConfigTransformations(); - public static IEnumerable StandaloneConfigTransformationsScenarios => StandaloneConfigTransformations.ToTheoryData(); - - [ConditionalTheory] - [MemberData(nameof(StandaloneConfigTransformationsScenarios))] - public async Task StartsWithWebConfigVariationsStandalone(string scenario) - { - var action = StandaloneConfigTransformations[scenario]; - var iisDeploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true); - iisDeploymentParameters.ApplicationType = ApplicationType.Standalone; - var expectedArguments = action(iisDeploymentParameters); - var result = await DeployAsync(iisDeploymentParameters); - Assert.Equal(expectedArguments, await result.HttpClient.GetStringAsync("/CommandLineArgs")); - } - - public static Dictionary> InitStandaloneConfigTransformations() - { - var dictionary = new Dictionary>(); - var pathWithSpace = "\u03c0 \u2260 3\u00b714"; - - dictionary.Add("App in subdirectory", - parameters => { - MoveApplication(parameters, pathWithSpace); - parameters.TransformPath((path, root) => Path.Combine(pathWithSpace, path)); - parameters.TransformArguments((arguments, root) => "\"additional argument\""); - return "additional argument"; - }); - - dictionary.Add("App in bin subdirectory full path", - parameters => { - MoveApplication(parameters, pathWithSpace); - parameters.TransformPath((path, root) => Path.Combine(root, pathWithSpace, path)); - parameters.TransformArguments((arguments, root) => "additional arguments"); - return "additional|arguments"; - }); - - return dictionary; - } - - private static void MoveApplication( - IISDeploymentParameters parameters, - string subdirectory) - { - parameters.WebConfigActionList.Add((config, contentRoot) => - { - var source = new DirectoryInfo(contentRoot); - var subDirectoryPath = source.CreateSubdirectory(subdirectory); - - // Copy everything into a subfolder - Helpers.CopyFiles(source, subDirectoryPath, null); - // Cleanup files - foreach (var fileSystemInfo in source.GetFiles()) - { - fileSystemInfo.Delete(); - } - }); - } - - private async Task AssertSiteFailsToStartWithInProcessStaticContent(IISDeploymentResult deploymentResult) - { - var response = await deploymentResult.HttpClient.GetAsync("/HelloWorld"); - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - Assert.Contains("HTTP Error 500.0 - ANCM In-Process Handler Load Failure", await response.Content.ReadAsStringAsync()); - StopServer(); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/SynchronousReadAndWriteTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/SynchronousReadAndWriteTests.cs deleted file mode 100644 index 03aa0e16e6..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Inprocess/SynchronousReadAndWriteTests.cs +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class SynchronousReadAndWriteTests: FixtureLoggedTest - { - private readonly IISTestSiteFixture _fixture; - - public SynchronousReadAndWriteTests(IISTestSiteFixture fixture): base(fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task ReadAndWriteSynchronously() - { - for (int i = 0; i < 100; i++) - { - var content = new StringContent(new string('a', 100000)); - var response = await _fixture.Client.PostAsync("ReadAndWriteSynchronously", content); - var responseText = await response.Content.ReadAsStringAsync(); - - Assert.Equal(expected: 110000, actual: responseText.Length); - } - } - - [ConditionalFact] - public async Task ReadAndWriteEcho() - { - var body = new string('a', 100000); - var content = new StringContent(body); - var response = await _fixture.Client.PostAsync("ReadAndWriteEcho", content); - var responseText = await response.Content.ReadAsStringAsync(); - - Assert.Equal(body, responseText); - } - - [ConditionalFact] - public async Task ReadAndWriteCopyToAsync() - { - var body = new string('a', 100000); - var content = new StringContent(body); - var response = await _fixture.Client.PostAsync("ReadAndWriteCopyToAsync", content); - var responseText = await response.Content.ReadAsStringAsync(); - - Assert.Equal(body, responseText); - } - - [ConditionalFact] - public async Task ReadAndWriteEchoTwice() - { - var requestBody = new string('a', 10000); - var content = new StringContent(requestBody); - var response = await _fixture.Client.PostAsync("ReadAndWriteEchoTwice", content); - var responseText = await response.Content.ReadAsStringAsync(); - - Assert.Equal(requestBody.Length * 2, responseText.Length); - } - - [ConditionalFact] - public async Task ReadSetHeaderWrite() - { - var body = "Body text"; - var content = new StringContent(body); - var response = await _fixture.Client.PostAsync("SetHeaderFromBody", content); - var responseText = await response.Content.ReadAsStringAsync(); - - Assert.Equal(body, response.Headers.GetValues("BodyAsString").Single()); - Assert.Equal(body, responseText); - } - - [ConditionalFact] - public async Task ReadAndWriteSlowConnection() - { - using (var connection = _fixture.CreateTestConnection()) - { - var testString = "hello world"; - var request = $"POST /ReadAndWriteSlowConnection HTTP/1.0\r\n" + - $"Content-Length: {testString.Length}\r\n" + - "Host: " + "localhost\r\n" + - "\r\n" + testString; - - foreach (var c in request) - { - await connection.Send(c.ToString()); - await Task.Delay(10); - } - - await connection.Receive( - "HTTP/1.1 200 OK", - ""); - await connection.ReceiveHeaders(); - - for (int i = 0; i < 100; i++) - { - foreach (var c in testString) - { - await connection.Receive(c.ToString()); - } - await Task.Delay(10); - } - await connection.WaitForConnectionClose(); - } - } - - [ConditionalFact] - public async Task ReadAndWriteInterleaved() - { - using (var connection = _fixture.CreateTestConnection()) - { - var requestLength = 0; - var messages = new List(); - for (var i = 1; i < 100; i++) - { - var message = i + Environment.NewLine; - requestLength += message.Length; - messages.Add(message); - } - - await connection.Send( - "POST /ReadAndWriteEchoLines HTTP/1.0", - $"Content-Length: {requestLength}", - "Host: localhost", - "", - ""); - - await connection.Receive( - "HTTP/1.1 200 OK", - ""); - await connection.ReceiveHeaders(); - - foreach (var message in messages) - { - await connection.Send(message); - await connection.Receive(message); - } - - await connection.Send("\r\n"); - await connection.WaitForConnectionClose(); - } - } - - [ConditionalFact] - public async Task ConsumePartialBody() - { - using (var connection = _fixture.CreateTestConnection()) - { - var message = "Hello"; - await connection.Send( - "POST /ReadPartialBody HTTP/1.1", - $"Content-Length: {100}", - "Host: localhost", - "Connection: close", - "", - ""); - - await connection.Send(message); - - await connection.Receive( - "HTTP/1.1 200 OK", - ""); - - // This test can return both content length or chunked response - // depending on if appfunc managed to complete before write was - // issued - var headers = await connection.ReceiveHeaders(); - if (headers.Contains("Content-Length: 5")) - { - await connection.Receive("Hello"); - } - else - { - await connection.Receive( - "5", - message, - ""); - await connection.Receive( - "0", - "", - ""); - } - - await connection.WaitForConnectionClose(); - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/LogFileTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/LogFileTests.cs deleted file mode 100644 index 1e15cde5c2..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/LogFileTests.cs +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class LoggingTests : LogFileTestBase - { - private readonly PublishedSitesFixture _fixture; - - public LoggingTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - public static TestMatrix TestVariants - => TestMatrix.ForServers(DeployerSelector.ServerType) - .WithTfms(Tfm.NetCoreApp22) - .WithAllApplicationTypes() - .WithAncmVersions(AncmVersion.AspNetCoreModuleV2) - .WithAllHostingModels(); - - [ConditionalTheory] - [MemberData(nameof(TestVariants))] - public async Task CheckStdoutLoggingToFile(TestVariant variant) - { - await CheckStdoutToFile(variant, "ConsoleWrite"); - } - - [ConditionalTheory] - [MemberData(nameof(TestVariants))] - public async Task CheckStdoutErrLoggingToFile(TestVariant variant) - { - await CheckStdoutToFile(variant, "ConsoleErrorWrite"); - } - - private async Task CheckStdoutToFile(TestVariant variant, string path) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant, publish: true); - deploymentParameters.EnableLogging(_logFolderPath); - - var deploymentResult = await DeployAsync(deploymentParameters); - - await Helpers.AssertStarts(deploymentResult, path); - - StopServer(); - - var contents = Helpers.ReadAllTextFromFile(Helpers.GetExpectedLogName(deploymentResult, _logFolderPath), Logger); - - Assert.Contains("TEST MESSAGE", contents); - } - - // Move to separate file - [ConditionalTheory] - [MemberData(nameof(TestVariants))] - public async Task InvalidFilePathForLogs_ServerStillRuns(TestVariant variant) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant, publish: true); - - deploymentParameters.WebConfigActionList.Add( - WebConfigHelpers.AddOrModifyAspNetCoreSection("stdoutLogEnabled", "true")); - deploymentParameters.WebConfigActionList.Add( - WebConfigHelpers.AddOrModifyAspNetCoreSection("stdoutLogFile", Path.Combine("Q:", "std"))); - - var deploymentResult = await DeployAsync(deploymentParameters); - - await Helpers.AssertStarts(deploymentResult, "HelloWorld"); - - StopServer(); - if (variant.HostingModel == HostingModel.InProcess) - { - EventLogHelpers.VerifyEventLogEvent(deploymentResult, "Could not start stdout redirection in (.*)aspnetcorev2.dll. Exception message: HRESULT 0x80070003"); - EventLogHelpers.VerifyEventLogEvent(deploymentResult, "Could not stop stdout redirection in (.*)aspnetcorev2.dll. Exception message: HRESULT 0x80070002"); - } - } - - [ConditionalTheory] - [MemberData(nameof(TestVariants))] - public async Task StartupMessagesAreLoggedIntoDebugLogFile(TestVariant variant) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant, publish: true); - deploymentParameters.HandlerSettings["debugLevel"] = "file"; - deploymentParameters.HandlerSettings["debugFile"] = "debug.txt"; - - var deploymentResult = await DeployAsync(deploymentParameters); - - await deploymentResult.HttpClient.GetAsync("/"); - - AssertLogs(Path.Combine(deploymentResult.ContentRoot, "debug.txt")); - } - - [ConditionalTheory] - [MemberData(nameof(TestVariants))] - public async Task StartupMessagesAreLoggedIntoDefaultDebugLogFile(TestVariant variant) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant, publish: true); - deploymentParameters.HandlerSettings["debugLevel"] = "file"; - - var deploymentResult = await DeployAsync(deploymentParameters); - - await deploymentResult.HttpClient.GetAsync("/"); - - AssertLogs(Path.Combine(deploymentResult.ContentRoot, "aspnetcore-debug.log")); - } - - [ConditionalTheory] - [RequiresIIS(IISCapability.PoolEnvironmentVariables)] - [MemberData(nameof(TestVariants))] - public async Task StartupMessagesAreLoggedIntoDefaultDebugLogFileWhenEnabledWithEnvVar(TestVariant variant) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant, publish: true); - deploymentParameters.EnvironmentVariables["ASPNETCORE_MODULE_DEBUG"] = "file"; - // Add empty debugFile handler setting to prevent IIS deployer from overriding debug settings - deploymentParameters.HandlerSettings["debugFile"] = ""; - var deploymentResult = await DeployAsync(deploymentParameters); - - await deploymentResult.HttpClient.GetAsync("/"); - - AssertLogs(Path.Combine(deploymentResult.ContentRoot, "aspnetcore-debug.log")); - } - - [ConditionalTheory] - [RequiresIIS(IISCapability.PoolEnvironmentVariables)] - [MemberData(nameof(TestVariants))] - public async Task StartupMessagesLogFileSwitchedWhenLogFilePresentInWebConfig(TestVariant variant) - { - var firstTempFile = Path.GetTempFileName(); - var secondTempFile = Path.GetTempFileName(); - - try - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant, publish: true); - deploymentParameters.EnvironmentVariables["ASPNETCORE_MODULE_DEBUG_FILE"] = firstTempFile; - deploymentParameters.AddDebugLogToWebConfig(secondTempFile); - - var deploymentResult = await DeployAsync(deploymentParameters); - - var response = await deploymentResult.HttpClient.GetAsync("/"); - - StopServer(); - var logContents = Helpers.ReadAllTextFromFile(firstTempFile, Logger); - - Assert.Contains("Switching debug log files to", logContents); - - AssertLogs(secondTempFile); - } - finally - { - File.Delete(firstTempFile); - File.Delete(secondTempFile); - } - } - - [ConditionalTheory] - [MemberData(nameof(TestVariants))] - - public async Task DebugLogsAreWrittenToEventLog(TestVariant variant) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant, publish: true); - deploymentParameters.HandlerSettings["debugLevel"] = "file,eventlog"; - var deploymentResult = await StartAsync(deploymentParameters); - StopServer(); - EventLogHelpers.VerifyEventLogEvent(deploymentResult, @"\[aspnetcorev2.dll\] Initializing logs for .*?Description: IIS ASP.NET Core Module V2"); - } - - [ConditionalTheory] - [MemberData(nameof(TestVariants))] - public async Task CheckUTF8File(TestVariant variant) - { - var path = "CheckConsoleFunctions"; - - var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, variant.HostingModel, publish: true); - deploymentParameters.TransformArguments((a, _) => $"{a} {path}"); // For standalone this will need to remove space - - var logFolderPath = _logFolderPath + "\\彡⾔"; - deploymentParameters.EnableLogging(logFolderPath); - - var deploymentResult = await DeployAsync(deploymentParameters); - - var response = await deploymentResult.HttpClient.GetAsync(path); - - Assert.False(response.IsSuccessStatusCode); - - StopServer(); - - var contents = Helpers.ReadAllTextFromFile(Helpers.GetExpectedLogName(deploymentResult, logFolderPath), Logger); - Assert.Contains("彡⾔", contents); - - if (variant.HostingModel == HostingModel.InProcess) - { - EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.InProcessThreadExitStdOut(deploymentResult, "12", "(.*)彡⾔(.*)")); - } - else - { - EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.OutOfProcessFailedToStart(deploymentResult)); - } - } - - [ConditionalTheory] - [MemberData(nameof(TestVariants))] - public async Task OnlyOneFileCreatedWithProcessStartTime(TestVariant variant) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant, publish: true); - - deploymentParameters.EnableLogging(_logFolderPath); - - var deploymentResult = await DeployAsync(deploymentParameters); - await Helpers.AssertStarts(deploymentResult, "ConsoleWrite"); - - StopServer(); - - Assert.Single(Directory.GetFiles(_logFolderPath), Helpers.GetExpectedLogName(deploymentResult, _logFolderPath)); - } - - private static string ReadLogs(string logPath) - { - using (var stream = File.Open(logPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) - using (var streamReader = new StreamReader(stream)) - { - return streamReader.ReadToEnd(); - } - } - - private static void AssertLogs(string logPath) - { - var logContents = ReadLogs(logPath); - Assert.Contains("[aspnetcorev2.dll]", logContents); - Assert.True(logContents.Contains("[aspnetcorev2_inprocess.dll]") || logContents.Contains("[aspnetcorev2_outofprocess.dll]")); - Assert.Contains("Description: IIS ASP.NET Core Module V2. Commit:", logContents); - Assert.Contains("Description: IIS ASP.NET Core Module V2 Request Handler. Commit:", logContents); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/MultiApplicationTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/MultiApplicationTests.cs deleted file mode 100644 index 3723369c89..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/MultiApplicationTests.cs +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using System.Xml.Linq; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.AspNetCore.Testing.xunit; -using Microsoft.Extensions.Logging; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class MultiApplicationTests : IISFunctionalTestBase - { - private readonly PublishedSitesFixture _fixture; - - private PublishedApplication _publishedApplication; - private PublishedApplication _rootApplication; - - public MultiApplicationTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task RunsTwoOutOfProcessApps() - { - var parameters = _fixture.GetBaseDeploymentParameters(HostingModel.OutOfProcess, publish: true); - parameters.ServerConfigActionList.Add(DuplicateApplication); - var result = await DeployAsync(parameters); - var id1 = await result.HttpClient.GetStringAsync("/app1/ProcessId"); - var id2 = await result.HttpClient.GetStringAsync("/app2/ProcessId"); - Assert.NotEqual(id2, id1); - } - - [ConditionalFact] - public async Task FailsAndLogsWhenRunningTwoInProcessApps() - { - var parameters = _fixture.GetBaseDeploymentParameters(HostingModel.InProcess, publish: true); - parameters.ServerConfigActionList.Add(DuplicateApplication); - - var result = await DeployAsync(parameters); - var result1 = await result.HttpClient.GetAsync("/app1/HelloWorld"); - var result2 = await result.HttpClient.GetAsync("/app2/HelloWorld"); - Assert.Equal(200, (int)result1.StatusCode); - Assert.Equal(500, (int)result2.StatusCode); - StopServer(); - EventLogHelpers.VerifyEventLogEvent(result, "Only one inprocess application is allowed per IIS application pool"); - } - - [ConditionalTheory] - [InlineData(HostingModel.OutOfProcess)] - [InlineData(HostingModel.InProcess)] - public async Task FailsAndLogsEventLogForMixedHostingModel(HostingModel firstApp) - { - var parameters = _fixture.GetBaseDeploymentParameters(firstApp, publish: true); - parameters.ServerConfigActionList.Add(DuplicateApplication); - var result = await DeployAsync(parameters); - - // Modify hosting model of other app to be the opposite - var otherApp = firstApp == HostingModel.InProcess ? HostingModel.OutOfProcess : HostingModel.InProcess; - SetHostingModel(_publishedApplication.Path, otherApp); - - var result1 = await result.HttpClient.GetAsync("/app1/HelloWorld"); - var result2 = await result.HttpClient.GetAsync("/app2/HelloWorld"); - Assert.Equal(200, (int)result1.StatusCode); - Assert.Equal(500, (int)result2.StatusCode); - StopServer(); - EventLogHelpers.VerifyEventLogEvent(result, "Mixed hosting model is not supported."); - } - - private void SetHostingModel(string directory, HostingModel model) - { - var webConfigLocation = GetWebConfigLocation(directory); - XDocument webConfig = XDocument.Load(webConfigLocation); - webConfig.Root - .Descendants("system.webServer") - .Single() - .GetOrAdd("aspNetCore") - .SetAttributeValue("hostingModel", model.ToString()); - webConfig.Save(webConfigLocation); - } - - private void DuplicateApplication(XElement config, string contentRoot) - { - var siteElement = config - .RequiredElement("system.applicationHost") - .RequiredElement("sites") - .RequiredElement("site"); - - var application = siteElement - .RequiredElement("application"); - - application.SetAttributeValue("path", "/app1"); - - var source = new DirectoryInfo(contentRoot); - - var destination = new DirectoryInfo(contentRoot + "anotherApp"); - destination.Create(); - Helpers.CopyFiles(source, destination, Logger); - - _publishedApplication = new PublishedApplication(destination.FullName, Logger); - - var newApplication = new XElement(application); - newApplication.SetAttributeValue("path", "/app2"); - newApplication.RequiredElement("virtualDirectory") - .SetAttributeValue("physicalPath", destination.FullName); - - siteElement.Add(newApplication); - - // IIS Express requires root application to exist - var rootApplicationDirectory = new DirectoryInfo(contentRoot + "rootApp"); - rootApplicationDirectory.Create(); - - _rootApplication = new PublishedApplication(rootApplicationDirectory.FullName, Logger); - File.WriteAllText(GetWebConfigLocation(rootApplicationDirectory.FullName), ""); - - var rootApplication = new XElement(application); - rootApplication.SetAttributeValue("path", "/"); - rootApplication.RequiredElement("virtualDirectory") - .SetAttributeValue("physicalPath", rootApplicationDirectory.FullName); - - siteElement.Add(rootApplication); - } - - private static string GetWebConfigLocation(string siteRoot) - { - return Path.Combine(siteRoot, "web.config"); - } - - public override void Dispose() - { - base.Dispose(); - _rootApplication.Dispose(); - _publishedApplication.Dispose(); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/OutOfProcess/AspNetCorePortTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/OutOfProcess/AspNetCorePortTests.cs deleted file mode 100644 index 3b86662717..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/OutOfProcess/AspNetCorePortTests.cs +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Threading.Tasks; -using Xunit; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Testing.xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class AspNetCorePortTests : IISFunctionalTestBase - { - // Port range allowed by ANCM config - private const int _minPort = 1025; - private const int _maxPort = 48000; - - private static readonly Random _random = new Random(); - - private readonly PublishedSitesFixture _fixture; - - public AspNetCorePortTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - public static TestMatrix TestVariants - => TestMatrix.ForServers(DeployerSelector.ServerType) - .WithTfms(Tfm.NetCoreApp22) - .WithApplicationTypes(ApplicationType.Portable) - .WithAllAncmVersions(); - - public static IEnumerable InvalidTestVariants - => from v in TestVariants.Select(v => v.Single()) - from s in new string[] { (_minPort - 1).ToString(), (_maxPort + 1).ToString(), "noninteger" } - select new object[] { v, s }; - - [ConditionalTheory] - [MemberData(nameof(TestVariants))] - public async Task EnvVarInWebConfig_Valid(TestVariant variant) - { - // Must publish to set env vars in web.config - var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant, publish: true); - var port = GetUnusedRandomPort(); - deploymentParameters.WebConfigBasedEnvironmentVariables["ASPNETCORE_PORT"] = port.ToString(); - - var deploymentResult = await DeployAsync(deploymentParameters); - - var responseText = await deploymentResult.HttpClient.GetStringAsync("/ServerAddresses"); - - Assert.Equal(port, new Uri(responseText).Port); - } - - [ConditionalTheory] - [MemberData(nameof(TestVariants))] - public async Task EnvVarInWebConfig_Empty(TestVariant variant) - { - // Must publish to set env vars in web.config - var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant, publish: true); - deploymentParameters.WebConfigBasedEnvironmentVariables["ASPNETCORE_PORT"] = string.Empty; - - var deploymentResult = await DeployAsync(deploymentParameters); - - var responseText = await deploymentResult.HttpClient.GetStringAsync("/ServerAddresses"); - - // If env var is empty, ANCM should assign a random port (same as no env var) - Assert.InRange(new Uri(responseText).Port, _minPort, _maxPort); - } - - [ConditionalTheory] - [MemberData(nameof(InvalidTestVariants))] - public async Task EnvVarInWebConfig_Invalid(TestVariant variant, string port) - { - // Must publish to set env vars in web.config - var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant, publish: true); - deploymentParameters.WebConfigBasedEnvironmentVariables["ASPNETCORE_PORT"] = port; - - var deploymentResult = await DeployAsync(deploymentParameters); - - var response = await deploymentResult.HttpClient.GetAsync("/ServerAddresses"); - - Assert.Equal(HttpStatusCode.BadGateway, response.StatusCode); - } - - private static int GetUnusedRandomPort() - { - // Large number of retries to prevent test failures due to port collisions, but not infinite - // to prevent infinite loop in case Bind() fails repeatedly for some other reason. - const int retries = 100; - - List exceptions = null; - - for (var i = 0; i < retries; i++) - { - var port = _random.Next(_minPort, _maxPort); - - using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) - { - try - { - socket.Bind(new IPEndPoint(IPAddress.Loopback, port)); - return port; - } - catch (Exception e) - { - // Bind failed, most likely because port is in use. Save exception and retry. - if (exceptions == null) - { - exceptions = new List(retries); - } - exceptions.Add(e); - } - } - } - - throw new AggregateException($"Unable to find unused random port after {retries} retries.", exceptions); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/OutOfProcess/GlobalVersionTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/OutOfProcess/GlobalVersionTests.cs deleted file mode 100644 index f9e6836b6f..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/OutOfProcess/GlobalVersionTests.cs +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using System.Xml.Linq; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class GlobalVersionTests : IISFunctionalTestBase - { - private readonly PublishedSitesFixture _fixture; - - public GlobalVersionTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - private const string _handlerVersion20 = "2.0.0"; - private const string _helloWorldRequest = "HelloWorld"; - private const string _helloWorldResponse = "Hello World"; - - [ConditionalFact] - public async Task GlobalVersion_DefaultWorks() - { - var deploymentParameters = GetGlobalVersionBaseDeploymentParameters(); - - deploymentParameters.HandlerSettings["handlerVersion"] = _handlerVersion20; - - var deploymentResult = await DeployAsync(deploymentParameters); - - var response = await deploymentResult.HttpClient.GetAsync(_helloWorldRequest); - var responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(_helloWorldResponse, responseText); - } - - [ConditionalFact] - [RequiresIIS(IISCapability.PoolEnvironmentVariables)] - [RequiresNewShim] - public async Task GlobalVersion_EnvironmentVariableWorks() - { - var temporaryFile = Path.GetTempFileName(); - try - { - var deploymentParameters = GetGlobalVersionBaseDeploymentParameters(); - CopyShimToOutput(deploymentParameters); - deploymentParameters.PublishApplicationBeforeDeployment = true; - deploymentParameters.EnvironmentVariables["ASPNETCORE_MODULE_OUTOFPROCESS_HANDLER"] = temporaryFile; - - var deploymentResult = await DeployAsync(deploymentParameters); - var requestHandlerPath = Path.Combine(GetANCMRequestHandlerPath(deploymentResult, _handlerVersion20), "aspnetcorev2_outofprocess.dll"); - - File.Delete(temporaryFile); - File.Move(requestHandlerPath, temporaryFile); - - var response = await deploymentResult.HttpClient.GetAsync(_helloWorldRequest); - var responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(_helloWorldResponse, responseText); - StopServer(); - } - finally - { - File.Delete(temporaryFile); - } - } - - [ConditionalTheory] - [InlineData("2.1.0")] - [InlineData("2.1.0-preview")] - public async Task GlobalVersion_NewVersionNumber_Fails(string version) - { - var deploymentParameters = GetGlobalVersionBaseDeploymentParameters(); - deploymentParameters.HandlerSettings["handlerVersion"] = version; - - var deploymentResult = await DeployAsync(deploymentParameters); - - var response = await deploymentResult.HttpClient.GetAsync(_helloWorldRequest); - Assert.False(response.IsSuccessStatusCode); - var responseString = await response.Content.ReadAsStringAsync(); - Assert.Contains("HTTP Error 500.0 - ANCM Out-Of-Process Handler Load Failure", responseString); - } - - [ConditionalTheory] - [InlineData("2.1.0")] - [InlineData("2.1.0-preview")] - public async Task GlobalVersion_NewVersionNumber(string version) - { - var deploymentParameters = GetGlobalVersionBaseDeploymentParameters(); - CopyShimToOutput(deploymentParameters); - deploymentParameters.HandlerSettings["handlerVersion"] = version; - - var deploymentResult = await DeployAsync(deploymentParameters); - - var originalANCMPath = GetANCMRequestHandlerPath(deploymentResult, _handlerVersion20); - var newANCMPath = GetANCMRequestHandlerPath(deploymentResult, version); - Directory.Move(originalANCMPath, newANCMPath); - - var response = await deploymentResult.HttpClient.GetAsync(_helloWorldRequest); - var responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(_helloWorldResponse, responseText); - AssertLoadedVersion(version); - } - - [ConditionalTheory] - [InlineData("2.1.0")] - [InlineData("2.1.0-preview")] - public async Task GlobalVersion_MultipleRequestHandlers_PicksHighestOne(string version) - { - var deploymentParameters = GetGlobalVersionBaseDeploymentParameters(); - CopyShimToOutput(deploymentParameters); - var deploymentResult = await DeployAsync(deploymentParameters); - - var originalANCMPath = GetANCMRequestHandlerPath(deploymentResult, _handlerVersion20); - - var newANCMPath = GetANCMRequestHandlerPath(deploymentResult, version); - - CopyDirectory(originalANCMPath, newANCMPath); - - deploymentResult.HttpClient.DefaultRequestHeaders.Add("ANCMRHPath", newANCMPath); - var response = await deploymentResult.HttpClient.GetAsync("CheckRequestHandlerVersion"); - var responseText = await response.Content.ReadAsStringAsync(); - - Assert.Equal(_helloWorldResponse, responseText); - AssertLoadedVersion(version); - } - - [ConditionalTheory] - [InlineData("2.1.0")] - [InlineData("2.1.0-preview")] - public async Task GlobalVersion_MultipleRequestHandlers_UpgradeWorks(string version) - { - var deploymentParameters = GetGlobalVersionBaseDeploymentParameters(); - CopyShimToOutput(deploymentParameters); - var deploymentResult = await DeployAsync(deploymentParameters); - - var originalANCMPath = GetANCMRequestHandlerPath(deploymentResult, _handlerVersion20); - - deploymentResult.HttpClient.DefaultRequestHeaders.Add("ANCMRHPath", originalANCMPath); - var response = await deploymentResult.HttpClient.GetAsync("CheckRequestHandlerVersion"); - var responseText = await response.Content.ReadAsStringAsync(); - - Assert.Equal(_helloWorldResponse, responseText); - - StopServer(); - - deploymentResult = await DeployAsync(deploymentParameters); - - originalANCMPath = GetANCMRequestHandlerPath(deploymentResult, _handlerVersion20); - - var newANCMPath = GetANCMRequestHandlerPath(deploymentResult, version); - - CopyDirectory(originalANCMPath, newANCMPath); - - deploymentResult.HttpClient.DefaultRequestHeaders.Add("ANCMRHPath", newANCMPath); - response = await deploymentResult.HttpClient.GetAsync("CheckRequestHandlerVersion"); - responseText = await response.Content.ReadAsStringAsync(); - - Assert.Equal(_helloWorldResponse, responseText); - AssertLoadedVersion(version); - } - - [ConditionalFact] - public async Task DoesNotCrashWhenNoVersionsAvailable() - { - var deploymentParameters = GetGlobalVersionBaseDeploymentParameters(); - CopyShimToOutput(deploymentParameters); - var deploymentResult = await DeployAsync(deploymentParameters); - - var originalANCMPath = GetANCMRequestHandlerPath(deploymentResult, _handlerVersion20); - Directory.Delete(originalANCMPath, true); - var response = await deploymentResult.HttpClient.GetAsync("HelloWorld"); - - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - } - - private IISDeploymentParameters GetGlobalVersionBaseDeploymentParameters() - { - return _fixture.GetBaseDeploymentParameters(HostingModel.OutOfProcess, publish: true); - } - - private void CopyDirectory(string from, string to) - { - var toInfo = new DirectoryInfo(to); - toInfo.Create(); - - foreach (var file in new DirectoryInfo(from).GetFiles()) - { - file.CopyTo(Path.Combine(toInfo.FullName, file.Name)); - } - } - - private string GetANCMRequestHandlerPath(IISDeploymentResult deploymentResult, string version) - { - return Path.Combine(deploymentResult.ContentRoot, - deploymentResult.DeploymentParameters.RuntimeArchitecture.ToString(), - version); - } - - private void AssertLoadedVersion(string version) - { - StopServer(); - Assert.Contains(TestSink.Writes, context => context.Message.Contains(version + @"\aspnetcorev2_outofprocess.dll")); - } - - private static void CopyShimToOutput(IISDeploymentParameters parameters) - { - parameters.AddServerConfigAction( - (config, contentRoot) => { - var moduleNodes = config.DescendantNodesAndSelf() - .OfType() - .Where(element => - element.Name == "add" && - element.Attribute("name")?.Value.StartsWith("AspNetCoreModule") == true && - element.Attribute("image") != null); - - var sourceDirectory = new DirectoryInfo(Path.GetDirectoryName(moduleNodes.First().Attribute("image").Value)); - var destinationDirectory = new DirectoryInfo(Path.Combine(contentRoot, sourceDirectory.Name)); - destinationDirectory.Create(); - foreach (var element in moduleNodes) - { - var imageAttribute = element.Attribute("image"); - imageAttribute.Value = imageAttribute.Value.Replace(sourceDirectory.FullName, destinationDirectory.FullName); - } - CopyFiles(sourceDirectory, destinationDirectory); - }); - } - - private static void CopyFiles(DirectoryInfo source, DirectoryInfo target) - { - foreach (DirectoryInfo directoryInfo in source.GetDirectories()) - { - CopyFiles(directoryInfo, target.CreateSubdirectory(directoryInfo.Name)); - } - - foreach (FileInfo fileInfo in source.GetFiles()) - { - var destFileName = Path.Combine(target.FullName, fileInfo.Name); - fileInfo.CopyTo(destFileName); - } - } - - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/OutOfProcess/HelloWorldTest.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/OutOfProcess/HelloWorldTest.cs deleted file mode 100644 index f6e36613d7..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/OutOfProcess/HelloWorldTest.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Diagnostics; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class HelloWorldTests : IISFunctionalTestBase - { - private readonly PublishedSitesFixture _fixture; - - public HelloWorldTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - public static TestMatrix TestVariants - => TestMatrix.ForServers(DeployerSelector.ServerType) - .WithTfms(Tfm.NetCoreApp22, Tfm.Net461) - .WithAllApplicationTypes() - .WithAllAncmVersions(); - - [ConditionalTheory] - [MemberData(nameof(TestVariants))] - public async Task HelloWorld(TestVariant variant) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant); - deploymentParameters.ServerConfigActionList.Add( - (element, _) => { - element - .RequiredElement("system.webServer") - .RequiredElement("security") - .RequiredElement("authentication") - .Element("windowsAuthentication") - ?.SetAttributeValue("enabled", "false"); - }); - - var deploymentResult = await DeployAsync(deploymentParameters); - - var response = await deploymentResult.HttpClient.GetAsync("/HelloWorld"); - var responseText = await response.Content.ReadAsStringAsync(); - - Assert.Equal("Hello World", responseText); - - response = await deploymentResult.HttpClient.GetAsync("/Path/%3F%3F?query"); - responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal("/??", responseText); - - response = await deploymentResult.HttpClient.GetAsync("/Query/%3FPath?query?"); - responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal("?query?", responseText); - - response = await deploymentResult.HttpClient.GetAsync("/BodyLimit"); - responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal("null", responseText); - - response = await deploymentResult.HttpClient.GetAsync("/Auth"); - responseText = await response.Content.ReadAsStringAsync(); - - Assert.Equal("null", responseText); - - Assert.Equal( - $"ContentRootPath {deploymentResult.ContentRoot}" + Environment.NewLine + - $"WebRootPath {deploymentResult.ContentRoot}\\wwwroot" + Environment.NewLine + - $"CurrentDirectory {deploymentResult.ContentRoot}", - await deploymentResult.HttpClient.GetStringAsync("/HostingEnvironment")); - - var expectedDll = variant.AncmVersion == AncmVersion.AspNetCoreModule ? "aspnetcore.dll" : "aspnetcorev2.dll"; - Assert.Contains(deploymentResult.HostProcess.Modules.OfType(), m=> m.FileName.Contains(expectedDll)); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/PublishedSitesFixture.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/PublishedSitesFixture.cs deleted file mode 100644 index 282ee26109..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/PublishedSitesFixture.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - /// - /// This type just maps collection names to available fixtures - /// - [CollectionDefinition(Name)] - public class PublishedSitesCollection : ICollectionFixture, ICollectionFixture - { - public const string Name = nameof(PublishedSitesCollection); - } - - public class PublishedSitesFixture : IDisposable - { - public CachingApplicationPublisher InProcessTestSite { get; } = new CachingApplicationPublisher(Helpers.GetInProcessTestSitesPath()); - public CachingApplicationPublisher OutOfProcessTestSite { get; } = new CachingApplicationPublisher(Helpers.GetOutOfProcessTestSitesPath()); - - public void Dispose() - { - InProcessTestSite.Dispose(); - OutOfProcessTestSite.Dispose(); - } - - public IISDeploymentParameters GetBaseDeploymentParameters(HostingModel hostingModel = HostingModel.InProcess, bool publish = false) - { - var publisher = hostingModel == HostingModel.InProcess ? InProcessTestSite : OutOfProcessTestSite; - return GetBaseDeploymentParameters(publisher, hostingModel, publish); - } - public IISDeploymentParameters GetBaseDeploymentParameters(TestVariant variant, bool publish = false) - { - var publisher = variant.HostingModel == HostingModel.InProcess ? InProcessTestSite : OutOfProcessTestSite; - return GetBaseDeploymentParameters(publisher, new DeploymentParameters(variant), publish); - } - - public IISDeploymentParameters GetBaseDeploymentParameters(ApplicationPublisher publisher, HostingModel hostingModel = HostingModel.InProcess, bool publish = false) - { - return GetBaseDeploymentParameters( - publisher, - new DeploymentParameters(publisher.ApplicationPath, DeployerSelector.ServerType, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64) - { - HostingModel = hostingModel, - TargetFramework = "netcoreapp2.2", - AncmVersion = AncmVersion.AspNetCoreModuleV2 - }, - publish); - } - - public IISDeploymentParameters GetBaseDeploymentParameters(ApplicationPublisher publisher, DeploymentParameters baseParameters, bool publish = false) - { - return new IISDeploymentParameters(baseParameters) - { - ApplicationPublisher = publisher, - ApplicationPath = publisher.ApplicationPath, - PublishApplicationBeforeDeployment = publish - }; - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/RequiresNewHandler.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/RequiresNewHandler.cs deleted file mode 100644 index cbe43ec0c7..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/RequiresNewHandler.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Testing.xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)] - public sealed class RequiresNewHandlerAttribute : Attribute, ITestCondition - { - public bool IsMet => !DeployerSelector.IsForwardsCompatibilityTest; - - public string SkipReason => "Test verifies new behavior in the aspnetcorev2_inprocess.dll that isn't supported in earlier versions."; - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/RequiresNewShim.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/RequiresNewShim.cs deleted file mode 100644 index b0bc50a83b..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/RequiresNewShim.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Testing.xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)] - public sealed class RequiresNewShimAttribute : Attribute, ITestCondition - { - public bool IsMet => !DeployerSelector.IsBackwardsCompatiblityTest; - - public string SkipReason => "Test verifies new behavior in the aspnetcorev2.dll that isn't supported in earlier versions."; - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/ServerAbortTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/ServerAbortTests.cs deleted file mode 100644 index 8ebd70db12..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/ServerAbortTests.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - public abstract class ServerAbortTests: FixtureLoggedTest - { - private readonly IISTestSiteFixture _fixture; - - [Collection(IISTestSiteCollection.Name)] - public class InProc: ServerAbortTests - { - public InProc(IISTestSiteFixture fixture) : base(fixture) { } - } - - [Collection(OutOfProcessTestSiteCollection.Name)] - public class OutOfProcess: ServerAbortTests - { - public OutOfProcess(OutOfProcessTestSiteFixture fixture) : base(fixture) { } - } - - [Collection(OutOfProcessV1TestSiteCollection.Name)] - public class OutOfProcessV1: ServerAbortTests - { - public OutOfProcessV1(OutOfProcessV1TestSiteFixture fixture) : base(fixture) { } - } - - protected ServerAbortTests(IISTestSiteFixture fixture) : base(fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task ClosesConnectionOnServerAbort() - { - try - { - var response = await _fixture.Client.GetAsync("/Abort").DefaultTimeout(); - - // 502 is expected for outofproc but not for inproc - if (_fixture.DeploymentResult.DeploymentParameters.HostingModel == HostingModel.OutOfProcess) - { - Assert.Equal(HttpStatusCode.BadGateway, response.StatusCode); - // 0x80072f78 ERROR_HTTP_INVALID_SERVER_RESPONSE The server returned an invalid or unrecognized response - Assert.Contains("0x80072f78", await response.Content.ReadAsStringAsync()); - } - else - { - Assert.True(false, "Should not reach here"); - } - } - catch (HttpRequestException) - { - // Connection reset is expected both for outofproc and inproc - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/SkipIfNotAdminAttribute.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/SkipIfNotAdminAttribute.cs deleted file mode 100644 index d2acb70415..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/SkipIfNotAdminAttribute.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Security.Principal; -using Microsoft.AspNetCore.Testing.xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)] - public sealed class SkipIfNotAdminAttribute : Attribute, ITestCondition - { - public bool IsMet - { - get - { - var identity = WindowsIdentity.GetCurrent(); - var principal = new WindowsPrincipal(identity); - return principal.IsInRole(WindowsBuiltInRole.Administrator); - } - } - - public string SkipReason => "The current process is not running as admin."; - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/SkipVSTSAttribute.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/SkipVSTSAttribute.cs deleted file mode 100644 index 8e88fc8c26..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/SkipVSTSAttribute.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Testing.xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)] - public sealed class SkipInVSTSAttribute : Attribute, ITestCondition - { - public bool IsMet => string.IsNullOrEmpty(Environment.GetEnvironmentVariable("SYSTEM_TASKDEFINITIONSURI")); - - public string SkipReason => "Running in VSTS"; - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/AppVerifier.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/AppVerifier.cs deleted file mode 100644 index 7984193e29..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/AppVerifier.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Diagnostics; -using System.Linq; - -namespace Microsoft.AspNetCore.Server.IntegrationTesting -{ - public class AppVerifier - { - private static readonly TimeSpan AppVerifierCommandTimeout = TimeSpan.FromSeconds(5); - - public static IDisposable Disable(ServerType serverType, int code) - { - // Set in SetupTestEnvironment.ps1 - var enabledCodes = (Environment.GetEnvironmentVariable("APPVERIFIER_ENABLED_CODES") ?? "").Split(' '); - string processName; - switch (serverType) - { - case ServerType.IISExpress: - processName = "iisexpress.exe"; - break; - case ServerType.IIS: - processName = "w3wp.exe"; - break; - default: - throw new ArgumentOutOfRangeException(nameof(serverType), serverType, null); - } - - if (!enabledCodes.Contains(code.ToString())) - { - return null; - } - - RunProcessAndWaitForExit("appverif.exe", $"-configure {code} -for {processName} -with ErrorReport=0", AppVerifierCommandTimeout); - return new AppVerifierToken(processName, code.ToString()); - } - - private static void RunProcessAndWaitForExit(string fileName, string arguments, TimeSpan timeout) - { - var startInfo = new ProcessStartInfo - { - FileName = fileName, - Arguments = arguments, - RedirectStandardOutput = true, - RedirectStandardError = true, - UseShellExecute = false, - }; - - var process = Process.Start(startInfo); - - if (!process.WaitForExit((int)timeout.TotalMilliseconds)) - { - process.Kill(); - } - - if (process.ExitCode != 0) - { - throw new InvalidOperationException($"Exit code {process.ExitCode} when running {fileName} {arguments}. Stdout: {process.StandardOutput.ReadToEnd()} Stderr: {process.StandardError.ReadToEnd()}"); - } - } - - public class AppVerifierToken : IDisposable - { - private readonly string _processName; - - private readonly string _codes; - - public AppVerifierToken(string processName, string codes) - { - _processName = processName; - _codes = codes; - } - - public void Dispose() - { - // - RunProcessAndWaitForExit("appverif.exe", $"-configure {_codes} -for {_processName} -with ErrorReport={Environment.GetEnvironmentVariable("APPVERIFIER_LEVEL")}", AppVerifierCommandTimeout); - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/EventLogHelpers.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/EventLogHelpers.cs deleted file mode 100644 index 78c77fd2ca..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/EventLogHelpers.cs +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text.RegularExpressions; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.Extensions.Logging; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - public class EventLogHelpers - { - public static void VerifyEventLogEvent(IISDeploymentResult deploymentResult, string expectedRegexMatchString) - { - Assert.True(deploymentResult.HostProcess.HasExited); - - var entries = GetEntries(deploymentResult); - AssertSingleEntry(expectedRegexMatchString, entries); - } - - public static void VerifyEventLogEvent(IISDeploymentResult deploymentResult, string expectedRegexMatchString, ILogger logger) - { - Assert.True(deploymentResult.HostProcess.HasExited); - - var entries = GetEntries(deploymentResult); - try - { - AssertSingleEntry(expectedRegexMatchString, entries); - } - catch (Exception ex) - { - foreach (var entry in entries) - { - logger.LogInformation(entry.Message); - } - throw ex; - } - } - - public static void VerifyEventLogEvents(IISDeploymentResult deploymentResult, params string[] expectedRegexMatchString) - { - Assert.True(deploymentResult.HostProcess.HasExited); - - var entries = GetEntries(deploymentResult).ToList(); - foreach (var regexString in expectedRegexMatchString) - { - var matchedEntries = AssertSingleEntry(regexString, entries); - - foreach (var matchedEntry in matchedEntries) - { - entries.Remove(matchedEntry); - } - } - - Assert.True(0 == entries.Count, $"Some entries were not matched by any regex {FormatEntries(entries)}"); - } - - private static EventLogEntry[] AssertSingleEntry(string regexString, IEnumerable entries) - { - var expectedRegex = new Regex(regexString, RegexOptions.Singleline); - var matchedEntries = entries.Where(entry => expectedRegex.IsMatch(entry.Message)).ToArray(); - Assert.True(matchedEntries.Length > 0, $"No entries matched by '{regexString}'"); - Assert.True(matchedEntries.Length < 2, $"Multiple entries matched by '{regexString}': {FormatEntries(matchedEntries)}"); - return matchedEntries; - } - - private static string FormatEntries(IEnumerable entries) - { - return string.Join(",", entries.Select(e => e.Message)); - } - - private static IEnumerable GetEntries(IISDeploymentResult deploymentResult) - { - var eventLog = new EventLog("Application"); - - // Eventlog is already sorted based on time of event in ascending time. - // Check results in reverse order. - var processIdString = $"Process Id: {deploymentResult.HostProcess.Id}."; - - // Event log messages round down to the nearest second, so subtract a second - var processStartTime = deploymentResult.HostProcess.StartTime.AddSeconds(-1); - for (var i = eventLog.Entries.Count - 1; i >= 0; i--) - { - var eventLogEntry = eventLog.Entries[i]; - if (eventLogEntry.TimeGenerated < processStartTime) - { - // If event logs is older than the process start time, we didn't find a match. - break; - } - - if (eventLogEntry.ReplacementStrings == null || - eventLogEntry.ReplacementStrings.Length < 3) - { - continue; - } - - // ReplacementStings == EventData collection in EventLog - // This is unaffected if event providers are not registered correctly - if (eventLogEntry.Source == AncmVersionToMatch(deploymentResult) && - processIdString == eventLogEntry.ReplacementStrings[1]) - { - yield return eventLogEntry; - } - } - } - - private static string AncmVersionToMatch(IISDeploymentResult deploymentResult) - { - return "IIS " + - (deploymentResult.DeploymentParameters.ServerType == ServerType.IISExpress ? "Express " : "") + - "AspNetCore Module" + - (deploymentResult.DeploymentParameters.AncmVersion == AncmVersion.AspNetCoreModuleV2 ? " V2" : ""); - } - - public static string Started(IISDeploymentResult deploymentResult) - { - if (deploymentResult.DeploymentParameters.HostingModel == HostingModel.InProcess) - { - return InProcessStarted(deploymentResult); - } - else - { - return OutOfProcessStarted(deploymentResult); - } - } - - public static string InProcessStarted(IISDeploymentResult deploymentResult) - { - return $"Application '{EscapedContentRoot(deploymentResult)}' started the coreclr in-process successfully"; - } - - public static string OutOfProcessStarted(IISDeploymentResult deploymentResult) - { - return $"Application '/LM/W3SVC/1/ROOT' started process '\\d+' successfully and process '\\d+' is listening on port '\\d+'."; - } - - public static string InProcessFailedToStart(IISDeploymentResult deploymentResult, string reason) - { - return $"Application '/LM/W3SVC/1/ROOT' with physical root '{EscapedContentRoot(deploymentResult)}' failed to load clr and managed application. {reason}"; - } - - public static string InProcessFailedToStop(IISDeploymentResult deploymentResult, string reason) - { - return "Failed to gracefully shutdown application 'MACHINE/WEBROOT/APPHOST/.*?'."; - } - - public static string InProcessThreadException(IISDeploymentResult deploymentResult, string reason) - { - return $"Application '/LM/W3SVC/1/ROOT' with physical root '{EscapedContentRoot(deploymentResult)}' hit unexpected managed exception{reason}"; - } - - public static string InProcessThreadExit(IISDeploymentResult deploymentResult, string code) - { - return $"Application '/LM/W3SVC/1/ROOT' with physical root '{EscapedContentRoot(deploymentResult)}' hit unexpected managed background thread exit, exit code = '{code}'."; - } - public static string InProcessThreadExitStdOut(IISDeploymentResult deploymentResult, string code, string output) - { - return $"Application '/LM/W3SVC/1/ROOT' with physical root '{EscapedContentRoot(deploymentResult)}' hit unexpected managed background thread exit, exit code = '{code}'. Last 4KB characters of captured stdout and stderr logs:\r\n{output}"; - } - - public static string FailedToStartApplication(IISDeploymentResult deploymentResult, string code) - { - return $"Failed to start application '/LM/W3SVC/1/ROOT', ErrorCode '{code}'."; - } - - public static string ConfigurationLoadError(IISDeploymentResult deploymentResult, string reason) - { - return $"Could not load configuration. Exception message: {reason}"; - } - - public static string OutOfProcessFailedToStart(IISDeploymentResult deploymentResult) - { - return $"Application '/LM/W3SVC/1/ROOT' with physical root '{EscapedContentRoot(deploymentResult)}' failed to start process with " + - $"commandline '(.*)' with multiple retries. " + - $"The last try of listening port is '(.*)'. See previous warnings for details."; - } - - public static string InProcessHostfxrInvalid(IISDeploymentResult deploymentResult) - { - return $"Hostfxr version used does not support 'hostfxr_get_native_search_directories', update the version of hostfxr to a higher version. Path to hostfxr: '(.*)'."; - } - - public static string InProcessFailedToFindNativeDependencies(IISDeploymentResult deploymentResult) - { - return "Invoking hostfxr to find the inprocess request handler failed without finding any native dependencies. " + - "This most likely means the app is misconfigured, please check the versions of Microsoft.NetCore.App and Microsoft.AspNetCore.App that " + - "are targeted by the application and are installed on the machine."; - } - - public static string InProcessFailedToFindRequestHandler(IISDeploymentResult deploymentResult) - { - return "Could not find the assembly '(.*)' referenced for the in-process application. Please confirm the Microsoft.AspNetCore.Server.IIS package is referenced in your application."; - } - - private static string EscapedContentRoot(IISDeploymentResult deploymentResult) - { - var contentRoot = deploymentResult.ContentRoot; - if (!contentRoot.EndsWith('\\')) - { - contentRoot += '\\'; - } - return Regex.Escape(contentRoot); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/FunctionalTestsBase.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/FunctionalTestsBase.cs deleted file mode 100644 index 1a1a4ce490..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/FunctionalTestsBase.cs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.Extensions.Logging.Testing; -using Xunit.Abstractions; - -namespace Microsoft.AspNetCore.Server.IntegrationTesting -{ - public class FunctionalTestsBase : LoggedTest - { - private const string DebugEnvironmentVariable = "ASPNETCORE_MODULE_DEBUG"; - - public FunctionalTestsBase(ITestOutputHelper output = null) : base(output) - { - } - - protected IISDeployerBase _deployer; - - protected ApplicationDeployer CreateDeployer(IISDeploymentParameters parameters) - { - if (parameters.ServerType == ServerType.IISExpress && - !parameters.EnvironmentVariables.ContainsKey(DebugEnvironmentVariable)) - { - parameters.EnvironmentVariables[DebugEnvironmentVariable] = "console"; - } - - return IISApplicationDeployerFactory.Create(parameters, LoggerFactory); - } - - protected virtual async Task DeployAsync(IISDeploymentParameters parameters) - { - _deployer = (IISDeployerBase)CreateDeployer(parameters); - return (IISDeploymentResult)await _deployer.DeployAsync(); - } - - protected virtual async Task StartAsync(IISDeploymentParameters parameters) - { - var result = await DeployAsync(parameters); - await result.AssertStarts(); - return result; - } - - public override void Dispose() - { - StopServer(false); - } - - public void StopServer(bool gracefulShutdown = true) - { - _deployer?.Dispose(gracefulShutdown); - _deployer = null; - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/Helpers.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/Helpers.cs deleted file mode 100644 index 1e31126eab..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/Helpers.cs +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Threading.Tasks; -using System.Xml.Linq; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.AspNetCore.Testing; -using Microsoft.Extensions.Logging; -using Newtonsoft.Json; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - public static class Helpers - { - private static readonly TimeSpan RetryRequestDelay = TimeSpan.FromMilliseconds(100); - private static readonly int RetryRequestCount = 10; - - public static string GetTestWebSitePath(string name) - { - return Path.Combine(TestPathUtilities.GetSolutionRootDirectory("IISIntegration"),"test", "WebSites", name); - } - - public static string GetInProcessTestSitesPath() - { - return DeployerSelector.IsForwardsCompatibilityTest ? GetTestWebSitePath("InProcessForwardsCompatWebSite") : GetTestWebSitePath("InProcessWebSite"); - } - - public static string GetOutOfProcessTestSitesPath() => GetTestWebSitePath("OutOfProcessWebSite"); - - public static async Task AssertStarts(this IISDeploymentResult deploymentResult, string path = "/HelloWorld") - { - var response = await deploymentResult.HttpClient.GetAsync(path); - - var responseText = await response.Content.ReadAsStringAsync(); - - Assert.Equal("Hello World", responseText); - } - - public static async Task StressLoad(HttpClient httpClient, string path, Action action) - { - async Task RunRequests() - { - var connection = new HttpClient() { BaseAddress = httpClient.BaseAddress }; - - for (int j = 0; j < 10; j++) - { - var response = await connection.GetAsync(path); - action(response); - } - } - - List tasks = new List(); - for (int i = 0; i < 10; i++) - { - tasks.Add(Task.Run(RunRequests)); - } - - await Task.WhenAll(tasks); - } - - public static string GetFrebFolder(string folder, IISDeploymentResult result) - { - if (result.DeploymentParameters.ServerType == ServerType.IISExpress) - { - return Path.Combine(folder, result.DeploymentParameters.SiteName); - } - else - { - return Path.Combine(folder, "W3SVC1"); - } - } - - public static void CopyFiles(DirectoryInfo source, DirectoryInfo target, ILogger logger) - { - foreach (DirectoryInfo directoryInfo in source.GetDirectories()) - { - if (directoryInfo.FullName != target.FullName) - { - CopyFiles(directoryInfo, target.CreateSubdirectory(directoryInfo.Name), logger); - } - } - logger?.LogDebug($"Processing {target.FullName}"); - foreach (FileInfo fileInfo in source.GetFiles()) - { - logger?.LogDebug($" Copying {fileInfo.Name}"); - var destFileName = Path.Combine(target.FullName, fileInfo.Name); - fileInfo.CopyTo(destFileName); - } - } - - public static void ModifyWebConfig(this DeploymentResult deploymentResult, Action action) - { - var webConfigPath = Path.Combine(deploymentResult.ContentRoot, "web.config"); - var document = XDocument.Load(webConfigPath); - action(document.Root); - document.Save(webConfigPath); - } - - public static Task RetryRequestAsync(this HttpClient client, string uri, Func predicate) - { - return RetryRequestAsync(client, uri, message => Task.FromResult(predicate(message))); - } - - public static async Task RetryRequestAsync(this HttpClient client, string uri, Func> predicate) - { - HttpResponseMessage response = await client.GetAsync(uri); - - for (var i = 0; i < RetryRequestCount && !await predicate(response); i++) - { - // Keep retrying until app_offline is present. - response = await client.GetAsync(uri); - await Task.Delay(RetryRequestDelay); - } - - if (!await predicate(response)) - { - throw new InvalidOperationException($"Didn't get response that satisfies predicate after {RetryRequestCount} retries"); - } - - return response; - } - - public static async Task Retry(Func func, int attempts, int msDelay) - { - var exceptions = new List(); - - for (var attempt = 0; attempt < attempts; attempt++) - { - try - { - await func(); - return; - } - catch (Exception e) - { - exceptions.Add(e); - } - await Task.Delay(msDelay); - } - - throw new AggregateException(exceptions); - } - - public static void AssertWorkerProcessStop(this IISDeploymentResult deploymentResult, int? timeout = null) - { - var hostProcess = deploymentResult.HostProcess; - Assert.True(hostProcess.WaitForExit(timeout ?? (int)TimeoutExtensions.DefaultTimeoutValue.TotalMilliseconds)); - - if (deploymentResult.DeploymentParameters.ServerType == ServerType.IISExpress) - { - Assert.Equal(0, hostProcess.ExitCode); - } - } - - - public static async Task AssertRecycledAsync(this IISDeploymentResult deploymentResult, Func verificationAction = null) - { - if (deploymentResult.DeploymentParameters.HostingModel != HostingModel.InProcess) - { - throw new NotSupportedException(); - } - - deploymentResult.AssertWorkerProcessStop(); - if (deploymentResult.DeploymentParameters.ServerType == ServerType.IIS) - { - verificationAction = verificationAction ?? (() => deploymentResult.AssertStarts()); - await verificationAction(); - } - } - - public static IEnumerable ToTheoryData(this Dictionary dictionary) - { - return dictionary.Keys.Select(k => new[] { k }); - } - - public static string GetExpectedLogName(IISDeploymentResult deploymentResult, string logFolderPath) - { - var startTime = deploymentResult.HostProcess.StartTime.ToUniversalTime(); - - if (deploymentResult.DeploymentParameters.HostingModel == HostingModel.InProcess) - { - return Path.Combine(logFolderPath, $"std_{startTime.Year}{startTime.Month:D2}" + - $"{startTime.Day:D2}{startTime.Hour:D2}" + - $"{startTime.Minute:D2}{startTime.Second:D2}_" + - $"{deploymentResult.HostProcess.Id}.log"); - } - else - { - return Directory.GetFiles(logFolderPath).Single(); - } - } - - public static void ModifyFrameworkVersionInRuntimeConfig(IISDeploymentResult deploymentResult) - { - var path = Path.Combine(deploymentResult.ContentRoot, "InProcessWebSite.runtimeconfig.json"); - dynamic depsFileContent = JsonConvert.DeserializeObject(File.ReadAllText(path)); - depsFileContent["runtimeOptions"]["framework"]["version"] = "2.9.9"; - var output = JsonConvert.SerializeObject(depsFileContent); - File.WriteAllText(path, output); - } - - public static void AllowNoLogs(this IISDeploymentResult deploymentResult) - { - File.AppendAllText( - Path.Combine(deploymentResult.DeploymentParameters.PublishedApplicationRootPath, "aspnetcore-debug.log"), - "Running test allowed log file to be empty." + Environment.NewLine); - } - - public static string ReadAllTextFromFile(string filename, ILogger logger) - { - try - { - return File.ReadAllText(filename); - } - catch (Exception ex) - { - // check if there is a dotnet.exe, iisexpress.exe, or w3wp.exe processes still running. - var hostingProcesses = Process.GetProcessesByName("dotnet") - .Concat(Process.GetProcessesByName("iisexpress")) - .Concat(Process.GetProcessesByName("w3wp")); - - logger.LogError($"Could not read file content. Exception message {ex.Message}"); - logger.LogError("Current hosting exes running:"); - - foreach (var hostingProcess in hostingProcesses) - { - logger.LogError($"{hostingProcess.ProcessName} pid: {hostingProcess.Id} hasExited: {hostingProcess.HasExited.ToString()}"); - } - throw ex; - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISCapability.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISCapability.cs deleted file mode 100644 index 0a080bb702..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISCapability.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Flags] - public enum IISCapability - { - None = 0, - Websockets = 1, - WindowsAuthentication = 2, - PoolEnvironmentVariables = 4, - ShutdownToken = 8, - DynamicCompression = 16, - ApplicationInitialization = 32, - TracingModule = 64, - FailedRequestTracingModule = 128, - BasicAuthentication = 256 - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISCompressionSiteCollection.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISCompressionSiteCollection.cs deleted file mode 100644 index 2c424943f3..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISCompressionSiteCollection.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [CollectionDefinition(Name)] - public class IISCompressionSiteCollection : ICollectionFixture - { - public const string Name = nameof(IISCompressionSiteCollection); - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISCompressionSiteFixture.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISCompressionSiteFixture.cs deleted file mode 100644 index 3aff68d11b..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISCompressionSiteFixture.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Net.Http; -using System.Threading; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Testing; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - public class IISCompressionSiteFixture : IISTestSiteFixture - { - public IISCompressionSiteFixture() : base(Configure) - { - } - - private static void Configure(IISDeploymentParameters deploymentParameters) - { - // Enable dynamic compression - deploymentParameters.ServerConfigActionList.Add( - (element, _) => { - var webServerElement = element - .RequiredElement("system.webServer"); - - webServerElement - .GetOrAdd("urlCompression") - .SetAttributeValue("doDynamicCompression", "true"); - - webServerElement - .GetOrAdd("httpCompression") - .GetOrAdd("dynamicTypes") - .GetOrAdd("add", "mimeType", "text/*") - .SetAttributeValue("enabled", "true"); - - }); - - deploymentParameters.EnableModule("DynamicCompressionModule", "%IIS_BIN%\\compdyn.dll"); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISFunctionalTestBase.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISFunctionalTestBase.cs deleted file mode 100644 index a20a5e2e0e..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISFunctionalTestBase.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Xunit.Abstractions; - -namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities -{ - public class IISFunctionalTestBase : FunctionalTestsBase - { - public IISFunctionalTestBase(ITestOutputHelper output = null) : base(output) - { - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISTestSiteCollection.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISTestSiteCollection.cs deleted file mode 100644 index 562d63adbe..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISTestSiteCollection.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - /// - /// This type just maps collection names to available fixtures - /// - [CollectionDefinition(Name)] - public class IISTestSiteCollection : ICollectionFixture - { - public const string Name = nameof(IISTestSiteCollection); - } - - [CollectionDefinition(Name)] - public class OutOfProcessTestSiteCollection : ICollectionFixture - { - public const string Name = nameof(OutOfProcessTestSiteCollection); - } - - [CollectionDefinition(Name)] - public class OutOfProcessV1TestSiteCollection : ICollectionFixture - { - public const string Name = nameof(OutOfProcessV1TestSiteCollection); - } - -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISTestSiteFixture.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISTestSiteFixture.cs deleted file mode 100644 index e8cfd8f641..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/IISTestSiteFixture.cs +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Net.Http; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Testing; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - public class OutOfProcessTestSiteFixture : IISTestSiteFixture - { - public OutOfProcessTestSiteFixture() : base(Configure) - { - } - - private static void Configure(IISDeploymentParameters deploymentParameters) - { - deploymentParameters.ApplicationPath = Helpers.GetOutOfProcessTestSitesPath(); - deploymentParameters.HostingModel = HostingModel.OutOfProcess; - } - } - - public class OutOfProcessV1TestSiteFixture : IISTestSiteFixture - { - public OutOfProcessV1TestSiteFixture() : base(Configure) - { - } - - private static void Configure(IISDeploymentParameters deploymentParameters) - { - deploymentParameters.ApplicationPath = Helpers.GetOutOfProcessTestSitesPath(); - deploymentParameters.HostingModel = HostingModel.OutOfProcess; - deploymentParameters.AncmVersion = AncmVersion.AspNetCoreModule; - } - } - - public class IISTestSiteFixture : IDisposable - { - private ApplicationDeployer _deployer; - private ILoggerFactory _loggerFactory; - private ForwardingProvider _forwardingProvider; - private IISDeploymentResult _deploymentResult; - private readonly Action _configure; - - public IISTestSiteFixture() : this(_ => { }) - { - } - - public IISTestSiteFixture(Action configure) - { - var logging = AssemblyTestLog.ForAssembly(typeof(IISTestSiteFixture).Assembly); - _loggerFactory = logging.CreateLoggerFactory(null, nameof(IISTestSiteFixture)); - - _forwardingProvider = new ForwardingProvider(); - _loggerFactory.AddProvider(_forwardingProvider); - - _configure = configure; - } - - public HttpClient Client => DeploymentResult.HttpClient; - public IISDeploymentResult DeploymentResult - { - get - { - EnsureInitialized(); - return _deploymentResult; - } - } - - public TestConnection CreateTestConnection() - { - return new TestConnection(Client.BaseAddress.Port); - } - - public void Dispose() - { - _deployer?.Dispose(); - } - - public void Attach(LoggedTest test) - { - if (_forwardingProvider.LoggerFactory != null) - { - throw new InvalidOperationException("Test instance is already attached to this fixture"); - } - - _forwardingProvider.LoggerFactory = test.LoggerFactory; - } - - public void Detach(LoggedTest test) - { - if (_forwardingProvider.LoggerFactory != test.LoggerFactory) - { - throw new InvalidOperationException("Different test is attached to this fixture"); - } - - _forwardingProvider.LoggerFactory = null; - } - - private void EnsureInitialized() - { - if (_deployer != null) - { - return; - } - - var deploymentParameters = new IISDeploymentParameters(Helpers.GetInProcessTestSitesPath(), - DeployerSelector.ServerType, - RuntimeFlavor.CoreClr, - RuntimeArchitecture.x64) - { - TargetFramework = Tfm.NetCoreApp22, - AncmVersion = AncmVersion.AspNetCoreModuleV2, - HostingModel = HostingModel.InProcess, - PublishApplicationBeforeDeployment = true, - }; - - _configure(deploymentParameters); - - _deployer = IISApplicationDeployerFactory.Create(deploymentParameters, _loggerFactory); - _deploymentResult = (IISDeploymentResult)_deployer.DeployAsync().Result; - } - - private class ForwardingProvider : ILoggerProvider - { - private readonly List _loggers = new List(); - - private ILoggerFactory _loggerFactory; - - public ILoggerFactory LoggerFactory - { - get => _loggerFactory; - set - { - - lock (_loggers) - { - _loggerFactory = value; - foreach (var logger in _loggers) - { - logger.Logger = _loggerFactory?.CreateLogger("FIXTURE:" + logger.Name); - } - } - } - } - - public void Dispose() - { - lock (_loggers) - { - _loggers.Clear(); - } - } - - public ILogger CreateLogger(string categoryName) - { - lock (_loggers) - { - var logger = new ForwardingLogger(categoryName); - _loggers.Add(logger); - return logger; - } - } - } - - internal class ForwardingLogger : ILogger - { - public ForwardingLogger(string name) - { - Name = name; - } - - public ILogger Logger { get; set; } - public string Name { get; set; } - - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) - { - Logger?.Log(logLevel, eventId, state, exception, formatter); - } - - public bool IsEnabled(LogLevel logLevel) => Logger?.IsEnabled(logLevel) == true; - - public IDisposable BeginScope(TState state) => Logger?.BeginScope(state); - } - } - -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/LogFileTestBase.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/LogFileTestBase.cs deleted file mode 100644 index 17885f3547..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/LogFileTestBase.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Xunit.Abstractions; - -namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities -{ - public class LogFileTestBase : IISFunctionalTestBase - { - protected string _logFolderPath; - - public LogFileTestBase(ITestOutputHelper output = null) : base(output) - { - _logFolderPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); - } - public override void Dispose() - { - base.Dispose(); - if (Directory.Exists(_logFolderPath)) - { - Directory.Delete(_logFolderPath, true); - } - } - - public string GetLogFileContent(IISDeploymentResult deploymentResult) - { - return Helpers.ReadAllTextFromFile(Helpers.GetExpectedLogName(deploymentResult, _logFolderPath), Logger); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/RequiresEnvironmentVariableAttribute.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/RequiresEnvironmentVariableAttribute.cs deleted file mode 100644 index d2749db547..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/RequiresEnvironmentVariableAttribute.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Testing.xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)] - public sealed class RequiresEnvironmentVariableAttribute : Attribute, ITestCondition - { - private readonly string _name; - - public RequiresEnvironmentVariableAttribute(string name) - { - _name = name; - } - - public bool IsMet => !string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable(_name)); - - public string SkipReason => $"Environment variable {_name} is required to run this test."; - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/SkipIfDebugAttribute.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/SkipIfDebugAttribute.cs deleted file mode 100644 index 6cdd725392..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/Utilities/SkipIfDebugAttribute.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Testing.xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)] - public sealed class SkipIfDebugAttribute : Attribute, ITestCondition - { - public bool IsMet => - #if DEBUG - false; - #else - true; - #endif - - public string SkipReason => "Test cannot be run in Debug mode."; - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/WindowsAuthTests.cs b/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/WindowsAuthTests.cs deleted file mode 100644 index 8431b15801..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.FunctionalTests/WindowsAuthTests.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class WindowsAuthTests : IISFunctionalTestBase - { - private readonly PublishedSitesFixture _fixture; - - public WindowsAuthTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - public static TestMatrix TestVariants - => TestMatrix.ForServers(DeployerSelector.ServerType) - .WithTfms(Tfm.NetCoreApp22, Tfm.Net461) - .WithApplicationTypes(ApplicationType.Portable) - .WithAllAncmVersions() - .WithAllHostingModels(); - - [ConditionalTheory] - [RequiresIIS(IISCapability.WindowsAuthentication)] - [MemberData(nameof(TestVariants))] - public async Task WindowsAuthTest(TestVariant variant) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant); - deploymentParameters.SetAnonymousAuth(enabled: false); - deploymentParameters.SetWindowsAuth(); - - // The default in hosting sets windows auth to true. - var deploymentResult = await DeployAsync(deploymentParameters); - - var client = deploymentResult.CreateClient(new HttpClientHandler { UseDefaultCredentials = true }); - var response = await client.GetAsync("/Auth"); - var responseText = await response.Content.ReadAsStringAsync(); - - Assert.StartsWith("Windows:", responseText); - Assert.Contains(Environment.UserName, responseText); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.Tests/Common.Tests.csproj b/src/IISIntegration/src/IISIntegration/test/Common.Tests/Common.Tests.csproj deleted file mode 100644 index ede80732ee..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.Tests/Common.Tests.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - netcoreapp2.2 - false - - - - - - - - - - - - - - - - - diff --git a/src/IISIntegration/src/IISIntegration/test/Common.Tests/Utilities/DisposableList.cs b/src/IISIntegration/src/IISIntegration/test/Common.Tests/Utilities/DisposableList.cs deleted file mode 100644 index 78f76e41c2..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.Tests/Utilities/DisposableList.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; - -namespace Microsoft.AspNetCore.Server.IntegrationTesting -{ - public class DisposableList : List, IDisposable where T : IDisposable - { - public DisposableList() : base() { } - - public DisposableList(IEnumerable collection) : base(collection) { } - - public DisposableList(int capacity) : base(capacity) { } - - public void Dispose() - { - foreach (var item in this) - { - item?.Dispose(); - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.Tests/Utilities/TestConnections.cs b/src/IISIntegration/src/IISIntegration/test/Common.Tests/Utilities/TestConnections.cs deleted file mode 100644 index 3b7a870cf3..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.Tests/Utilities/TestConnections.cs +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IntegrationTesting -{ - /// - /// Summary description for TestConnection - /// - public class TestConnection : IDisposable - { - private static readonly TimeSpan Timeout = TimeSpan.FromMinutes(1); - - private readonly bool _ownsSocket; - private readonly Socket _socket; - private readonly NetworkStream _stream; - - public TestConnection(int port) - : this(port, AddressFamily.InterNetwork) - { - } - - public TestConnection(int port, AddressFamily addressFamily) - : this(CreateConnectedLoopbackSocket(port, addressFamily), ownsSocket: true) - { - } - - public TestConnection(Socket socket) - : this(socket, ownsSocket: false) - { - } - - private TestConnection(Socket socket, bool ownsSocket) - { - _ownsSocket = ownsSocket; - _socket = socket; - _stream = new NetworkStream(_socket, ownsSocket: false); - } - - public Socket Socket => _socket; - public Stream Stream => _stream; - - public void Dispose() - { - _stream.Dispose(); - - if (_ownsSocket) - { - _socket.Dispose(); - } - } - - public async Task Send(params string[] lines) - { - var bytes = Encoding.ASCII.GetBytes(string.Join("\r\n", lines)); - - for (var index = 0; index < bytes.Length; index++) - { - await _stream.WriteAsync(bytes, index, 1).ConfigureAwait(false); - await _stream.FlushAsync().ConfigureAwait(false); - // Re-add delay to help find socket input consumption bugs more consistently - //await Task.Delay(TimeSpan.FromMilliseconds(5)); - } - } - - public async Task ReadCharAsync() - { - var bytes = new byte[1]; - return (await _stream.ReadAsync(bytes, 0, 1) == 1) ? bytes[0] : -1; - } - - public async Task ReadLineAsync() - { - var builder = new StringBuilder(); - var current = await ReadCharAsync(); - while (current != '\r') - { - builder.Append((char)current); - current = await ReadCharAsync(); - } - - // Consume \n - await ReadCharAsync(); - - return builder.ToString(); - } - - public async Task> ReceiveChunk() - { - var length = int.Parse(await ReadLineAsync(), System.Globalization.NumberStyles.HexNumber); - - var bytes = await Receive(length); - - await ReadLineAsync(); - - return bytes; - } - - public async Task ReceiveChunk(string expected) - { - Assert.Equal(expected, Encoding.ASCII.GetString((await ReceiveChunk()).Span)); - } - - public async Task Receive(params string[] lines) - { - var expected = string.Join("\r\n", lines); - var actual = await Receive(expected.Length); - - Assert.Equal(expected, Encoding.ASCII.GetString(actual.Span)); - } - - private async Task> Receive(int length) - { - var actual = new byte[length]; - int offset = 0; - try - { - while (offset < length) - { - var task = _stream.ReadAsync(actual, offset, actual.Length - offset); - if (!Debugger.IsAttached) - { - task = task.TimeoutAfter(Timeout); - } - - var count = await task.ConfigureAwait(false); - if (count == 0) - { - break; - } - - offset += count; - } - } - catch (TimeoutException ex) when (offset != 0) - { - throw new TimeoutException( - $"Did not receive a complete response within {Timeout}.{Environment.NewLine}{Environment.NewLine}" + - $"Expected:{Environment.NewLine}{length} bytes of data{Environment.NewLine}{Environment.NewLine}" + - $"Actual:{Environment.NewLine}{Encoding.ASCII.GetString(actual, 0, offset)}{Environment.NewLine}", - ex); - } - - return actual.AsMemory(0, offset); - } - - public async Task ReceiveStartsWith(string prefix, int maxLineLength = 1024) - { - var actual = new byte[maxLineLength]; - var offset = 0; - - while (offset < maxLineLength) - { - // Read one char at a time so we don't read past the end of the line. - var task = _stream.ReadAsync(actual, offset, 1); - if (!Debugger.IsAttached) - { - Assert.True(task.Wait(4000), "timeout"); - } - var count = await task.ConfigureAwait(false); - if (count == 0) - { - break; - } - - Assert.True(count == 1); - offset++; - - if (actual[offset - 1] == '\n') - { - break; - } - } - - var actualLine = Encoding.ASCII.GetString(actual, 0, offset); - Assert.StartsWith(prefix, actualLine); - } - - public async Task ReceiveHeaders(params string[] lines) - { - List headers = new List(); - string line; - do - { - line = await ReadLineAsync(); - headers.Add(line); - } while (line != ""); - - foreach (var s in lines) - { - Assert.Contains(s, headers); - } - - return headers.ToArray(); - } - - public Task WaitForConnectionClose() - { - var tcs = new TaskCompletionSource(); - var eventArgs = new SocketAsyncEventArgs(); - eventArgs.SetBuffer(new byte[128], 0, 128); - eventArgs.Completed += ReceiveAsyncCompleted; - eventArgs.UserToken = tcs; - - if (!_socket.ReceiveAsync(eventArgs)) - { - ReceiveAsyncCompleted(this, eventArgs); - } - - return tcs.Task; - } - - private void ReceiveAsyncCompleted(object sender, SocketAsyncEventArgs e) - { - var tcs = (TaskCompletionSource)e.UserToken; - if (e.BytesTransferred == 0) - { - tcs.SetResult(null); - } - else - { - tcs.SetException(new IOException( - $"Expected connection close, received data instead: \"{Encoding.ASCII.GetString(e.Buffer, 0, e.BytesTransferred)}\"")); - } - } - - public static Socket CreateConnectedLoopbackSocket(int port, AddressFamily addressFamily) - { - if (addressFamily != AddressFamily.InterNetwork && addressFamily != AddressFamily.InterNetworkV6) - { - throw new ArgumentException($"TestConnection does not support address family of type {addressFamily}", nameof(addressFamily)); - } - - var socket = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp); - var address = addressFamily == AddressFamily.InterNetworkV6 - ? IPAddress.IPv6Loopback - : IPAddress.Loopback; - socket.Connect(new IPEndPoint(address, port)); - return socket; - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Common.Tests/Utilities/TimeoutExtensions.cs b/src/IISIntegration/src/IISIntegration/test/Common.Tests/Utilities/TimeoutExtensions.cs deleted file mode 100644 index ce7175dff9..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Common.Tests/Utilities/TimeoutExtensions.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Runtime.CompilerServices; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing; - -namespace Microsoft.AspNetCore.Server.IntegrationTesting -{ - - public static class TimeoutExtensions - { - public static TimeSpan DefaultTimeoutValue = TimeSpan.FromSeconds(300); - - public static Task DefaultTimeout(this Task task, [CallerFilePath] string filePath = null, [CallerLineNumber] int lineNumber = -1) - { - return task.TimeoutAfter(DefaultTimeoutValue, filePath, lineNumber); - } - - public static Task DefaultTimeout(this Task task, [CallerFilePath] string filePath = null, [CallerLineNumber] int lineNumber = -1) - { - return task.TimeoutAfter(DefaultTimeoutValue, filePath, lineNumber); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/CommonLibTests.vcxproj b/src/IISIntegration/src/IISIntegration/test/CommonLibTests/CommonLibTests.vcxproj deleted file mode 100644 index 87dbd16675..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/CommonLibTests.vcxproj +++ /dev/null @@ -1,196 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - {1eac8125-1765-4e2d-8cbe-56dc98a1c8c1} - Win32Proj - 10.0.15063.0 - Application - v141 - Unicode - - - - - - - - - $(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\ - - - $(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\ - - - $(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\ - - - $(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\ - - - - - - - - - - - - - - - - - - - - {ec82302f-d2f0-4727-99d1-eabc0dd9dc3b} - - - {55494e58-e061-4c4c-a0a8-837008e72f85} - - - {09d9d1d6-2951-4e14-bc35-76a23cf9391a} - - - {1533e271-f61b-441b-8b74-59fb61df0552} - - - {cac1267b-8778-4257-aac6-caf481723b01} - - - {d57ea297-6dc2-4bc0-8c91-334863327863} - - - - - - - NotUsing - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(IntDir)$(TargetName).pch - stdafx.h - true - EnableFastChecks - MultiThreadedDebug - Level3 - $(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories);..\..\src\AspNetCoreModuleV2\RequestHandlerLib;..\..\src\AspNetCoreModuleV2\IISLib;..\..\src\AspNetCoreModuleV2\CommonLib;..\gtest\googletest\googletest\include;..\gtest\googletest\googlemock\include;...\..\src\AspNetCoreModuleV2\AspNetCore\Inc;..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\ - /D "_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING" - stdcpp17 - - - true - Console - ..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\$(Configuration)\; - kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;inprocessapplication.obj;inprocesshandler.obj;ahadmin.lib;Rpcrt4.lib;inprocessapplicationbase.obj;stdafx.obj;version.lib;inprocessoptions.obj;%(AdditionalDependencies) - UseLinkTimeCodeGeneration - - - - - - - - - NotUsing - Disabled - X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(IntDir)$(TargetName).pch - stdafx.h - true - EnableFastChecks - MultiThreadedDebug - Level3 - $(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories);..\..\src\AspNetCoreModuleV2\RequestHandlerLib;..\..\src\AspNetCoreModuleV2\IISLib;..\..\src\AspNetCoreModuleV2\CommonLib;..\gtest\googletest\googletest\include;..\gtest\googletest\googlemock\include;...\..\src\AspNetCoreModuleV2\AspNetCore\Inc;..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\ - /D "_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING" - stdcpp17 - - - true - Console - ..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\x64\$(Configuration)\; - kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;inprocessapplication.obj;inprocesshandler.obj;ahadmin.lib;Rpcrt4.lib;inprocessapplicationbase.obj;stdafx.obj;version.lib;inprocessoptions.obj;%(AdditionalDependencies) - UseLinkTimeCodeGeneration - - - - - - - - - NotUsing - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(IntDir)$(TargetName).pch - stdafx.h - MultiThreaded - Level3 - ProgramDatabase - $(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories);..\..\src\AspNetCoreModuleV2\RequestHandlerLib;..\..\src\AspNetCoreModuleV2\IISLib;..\..\src\AspNetCoreModuleV2\CommonLib;..\gtest\googletest\googletest\include;..\gtest\googletest\googlemock\include;...\..\src\AspNetCoreModuleV2\AspNetCore\Inc;..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\ - /D "_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING" - stdcpp17 - - - true - Console - /NODEFAULTLIB:libucrt.lib /DEFAULTLIB:ucrt.lib %(AdditionalOptions) - true - true - ..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\$(Configuration)\; - kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;inprocessapplication.obj;inprocesshandler.obj;ahadmin.lib;Rpcrt4.lib;inprocessapplicationbase.obj;stdafx.obj;version.lib;inprocessoptions.obj;%(AdditionalDependencies) - UseLinkTimeCodeGeneration - - - - - - - - - NotUsing - X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(IntDir)$(TargetName).pch - stdafx.h - MultiThreaded - Level3 - ProgramDatabase - $(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories);..\..\src\AspNetCoreModuleV2\RequestHandlerLib;..\..\src\AspNetCoreModuleV2\IISLib;..\..\src\AspNetCoreModuleV2\CommonLib;..\gtest\googletest\googletest\include;..\gtest\googletest\googlemock\include;...\..\src\AspNetCoreModuleV2\AspNetCore\Inc;..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\ - /D "_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING" - stdcpp17 - - - true - Console - /NODEFAULTLIB:libucrt.lib /DEFAULTLIB:ucrt.lib %(AdditionalOptions) - true - true - ..\..\src\AspNetCoreModuleV2\InProcessRequestHandler\x64\$(Configuration)\; - kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;inprocessapplication.obj;inprocesshandler.obj;ahadmin.lib;Rpcrt4.lib;inprocessapplicationbase.obj;stdafx.obj;version.lib;inprocessoptions.obj;%(AdditionalDependencies) - UseLinkTimeCodeGeneration - - - - - - - - \ No newline at end of file diff --git a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/ConfigUtilityTests.cpp b/src/IISIntegration/src/IISIntegration/test/CommonLibTests/ConfigUtilityTests.cpp deleted file mode 100644 index 9b5bf6e9e6..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/ConfigUtilityTests.cpp +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -#include "stdafx.h" -#include "gmock/gmock.h" -using ::testing::_; -using ::testing::NiceMock; - -namespace ConfigUtilityTests -{ - using ::testing::Test; - - class ConfigUtilityTest : public Test - { - protected: - void TestHandlerVersion(std::wstring key, std::wstring value, std::wstring expected, HRESULT(*func)(IAppHostElement*, STRU&)) - { - IAppHostElement* retElement = NULL; - - STRU handlerVersion; - - // NiceMock removes warnings about "uninteresting calls", - auto element = std::make_unique>(); - auto innerElement = std::make_unique>(); - auto collection = std::make_unique>(); - auto nameElement = std::make_unique>(); - auto mockProperty = std::make_unique>(); - - ON_CALL(*element, GetElementByName(_, _)) - .WillByDefault(DoAll(testing::SetArgPointee<1>(innerElement.get()), testing::Return(S_OK))); - ON_CALL(*innerElement, get_Collection(_)) - .WillByDefault(testing::DoAll(testing::SetArgPointee<0>(collection.get()), testing::Return(S_OK))); - ON_CALL(*collection, get_Count(_)) - .WillByDefault(DoAll(testing::SetArgPointee<0>(1), testing::Return(S_OK))); - ON_CALL(*collection, get_Item(_, _)) - .WillByDefault(DoAll(testing::SetArgPointee<1>(nameElement.get()), testing::Return(S_OK))); - ON_CALL(*nameElement, GetPropertyByName(_, _)) - .WillByDefault(DoAll(testing::SetArgPointee<1>(mockProperty.get()), testing::Return(S_OK))); - EXPECT_CALL(*mockProperty, get_StringValue(_)) - .WillOnce(DoAll(testing::SetArgPointee<0>(SysAllocString(key.c_str())), testing::Return(S_OK))) - .WillOnce(DoAll(testing::SetArgPointee<0>(SysAllocString(value.c_str())), testing::Return(S_OK))); - - HRESULT hr = func(element.get(), handlerVersion); - - EXPECT_EQ(hr, S_OK); - EXPECT_STREQ(handlerVersion.QueryStr(), expected.c_str()); - } - }; - - TEST_F(ConfigUtilityTest, CheckHandlerVersionKeysAndValues) - { - auto func = ConfigUtility::FindHandlerVersion; - TestHandlerVersion(L"handlerVersion", L"value", L"value", func); - TestHandlerVersion(L"handlerversion", L"value", L"value", func); - TestHandlerVersion(L"HandlerversioN", L"value", L"value", func); - TestHandlerVersion(L"randomvalue", L"value", L"", func); - TestHandlerVersion(L"", L"value", L"", func); - TestHandlerVersion(L"", L"", L"", func); - } - - TEST_F(ConfigUtilityTest, CheckDebugLogFile) - { - auto func = ConfigUtility::FindDebugFile; - - TestHandlerVersion(L"debugFile", L"value", L"value", func); - TestHandlerVersion(L"debugFILE", L"value", L"value", func); - } - - TEST_F(ConfigUtilityTest, CheckDebugLevel) - { - auto func = ConfigUtility::FindDebugLevel; - - TestHandlerVersion(L"debugLevel", L"value", L"value", func); - TestHandlerVersion(L"debugLEVEL", L"value", L"value", func); - } - - TEST(ConfigUtilityTestSingle, MultipleElements) - { - IAppHostElement* retElement = NULL; - STRU handlerVersion; - - auto element = std::make_unique>(); - auto innerElement = std::make_unique>(); - auto collection = std::make_unique>(); - auto nameElement = std::make_unique>(); - auto mockProperty = std::make_unique>(); - - ON_CALL(*element, GetElementByName(_, _)) - .WillByDefault(DoAll(testing::SetArgPointee<1>(innerElement.get()), testing::Return(S_OK))); - ON_CALL(*innerElement, get_Collection(_)) - .WillByDefault(testing::DoAll(testing::SetArgPointee<0>(collection.get()), testing::Return(S_OK))); - ON_CALL(*collection, get_Count(_)) - .WillByDefault(DoAll(testing::SetArgPointee<0>(2), testing::Return(S_OK))); - ON_CALL(*collection, get_Item(_, _)) - .WillByDefault(DoAll(testing::SetArgPointee<1>(nameElement.get()), testing::Return(S_OK))); - ON_CALL(*nameElement, GetPropertyByName(_, _)) - .WillByDefault(DoAll(testing::SetArgPointee<1>(mockProperty.get()), testing::Return(S_OK))); - EXPECT_CALL(*mockProperty, get_StringValue(_)) - .WillOnce(DoAll(testing::SetArgPointee<0>(SysAllocString(L"key")), testing::Return(S_OK))) - .WillOnce(DoAll(testing::SetArgPointee<0>(SysAllocString(L"value")), testing::Return(S_OK))) - .WillOnce(DoAll(testing::SetArgPointee<0>(SysAllocString(L"handlerVersion")), testing::Return(S_OK))) - .WillOnce(DoAll(testing::SetArgPointee<0>(SysAllocString(L"value2")), testing::Return(S_OK))); - - HRESULT hr = ConfigUtility::FindHandlerVersion(element.get(), handlerVersion); - - EXPECT_EQ(hr, S_OK); - EXPECT_STREQ(handlerVersion.QueryStr(), L"value2"); - } - - TEST(ConfigUtilityTestSingle, IgnoresFailedGetElement) - { - STRU handlerVersion; - - auto element = std::make_unique>(); - ON_CALL(*element, GetElementByName(_, _)) - .WillByDefault(DoAll(testing::SetArgPointee<1>(nullptr), testing::Return(HRESULT_FROM_WIN32( ERROR_INVALID_INDEX )))); - - HRESULT hr = ConfigUtility::FindHandlerVersion(element.get(), handlerVersion); - - EXPECT_EQ(hr, S_OK); - EXPECT_STREQ(handlerVersion.QueryStr(), L""); - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/FileOutputManagerTests.cpp b/src/IISIntegration/src/IISIntegration/test/CommonLibTests/FileOutputManagerTests.cpp deleted file mode 100644 index 66a9ff7f0b..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/FileOutputManagerTests.cpp +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -#include "stdafx.h" -#include "gtest/internal/gtest-port.h" -#include "FileOutputManager.h" - -class FileManagerWrapper -{ -public: - FileOutputManager* manager; - FileManagerWrapper(FileOutputManager* m) - : manager(m) - { - manager->Start(); - } - - ~FileManagerWrapper() - { - delete manager; - } -}; - -namespace FileOutManagerStartupTests -{ - using ::testing::Test; - class FileOutputManagerTest : public Test - { - protected: - void - Test(std::wstring fileNamePrefix, FILE* out) - { - PCWSTR expected = L"test"; - - auto tempDirectory = TempDirectory(); - FileOutputManager* pManager = new FileOutputManager(fileNamePrefix, tempDirectory.path()); - - { - FileManagerWrapper wrapper(pManager); - - wprintf(expected, out); - } - - for (auto & p : std::filesystem::directory_iterator(tempDirectory.path())) - { - std::wstring filename(p.path().filename()); - ASSERT_EQ(filename.substr(0, fileNamePrefix.size()), fileNamePrefix); - - std::wstring content = Helpers::ReadFileContent(std::wstring(p.path())); - } - } - }; - - TEST_F(FileOutputManagerTest, WriteToFileCheckContentsWritten) - { - Test(L"", stdout); - Test(L"log", stdout); - } - - TEST_F(FileOutputManagerTest, WriteToFileCheckContentsWrittenErr) - { - Test(L"", stderr); - Test(L"log", stderr); - } -} - -namespace FileOutManagerOutputTests -{ - TEST(FileOutManagerOutputTest, StdOut) - { - PCWSTR expected = L"test"; - - auto tempDirectory = TempDirectory(); - - FileOutputManager* pManager = new FileOutputManager(L"", tempDirectory.path()); - { - FileManagerWrapper wrapper(pManager); - - fwprintf(stdout, expected); - pManager->Stop(); - - auto output = pManager->GetStdOutContent(); - ASSERT_FALSE(output.empty()); - - ASSERT_STREQ(output.c_str(), expected); - } - } - - TEST(FileOutManagerOutputTest, StdErr) - { - PCWSTR expected = L"test"; - - auto tempDirectory = TempDirectory(); - - FileOutputManager* pManager = new FileOutputManager(L"", tempDirectory.path().c_str()); - { - FileManagerWrapper wrapper(pManager); - - fwprintf(stderr, expected); - pManager->Stop(); - - auto output = pManager->GetStdOutContent(); - ASSERT_FALSE(output.empty()); - - ASSERT_STREQ(output.c_str(), expected); - } - } - - TEST(FileOutManagerOutputTest, CapAt30KB) - { - PCWSTR expected = L"hello world"; - - auto tempDirectory = TempDirectory(); - - FileOutputManager* pManager = new FileOutputManager(L"", tempDirectory.path()); - { - FileManagerWrapper wrapper(pManager); - - for (int i = 0; i < 3000; i++) - { - wprintf(expected); - } - pManager->Stop(); - auto output = pManager->GetStdOutContent(); - ASSERT_FALSE(output.empty()); - - ASSERT_EQ(output.size(), 30000); - } - } - - TEST(FileOutManagerOutputTest, StartStopRestoresCorrectly) - { - PCWSTR expected = L"test"; - - auto tempDirectory = TempDirectory(); - - for (int i = 0; i < 10; i++) - { - FileOutputManager* pManager = new FileOutputManager(L"", tempDirectory.path()); - { - FileManagerWrapper wrapper(pManager); - - wprintf(expected); - pManager->Stop(); - auto output = pManager->GetStdOutContent(); - ASSERT_FALSE(output.empty()); - - ASSERT_STREQ(output.c_str(), expected); - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/GlobalVersionTests.cpp b/src/IISIntegration/src/IISIntegration/test/CommonLibTests/GlobalVersionTests.cpp deleted file mode 100644 index f38c9361d2..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/GlobalVersionTests.cpp +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -#include "stdafx.h" -#include "gtest/internal/gtest-port.h" - -namespace GlobalVersionTests -{ - using ::testing::Test; - namespace fs = std::filesystem; - - class GlobalVersionTest : public Test - { - protected: - void - RemoveFileNamePath(PCWSTR dllPath, PCWSTR expected) - { - std::wstring res = GlobalVersionUtility::RemoveFileNameFromFolderPath(dllPath); - EXPECT_STREQ(res.c_str(), expected); - } - }; - - TEST_F(GlobalVersionTest, RemovesPathCorrectly) - { - RemoveFileNamePath(L"test\\log.txt", L"test"); - RemoveFileNamePath(L"test\\log", L"test"); - RemoveFileNamePath(L"C:\\Program Files\\IIS\\aspnetcorev2.dll", L"C:\\Program Files\\IIS"); - RemoveFileNamePath(L"test\\log.txt", L"test"); - } - - TEST(GetRequestHandlerVersions, GetFolders) - { - auto tempPath = TempDirectory(); - EXPECT_TRUE(fs::create_directories(tempPath.path() / L"2.0.0")); - - auto res = GlobalVersionUtility::GetRequestHandlerVersions(tempPath.path().c_str()); - EXPECT_EQ(res.size(), 1); - EXPECT_EQ(res.at(0), fx_ver_t(2, 0, 0, std::wstring())); - } - - TEST(GetRequestHandlerVersions, GetFolderPreview) - { - auto tempPath = TempDirectory(); - EXPECT_TRUE(fs::create_directories(tempPath.path() / L"2.0.0-preview")); - - auto res = GlobalVersionUtility::GetRequestHandlerVersions(tempPath.path().c_str()); - EXPECT_EQ(res.size(), 1); - EXPECT_EQ(res.at(0), fx_ver_t(2, 0, 0, std::wstring(L"-preview"))); - } - - TEST(GetRequestHandlerVersions, GetFolderManyVersions) - { - auto tempPath = TempDirectory(); - EXPECT_TRUE(fs::create_directories(tempPath.path() / + L"2.0.0")); - EXPECT_TRUE(fs::create_directories(tempPath.path() / + L"1.9.0")); - EXPECT_TRUE(fs::create_directories(tempPath.path() / + L"2.1.0")); - - auto res = GlobalVersionUtility::GetRequestHandlerVersions(tempPath.path().c_str()); - EXPECT_EQ(res.size(), 3); - EXPECT_TRUE(std::find(res.begin(), res.end(), fx_ver_t(1, 9, 0, std::wstring())) != std::end(res)); - EXPECT_TRUE(std::find(res.begin(), res.end(), fx_ver_t(2, 0, 0, std::wstring())) != std::end(res)); - EXPECT_TRUE(std::find(res.begin(), res.end(), fx_ver_t(2, 1, 0, std::wstring())) != std::end(res)); - } - - TEST(FindHighestGlobalVersion, HighestVersionWithSingleFolder) - { - auto tempPath = TempDirectory(); - EXPECT_TRUE(fs::create_directories(tempPath.path() / "2.0.0")); - - auto res = GlobalVersionUtility::FindHighestGlobalVersion(tempPath.path().c_str()); - - EXPECT_STREQ(res.c_str(), L"2.0.0"); - } - - TEST(FindHighestGlobalVersion, HighestVersionWithMultipleVersions) - { - auto tempPath = TempDirectory(); - EXPECT_TRUE(fs::create_directories(tempPath.path() / "2.0.0")); - EXPECT_TRUE(fs::create_directories(tempPath.path() / "2.1.0")); - - auto res = GlobalVersionUtility::FindHighestGlobalVersion(tempPath.path().c_str()); - - EXPECT_STREQ(res.c_str(), L"2.1.0"); - } - - TEST(FindHighestGlobalVersion, HighestVersionWithMultipleVersionsPreview) - { - auto tempPath = TempDirectory(); - EXPECT_TRUE(fs::create_directories(tempPath.path() / "2.0.0")); - EXPECT_TRUE(fs::create_directories(tempPath.path() / "2.1.0")); - EXPECT_TRUE(fs::create_directories(tempPath.path() / "2.2.0-preview")); - - auto res = GlobalVersionUtility::FindHighestGlobalVersion(tempPath.path().c_str()); - - EXPECT_STREQ(res.c_str(), L"2.2.0-preview"); - } - - TEST(FindHighestGlobalVersion, HighestVersionWithMultipleVersionNoPreview) - { - auto tempPath = TempDirectory(); - EXPECT_TRUE(fs::create_directories(tempPath.path() / "2.0.0")); - EXPECT_TRUE(fs::create_directories(tempPath.path() / "2.1.0-preview")); - EXPECT_TRUE(fs::create_directories(tempPath.path() / "2.1.0")); - - auto res = GlobalVersionUtility::FindHighestGlobalVersion(tempPath.path().c_str()); - - EXPECT_STREQ(res.c_str(), L"2.1.0"); - } - - TEST(GetGlobalRequestHandlerPath, FindHighestVersionNoHandlerName) - { - auto tempPath = TempDirectory(); - EXPECT_TRUE(fs::create_directories(tempPath.path() / "2.0.0")); - auto result = GlobalVersionUtility::GetGlobalRequestHandlerPath(tempPath.path().c_str(), L"", L"aspnetcorev2_outofprocess.dll"); - - EXPECT_STREQ(result.c_str(), (tempPath.path() / L"2.0.0\\aspnetcorev2_outofprocess.dll").c_str()); - } - - TEST(GetGlobalRequestHandlerPath, FindHighestVersionPreviewWins) - { - auto tempPath = TempDirectory(); - EXPECT_TRUE(fs::create_directories(tempPath.path() / "2.0.0")); - EXPECT_TRUE(fs::create_directories(tempPath.path() / "2.1.0-preview")); - - auto result = GlobalVersionUtility::GetGlobalRequestHandlerPath(tempPath.path().c_str(), L"", L"aspnetcorev2_outofprocess.dll"); - - EXPECT_STREQ(result.c_str(), (tempPath.path() / L"2.1.0-preview\\aspnetcorev2_outofprocess.dll").c_str()); - } - - TEST(GetGlobalRequestHandlerPath, FindHighestVersionSpecificVersion) - { - auto tempPath = TempDirectory(); - EXPECT_TRUE(fs::create_directories(tempPath.path() / "2.0.0")); - EXPECT_TRUE(fs::create_directories(tempPath.path() / "2.1.0-preview")); - - auto result = GlobalVersionUtility::GetGlobalRequestHandlerPath(tempPath.path().c_str(), L"2.0.0", L"aspnetcorev2_outofprocess.dll"); - - EXPECT_STREQ(result.c_str(), (tempPath.path() / L"2.0.0\\aspnetcorev2_outofprocess.dll").c_str()); - } - - TEST(GetGlobalRequestHandlerPath, FindHighestVersionSpecificPreview) - { - auto tempPath = TempDirectory(); - EXPECT_TRUE(fs::create_directories(tempPath.path() / "2.0.0")); - EXPECT_TRUE(fs::create_directories(tempPath.path() / "2.1.0-preview")); - EXPECT_TRUE(fs::create_directories(tempPath.path() / "2.2.0")); - - - auto result = GlobalVersionUtility::GetGlobalRequestHandlerPath(tempPath.path().c_str(), L"2.1.0-preview", L"aspnetcorev2_outofprocess.dll"); - - EXPECT_STREQ(result.c_str(), (tempPath.path() / L"2.1.0-preview\\aspnetcorev2_outofprocess.dll").c_str()); - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/Helpers.cpp b/src/IISIntegration/src/IISIntegration/test/CommonLibTests/Helpers.cpp deleted file mode 100644 index ccca6cad5b..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/Helpers.cpp +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -#include "stdafx.h" - -std::wstring -Helpers::ReadFileContent(std::wstring file) -{ - std::wcout << file << std::endl; - - std::fstream t(file); - std::stringstream buffer; - buffer << t.rdbuf(); - - int nChars = MultiByteToWideChar(CP_ACP, 0, buffer.str().c_str(), -1, NULL, 0); - - std::wstring retVal(nChars, '\0'); - - MultiByteToWideChar(CP_UTF8, 0, buffer.str().c_str(), -1, retVal.data(), nChars); - - return retVal; -} - -TempDirectory::TempDirectory() -{ - UUID uuid; - UuidCreate(&uuid); - RPC_CSTR szUuid = NULL; - if (UuidToStringA(&uuid, &szUuid) == RPC_S_OK) - { - m_path = std::filesystem::temp_directory_path() / reinterpret_cast(szUuid); - RpcStringFreeA(&szUuid); - return; - } - throw std::exception("Cannot create temp directory"); -} - -TempDirectory::~TempDirectory() -{ - std::filesystem::remove_all(m_path); -} diff --git a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/Helpers.h b/src/IISIntegration/src/IISIntegration/test/CommonLibTests/Helpers.h deleted file mode 100644 index 67256966bb..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/Helpers.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -#pragma once -class Helpers -{ -public: - static - std::wstring - ReadFileContent(std::wstring file); -}; - -class TempDirectory -{ -public: - - TempDirectory(); - - ~TempDirectory(); - - std::filesystem::path path() const - { - return m_path; - } - -private: - std::filesystem::path m_path; -}; diff --git a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/NativeTests.targets b/src/IISIntegration/src/IISIntegration/test/CommonLibTests/NativeTests.targets deleted file mode 100644 index f3d2caf930..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/NativeTests.targets +++ /dev/null @@ -1,8 +0,0 @@ - - - $(VCIDEInstallDir)..\CommonExtensions\Microsoft\TestWindow\vstest.console.exe - - - - - \ No newline at end of file diff --git a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/PipeOutputManagerTests.cpp b/src/IISIntegration/src/IISIntegration/test/CommonLibTests/PipeOutputManagerTests.cpp deleted file mode 100644 index 385d6df9e0..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/PipeOutputManagerTests.cpp +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -#include "stdafx.h" -#include "gtest/internal/gtest-port.h" -#include "PipeOutputManager.h" - -class FileManagerWrapper -{ -public: - PipeOutputManager * manager; - FileManagerWrapper(PipeOutputManager* m) - : manager(m) - { - manager->Start(); - } - - ~FileManagerWrapper() - { - delete manager; - } -}; - -namespace PipeOutputManagerTests -{ - TEST(PipeManagerOutputTest, StdOut) - { - PCWSTR expected = L"test"; - - PipeOutputManager* pManager = new PipeOutputManager(true); - - pManager->Start(); - fwprintf(stdout, expected); - pManager->Stop(); - - auto output = pManager->GetStdOutContent(); - ASSERT_STREQ(output.c_str(), expected); - delete pManager; - } - - TEST(PipeManagerOutputTest, StdOutMultiToWide) - { - PipeOutputManager* pManager = new PipeOutputManager(true); - - pManager->Start(); - fprintf(stdout, "test"); - pManager->Stop(); - - auto output = pManager->GetStdOutContent(); - ASSERT_STREQ(output.c_str(), L"test"); - delete pManager; - } - - TEST(PipeManagerOutputTest, StdErr) - { - PCWSTR expected = L"test"; - - PipeOutputManager* pManager = new PipeOutputManager(); - - pManager->Start(); - fwprintf(stderr, expected); - pManager->Stop(); - - auto output = pManager->GetStdOutContent(); - ASSERT_STREQ(output.c_str(), expected); - delete pManager; - } - - TEST(PipeManagerOutputTest, CheckMaxPipeSize) - { - std::wstring test; - for (int i = 0; i < 3000; i++) - { - test.append(L"hello world"); - } - - PipeOutputManager* pManager = new PipeOutputManager(); - - pManager->Start(); - wprintf(test.c_str()); - pManager->Stop(); - - auto output = pManager->GetStdOutContent(); - ASSERT_EQ(output.size(), (DWORD)30000); - delete pManager; - } - - TEST(PipeManagerOutputTest, SetInvalidHandlesForErrAndOut) - { - auto m_fdPreviousStdOut = _dup(_fileno(stdout)); - auto m_fdPreviousStdErr = _dup(_fileno(stderr)); - - SetStdHandle(STD_ERROR_HANDLE, INVALID_HANDLE_VALUE); - SetStdHandle(STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE); - - PCWSTR expected = L"test"; - - PipeOutputManager* pManager = new PipeOutputManager(); - pManager->Start(); - - _dup2(m_fdPreviousStdOut, _fileno(stdout)); - _dup2(m_fdPreviousStdErr, _fileno(stderr)); - - // Test will fail if we didn't redirect stdout back to a file descriptor. - // This is because gtest relies on console output to know if a test succeeded or failed. - // If the output still points to a file/pipe, the test (and all other tests after it) will fail. - delete pManager; - } - - TEST(PipeManagerOutputTest, CreateDeleteMultipleTimesStdOutWorks) - { - for (int i = 0; i < 10; i++) - { - auto stdoutBefore = _fileno(stdout); - auto stderrBefore = _fileno(stderr); - PCWSTR expected = L"test"; - - PipeOutputManager* pManager = new PipeOutputManager(); - - pManager->Start(); - fwprintf(stdout, expected); - - pManager->Stop(); - - auto output = pManager->GetStdOutContent(); - ASSERT_STREQ(output.c_str(), expected); - ASSERT_EQ(stdoutBefore, _fileno(stdout)); - ASSERT_EQ(stderrBefore, _fileno(stderr)); - delete pManager; - } - // When this returns, we get an AV from gtest. - } - - TEST(PipeManagerOutputTest, CreateDeleteKeepOriginalStdErr) - { - for (int i = 0; i < 10; i++) - { - auto stdoutBefore = _fileno(stdout); - auto stderrBefore = _fileno(stderr); - auto stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); - auto stderrHandle = GetStdHandle(STD_ERROR_HANDLE); - PCWSTR expected = L"test"; - - PipeOutputManager* pManager = new PipeOutputManager(); - - pManager->Start(); - fwprintf(stderr, expected); - pManager->Stop(); - - auto output = pManager->GetStdOutContent(); - ASSERT_STREQ(output.c_str(), expected); - ASSERT_EQ(stdoutBefore, _fileno(stdout)); - - ASSERT_EQ(stderrBefore, _fileno(stderr)); - - delete pManager; - } - - wprintf(L"Hello!"); - } -} - diff --git a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/exception_handler_tests.cpp b/src/IISIntegration/src/IISIntegration/test/CommonLibTests/exception_handler_tests.cpp deleted file mode 100644 index d0a9e97fdb..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/exception_handler_tests.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -#include "stdafx.h" - -TEST(CaughtExceptionHResult, ReturnsOutOfMemoryForBadAlloc) -{ - HRESULT hr; - try - { - throw std::bad_alloc(); - } - catch(...) - { - hr = CaughtExceptionHResult(); - } - - EXPECT_EQ(E_OUTOFMEMORY, hr); -} - -TEST(CaughtExceptionHResult, ReturnsValueForSystemError) -{ - HRESULT hr; - try - { - throw std::system_error(E_INVALIDARG, std::system_category()); - } - catch(...) - { - hr = CaughtExceptionHResult(); - } - - EXPECT_EQ(E_INVALIDARG, hr); -} - -TEST(CaughtExceptionHResult, ReturnsUhandledExceptionForOtherExceptions) -{ - HRESULT hr; - try - { - throw E_INVALIDARG; - } - catch(...) - { - hr = CaughtExceptionHResult(); - } - - EXPECT_EQ(HRESULT_FROM_WIN32(ERROR_UNHANDLED_EXCEPTION), hr); -} diff --git a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/fakeclasses.h b/src/IISIntegration/src/IISIntegration/test/CommonLibTests/fakeclasses.h deleted file mode 100644 index a6f4a3e111..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/fakeclasses.h +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -#pragma once - -#include "gtest/gtest.h" -#include "gmock/gmock.h" -#include "InProcessOptions.h" - -class MockProperty : public IAppHostProperty -{ -public: - MOCK_METHOD2_WITH_CALLTYPE(__stdcall, QueryInterface, HRESULT(REFIID riid, void ** ppvObject)); - MOCK_METHOD0_WITH_CALLTYPE(__stdcall, AddRef, ULONG()); - MOCK_METHOD0_WITH_CALLTYPE(__stdcall, Release, ULONG()); - MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Name, HRESULT(BSTR* pbstrValue)); - MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Value, HRESULT(VARIANT * pVariant)); - MOCK_METHOD1_WITH_CALLTYPE(__stdcall, put_Value, HRESULT(VARIANT value)); - MOCK_METHOD0_WITH_CALLTYPE(__stdcall, Clear, HRESULT()); - MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_StringValue, HRESULT(BSTR* pbstrValue)); - MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Exception, HRESULT(IAppHostPropertyException ** ppException)); - MOCK_METHOD2_WITH_CALLTYPE(__stdcall, GetMetadata, HRESULT(BSTR bstrMetadataType, VARIANT * pValue)); - MOCK_METHOD2_WITH_CALLTYPE(__stdcall, SetMetadata, HRESULT(BSTR bstrMetadataType, VARIANT value)); - MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Schema, HRESULT(IAppHostPropertySchema ** ppSchema)); -}; - -class MockCollection : public IAppHostElementCollection -{ -public: - MOCK_METHOD2_WITH_CALLTYPE(__stdcall, QueryInterface, HRESULT(REFIID riid, void ** ppvObject)); - MOCK_METHOD0_WITH_CALLTYPE(__stdcall, AddRef, ULONG()); - MOCK_METHOD0_WITH_CALLTYPE(__stdcall, Release, ULONG()); - MOCK_METHOD0_WITH_CALLTYPE(__stdcall, Clear, HRESULT()); - MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Schema, HRESULT(IAppHostCollectionSchema** pSchema)); - MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Count, HRESULT(DWORD * dwordElem)); - MOCK_METHOD2_WITH_CALLTYPE(__stdcall, get_Item, HRESULT(VARIANT cIndex, IAppHostElement ** ppElement)); - MOCK_METHOD2_WITH_CALLTYPE(__stdcall, AddElement, HRESULT(IAppHostElement * pElement, INT cPosition)); - MOCK_METHOD1_WITH_CALLTYPE(__stdcall, DeleteElement, HRESULT(VARIANT cIndex)); - MOCK_METHOD2_WITH_CALLTYPE(__stdcall, CreateNewElement, HRESULT(BSTR bstrElementName, IAppHostElement** ppElement)); -}; - -class MockElement : public IAppHostElement -{ -public: - MOCK_METHOD2_WITH_CALLTYPE(__stdcall, QueryInterface, HRESULT(REFIID riid, void ** ppvObject)); - MOCK_METHOD0_WITH_CALLTYPE(__stdcall, AddRef, ULONG()); - MOCK_METHOD0_WITH_CALLTYPE(__stdcall, Release, ULONG()); - MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Name, HRESULT(BSTR * pbstrName)); - MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Collection, HRESULT(IAppHostElementCollection ** ppCollection)); - MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Properties, HRESULT(IAppHostPropertyCollection ** ppProperties)); - MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_ChildElements, HRESULT(IAppHostChildElementCollection ** ppElements)); - MOCK_METHOD2_WITH_CALLTYPE(__stdcall, GetMetadata, HRESULT(BSTR bstrMetadataType, VARIANT * pValue)); - MOCK_METHOD2_WITH_CALLTYPE(__stdcall, SetMetadata, HRESULT(BSTR bstrMetadataType, VARIANT value)); - MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Schema, HRESULT(IAppHostElementSchema** pSchema)); - MOCK_METHOD2_WITH_CALLTYPE(__stdcall, GetElementByName, HRESULT(BSTR bstrSubName, IAppHostElement ** ppElement)); - MOCK_METHOD2_WITH_CALLTYPE(__stdcall, GetPropertyByName, HRESULT(BSTR bstrSubName, IAppHostProperty ** ppProperty)); - MOCK_METHOD0_WITH_CALLTYPE(__stdcall, Clear, HRESULT()); - MOCK_METHOD1_WITH_CALLTYPE(__stdcall, get_Methods, HRESULT(IAppHostMethodCollection ** ppMethods)); -}; - -class MockHttpServer : public IHttpServer -{ - // Inherited via IHttpServer - virtual BOOL IsCommandLineLaunch(VOID) const override - { - return 0; - } - virtual PCWSTR GetAppPoolName(VOID) const override - { - return PCWSTR(); - } - virtual HRESULT AssociateWithThreadPool(HANDLE hHandle, LPOVERLAPPED_COMPLETION_ROUTINE completionRoutine) override - { - return E_NOTIMPL; - } - virtual VOID IncrementThreadCount(VOID) override - { - return VOID(); - } - virtual VOID DecrementThreadCount(VOID) override - { - return VOID(); - } - virtual VOID ReportUnhealthy(PCWSTR pszReasonString, HRESULT hrReason) override - { - return VOID(); - } - virtual VOID RecycleProcess(PCWSTR pszReason) override - { - return VOID(); - } - virtual IAppHostAdminManager * GetAdminManager(VOID) const override - { - return nullptr; - } - virtual HRESULT GetFileInfo(PCWSTR pszPhysicalPath, HANDLE hUserToken, PSID pSid, PCWSTR pszChangeNotificationPath, HANDLE hChangeNotificationToken, BOOL fCache, IHttpFileInfo ** ppFileInfo, IHttpTraceContext * pHttpTraceContext = NULL) override - { - return E_NOTIMPL; - } - virtual HRESULT FlushKernelCache(PCWSTR pszUrl) override - { - return E_NOTIMPL; - } - virtual HRESULT DoCacheOperation(CACHE_OPERATION cacheOperation, IHttpCacheKey * pCacheKey, IHttpCacheSpecificData ** ppCacheSpecificData, IHttpTraceContext * pHttpTraceContext = NULL) override - { - return E_NOTIMPL; - } - virtual GLOBAL_NOTIFICATION_STATUS NotifyCustomNotification(ICustomNotificationProvider * pCustomOutput) override - { - return GLOBAL_NOTIFICATION_STATUS(); - } - virtual IHttpPerfCounterInfo * GetPerfCounterInfo(VOID) override - { - return nullptr; - } - virtual VOID RecycleApplication(PCWSTR pszAppConfigPath) override - { - return VOID(); - } - virtual VOID NotifyConfigurationChange(PCWSTR pszPath) override - { - return VOID(); - } - virtual VOID NotifyFileChange(PCWSTR pszFileName) override - { - return VOID(); - } - virtual IDispensedHttpModuleContextContainer * DispenseContainer(VOID) override - { - return nullptr; - } - virtual HRESULT AddFragmentToCache(HTTP_DATA_CHUNK * pDataChunk, PCWSTR pszFragmentName) override - { - return E_NOTIMPL; - } - virtual HRESULT ReadFragmentFromCache(PCWSTR pszFragmentName, BYTE * pvBuffer, DWORD cbSize, DWORD * pcbCopied) override - { - return E_NOTIMPL; - } - virtual HRESULT RemoveFragmentFromCache(PCWSTR pszFragmentName) override - { - return E_NOTIMPL; - } - virtual HRESULT GetWorkerProcessSettings(IWpfSettings ** ppWorkerProcessSettings) override - { - return E_NOTIMPL; - } - virtual HRESULT GetProtocolManagerCustomInterface(PCWSTR pProtocolManagerDll, PCWSTR pProtocolManagerDllInitFunction, DWORD dwCustomInterfaceId, PVOID * ppCustomInterface) override - { - return E_NOTIMPL; - } - virtual BOOL SatisfiesPrecondition(PCWSTR pszPrecondition, BOOL * pfUnknownPrecondition = NULL) const override - { - return 0; - } - virtual IHttpTraceContext * GetTraceContext(VOID) const override - { - return nullptr; - } - virtual HRESULT RegisterFileChangeMonitor(PCWSTR pszPath, HANDLE hToken, IHttpFileMonitor ** ppFileMonitor) override - { - return E_NOTIMPL; - } - virtual HRESULT GetExtendedInterface(HTTP_SERVER_INTERFACE_VERSION version, PVOID * ppInterface) override - { - return E_NOTIMPL; - } -}; - - -class MockHttpApplication: public IHttpApplication -{ -public: - MOCK_CONST_METHOD0(GetApplicationPhysicalPath, PCWSTR ()); - MOCK_CONST_METHOD0(GetApplicationId, PCWSTR ()); - MOCK_CONST_METHOD0(GetAppConfigPath, PCWSTR ()); - MOCK_METHOD0(GetModuleContextContainer, IHttpModuleContextContainer* ()); -}; - -class MockInProcessOptions : public InProcessOptions -{ -public: - static - MockInProcessOptions* - CreateConfig() - { - return new MockInProcessOptions; - } -}; - diff --git a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/hostfxr_utility_tests.cpp b/src/IISIntegration/src/IISIntegration/test/CommonLibTests/hostfxr_utility_tests.cpp deleted file mode 100644 index 01c9541429..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/hostfxr_utility_tests.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -#include "stdafx.h" -#include -#include -#include -#include "hostfxr_utility.h" -#include "Environment.h" - -TEST(ParseHostFxrArguments, BasicHostFxrArguments) -{ - std::vector bstrArray; - - HOSTFXR_UTILITY::AppendArguments( - L"exec \"test.dll\"", // args - L"invalid", // physical path to application - bstrArray); // args array. - - EXPECT_EQ(2, bstrArray.size()); - ASSERT_STREQ(L"exec", bstrArray[0].c_str()); - ASSERT_STREQ(L"test.dll", bstrArray[1].c_str()); -} - -TEST(ParseHostFxrArguments, NoExecProvided) -{ - std::vector bstrArray; - - HOSTFXR_UTILITY::AppendArguments( - L"test.dll", // args - L"ignored", // physical path to application - bstrArray); // args array. - - EXPECT_EQ(1, bstrArray.size()); - ASSERT_STREQ(L"test.dll", bstrArray[0].c_str()); -} - -TEST(ParseHostFxrArguments, ConvertDllToAbsolutePath) -{ - std::vector bstrArray; - // we need to use existing dll so let's use ntdll that we know exists everywhere - auto system32 = Environment::ExpandEnvironmentVariables(L"%WINDIR%\\System32"); - HOSTFXR_UTILITY::AppendArguments( - L"exec \"ntdll.dll\"", // args - system32, // physical path to application - bstrArray, // args array. - true); // expandDllPaths - - EXPECT_EQ(2, bstrArray.size()); - ASSERT_STREQ(L"exec", bstrArray[0].c_str()); - ASSERT_STREQ((system32 + L"\\ntdll.dll").c_str(), bstrArray[1].c_str()); -} - -TEST(ParseHostFxrArguments, ProvideNoArgs_InvalidArgs) -{ - std::vector bstrArray; - std::filesystem::path struHostFxrDllLocation; - std::filesystem::path struExeLocation; - - EXPECT_THROW(HOSTFXR_UTILITY::GetHostFxrParameters( - L"dotnet", // processPath - L"some\\path", // application physical path, ignored. - L"", //arguments - struHostFxrDllLocation, - struExeLocation, - bstrArray), // args array. - InvalidOperationException); -} - -TEST(GetAbsolutePathToDotnetFromProgramFiles, BackupWorks) -{ - STRU struAbsolutePathToDotnet; - BOOL fDotnetInProgramFiles; - BOOL is64Bit; - BOOL fIsWow64 = FALSE; - SYSTEM_INFO systemInfo; - IsWow64Process(GetCurrentProcess(), &fIsWow64); - if (fIsWow64) - { - is64Bit = FALSE; - } - else - { - GetNativeSystemInfo(&systemInfo); - is64Bit = systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64; - } - - if (is64Bit) - { - fDotnetInProgramFiles = std::filesystem::is_regular_file(L"C:/Program Files/dotnet/dotnet.exe"); - } - else - { - fDotnetInProgramFiles = std::filesystem::is_regular_file(L"C:/Program Files (x86)/dotnet/dotnet.exe"); - } - - auto dotnetPath = HOSTFXR_UTILITY::GetAbsolutePathToDotnetFromProgramFiles(); - if (fDotnetInProgramFiles) - { - EXPECT_TRUE(dotnetPath.has_value()); - } - else - { - EXPECT_FALSE(dotnetPath.has_value()); - } -} - -TEST(GetHostFxrArguments, InvalidParams) -{ - std::vector bstrArray; - std::filesystem::path struHostFxrDllLocation; - std::filesystem::path struExeLocation; - - EXPECT_THROW(HOSTFXR_UTILITY::GetHostFxrParameters( - L"bogus", // processPath - L"", // application physical path, ignored. - L"ignored", //arguments - struHostFxrDllLocation, - struExeLocation, - bstrArray), // args array. - InvalidOperationException); -} diff --git a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/inprocess_application_tests.cpp b/src/IISIntegration/src/IISIntegration/test/CommonLibTests/inprocess_application_tests.cpp deleted file mode 100644 index d2ec985723..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/inprocess_application_tests.cpp +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -#include "stdafx.h" - -#include -#include "inprocessapplication.h" -#include "fakeclasses.h" - -using ::testing::_; -using ::testing::NiceMock; - -// Externals defined in inprocess -BOOL g_fProcessDetach; -HANDLE g_hEventLog; - -namespace InprocessTests -{ - TEST(InProcessTest, NoNullRefForExePath) - { - MockHttpServer server; - NiceMock application; - - ON_CALL(application, GetApplicationPhysicalPath()) - .WillByDefault(testing::Return(L"Some path")); - - ON_CALL(application, GetAppConfigPath()) - .WillByDefault(testing::Return(L"")); - - ON_CALL(application, GetApplicationId()) - .WillByDefault(testing::Return(L"")); - - auto requestHandlerConfig = std::unique_ptr(MockInProcessOptions::CreateConfig()); - - std::wstring exePath(L"hello"); - - std::array parameters{ - {"InProcessExeLocation", exePath.data()} - }; - - IN_PROCESS_APPLICATION *app = new IN_PROCESS_APPLICATION(server, application, std::move(requestHandlerConfig), parameters.data(), 1); - - ASSERT_STREQ(app->QueryExeLocation().c_str(), L"hello"); - } - - TEST(InProcessTest, GeneratesVirtualPath) - { - MockHttpServer server; - NiceMock application; - - ON_CALL(application, GetApplicationPhysicalPath()) - .WillByDefault(testing::Return(L"Some path")); - - ON_CALL(application, GetAppConfigPath()) - .WillByDefault(testing::Return(L"SECTION1/SECTION2/SECTION3/SECTION4/SECTION5")); - - ON_CALL(application, GetApplicationId()) - .WillByDefault(testing::Return(L"")); - - auto requestHandlerConfig = std::unique_ptr(MockInProcessOptions::CreateConfig()); - IN_PROCESS_APPLICATION *app = new IN_PROCESS_APPLICATION(server, application, std::move(requestHandlerConfig), nullptr, 0); - - ASSERT_STREQ(app->QueryApplicationVirtualPath().c_str(), L"/SECTION5"); - } - - TEST(InProcessTest, GeneratesVirtualPathForDefaultApp) - { - MockHttpServer server; - NiceMock application; - - ON_CALL(application, GetApplicationPhysicalPath()) - .WillByDefault(testing::Return(L"Some path")); - - ON_CALL(application, GetAppConfigPath()) - .WillByDefault(testing::Return(L"SECTION1/SECTION2/SECTION3/SECTION4")); - - ON_CALL(application, GetApplicationId()) - .WillByDefault(testing::Return(L"")); - - auto requestHandlerConfig = std::unique_ptr(MockInProcessOptions::CreateConfig()); - IN_PROCESS_APPLICATION *app = new IN_PROCESS_APPLICATION(server, application, std::move(requestHandlerConfig), nullptr, 0); - - ASSERT_STREQ(app->QueryApplicationVirtualPath().c_str(), L"/"); - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/main.cpp b/src/IISIntegration/src/IISIntegration/test/CommonLibTests/main.cpp deleted file mode 100644 index 1ad0a10ccd..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/main.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -#include "stdafx.h" - -DECLARE_DEBUG_PRINT_OBJECT2("tests", ASPNETCORE_DEBUG_FLAG_INFO | ASPNETCORE_DEBUG_FLAG_CONSOLE); - -int wmain(int argc, wchar_t* argv[]) -{ - ::testing::InitGoogleTest(&argc, argv); - RUN_ALL_TESTS(); -} diff --git a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/stdafx.h b/src/IISIntegration/src/IISIntegration/test/CommonLibTests/stdafx.h deleted file mode 100644 index 4b9ac7cd27..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/stdafx.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -#pragma once - -#define WIN32_LEAN_AND_MEAN - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "stringa.h" -#include "stringu.h" -#include "dbgutil.h" -#include "ahutil.h" -#include "multisz.h" -#include "multisza.h" -#include "base64.h" -#include -#include -#include -#include -#include - -#include "stringu.h" -#include "stringa.h" -#include "multisz.h" -#include "dbgutil.h" -#include "hashfn.h" - -#include "requesthandler_config.h" -#include "hostfxr_utility.h" -#include "config_utility.h" -#include "environmentvariablehash.h" -#include "iapplication.h" -#include "debugutil.h" -#include "requesthandler.h" -#include "resources.h" -#include "aspnetcore_msg.h" -#include "Helpers.h" -#include "GlobalVersionUtility.h" - -#undef assert // Macro redefinition in IISLib. -#include "gtest/gtest.h" -#include "fakeclasses.h" - diff --git a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/utility_tests.cpp b/src/IISIntegration/src/IISIntegration/test/CommonLibTests/utility_tests.cpp deleted file mode 100644 index ee69d79054..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/CommonLibTests/utility_tests.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -#include "stdafx.h" -#include "Environment.h" -#include "StringHelpers.h" - -TEST(PassUnexpandedEnvString, ExpandsResult) -{ - HRESULT hr = S_OK; - PCWSTR unexpandedString = L"ANCM_TEST_ENV_VAR"; - PCWSTR unexpandedStringValue = L"foobar"; - STRU struExpandedString; - SetEnvironmentVariable(L"ANCM_TEST_ENV_VAR", unexpandedStringValue); - - hr = struExpandedString.CopyAndExpandEnvironmentStrings(L"%ANCM_TEST_ENV_VAR%"); - EXPECT_EQ(hr, S_OK); - EXPECT_STREQ(L"foobar", struExpandedString.QueryStr()); -} - -TEST(PassUnexpandedEnvString, LongStringExpandsResults) -{ - HRESULT hr = S_OK; - PCWSTR unexpandedString = L"ANCM_TEST_ENV_VAR_LONG"; - STRU struStringValue; - STACK_STRU(struExpandedString, MAX_PATH); - - struStringValue.Append(L"TestValueThatIsLongerThan256CharactersLongToTriggerResize"); - struStringValue.Append(L"TestValueThatIsLongerThan256CharactersLongToTriggerResize"); - struStringValue.Append(L"TestValueThatIsLongerThan256CharactersLongToTriggerResize"); - struStringValue.Append(L"TestValueThatIsLongerThan256CharactersLongToTriggerResize"); - struStringValue.Append(L"TestValueThatIsLongerThan256CharactersLongToTriggerResize"); - struStringValue.Append(L"TestValueThatIsLongerThan256CharactersLongToTriggerResize"); - - SetEnvironmentVariable(unexpandedString, struStringValue.QueryStr()); - - hr = struExpandedString.CopyAndExpandEnvironmentStrings(L"%ANCM_TEST_ENV_VAR_LONG%"); - EXPECT_EQ(hr, S_OK); - EXPECT_EQ(struStringValue.QueryCCH(), struExpandedString.QueryCCH()); - // The values are exactly the same, however EXPECT_EQ is returning false. - //EXPECT_EQ(struStringValue.QueryStr(), struExpandedString.QueryStr()); - EXPECT_STREQ(struStringValue.QueryStr(), struExpandedString.QueryStr()); -} - - -TEST(GetEnvironmentVariableValue, ReturnsCorrectLenght) -{ - SetEnvironmentVariable(L"RANDOM_ENV_VAR_1", L"test"); - - auto result = Environment::GetEnvironmentVariableValue(L"RANDOM_ENV_VAR_1"); - EXPECT_TRUE(result.has_value()); - EXPECT_EQ(result.value().length(), 4); - EXPECT_STREQ(result.value().c_str(), L"test"); -} - - -TEST(GetEnvironmentVariableValue, ReturnsNulloptWhenNotFound) -{ - auto result = Environment::GetEnvironmentVariableValue(L"RANDOM_ENV_VAR_2"); - EXPECT_FALSE(result.has_value()); -} - -TEST(CheckStringHelpers, FormatWithoutContentDoesNotIncreaseSizeString) -{ - std::string testString = "test"; - auto result = format(testString); - EXPECT_EQ(testString.size(), result.size()); -} - -TEST(CheckStringHelpers, FormatWithoutContentDoesNotIncreaseSizeWstring) -{ - std::wstring testString = L"test"; - auto result = format(testString); - EXPECT_EQ(testString.size(), result.size()); -} diff --git a/src/IISIntegration/src/IISIntegration/test/Directory.Build.props b/src/IISIntegration/src/IISIntegration/test/Directory.Build.props deleted file mode 100644 index edfd666254..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Directory.Build.props +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - netcoreapp2.2 - $(DeveloperBuildTestTfms) - $(StandardTestTfms) - $(StandardTestTfms);net461 - - - - - - diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.BackwardsCompatibility.FunctionalTests/BackwardsCompatibilityTests.cs b/src/IISIntegration/src/IISIntegration/test/IIS.BackwardsCompatibility.FunctionalTests/BackwardsCompatibilityTests.cs deleted file mode 100644 index 2e4a7b1c40..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.BackwardsCompatibility.FunctionalTests/BackwardsCompatibilityTests.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Diagnostics; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; -using Xunit.Sdk; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class BackwardsCompatibilityTests : FixtureLoggedTest - { - private readonly IISTestSiteFixture _fixture; - - public BackwardsCompatibilityTests(IISTestSiteFixture fixture) : base(fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task CheckBackwardsCompatibilityIsUsed() - { - var response = await _fixture.Client.GetAsync("/HelloWorld"); - var handles = _fixture.DeploymentResult.HostProcess.Modules; - - foreach (ProcessModule handle in handles) - { - if (handle.ModuleName == "aspnetcorev2.dll") - { - Assert.Equal("12.2.18287.0", handle.FileVersionInfo.FileVersion); - return; - } - } - throw new XunitException($"Could not find aspnetcorev2.dll loaded in process {_fixture.DeploymentResult.HostProcess.ProcessName}"); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.BackwardsCompatibility.FunctionalTests/DeployerSelector.cs b/src/IISIntegration/src/IISIntegration/test/IIS.BackwardsCompatibility.FunctionalTests/DeployerSelector.cs deleted file mode 100644 index 5c6f3739a4..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.BackwardsCompatibility.FunctionalTests/DeployerSelector.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.Server.IntegrationTesting; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - public static class DeployerSelector - { - public static ServerType ServerType => ServerType.IIS; - public static bool IsBackwardsCompatiblityTest => true; - public static bool IsForwardsCompatibilityTest => false; - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.BackwardsCompatibility.FunctionalTests/IIS.BackwardsCompatibility.FunctionalTests.csproj b/src/IISIntegration/src/IISIntegration/test/IIS.BackwardsCompatibility.FunctionalTests/IIS.BackwardsCompatibility.FunctionalTests.csproj deleted file mode 100644 index c819a03ab1..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.BackwardsCompatibility.FunctionalTests/IIS.BackwardsCompatibility.FunctionalTests.csproj +++ /dev/null @@ -1,46 +0,0 @@ - - - - netcoreapp2.2 - IISBackwardsCompatibility.FunctionalTests - True - - - - - - - - - - - False - - - False - - - False - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.ForwardsCompatibility.FunctionalTests/DeployerSelector.cs b/src/IISIntegration/src/IISIntegration/test/IIS.ForwardsCompatibility.FunctionalTests/DeployerSelector.cs deleted file mode 100644 index bd7aabbe0f..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.ForwardsCompatibility.FunctionalTests/DeployerSelector.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.Server.IntegrationTesting; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - public static class DeployerSelector - { - public static ServerType ServerType => ServerType.IIS; - public static bool IsBackwardsCompatiblityTest => false; - public static bool IsForwardsCompatibilityTest => true; - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.ForwardsCompatibility.FunctionalTests/ForwardsCompatibilityTests.cs b/src/IISIntegration/src/IISIntegration/test/IIS.ForwardsCompatibility.FunctionalTests/ForwardsCompatibilityTests.cs deleted file mode 100644 index 5f4ebb5608..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.ForwardsCompatibility.FunctionalTests/ForwardsCompatibilityTests.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Diagnostics; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; -using Xunit.Sdk; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - public class ForwardsCompatibilityTests : FixtureLoggedTest - { - private readonly IISTestSiteFixture _fixture; - - public ForwardsCompatibilityTests(IISTestSiteFixture fixture) : base(fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task CheckForwardsCompatibilityIsUsed() - { - var response = await _fixture.Client.GetAsync("/HelloWorld"); - var handles = _fixture.DeploymentResult.HostProcess.Modules; - foreach (ProcessModule handle in handles) - { - if (handle.ModuleName == "aspnetcorev2_inprocess.dll") - { - Assert.Equal("12.2.18287.0", handle.FileVersionInfo.FileVersion); - return; - } - } - throw new XunitException($"Could not find aspnetcorev2_inprocess.dll loaded in process {_fixture.DeploymentResult.HostProcess.ProcessName}"); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.ForwardsCompatibility.FunctionalTests/IIS.ForwardsCompatibility.FunctionalTests.csproj b/src/IISIntegration/src/IISIntegration/test/IIS.ForwardsCompatibility.FunctionalTests/IIS.ForwardsCompatibility.FunctionalTests.csproj deleted file mode 100644 index 929f6ec6b0..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.ForwardsCompatibility.FunctionalTests/IIS.ForwardsCompatibility.FunctionalTests.csproj +++ /dev/null @@ -1,45 +0,0 @@ - - - - netcoreapp2.2 - IISForwardsCompatibility.FunctionalTests - True - - - - - - - - - - False - - - False - - - False - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.FunctionalTests/DeployerSelector.cs b/src/IISIntegration/src/IISIntegration/test/IIS.FunctionalTests/DeployerSelector.cs deleted file mode 100644 index f2e1be321e..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.FunctionalTests/DeployerSelector.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.Server.IntegrationTesting; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - public static class DeployerSelector - { - public static ServerType ServerType => ServerType.IIS; - public static bool IsBackwardsCompatiblityTest => false; - public static bool IsForwardsCompatibilityTest => false; - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.FunctionalTests/IIS.FunctionalTests.csproj b/src/IISIntegration/src/IISIntegration/test/IIS.FunctionalTests/IIS.FunctionalTests.csproj deleted file mode 100644 index 62dec62e60..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.FunctionalTests/IIS.FunctionalTests.csproj +++ /dev/null @@ -1,46 +0,0 @@ - - - - netcoreapp2.2 - IIS.FunctionalTests - True - - - - - - - - - - - False - - - False - - - False - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.Shared.FunctionalTests/Inprocess/StdOutRedirectionTests.cs b/src/IISIntegration/src/IISIntegration/test/IIS.Shared.FunctionalTests/Inprocess/StdOutRedirectionTests.cs deleted file mode 100644 index 35f10b13ab..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.Shared.FunctionalTests/Inprocess/StdOutRedirectionTests.cs +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.AspNetCore.Testing.xunit; -using Newtonsoft.Json; -using Xunit; - -namespace IIS.FunctionalTests.Inprocess -{ - [Collection(PublishedSitesCollection.Name)] - public class StdOutRedirectionTests : LogFileTestBase - { - private readonly PublishedSitesFixture _fixture; - - public StdOutRedirectionTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - [SkipIfDebug] - public async Task FrameworkNotFoundExceptionLogged_Pipe() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true); - - var deploymentResult = await DeployAsync(deploymentParameters); - - Helpers.ModifyFrameworkVersionInRuntimeConfig(deploymentResult); - - var response = await deploymentResult.HttpClient.GetAsync("/HelloWorld"); - Assert.False(response.IsSuccessStatusCode); - - StopServer(); - - EventLogHelpers.VerifyEventLogEvent(deploymentResult, - "The specified framework 'Microsoft.NETCore.App', version '2.9.9' was not found."); - } - - [ConditionalFact] - [SkipIfDebug] - public async Task FrameworkNotFoundExceptionLogged_File() - { - var deploymentParameters = - _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true); - - deploymentParameters.EnableLogging(_logFolderPath); - - var deploymentResult = await DeployAsync(deploymentParameters); - - Helpers.ModifyFrameworkVersionInRuntimeConfig(deploymentResult); - - var response = await deploymentResult.HttpClient.GetAsync("/HelloWorld"); - Assert.False(response.IsSuccessStatusCode); - - StopServer(); - - var contents = Helpers.ReadAllTextFromFile(Helpers.GetExpectedLogName(deploymentResult, _logFolderPath), Logger); - var expectedString = "The specified framework 'Microsoft.NETCore.App', version '2.9.9' was not found."; - EventLogHelpers.VerifyEventLogEvent(deploymentResult, expectedString); - Assert.Contains(expectedString, contents); - } - - [ConditionalFact] - [RequiresIIS(IISCapability.PoolEnvironmentVariables)] - [SkipIfDebug] - public async Task EnableCoreHostTraceLogging_TwoLogFilesCreated() - { - var deploymentParameters = - _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true); - deploymentParameters.TransformArguments((a, _) => $"{a} CheckLargeStdOutWrites"); - - deploymentParameters.EnvironmentVariables["COREHOST_TRACE"] = "1"; - - deploymentParameters.EnableLogging(_logFolderPath); - - var deploymentResult = await DeployAsync(deploymentParameters); - - var response = await deploymentResult.HttpClient.GetAsync("/HelloWorld"); - Assert.False(response.IsSuccessStatusCode); - - StopServer(); - - var fileInDirectory = Directory.GetFiles(_logFolderPath).Single(); - var contents = Helpers.ReadAllTextFromFile(fileInDirectory, Logger); - EventLogHelpers.VerifyEventLogEvent(deploymentResult, "Invoked hostfxr"); - Assert.Contains("Invoked hostfxr", contents); - } - - [ConditionalTheory] - [RequiresIIS(IISCapability.PoolEnvironmentVariables)] - [SkipIfDebug] - [InlineData("CheckLargeStdErrWrites")] - [InlineData("CheckLargeStdOutWrites")] - [InlineData("CheckOversizedStdErrWrites")] - [InlineData("CheckOversizedStdOutWrites")] - public async Task EnableCoreHostTraceLogging_PipeCaptureNativeLogs(string path) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true); - deploymentParameters.EnvironmentVariables["COREHOST_TRACE"] = "1"; - deploymentParameters.TransformArguments((a, _) => $"{a} {path}"); - - var deploymentResult = await DeployAsync(deploymentParameters); - - var response = await deploymentResult.HttpClient.GetAsync("/HelloWorld"); - - Assert.False(response.IsSuccessStatusCode); - - StopServer(); - - EventLogHelpers.VerifyEventLogEvent(deploymentResult, "Invoked hostfxr"); - } - - [ConditionalTheory] - [RequiresIIS(IISCapability.PoolEnvironmentVariables)] - [SkipIfDebug] - [InlineData("CheckLargeStdErrWrites")] - [InlineData("CheckLargeStdOutWrites")] - [InlineData("CheckOversizedStdErrWrites")] - [InlineData("CheckOversizedStdOutWrites")] - public async Task EnableCoreHostTraceLogging_FileCaptureNativeLogs(string path) - { - var deploymentParameters = - _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true); - deploymentParameters.EnvironmentVariables["COREHOST_TRACE"] = "1"; - deploymentParameters.TransformArguments((a, _) => $"{a} {path}"); - - deploymentParameters.EnableLogging(_logFolderPath); - - var deploymentResult = await DeployAsync(deploymentParameters); - - var response = await deploymentResult.HttpClient.GetAsync("/HelloWorld"); - Assert.False(response.IsSuccessStatusCode); - - StopServer(); - - var fileInDirectory = Directory.GetFiles(_logFolderPath).First(); - var contents = Helpers.ReadAllTextFromFile(fileInDirectory, Logger); - - EventLogHelpers.VerifyEventLogEvent(deploymentResult, "Invoked hostfxr"); - Assert.Contains("Invoked hostfxr", contents); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.Shared.FunctionalTests/MofFileTests.cs b/src/IISIntegration/src/IISIntegration/test/IIS.Shared.FunctionalTests/MofFileTests.cs deleted file mode 100644 index a054225ac5..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.Shared.FunctionalTests/MofFileTests.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Diagnostics; -using System.IO; -using Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests; -using Microsoft.AspNetCore.Testing; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace IIS.FunctionalTests -{ - public class MofFileTests - { - [ConditionalFact] - [OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)] - [RequiresIIS(IISCapability.TracingModule)] - public void CheckMofFile() - { - var path = Path.Combine(TestPathUtilities.GetSolutionRootDirectory("IISIntegration"), "src", "aspnetcoremodulev2", "aspnetcore", "ancm.mof"); - var process = Process.Start("mofcomp.exe", path); - process.WaitForExit(); - Assert.Equal(0, process.ExitCode); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.Shared.FunctionalTests/Properties/AssemblyInfo.cs b/src/IISIntegration/src/IISIntegration/test/IIS.Shared.FunctionalTests/Properties/AssemblyInfo.cs deleted file mode 100644 index b26f48a815..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.Shared.FunctionalTests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests; -using Microsoft.Extensions.Logging.Testing; -using Xunit; - -[assembly: CollectionBehavior(DisableTestParallelization = true)] -[assembly: RequiresIIS] -[assembly: ShortClassName] diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.Shared.FunctionalTests/RequiresIISAttribute.cs b/src/IISIntegration/src/IISIntegration/test/IIS.Shared.FunctionalTests/RequiresIISAttribute.cs deleted file mode 100644 index cfbbf70486..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.Shared.FunctionalTests/RequiresIISAttribute.cs +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using System.Security.Principal; -using System.Xml.Linq; -using Microsoft.AspNetCore.Testing.xunit; -using Microsoft.Win32; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)] - public sealed class RequiresIISAttribute : Attribute, ITestCondition - { - private static readonly (IISCapability Capability, string DllName)[] Modules = - { - (IISCapability.Websockets, "iiswsock.dll"), - (IISCapability.WindowsAuthentication, "authsspi.dll"), - (IISCapability.DynamicCompression, "compdyn.dll"), - (IISCapability.ApplicationInitialization, "warmup.dll"), - (IISCapability.TracingModule, "iisetw.dll"), - (IISCapability.FailedRequestTracingModule, "iisfreb.dll"), - (IISCapability.BasicAuthentication, "authbas.dll"), - }; - - private static readonly bool _isMetStatic; - private static readonly string _skipReasonStatic; - private static readonly bool _poolEnvironmentVariablesAvailable; - private static readonly IISCapability _modulesAvailable; - - static RequiresIISAttribute() - { - if (Environment.GetEnvironmentVariable("ASPNETCORE_TEST_SKIP_IIS") == "true") - { - _skipReasonStatic = "Test skipped using ASPNETCORE_TEST_SKIP_IIS environment variable"; - return; - } - - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - _skipReasonStatic = "IIS tests can only be run on Windows"; - return; - } - - var identity = WindowsIdentity.GetCurrent(); - var principal = new WindowsPrincipal(identity); - if (!principal.IsInRole(WindowsBuiltInRole.Administrator)) - { - _skipReasonStatic += "The current console is not running as admin."; - return; - } - - if (!File.Exists(Path.Combine(Environment.SystemDirectory, "inetsrv", "w3wp.exe"))) - { - _skipReasonStatic += "The machine does not have IIS installed."; - return; - } - - var ancmConfigPath = Path.Combine(Environment.SystemDirectory, "inetsrv", "config", "schema", "aspnetcore_schema_v2.xml"); - - if (!File.Exists(ancmConfigPath)) - { - _skipReasonStatic = "IIS Schema is not installed."; - return; - } - - XDocument ancmConfig; - - try - { - ancmConfig = XDocument.Load(ancmConfigPath); - } - catch - { - _skipReasonStatic = "Could not read ANCM schema configuration"; - return; - } - - _isMetStatic = ancmConfig - .Root - .Descendants("attribute") - .Any(n => "hostingModel".Equals(n.Attribute("name")?.Value, StringComparison.Ordinal)); - - _skipReasonStatic = _isMetStatic ? null : "IIS schema needs to be upgraded to support ANCM."; - - foreach (var module in Modules) - { - if (File.Exists(Path.Combine(Environment.SystemDirectory, "inetsrv", module.DllName))) - { - _modulesAvailable |= module.Capability; - } - } - - var iisRegistryKey = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\InetStp", writable: false); - if (iisRegistryKey == null) - { - _poolEnvironmentVariablesAvailable = false; - } - else - { - var majorVersion = (int)iisRegistryKey.GetValue("MajorVersion", -1); - var minorVersion = (int)iisRegistryKey.GetValue("MinorVersion", -1); - var version = new Version(majorVersion, minorVersion); - _poolEnvironmentVariablesAvailable = version >= new Version(10, 0); - } - } - - public RequiresIISAttribute() - : this(IISCapability.None) { } - - public RequiresIISAttribute(IISCapability capabilities) - { - IsMet = _isMetStatic; - SkipReason = _skipReasonStatic; - if (capabilities.HasFlag(IISCapability.PoolEnvironmentVariables)) - { - IsMet &= _poolEnvironmentVariablesAvailable; - if (!_poolEnvironmentVariablesAvailable) - { - SkipReason += "The machine does allow for setting environment variables on application pools."; - } - } - - if (capabilities.HasFlag(IISCapability.ShutdownToken)) - { - IsMet = false; - SkipReason += "https://github.com/aspnet/IISIntegration/issues/1074"; - } - - foreach (var module in Modules) - { - if (capabilities.HasFlag(module.Capability)) - { - var available = _modulesAvailable.HasFlag(module.Capability); - IsMet &= available; - if (!available) - { - SkipReason += $"The machine does have {module.Capability} available."; - } - } - } - } - - public bool IsMet { get; } - public string SkipReason { get; } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.Shared.FunctionalTests/ServicesTests.cs b/src/IISIntegration/src/IISIntegration/test/IIS.Shared.FunctionalTests/ServicesTests.cs deleted file mode 100644 index 875b5b13be..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.Shared.FunctionalTests/ServicesTests.cs +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.ServiceProcess; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.AspNetCore.Testing; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace IIS.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class ApplicationInitializationTests : IISFunctionalTestBase - { - private readonly PublishedSitesFixture _fixture; - - public ApplicationInitializationTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - [ConditionalTheory] - [RequiresIIS(IISCapability.ApplicationInitialization)] - [InlineData(HostingModel.InProcess)] - [InlineData(HostingModel.OutOfProcess)] - public async Task ApplicationPreloadStartsApp(HostingModel hostingModel) - { - // This test often hits a memory leak in warmup.dll module, it has been reported to IIS team - using (AppVerifier.Disable(DeployerSelector.ServerType, 0x900)) - { - var baseDeploymentParameters = _fixture.GetBaseDeploymentParameters(hostingModel, publish: true); - baseDeploymentParameters.TransformArguments( - (args, contentRoot) => $"{args} CreateFile \"{Path.Combine(contentRoot, "Started.txt")}\""); - EnablePreload(baseDeploymentParameters); - - var result = await DeployAsync(baseDeploymentParameters); - - await Helpers.Retry(async () => await File.ReadAllTextAsync(Path.Combine(result.ContentRoot, "Started.txt")), 10, 200); - StopServer(); - EventLogHelpers.VerifyEventLogEvent(result, EventLogHelpers.Started(result)); - } - } - - [ConditionalTheory] - [RequiresIIS(IISCapability.ApplicationInitialization)] - [InlineData(HostingModel.InProcess)] - [InlineData(HostingModel.OutOfProcess)] - public async Task ApplicationInitializationPageIsRequested(HostingModel hostingModel) - { - // This test often hits a memory leak in warmup.dll module, it has been reported to IIS team - using (AppVerifier.Disable(DeployerSelector.ServerType, 0x900)) - { - var baseDeploymentParameters = _fixture.GetBaseDeploymentParameters(hostingModel, publish: true); - EnablePreload(baseDeploymentParameters); - - baseDeploymentParameters.ServerConfigActionList.Add( - (config, _) => { - config - .RequiredElement("system.webServer") - .GetOrAdd("applicationInitialization") - .GetOrAdd("add", "initializationPage", "/CreateFile"); - }); - - var result = await DeployAsync(baseDeploymentParameters); - - await Helpers.Retry(async () => await File.ReadAllTextAsync(Path.Combine(result.ContentRoot, "Started.txt")), 10, 200); - StopServer(); - EventLogHelpers.VerifyEventLogEvent(result, EventLogHelpers.Started(result)); - } - } - - private static void EnablePreload(IISDeploymentParameters baseDeploymentParameters) - { - baseDeploymentParameters.EnsureSection("applicationInitialization", "system.webServer"); - baseDeploymentParameters.ServerConfigActionList.Add( - (config, _) => { - - config - .RequiredElement("system.applicationHost") - .RequiredElement("sites") - .RequiredElement("site") - .RequiredElement("application") - .SetAttributeValue("preloadEnabled", true); - }); - - baseDeploymentParameters.EnableModule("ApplicationInitializationModule", "%IIS_BIN%\\warmup.dll"); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.Tests/AppHostConfig/HostableWebCore.config b/src/IISIntegration/src/IISIntegration/test/IIS.Tests/AppHostConfig/HostableWebCore.config deleted file mode 100644 index 5e994d2855..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.Tests/AppHostConfig/HostableWebCore.config +++ /dev/null @@ -1,198 +0,0 @@ - - - - - - - - -
-
-
-
-
-
-
-
- - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
- -
-
-
-
-
-
- -
-
-
-
-
- -
-
-
- -
-
- -
-
- -
-
-
- -
- - -
-
-
-
- -
-
-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.Tests/ClientDisconnectTests.cs b/src/IISIntegration/src/IISIntegration/test/IIS.Tests/ClientDisconnectTests.cs deleted file mode 100644 index dbe562aa7c..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.Tests/ClientDisconnectTests.cs +++ /dev/null @@ -1,302 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Connections; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [SkipIfHostableWebCoreNotAvailable] - [OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, "https://github.com/aspnet/IISIntegration/issues/866")] - public class ClientDisconnectTests : StrictTestServerTests - { - [ConditionalFact] - public async Task WritesSucceedAfterClientDisconnect() - { - var requestStartedCompletionSource = CreateTaskCompletionSource(); - var clientDisconnectedCompletionSource = CreateTaskCompletionSource(); - var requestCompletedCompletionSource = CreateTaskCompletionSource(); - - var data = new byte[1024]; - using (var testServer = await TestServer.Create( - async ctx => - { - requestStartedCompletionSource.SetResult(true); - await clientDisconnectedCompletionSource.Task; - for (var i = 0; i < 1000; i++) - { - await ctx.Response.Body.WriteAsync(data); - } - - requestCompletedCompletionSource.SetResult(true); - }, LoggerFactory)) - { - using (var connection = testServer.CreateConnection()) - { - await SendContentLength1Post(connection); - await requestStartedCompletionSource.Task.DefaultTimeout(); - } - clientDisconnectedCompletionSource.SetResult(true); - - await requestCompletedCompletionSource.Task.DefaultTimeout(); - } - - AssertConnectionDisconnectLog(); - } - - [ConditionalFact] - public async Task WritesCancelledWhenUsingAbortedToken() - { - var requestStartedCompletionSource = CreateTaskCompletionSource(); - var requestCompletedCompletionSource = CreateTaskCompletionSource(); - - Exception exception = null; - - var data = new byte[1]; - using (var testServer = await TestServer.Create(async ctx => - { - requestStartedCompletionSource.SetResult(true); - try - { - while (true) - { - await ctx.Response.Body.WriteAsync(data, ctx.RequestAborted); - } - } - catch (Exception e) - { - exception = e; - } - - requestCompletedCompletionSource.SetResult(true); - }, LoggerFactory)) - { - using (var connection = testServer.CreateConnection()) - { - await SendContentLength1Post(connection); - - await requestStartedCompletionSource.Task.DefaultTimeout(); - } - - await requestCompletedCompletionSource.Task.DefaultTimeout(); - - Assert.IsType(exception); - } - - AssertConnectionDisconnectLog(); - } - - [ConditionalFact] - public async Task ReadThrowsAfterClientDisconnect() - { - var requestStartedCompletionSource = CreateTaskCompletionSource(); - var requestCompletedCompletionSource = CreateTaskCompletionSource(); - - Exception exception = null; - - var data = new byte[1024]; - using (var testServer = await TestServer.Create(async ctx => - { - requestStartedCompletionSource.SetResult(true); - try - { - await ctx.Request.Body.ReadAsync(data); - } - catch (Exception e) - { - exception = e; - } - - requestCompletedCompletionSource.SetResult(true); - }, LoggerFactory)) - { - using (var connection = testServer.CreateConnection()) - { - await SendContentLength1Post(connection); - await requestStartedCompletionSource.Task.DefaultTimeout(); - } - - await requestCompletedCompletionSource.Task.DefaultTimeout(); - } - - Assert.IsType(exception); - Assert.Equal("The client has disconnected", exception.Message); - - AssertConnectionDisconnectLog(); - } - - [ConditionalFact] - public async Task WriterThrowsCancelledException() - { - var requestStartedCompletionSource = CreateTaskCompletionSource(); - var requestCompletedCompletionSource = CreateTaskCompletionSource(); - - Exception exception = null; - var cancellationTokenSource = new CancellationTokenSource(); - - var data = new byte[1]; - using (var testServer = await TestServer.Create(async ctx => - { - requestStartedCompletionSource.SetResult(true); - try - { - while (true) - { - await ctx.Response.Body.WriteAsync(data, cancellationTokenSource.Token); - } - } - catch (Exception e) - { - exception = e; - } - - requestCompletedCompletionSource.SetResult(true); - }, LoggerFactory)) - { - using (var connection = testServer.CreateConnection()) - { - await SendContentLength1Post(connection); - - await requestStartedCompletionSource.Task.DefaultTimeout(); - cancellationTokenSource.Cancel(); - await requestCompletedCompletionSource.Task.DefaultTimeout(); - } - - Assert.IsType(exception); - } - } - - [ConditionalFact] - public async Task ReaderThrowsCancelledException() - { - var requestStartedCompletionSource = CreateTaskCompletionSource(); - var requestCompletedCompletionSource = CreateTaskCompletionSource(); - - Exception exception = null; - var cancellationTokenSource = new CancellationTokenSource(); - - var data = new byte[1024]; - using (var testServer = await TestServer.Create(async ctx => - { - requestStartedCompletionSource.SetResult(true); - try - { - await ctx.Request.Body.ReadAsync(data, cancellationTokenSource.Token); - } - catch (Exception e) - { - exception = e; - } - - requestCompletedCompletionSource.SetResult(true); - }, LoggerFactory)) - { - using (var connection = testServer.CreateConnection()) - { - await SendContentLength1Post(connection); - await requestStartedCompletionSource.Task.DefaultTimeout(); - cancellationTokenSource.Cancel(); - await requestCompletedCompletionSource.Task.DefaultTimeout(); - } - Assert.IsType(exception); - } - } - - [ConditionalFact] - public async Task ReaderThrowsResetExceptionOnInvalidBody() - { - var requestStartedCompletionSource = CreateTaskCompletionSource(); - var requestCompletedCompletionSource = CreateTaskCompletionSource(); - - Exception exception = null; - - var data = new byte[1024]; - using (var testServer = await TestServer.Create(async ctx => - { - requestStartedCompletionSource.SetResult(true); - try - { - await ctx.Request.Body.ReadAsync(data); - } - catch (Exception e) - { - exception = e; - } - - requestCompletedCompletionSource.SetResult(true); - }, LoggerFactory)) - { - using (var connection = testServer.CreateConnection()) - { - await connection.Send( - "POST / HTTP/1.1", - "Transfer-Encoding: chunked", - "Host: localhost", - "Connection: close", - "", - ""); - - await requestStartedCompletionSource.Task; - await connection.Send( - "ZZZZZZZZZZZZZ"); - - await connection.Receive( - "HTTP/1.1 400 Bad Request", - "" - ); - - } - await requestCompletedCompletionSource.Task.DefaultTimeout(); - } - - Assert.IsType(exception); - Assert.Equal("The client has disconnected", exception.Message); - AssertConnectionDisconnectLog(); - } - - [ConditionalFact] - public async Task RequestAbortedIsTrippedWithoutIO() - { - var requestStarted = CreateTaskCompletionSource(); - var requestAborted = CreateTaskCompletionSource(); - - using (var testServer = await TestServer.Create( - async ctx => { - ctx.RequestAborted.Register(() => requestAborted.SetResult(true)); - requestStarted.SetResult(true); - await requestAborted.Task; - }, LoggerFactory)) - { - using (var connection = testServer.CreateConnection()) - { - await SendContentLength1Post(connection); - await requestStarted.Task; - } - await requestAborted.Task; - } - - AssertConnectionDisconnectLog(); - } - - private void AssertConnectionDisconnectLog() - { - Assert.Single(TestSink.Writes, w => w.EventId.Name == "ConnectionDisconnect"); - } - - private static async Task SendContentLength1Post(TestConnection connection) - { - await connection.Send( - "POST / HTTP/1.1", - "Content-Length: 1", - "Host: localhost", - "Connection: close", - "", - ""); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.Tests/ConnectionIdFeatureTests.cs b/src/IISIntegration/src/IISIntegration/test/IIS.Tests/ConnectionIdFeatureTests.cs deleted file mode 100644 index 37e69b3a32..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.Tests/ConnectionIdFeatureTests.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http.Features; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [SkipIfHostableWebCoreNotAvailable] - [OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, "https://github.com/aspnet/IISIntegration/issues/866")] - public class HttpBodyControlFeatureTests : StrictTestServerTests - { - [ConditionalFact] - public async Task ThrowsOnSyncReadOrWrite() - { - Exception writeException = null; - Exception readException = null; - using (var testServer = await TestServer.Create( - ctx => { - var bodyControl = ctx.Features.Get(); - bodyControl.AllowSynchronousIO = false; - - try - { - ctx.Response.Body.Write(new byte[10]); - } - catch (Exception ex) - { - writeException = ex; - } - - try - { - ctx.Request.Body.Read(new byte[10]); - } - catch (Exception ex) - { - readException = ex; - } - - return Task.CompletedTask; - }, LoggerFactory)) - { - await testServer.HttpClient.GetStringAsync("/"); - } - - Assert.IsType(readException); - Assert.IsType(writeException); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.Tests/HttpBodyControlFeatureTests.cs b/src/IISIntegration/src/IISIntegration/test/IIS.Tests/HttpBodyControlFeatureTests.cs deleted file mode 100644 index 3d91c445ca..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.Tests/HttpBodyControlFeatureTests.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http.Features; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [SkipIfHostableWebCoreNotAvailable] - [OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, "https://github.com/aspnet/IISIntegration/issues/866")] - public class ConnectionIdFeatureTests : StrictTestServerTests - { - [ConditionalFact] - public async Task ProvidesConnectionId() - { - string connectionId = null; - using (var testServer = await TestServer.Create(ctx => { - var connectionIdFeature = ctx.Features.Get(); - connectionId = connectionIdFeature.ConnectionId; - return Task.CompletedTask; - }, LoggerFactory)) - { - await testServer.HttpClient.GetStringAsync("/"); - } - - Assert.NotNull(connectionId); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.Tests/IIS.Tests.csproj b/src/IISIntegration/src/IISIntegration/test/IIS.Tests/IIS.Tests.csproj deleted file mode 100644 index 3fdb2a5363..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.Tests/IIS.Tests.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - netcoreapp2.2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.Tests/ResponseAbortTests.cs b/src/IISIntegration/src/IISIntegration/test/IIS.Tests/ResponseAbortTests.cs deleted file mode 100644 index c7ec472586..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.Tests/ResponseAbortTests.cs +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Connections; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [SkipIfHostableWebCoreNotAvailable] - [OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, "https://github.com/aspnet/IISIntegration/issues/866")] - public class ResponseAbortTests : StrictTestServerTests - { - [ConditionalFact] - public async Task ClosesWithoutSendingAnything() - { - using (var testServer = await TestServer.Create( - ctx => { - ctx.Abort(); - return Task.CompletedTask; - }, LoggerFactory)) - { - using (var connection = testServer.CreateConnection()) - { - await SendContentLength1Post(connection); - await connection.WaitForConnectionClose(); - } - } - } - - [ConditionalFact] - public async Task ClosesAfterDataSent() - { - var bodyReceived = CreateTaskCompletionSource(); - using (var testServer = await TestServer.Create( - async ctx => { - await ctx.Response.WriteAsync("Abort"); - await ctx.Response.Body.FlushAsync(); - await bodyReceived.Task.DefaultTimeout(); - ctx.Abort(); - }, LoggerFactory)) - { - using (var connection = testServer.CreateConnection()) - { - await SendContentLength1Post(connection); - await connection.Receive( - "HTTP/1.1 200 OK", - ""); - await connection.ReceiveHeaders( - "Transfer-Encoding: chunked"); - - await connection.ReceiveChunk("Abort"); - bodyReceived.SetResult(true); - await connection.WaitForConnectionClose(); - } - } - } - - [ConditionalFact] - public async Task ReadsThrowAfterAbort() - { - Exception exception = null; - - using (var testServer = await TestServer.Create( - async ctx => { - ctx.Abort(); - try - { - var a = new byte[10]; - await ctx.Request.Body.ReadAsync(a); - } - catch (Exception e) - { - exception = e; - } - }, LoggerFactory)) - { - using (var connection = testServer.CreateConnection()) - { - await SendContentLength1Post(connection); - await connection.WaitForConnectionClose(); - } - } - - Assert.IsType(exception); - } - - [ConditionalFact] - public async Task WritesNoopAfterAbort() - { - Exception exception = null; - - using (var testServer = await TestServer.Create( - async ctx => { - ctx.Abort(); - try - { - await ctx.Response.Body.WriteAsync(new byte[10]); - } - catch (Exception e) - { - exception = e; - } - }, LoggerFactory)) - { - using (var connection = testServer.CreateConnection()) - { - await SendContentLength1Post(connection); - await connection.WaitForConnectionClose(); - } - } - - Assert.Null(exception); - } - - [ConditionalFact] - public async Task RequestAbortedIsTrippedAfterAbort() - { - bool tokenAborted = false; - using (var testServer = await TestServer.Create( - ctx => { - ctx.Abort(); - tokenAborted = ctx.RequestAborted.IsCancellationRequested; - return Task.CompletedTask; - }, LoggerFactory)) - { - using (var connection = testServer.CreateConnection()) - { - await SendContentLength1Post(connection); - await connection.WaitForConnectionClose(); - } - } - - Assert.True(tokenAborted); - } - - private static async Task SendContentLength1Post(TestConnection connection) - { - await connection.Send( - "POST / HTTP/1.1", - "Content-Length: 1", - "Host: localhost", - "", - ""); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.Tests/StrictTestServerTests.cs b/src/IISIntegration/src/IISIntegration/test/IIS.Tests/StrictTestServerTests.cs deleted file mode 100644 index c8f62beedb..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.Tests/StrictTestServerTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Testing; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - public class StrictTestServerTests: LoggedTest - { - public override void Dispose() - { - base.Dispose(); - Assert.DoesNotContain(TestSink.Writes, w => w.LogLevel > LogLevel.Information); - } - - protected static TaskCompletionSource CreateTaskCompletionSource() - { - return new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.Tests/TestServerTest.cs b/src/IISIntegration/src/IISIntegration/test/IIS.Tests/TestServerTest.cs deleted file mode 100644 index 40b538ea52..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.Tests/TestServerTest.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Testing.xunit; -using Microsoft.Extensions.Logging.Testing; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [SkipIfHostableWebCoreNotAvailable] - [OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, "https://github.com/aspnet/IISIntegration/issues/866")] - public class TestServerTest : StrictTestServerTests - { - [ConditionalFact] - public async Task SingleProcessTestServer_HelloWorld() - { - var helloWorld = "Hello World"; - var expectedPath = "/Path"; - - string path = null; - using (var testServer = await TestServer.Create(ctx => - { - path = ctx.Request.Path.ToString(); - return ctx.Response.WriteAsync(helloWorld); - }, LoggerFactory)) - { - var result = await testServer.HttpClient.GetAsync(expectedPath); - Assert.Equal(helloWorld, await result.Content.ReadAsStringAsync()); - Assert.Equal(expectedPath, path); - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.Tests/Utilities/SkipIfHostableWebCoreNotAvailibleAttribute.cs b/src/IISIntegration/src/IISIntegration/test/IIS.Tests/Utilities/SkipIfHostableWebCoreNotAvailibleAttribute.cs deleted file mode 100644 index b63743f106..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.Tests/Utilities/SkipIfHostableWebCoreNotAvailibleAttribute.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using Microsoft.AspNetCore.Testing.xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)] - public sealed class SkipIfHostableWebCoreNotAvailableAttribute : Attribute, ITestCondition - { - public bool IsMet { get; } = File.Exists(TestServer.HostableWebCoreLocation); - - public string SkipReason { get; } = $"Hostable Web Core not available, {TestServer.HostableWebCoreLocation} not found."; - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IIS.Tests/Utilities/TestServer.cs b/src/IISIntegration/src/IISIntegration/test/IIS.Tests/Utilities/TestServer.cs deleted file mode 100644 index 351b826316..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IIS.Tests/Utilities/TestServer.cs +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Net.Http; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Runtime.Loader; -using System.Threading; -using System.Threading.Tasks; -using System.Xml.Linq; -using System.Xml.XPath; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Extensions; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.Common; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - public class TestServer: IDisposable, IStartup - { - private const string InProcessHandlerDll = "aspnetcorev2_inprocess.dll"; - private const string AspNetCoreModuleDll = "aspnetcorev2.dll"; - private const string HWebCoreDll = "hwebcore.dll"; - - internal static string HostableWebCoreLocation => Environment.ExpandEnvironmentVariables($@"%windir%\system32\inetsrv\{HWebCoreDll}"); - internal static string BasePath => Path.GetDirectoryName(new Uri(typeof(TestServer).Assembly.CodeBase).AbsolutePath); - - internal static string AspNetCoreModuleLocation => Path.Combine(BasePath, AspNetCoreModuleDll); - - private static readonly SemaphoreSlim WebCoreLock = new SemaphoreSlim(1, 1); - - private static readonly int PortRetryCount = 10; - - private readonly TaskCompletionSource _startedTaskCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - - private readonly Action _appBuilder; - private readonly ILoggerFactory _loggerFactory; - private readonly hostfxr_main_fn _hostfxrMainFn; - - private Uri BaseUri => new Uri("http://localhost:" + _currentPort); - public HttpClient HttpClient { get; private set; } - public TestConnection CreateConnection() => new TestConnection(_currentPort); - - private IWebHost _host; - - private string _appHostConfigPath; - private int _currentPort; - - private TestServer(Action appBuilder, ILoggerFactory loggerFactory) - { - _hostfxrMainFn = Main; - _appBuilder = appBuilder; - _loggerFactory = loggerFactory; - } - - public static async Task Create(Action appBuilder, ILoggerFactory loggerFactory) - { - await WebCoreLock.WaitAsync(); - var server = new TestServer(appBuilder, loggerFactory); - server.Start(); - (await server.HttpClient.GetAsync("/start")).EnsureSuccessStatusCode(); - await server._startedTaskCompletionSource.Task; - return server; - } - - public static Task Create(RequestDelegate app, ILoggerFactory loggerFactory) - { - return Create(builder => builder.Run(app), loggerFactory); - } - - private void Start() - { - LoadLibrary(HostableWebCoreLocation); - _appHostConfigPath = Path.GetTempFileName(); - - set_main_handler(_hostfxrMainFn); - - Retry(() => - { - _currentPort = TestPortHelper.GetNextPort(); - - InitializeConfig(_currentPort); - - var startResult = WebCoreActivate(_appHostConfigPath, null, "Instance"); - if (startResult != 0) - { - throw new InvalidOperationException($"Error while running WebCoreActivate: {startResult} on port {_currentPort}"); - } - }, PortRetryCount); - - HttpClient = new HttpClient(new LoggingHandler(new SocketsHttpHandler(), _loggerFactory.CreateLogger())) - { - BaseAddress = BaseUri - }; - } - - private void InitializeConfig(int port) - { - var webHostConfig = XDocument.Load(Path.GetFullPath("HostableWebCore.config")); - webHostConfig.XPathSelectElement("/configuration/system.webServer/globalModules/add[@name='AspNetCoreModuleV2']") - .SetAttributeValue("image", AspNetCoreModuleLocation); - - var siteElement = webHostConfig.Root - .RequiredElement("system.applicationHost") - .RequiredElement("sites") - .RequiredElement("site"); - - siteElement - .RequiredElement("bindings") - .RequiredElement("binding") - .SetAttributeValue("bindingInformation", $":{port}:localhost"); - - webHostConfig.Save(_appHostConfigPath); - } - - private int Main(IntPtr argc, IntPtr argv) - { - _host = new WebHostBuilder() - .UseIIS() - .ConfigureServices(services => { - services.AddSingleton(this); - services.AddSingleton(_loggerFactory); - }) - .UseSetting(WebHostDefaults.ApplicationKey, typeof(TestServer).GetTypeInfo().Assembly.FullName) - .Build(); - - var doneEvent = new ManualResetEventSlim(); - var lifetime = _host.Services.GetService(); - - lifetime.ApplicationStopping.Register(() => doneEvent.Set()); - _host.Start(); - _startedTaskCompletionSource.SetResult(null); - doneEvent.Wait(); - _host.Dispose(); - return 0; - } - - public void Dispose() - { - HttpClient.Dispose(); - - // WebCoreShutdown occasionally AVs - // This causes the dotnet test process to crash - // To avoid this, we have to wait to shutdown - // and pass in true to immediately shutdown the hostable web core - // Both of these seem to be required. - Thread.Sleep(100); - WebCoreShutdown(immediate: true); - WebCoreLock.Release(); - } - - public IServiceProvider ConfigureServices(IServiceCollection services) - { - return services.BuildServiceProvider(); - } - - public void Configure(IApplicationBuilder app) - { - app.Map("/start", builder => builder.Run(context => context.Response.WriteAsync("Done"))); - _appBuilder(app); - } - - private delegate int hostfxr_main_fn(IntPtr argc, IntPtr argv); - - [DllImport(HWebCoreDll)] - private static extern int WebCoreActivate( - [In, MarshalAs(UnmanagedType.LPWStr)] - string appHostConfigPath, - [In, MarshalAs(UnmanagedType.LPWStr)] - string rootWebConfigPath, - [In, MarshalAs(UnmanagedType.LPWStr)] - string instanceName); - - [DllImport(HWebCoreDll)] - private static extern int WebCoreShutdown(bool immediate); - - [DllImport(InProcessHandlerDll)] - private static extern int set_main_handler(hostfxr_main_fn main); - - [DllImport("kernel32", SetLastError=true, CharSet = CharSet.Ansi)] - private static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName); - - private void Retry(Action func, int attempts) - { - var exceptions = new List(); - - for (var attempt = 0; attempt < attempts; attempt++) - { - try - { - func(); - return; - } - catch (Exception e) - { - exceptions.Add(e); - } - } - - throw new AggregateException(exceptions); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/DeployerSelector.cs b/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/DeployerSelector.cs deleted file mode 100644 index ba6a1ec6e2..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/DeployerSelector.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.Server.IntegrationTesting; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - public static class DeployerSelector - { - public static ServerType ServerType => ServerType.IISExpress; - public static bool IsBackwardsCompatiblityTest => false; - public static bool IsForwardsCompatibilityTest => false; - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/HttpsTests.cs b/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/HttpsTests.cs deleted file mode 100644 index ac58f73c0e..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/HttpsTests.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.Common; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class HttpsTests : IISFunctionalTestBase - { - private readonly PublishedSitesFixture _fixture; - - public HttpsTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - public static TestMatrix TestVariants - => TestMatrix.ForServers(DeployerSelector.ServerType) - .WithTfms(Tfm.NetCoreApp22, Tfm.Net461) - .WithAllApplicationTypes() - .WithAllAncmVersions() - .WithAllHostingModels(); - - [ConditionalTheory] - [MemberData(nameof(TestVariants))] - public async Task HttpsHelloWorld(TestVariant variant) - { - var port = TestPortHelper.GetNextSSLPort(); - var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant); - deploymentParameters.ApplicationBaseUriHint = $"https://localhost:{port}/"; - deploymentParameters.AddHttpsToServerConfig(); - - var deploymentResult = await DeployAsync(deploymentParameters); - - var handler = new HttpClientHandler - { - ServerCertificateCustomValidationCallback = (a, b, c, d) => true - }; - var client = deploymentResult.CreateClient(handler); - var response = await client.GetAsync("HttpsHelloWorld"); - var responseText = await response.Content.ReadAsStringAsync(); - if (variant.HostingModel == HostingModel.OutOfProcess) - { - Assert.Equal("Scheme:https; Original:http", responseText); - } - else - { - Assert.Equal("Scheme:https; Original:", responseText); - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/IISExpress.FunctionalTests.csproj b/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/IISExpress.FunctionalTests.csproj deleted file mode 100644 index 988c2d5943..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/IISExpress.FunctionalTests.csproj +++ /dev/null @@ -1,38 +0,0 @@ - - - - netcoreapp2.2 - True - - - - - - - - - - - False - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/InProcess/AuthenticationTests.cs b/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/InProcess/AuthenticationTests.cs deleted file mode 100644 index 47fb3a6553..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/InProcess/AuthenticationTests.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class AuthenticationTests : IISFunctionalTestBase - { - private readonly PublishedSitesFixture _fixture; - - public AuthenticationTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - [RequiresIIS(IISCapability.WindowsAuthentication)] - public async Task Authentication_InProcess() - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true); - deploymentParameters.SetWindowsAuth(); - - var deploymentResult = await DeployAsync(deploymentParameters); - - var response = await deploymentResult.HttpClient.GetAsync("/AuthenticationAnonymous"); - - var responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal("Anonymous?True", responseText); - - response = await deploymentResult.HttpClient.GetAsync("/AuthenticationRestricted"); - responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); - Assert.Contains("NTLM", response.Headers.WwwAuthenticate.ToString()); - Assert.Contains("Negotiate", response.Headers.WwwAuthenticate.ToString()); - - response = await deploymentResult.HttpClient.GetAsync("/AuthenticationRestrictedNTLM"); - responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); - Assert.Contains("NTLM", response.Headers.WwwAuthenticate.ToString()); - // Note we can't restrict a challenge to a specific auth type, the native auth modules always add themselves. - Assert.Contains("Negotiate", response.Headers.WwwAuthenticate.ToString()); - - response = await deploymentResult.HttpClient.GetAsync("/AuthenticationForbidden"); - responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); - - var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true }; - var httpClient = deploymentResult.CreateHttpClient(httpClientHandler); - - response = await httpClient.GetAsync("/AuthenticationAnonymous"); - responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal("Anonymous?True", responseText); - - response = await httpClient.GetAsync("/AuthenticationRestricted"); - responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotEmpty(responseText); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/InProcess/ShutdownTests.cs b/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/InProcess/ShutdownTests.cs deleted file mode 100644 index caaf728c64..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/InProcess/ShutdownTests.cs +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Net.Http; -using System.Net.Sockets; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class ShutdownTests : IISFunctionalTestBase - { - private readonly PublishedSitesFixture _fixture; - - public ShutdownTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public async Task ServerShutsDownWhenMainExits() - { - var parameters = _fixture.GetBaseDeploymentParameters(publish: true); - var deploymentResult = await DeployAsync(parameters); - try - { - await deploymentResult.HttpClient.GetAsync("/Shutdown"); - } - catch (HttpRequestException ex) when (ex.InnerException is IOException) - { - // Server might close a connection before request completes - } - - deploymentResult.AssertWorkerProcessStop(); - } - - - [ConditionalFact] - public async Task ServerShutsDownWhenMainExitsStress() - { - var parameters = _fixture.GetBaseDeploymentParameters(publish: true); - var deploymentResult = await StartAsync(parameters); - - var load = Helpers.StressLoad(deploymentResult.HttpClient, "/HelloWorld", response => { - var statusCode = (int)response.StatusCode; - Assert.True(statusCode == 200 || statusCode == 503, "Status code was " + statusCode); - }); - - try - { - await deploymentResult.HttpClient.GetAsync("/Shutdown"); - await load; - } - catch (HttpRequestException ex) when (ex.InnerException is IOException | ex.InnerException is SocketException) - { - // Server might close a connection before request completes - } - - deploymentResult.AssertWorkerProcessStop(); - } - - [ConditionalFact] - public async Task GracefulShutdown_DoesNotCrashProcess() - { - var parameters = _fixture.GetBaseDeploymentParameters(publish: true); - var result = await DeployAsync(parameters); - - var response = await result.HttpClient.GetAsync("/HelloWorld"); - StopServer(gracefulShutdown: true); - Assert.True(result.HostProcess.ExitCode == 0); - } - - [ConditionalFact] - public async Task ForcefulShutdown_DoesCrashProcess() - { - var parameters = _fixture.GetBaseDeploymentParameters(publish: true); - var result = await DeployAsync(parameters); - - var response = await result.HttpClient.GetAsync("/HelloWorld"); - StopServer(gracefulShutdown: false); - Assert.True(result.HostProcess.ExitCode == 1); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/InProcess/WebSocketTests.cs b/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/InProcess/WebSocketTests.cs deleted file mode 100644 index 826001c96d..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/InProcess/WebSocketTests.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Linq; -using System.Net.WebSockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(IISTestSiteCollection.Name)] - [OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, SkipReason = "No supported on this platform")] - public class WebSocketsTests - { - private readonly string _webSocketUri; - - public WebSocketsTests(IISTestSiteFixture fixture) - { - _webSocketUri = fixture.DeploymentResult.ApplicationBaseUri.Replace("http:", "ws:"); - } - - [ConditionalFact] - public async Task OnStartedCalledForWebSocket() - { - var cws = new ClientWebSocket(); - await cws.ConnectAsync(new Uri(_webSocketUri + "WebSocketLifetimeEvents"), default); - - await ReceiveMessage(cws, "OnStarting"); - await ReceiveMessage(cws, "Upgraded"); - } - - [ConditionalFact] - public async Task WebReadBeforeUpgrade() - { - var cws = new ClientWebSocket(); - await cws.ConnectAsync(new Uri(_webSocketUri + "WebReadBeforeUpgrade"), default); - - await ReceiveMessage(cws, "Yay"); - } - - [ConditionalFact] - public async Task CanSendAndReceieveData() - { - var cws = new ClientWebSocket(); - await cws.ConnectAsync(new Uri(_webSocketUri + "WebSocketEcho"), default); - - for (int i = 0; i < 1000; i++) - { - var mesage = i.ToString(); - await SendMessage(cws, mesage); - await ReceiveMessage(cws, mesage); - } - } - - private async Task SendMessage(ClientWebSocket webSocket, string message) - { - await webSocket.SendAsync(new ArraySegment(Encoding.ASCII.GetBytes(message)), WebSocketMessageType.Text, true, default); - } - - private async Task ReceiveMessage(ClientWebSocket webSocket, string expectedMessage) - { - var received = new byte[expectedMessage.Length]; - - var offset = 0; - WebSocketReceiveResult result; - do - { - result = await webSocket.ReceiveAsync(new ArraySegment(received, offset, received.Length - offset), default); - offset += result.Count; - } while (!result.EndOfMessage); - - Assert.Equal(expectedMessage, Encoding.ASCII.GetString(received)); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/OutOfProcess/MultipleAppTests.cs b/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/OutOfProcess/MultipleAppTests.cs deleted file mode 100644 index 349f72d7bf..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/OutOfProcess/MultipleAppTests.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class MultipleAppTests : IISFunctionalTestBase - { - private readonly PublishedSitesFixture _fixture; - - public MultipleAppTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - [ConditionalTheory] - [InlineData(AncmVersion.AspNetCoreModule)] - [InlineData(AncmVersion.AspNetCoreModuleV2)] - public Task Startup(AncmVersion ancmVersion) - { - // ANCM v1 currently does *not* retry if an app fails to start the first time due to a port collision. - // So, this test is expected to fail on v1 approximately 1 in 1,000 times (probably of at least one collision - // when 10 sites choose a random port from the range 1025-48000). Adding one retry should reduce the failure - // rate from 1 in 1,000 to 1 in 1,000,000. The previous product code (with "srand(GetTickCount())") should still - // fail the test reliably. - // https://github.com/aspnet/IISIntegration/issues/1350 - // - // ANCM v2 does retry on port collisions, so no retries should be required. - var attempts = (ancmVersion == AncmVersion.AspNetCoreModule) ? 2 : 1; - - return Helpers.Retry(async () => - { - const int numApps = 10; - - using (var deployers = new DisposableList()) - { - var deploymentResults = new List(); - - // Deploy all apps - for (var i = 0; i < numApps; i++) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(hostingModel: IntegrationTesting.HostingModel.OutOfProcess); - deploymentParameters.AncmVersion = ancmVersion; - - var deployer = CreateDeployer(deploymentParameters); - deployers.Add(deployer); - deploymentResults.Add(await deployer.DeployAsync()); - } - - // Start all requests as quickly as possible, so apps are started as quickly as possible, - // to test possible race conditions when multiple apps start at the same time. - var requestTasks = new List>(); - foreach (var deploymentResult in deploymentResults) - { - requestTasks.Add(deploymentResult.HttpClient.GetAsync("/HelloWorld")); - } - - // Verify all apps started and return expected response - foreach (var requestTask in requestTasks) - { - var response = await requestTask; - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal("Hello World", responseText); - } - } - }, - attempts: attempts, msDelay: 0); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/OutOfProcess/NtlmAuthentationTest.cs b/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/OutOfProcess/NtlmAuthentationTest.cs deleted file mode 100644 index 3ff46bf304..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/OutOfProcess/NtlmAuthentationTest.cs +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class NtlmAuthenticationTests : IISFunctionalTestBase - { - // Test only runs on IISExpress today as our CI machines do not have - // Windows auth installed globally. - // TODO either enable windows auth on our CI or use containers to test this - // behavior - - private readonly PublishedSitesFixture _fixture; - - public NtlmAuthenticationTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - public static TestMatrix TestVariants - => TestMatrix.ForServers(DeployerSelector.ServerType) - .WithTfms(Tfm.NetCoreApp22, Tfm.Net461) - .WithAllAncmVersions(); - - [ConditionalTheory] - [RequiresIIS(IISCapability.WindowsAuthentication)] - [MemberData(nameof(TestVariants))] - public async Task NtlmAuthentication(TestVariant variant) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant); - deploymentParameters.ApplicationBaseUriHint = $"https://localhost:0/"; - - deploymentParameters.SetWindowsAuth(enabled: true); - - var result = await DeployAsync(deploymentParameters); - var response = await result.HttpClient.GetAsync("/HelloWorld"); - - var responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal("Hello World", responseText); - - var httpClient = result.HttpClient; - response = await httpClient.GetAsync("/Anonymous"); - responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal("Anonymous?True", responseText); - - response = await httpClient.GetAsync("/Restricted"); - Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); - Assert.Contains("NTLM", response.Headers.WwwAuthenticate.ToString()); - Assert.Contains("Negotiate", response.Headers.WwwAuthenticate.ToString()); - - response = await httpClient.GetAsync("/RestrictedNTLM"); - Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); - Assert.Contains("NTLM", response.Headers.WwwAuthenticate.ToString()); - // Note we can't restrict a challenge to a specific auth type, the native auth modules always add themselves. - Assert.Contains("Negotiate", response.Headers.WwwAuthenticate.ToString()); - - response = await httpClient.GetAsync("/Forbidden"); - Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); - - var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true }; - httpClient = result.CreateClient(httpClientHandler); - - response = await httpClient.GetAsync("/Anonymous"); - responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal("Anonymous?True", responseText); - - response = await httpClient.GetAsync("/Restricted"); - responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.NotEmpty(responseText); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/Properties/AssemblyInfo.cs b/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/Properties/AssemblyInfo.cs deleted file mode 100644 index b26f48a815..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests; -using Microsoft.Extensions.Logging.Testing; -using Xunit; - -[assembly: CollectionBehavior(DisableTestParallelization = true)] -[assembly: RequiresIIS] -[assembly: ShortClassName] diff --git a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/RequiresIISAttribute.cs b/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/RequiresIISAttribute.cs deleted file mode 100644 index 2e0a68b9f7..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/RequiresIISAttribute.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Testing.xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)] - public sealed class RequiresIISAttribute : Attribute, ITestCondition - { - public bool IsMet => IISExpressAncmSchema.SupportsInProcessHosting; - - public string SkipReason => IISExpressAncmSchema.SkipReason; - - public RequiresIISAttribute() { } - - public RequiresIISAttribute(IISCapability capabilities) - { - // IISCapabilities aren't pertinent to IISExpress - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/UpgradeFeatureDetectionTests.cs b/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/UpgradeFeatureDetectionTests.cs deleted file mode 100644 index 62d07c5fd9..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/IISExpress.FunctionalTests/UpgradeFeatureDetectionTests.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; -using Microsoft.AspNetCore.Testing.xunit; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests -{ - [Collection(PublishedSitesCollection.Name)] - public class UpgradeFeatureDetectionTests : IISFunctionalTestBase - { - private readonly string _isWebsocketsSupported = Environment.OSVersion.Version >= new Version(6, 2) ? "Enabled" : "Disabled"; - private readonly PublishedSitesFixture _fixture; - - public UpgradeFeatureDetectionTests(PublishedSitesFixture fixture) - { - _fixture = fixture; - } - - [ConditionalFact] - public Task UpgradeFeatureDetectionDisabled_InProcess() - { - // fails due to not modifying the apphost.config file. - return UpgradeFeatureDetectionDeployer( - disableWebSocket: true, - Helpers.GetInProcessTestSitesPath(), - "Disabled", HostingModel.InProcess); - } - - [ConditionalFact] - public Task UpgradeFeatureDetectionEnabled_InProcess() - { - return UpgradeFeatureDetectionDeployer( - disableWebSocket: false, - Helpers.GetInProcessTestSitesPath(), - _isWebsocketsSupported, HostingModel.InProcess); - } - - [ConditionalFact] - public Task UpgradeFeatureDetectionDisabled_OutOfProcess() - { - return UpgradeFeatureDetectionDeployer( - disableWebSocket: true, - Helpers.GetOutOfProcessTestSitesPath(), - "Disabled", HostingModel.OutOfProcess); - } - - [ConditionalFact] - public Task UpgradeFeatureDetectionEnabled_OutOfProcess() - { - return UpgradeFeatureDetectionDeployer( - disableWebSocket: false, - Helpers.GetOutOfProcessTestSitesPath(), - _isWebsocketsSupported, HostingModel.OutOfProcess); - } - - private async Task UpgradeFeatureDetectionDeployer(bool disableWebSocket, string sitePath, string expected, HostingModel hostingModel) - { - var deploymentParameters = _fixture.GetBaseDeploymentParameters(hostingModel, publish: true); - - if (disableWebSocket) - { - // For IIS, we need to modify the apphost.config file - deploymentParameters.AddServerConfigAction( - element => element.Descendants("webSocket") - .Single() - .SetAttributeValue("enabled", "false")); - } - - var deploymentResult = await DeployAsync(deploymentParameters); - - var response = await deploymentResult.HttpClient.GetAsync("UpgradeFeatureDetection"); - var responseText = await response.Content.ReadAsStringAsync(); - Assert.Equal(expected, responseText); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Microsoft.AspNetCore.Server.IISIntegration.Tests/IISExtensionTests.cs b/src/IISIntegration/src/IISIntegration/test/Microsoft.AspNetCore.Server.IISIntegration.Tests/IISExtensionTests.cs deleted file mode 100644 index 772fbde2c3..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Microsoft.AspNetCore.Server.IISIntegration.Tests/IISExtensionTests.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Linq; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.TestHost; -using Microsoft.Extensions.DependencyInjection; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration -{ - public class IISExtensionTests - { - [Fact] - public void CallingUseIISIntegrationMultipleTimesWorks() - { - - var builder = new WebHostBuilder() - .UseSetting("TOKEN", "TestToken") - .UseSetting("PORT", "12345") - .UseSetting("APPL_PATH", "/") - .UseIISIntegration() - .UseIISIntegration() - .Configure(app => { }); - var server = new TestServer(builder); - - var filters = server.Host.Services.GetServices() - .OfType(); - - Assert.Single(filters); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Microsoft.AspNetCore.Server.IISIntegration.Tests/IISMiddlewareTests.cs b/src/IISIntegration/src/IISIntegration/test/Microsoft.AspNetCore.Server.IISIntegration.Tests/IISMiddlewareTests.cs deleted file mode 100644 index 0898b7ae21..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Microsoft.AspNetCore.Server.IISIntegration.Tests/IISMiddlewareTests.cs +++ /dev/null @@ -1,420 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Net; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http.Features.Authentication; -using Microsoft.AspNetCore.TestHost; -using Microsoft.Extensions.DependencyInjection; -using Xunit; - -namespace Microsoft.AspNetCore.Server.IISIntegration -{ - public class IISMiddlewareTests - { - [Fact] - public async Task MiddlewareSkippedIfTokenIsMissing() - { - var assertsExecuted = false; - - var builder = new WebHostBuilder() - .UseSetting("PORT", "12345") - .UseSetting("APPL_PATH", "/") - .UseIISIntegration() - .Configure(app => - { - app.Run(context => - { - var auth = context.Features.Get(); - Assert.Null(auth); - assertsExecuted = true; - return Task.FromResult(0); - }); - }); - var server = new TestServer(builder); - - var req = new HttpRequestMessage(HttpMethod.Get, ""); - req.Headers.TryAddWithoutValidation("MS-ASPNETCORE-TOKEN", "TestToken"); - var response = await server.CreateClient().SendAsync(req); - Assert.True(assertsExecuted); - response.EnsureSuccessStatusCode(); - } - - [Fact] - public async Task MiddlewareRejectsRequestIfTokenHeaderIsMissing() - { - var assertsExecuted = false; - - var builder = new WebHostBuilder() - .UseSetting("TOKEN", "TestToken") - .UseSetting("PORT", "12345") - .UseSetting("APPL_PATH", "/") - .UseIISIntegration() - .Configure(app => - { - app.Run(context => - { - var auth = context.Features.Get(); - Assert.Null(auth); - assertsExecuted = true; - return Task.FromResult(0); - }); - }); - var server = new TestServer(builder); - - var req = new HttpRequestMessage(HttpMethod.Get, ""); - var response = await server.CreateClient().SendAsync(req); - Assert.False(assertsExecuted); - Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); - } - - [Theory] - [InlineData("/", "/iisintegration", "shutdown")] - [InlineData("/", "/iisintegration", "Shutdown")] - [InlineData("/pathBase", "/pathBase/iisintegration", "shutdown")] - [InlineData("/pathBase", "/pathBase/iisintegration", "Shutdown")] - public async Task MiddlewareShutsdownGivenANCMShutdown(string pathBase, string requestPath, string shutdownEvent) - { - var requestExecuted = new ManualResetEvent(false); - var applicationStoppingFired = new ManualResetEvent(false); - var builder = new WebHostBuilder() - .UseSetting("TOKEN", "TestToken") - .UseSetting("PORT", "12345") - .UseSetting("APPL_PATH", pathBase) - .UseIISIntegration() - .Configure(app => - { - var appLifetime = app.ApplicationServices.GetRequiredService(); - appLifetime.ApplicationStopping.Register(() => applicationStoppingFired.Set()); - - app.Run(context => - { - requestExecuted.Set(); - return Task.FromResult(0); - }); - }); - var server = new TestServer(builder); - - var request = new HttpRequestMessage(HttpMethod.Post, requestPath); - request.Headers.TryAddWithoutValidation("MS-ASPNETCORE-TOKEN", "TestToken"); - request.Headers.TryAddWithoutValidation("MS-ASPNETCORE-EVENT", shutdownEvent); - var response = await server.CreateClient().SendAsync(request); - - Assert.True(applicationStoppingFired.WaitOne(TimeSpan.FromSeconds(5))); - Assert.False(requestExecuted.WaitOne(0)); - Assert.Equal(HttpStatusCode.Accepted, response.StatusCode); - } - - public static TheoryData InvalidShutdownMethods - { - get - { - return new TheoryData - { - HttpMethod.Put, - HttpMethod.Trace, - HttpMethod.Head, - HttpMethod.Get, - HttpMethod.Delete, - HttpMethod.Options - }; - } - } - - [Theory] - [MemberData(nameof(InvalidShutdownMethods))] - public async Task MiddlewareIgnoresShutdownGivenWrongMethod(HttpMethod method) - { - var requestExecuted = new ManualResetEvent(false); - var applicationStoppingFired = new ManualResetEvent(false); - var builder = new WebHostBuilder() - .UseSetting("TOKEN", "TestToken") - .UseSetting("PORT", "12345") - .UseSetting("APPL_PATH", "/") - .UseIISIntegration() - .Configure(app => - { - var appLifetime = app.ApplicationServices.GetRequiredService(); - appLifetime.ApplicationStopping.Register(() => applicationStoppingFired.Set()); - - app.Run(context => - { - requestExecuted.Set(); - return Task.FromResult(0); - }); - }); - var server = new TestServer(builder); - - var request = new HttpRequestMessage(method, "/iisintegration"); - request.Headers.TryAddWithoutValidation("MS-ASPNETCORE-TOKEN", "TestToken"); - request.Headers.TryAddWithoutValidation("MS-ASPNETCORE-EVENT", "shutdown"); - var response = await server.CreateClient().SendAsync(request); - - Assert.False(applicationStoppingFired.WaitOne(TimeSpan.FromSeconds(1))); - Assert.True(requestExecuted.WaitOne(0)); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - } - - [Theory] - [InlineData("/")] - [InlineData("/path")] - [InlineData("/path/iisintegration")] - public async Task MiddlewareIgnoresShutdownGivenWrongPath(string path) - { - var requestExecuted = new ManualResetEvent(false); - var applicationStoppingFired = new ManualResetEvent(false); - var builder = new WebHostBuilder() - .UseSetting("TOKEN", "TestToken") - .UseSetting("PORT", "12345") - .UseSetting("APPL_PATH", "/") - .UseIISIntegration() - .Configure(app => - { - var appLifetime = app.ApplicationServices.GetRequiredService(); - appLifetime.ApplicationStopping.Register(() => applicationStoppingFired.Set()); - - app.Run(context => - { - requestExecuted.Set(); - return Task.FromResult(0); - }); - }); - var server = new TestServer(builder); - - var request = new HttpRequestMessage(HttpMethod.Post, path); - request.Headers.TryAddWithoutValidation("MS-ASPNETCORE-TOKEN", "TestToken"); - request.Headers.TryAddWithoutValidation("MS-ASPNETCORE-EVENT", "shutdown"); - var response = await server.CreateClient().SendAsync(request); - - Assert.False(applicationStoppingFired.WaitOne(TimeSpan.FromSeconds(1))); - Assert.True(requestExecuted.WaitOne(0)); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - } - - [Theory] - [InlineData("event")] - [InlineData("")] - [InlineData(null)] - public async Task MiddlewareIgnoresShutdownGivenWrongEvent(string shutdownEvent) - { - var requestExecuted = new ManualResetEvent(false); - var applicationStoppingFired = new ManualResetEvent(false); - var builder = new WebHostBuilder() - .UseSetting("TOKEN", "TestToken") - .UseSetting("PORT", "12345") - .UseSetting("APPL_PATH", "/") - .UseIISIntegration() - .Configure(app => - { - var appLifetime = app.ApplicationServices.GetRequiredService(); - appLifetime.ApplicationStopping.Register(() => applicationStoppingFired.Set()); - - app.Run(context => - { - requestExecuted.Set(); - return Task.FromResult(0); - }); - }); - var server = new TestServer(builder); - - var request = new HttpRequestMessage(HttpMethod.Post, "/iisintegration"); - request.Headers.TryAddWithoutValidation("MS-ASPNETCORE-TOKEN", "TestToken"); - request.Headers.TryAddWithoutValidation("MS-ASPNETCORE-EVENT", shutdownEvent); - var response = await server.CreateClient().SendAsync(request); - - Assert.False(applicationStoppingFired.WaitOne(TimeSpan.FromSeconds(1))); - Assert.True(requestExecuted.WaitOne(0)); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - } - - [Fact] - public void UrlDelayRegisteredAndPreferHostingUrlsSet() - { - var builder = new WebHostBuilder() - .UseSetting("TOKEN", "TestToken") - .UseSetting("PORT", "12345") - .UseSetting("APPL_PATH", "/") - .UseIISIntegration() - .Configure(app => - { - app.Run(context => Task.FromResult(0)); - }); - - Assert.Null(builder.GetSetting(WebHostDefaults.ServerUrlsKey)); - Assert.Null(builder.GetSetting(WebHostDefaults.PreferHostingUrlsKey)); - - // Adds a server and calls Build() - var server = new TestServer(builder); - - Assert.Equal("http://127.0.0.1:12345", builder.GetSetting(WebHostDefaults.ServerUrlsKey)); - Assert.Equal("true", builder.GetSetting(WebHostDefaults.PreferHostingUrlsKey)); - } - - [Fact] - public void PathBaseHiddenFromServer() - { - var builder = new WebHostBuilder() - .UseSetting("TOKEN", "TestToken") - .UseSetting("PORT", "12345") - .UseSetting("APPL_PATH", "/pathBase") - .UseIISIntegration() - .Configure(app => - { - app.Run(context => Task.FromResult(0)); - }); - new TestServer(builder); - - Assert.Equal("http://127.0.0.1:12345", builder.GetSetting(WebHostDefaults.ServerUrlsKey)); - } - - [Fact] - public async Task AddsUsePathBaseMiddlewareWhenPathBaseSpecified() - { - var requestPathBase = string.Empty; - var requestPath = string.Empty; - var builder = new WebHostBuilder() - .UseSetting("TOKEN", "TestToken") - .UseSetting("PORT", "12345") - .UseSetting("APPL_PATH", "/pathbase") - .UseIISIntegration() - .Configure(app => - { - app.Run(context => - { - requestPathBase = context.Request.PathBase.Value; - requestPath = context.Request.Path.Value; - return Task.FromResult(0); - }); - }); - var server = new TestServer(builder); - - var request = new HttpRequestMessage(HttpMethod.Get, "/PathBase/Path"); - request.Headers.TryAddWithoutValidation("MS-ASPNETCORE-TOKEN", "TestToken"); - var response = await server.CreateClient().SendAsync(request); - - Assert.Equal("/PathBase", requestPathBase); - Assert.Equal("/Path", requestPath); - } - - [Fact] - public async Task AddsAuthenticationHandlerByDefault() - { - var assertsExecuted = false; - - var builder = new WebHostBuilder() - .UseSetting("TOKEN", "TestToken") - .UseSetting("PORT", "12345") - .UseSetting("APPL_PATH", "/") - .UseIISIntegration() - .Configure(app => - { - app.Run(async context => - { - var auth = context.RequestServices.GetRequiredService(); - var windows = await auth.GetSchemeAsync(IISDefaults.AuthenticationScheme); - Assert.NotNull(windows); - Assert.Null(windows.DisplayName); - Assert.Equal("Microsoft.AspNetCore.Server.IISIntegration.AuthenticationHandler", windows.HandlerType.FullName); - assertsExecuted = true; - }); - }); - var server = new TestServer(builder); - - var req = new HttpRequestMessage(HttpMethod.Get, ""); - req.Headers.TryAddWithoutValidation("MS-ASPNETCORE-TOKEN", "TestToken"); - await server.CreateClient().SendAsync(req); - - Assert.True(assertsExecuted); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task OnlyAddAuthenticationHandlerIfForwardWindowsAuthentication(bool forward) - { - var assertsExecuted = false; - - var builder = new WebHostBuilder() - .UseSetting("TOKEN", "TestToken") - .UseSetting("PORT", "12345") - .UseSetting("APPL_PATH", "/") - .UseIISIntegration() - .ConfigureServices(services => - { - services.Configure(options => - { - options.ForwardWindowsAuthentication = forward; - }); - }) - .Configure(app => - { - app.Run(async context => - { - var auth = context.RequestServices.GetService(); - Assert.NotNull(auth); - var windowsAuth = await auth.GetSchemeAsync(IISDefaults.AuthenticationScheme); - if (forward) - { - Assert.NotNull(windowsAuth); - Assert.Null(windowsAuth.DisplayName); - Assert.Equal("AuthenticationHandler", windowsAuth.HandlerType.Name); - } - else - { - Assert.Null(windowsAuth); - } - assertsExecuted = true; - }); - }); - var server = new TestServer(builder); - - var req = new HttpRequestMessage(HttpMethod.Get, ""); - req.Headers.TryAddWithoutValidation("MS-ASPNETCORE-TOKEN", "TestToken"); - await server.CreateClient().SendAsync(req); - - Assert.True(assertsExecuted); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task DoesNotBlowUpWithoutAuth(bool forward) - { - var assertsExecuted = false; - - var builder = new WebHostBuilder() - .UseSetting("TOKEN", "TestToken") - .UseSetting("PORT", "12345") - .UseSetting("APPL_PATH", "/") - .UseIISIntegration() - .ConfigureServices(services => - { - services.Configure(options => - { - options.ForwardWindowsAuthentication = forward; - }); - }) - .Configure(app => - { - app.Run(context => - { - assertsExecuted = true; - return Task.FromResult(0); - }); - }); - var server = new TestServer(builder); - - var req = new HttpRequestMessage(HttpMethod.Get, ""); - req.Headers.TryAddWithoutValidation("MS-ASPNETCORE-TOKEN", "TestToken"); - await server.CreateClient().SendAsync(req); - - Assert.True(assertsExecuted); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/Microsoft.AspNetCore.Server.IISIntegration.Tests/Microsoft.AspNetCore.Server.IISIntegration.Tests.csproj b/src/IISIntegration/src/IISIntegration/test/Microsoft.AspNetCore.Server.IISIntegration.Tests/Microsoft.AspNetCore.Server.IISIntegration.Tests.csproj deleted file mode 100644 index ea19c2a1fc..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/Microsoft.AspNetCore.Server.IISIntegration.Tests/Microsoft.AspNetCore.Server.IISIntegration.Tests.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - $(StandardTestTfms) - - - - - - - - - - - - - - diff --git a/src/IISIntegration/src/IISIntegration/test/TestTasks/InjectRequestHandler.cs b/src/IISIntegration/src/IISIntegration/test/TestTasks/InjectRequestHandler.cs deleted file mode 100644 index 4da8129d71..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/TestTasks/InjectRequestHandler.cs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Diagnostics; -using System.IO; -using System.Linq; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace TestTasks -{ - public class InjectRequestHandler - { - private static void Main(string[] args) - { - string rid = args[0]; - string libraryLocation = args[1]; - string depsFile = args[2]; - - JToken deps; - using (var file = File.OpenText(depsFile)) - using (JsonTextReader reader = new JsonTextReader(file)) - { - deps = JObject.ReadFrom(reader); - } - - var libraryName = "ANCMRH/1.0"; - var libraries = (JObject)deps["libraries"]; - var targetName = (JValue)deps["runtimeTarget"]["name"]; - - var target = (JObject)deps["targets"][targetName.Value]; - var targetLibrary = target.Properties().FirstOrDefault(p => p.Name == libraryName); - targetLibrary?.Remove(); - targetLibrary = - new JProperty(libraryName, new JObject( - new JProperty("runtimeTargets", new JObject( - new JProperty(libraryLocation.Replace('\\', '/'), new JObject( - new JProperty("rid", rid), - new JProperty("assetType", "native") - )))))); - target.AddFirst(targetLibrary); - - var library = libraries.Properties().FirstOrDefault(p => p.Name == libraryName); - library?.Remove(); - library = - new JProperty(libraryName, new JObject( - new JProperty("type", "package"), - new JProperty("serviceable", true), - new JProperty("sha512", ""), - new JProperty("path", libraryName), - new JProperty("hashPath", ""))); - libraries.AddFirst(library); - - using (var file = File.CreateText(depsFile)) - using (var writer = new JsonTextWriter(file) { Formatting = Formatting.Indented }) - { - deps.WriteTo(writer); - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/TestTasks/TestTasks.csproj b/src/IISIntegration/src/IISIntegration/test/TestTasks/TestTasks.csproj deleted file mode 100644 index 3cf4f265bb..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/TestTasks/TestTasks.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - Exe - $(StandardTestTfms) - - - - - - - diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/Directory.Build.props b/src/IISIntegration/src/IISIntegration/test/WebSites/Directory.Build.props deleted file mode 100644 index 9b29d34f16..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/Directory.Build.props +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessForwardsCompatWebSite/InProcessWebSite.csproj b/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessForwardsCompatWebSite/InProcessWebSite.csproj deleted file mode 100644 index e08c2be69f..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessForwardsCompatWebSite/InProcessWebSite.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - netcoreapp2.2 - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessForwardsCompatWebSite/Properties/launchSettings.json b/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessForwardsCompatWebSite/Properties/launchSettings.json deleted file mode 100644 index 246b7a0b47..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessForwardsCompatWebSite/Properties/launchSettings.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "iisSettings": { - "windowsAuthentication": true, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:5762/", - "sslPort": 0 - } - }, - "profiles": { - "ANCM IIS Express": { - "commandName": "Executable", - "executablePath": "$(IISExpressPath)", - "commandLineArgs": "$(IISExpressArguments)", - "environmentVariables": { - "IIS_SITE_PATH": "$(MSBuildThisFileDirectory)", - "ANCM_PATH": "$(AspNetCoreModuleV1ShimDll)", - "ANCMV2_PATH": "$(AspNetCoreModuleV2ShimDll)", - "ANCM_OUTOFPROCESS_HANDLER": "$(AspNetCoreModuleV2OutOfProcessHandlerDll)", - "LAUNCHER_ARGS": "$(TargetPath)", - "ASPNETCORE_ENVIRONMENT": "Development", - "LAUNCHER_PATH": "$(DotNetPath)", - "ASPNETCORE_MODULE_DEBUG": "console" - } - }, - "ANCM IIS": { - "commandName": "Executable", - "executablePath": "$(IISPath)", - "commandLineArgs": "$(IISArguments)", - "environmentVariables": { - "IIS_SITE_PATH": "$(MSBuildThisFileDirectory)", - "ANCM_PATH": "$(AspNetCoreModuleV1ShimDll)", - "ANCMV2_PATH": "$(AspNetCoreModuleV2ShimDll)", - "ASPNETCORE_MODULE_OUTOFPROCESS_HANDLER": "$(AspNetCoreModuleV2OutOfProcessHandlerDll)", - "LAUNCHER_ARGS": "$(TargetPath)", - "ASPNETCORE_ENVIRONMENT": "Development", - "LAUNCHER_PATH": "$(DotNetPath)", - "ASPNETCORE_MODULE_DEBUG": "console" - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/DummyServer.cs b/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/DummyServer.cs deleted file mode 100644 index d122f05776..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/DummyServer.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Hosting.Server; -using Microsoft.AspNetCore.Http.Features; - -namespace TestSite -{ - public class DummyServer : IServer - { - public void Dispose() - { - } - - public Task StartAsync(IHttpApplication application, CancellationToken cancellationToken) - { - return Task.Delay(TimeSpan.MaxValue); - } - - public Task StopAsync(CancellationToken cancellationToken) - { - return Task.Delay(TimeSpan.MaxValue); - } - - public IFeatureCollection Features { get; } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/InProcessWebSite.csproj b/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/InProcessWebSite.csproj deleted file mode 100644 index d007d2daa1..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/InProcessWebSite.csproj +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - netcoreapp2.2 - true - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/Program.cs b/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/Program.cs deleted file mode 100644 index c40448ee91..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/Program.cs +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Hosting.Server; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; - -namespace TestSite -{ - public static class Program - { - public static int Main(string[] args) - { - var mode = args.FirstOrDefault(); - switch (mode) - { - case "CreateFile": - File.WriteAllText(args[1], ""); - return StartServer(); - case "CheckLargeStdOutWrites": - Console.WriteLine(new string('a', 30000)); - break; - case "CheckLargeStdErrWrites": - Console.Error.WriteLine(new string('a', 30000)); - Console.Error.Flush(); - break; - case "ConsoleWrite": - Console.WriteLine($"Random number: {args[1]}"); - break; - case "ConsoleErrorWrite": - Console.Error.WriteLine($"Random number: {args[1]}"); - Console.Error.Flush(); - break; - case "CheckOversizedStdErrWrites": - Console.WriteLine(new string('a', 31000)); - break; - case "CheckOversizedStdOutWrites": - Console.Error.WriteLine(new string('a', 31000)); - Console.Error.Flush(); - break; - case "Hang": - Thread.Sleep(Timeout.Infinite); - break; - case "Throw": - throw new InvalidOperationException("Program.Main exception"); - case "EarlyReturn": - return 12; - case "HangOnStop": - { - var host = new WebHostBuilder() - .UseIIS() - .UseStartup() - .Build(); - host.Run(); - - Thread.Sleep(Timeout.Infinite); - } - break; - case "CheckConsoleFunctions": - // Call a bunch of console functions and make sure none return invalid handle. - Console.OutputEncoding = Encoding.UTF8; - Console.Title = "Test"; - Console.WriteLine($"Is Console redirection: {Console.IsOutputRedirected}"); - Console.BackgroundColor = ConsoleColor.Blue; - Console.WriteLine("彡⾔"); - break; - case "OverriddenServer": - { - var host = new WebHostBuilder() - .UseIIS() - .ConfigureServices(services => services.AddSingleton()) - .Configure(builder => builder.Run(async context => { await context.Response.WriteAsync("I shouldn't work"); })) - .Build(); - host.Run(); - } - break; - case "ConsoleErrorWriteStartServer": - Console.Error.WriteLine("TEST MESSAGE"); - return StartServer(); - case "ConsoleWriteStartServer": - Console.WriteLine("TEST MESSAGE"); - return StartServer(); - default: - return StartServer(); - - } - return 12; - } - - private static int StartServer() - { - var host = new WebHostBuilder() - .ConfigureLogging((_, factory) => - { - factory.AddConsole(); - factory.AddFilter("Console", level => level >= LogLevel.Information); - }) - .UseIIS() - .UseStartup() - .Build(); - - host.Run(); - return 0; - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/Properties/launchSettings.json b/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/Properties/launchSettings.json deleted file mode 100644 index 246b7a0b47..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/Properties/launchSettings.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "iisSettings": { - "windowsAuthentication": true, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:5762/", - "sslPort": 0 - } - }, - "profiles": { - "ANCM IIS Express": { - "commandName": "Executable", - "executablePath": "$(IISExpressPath)", - "commandLineArgs": "$(IISExpressArguments)", - "environmentVariables": { - "IIS_SITE_PATH": "$(MSBuildThisFileDirectory)", - "ANCM_PATH": "$(AspNetCoreModuleV1ShimDll)", - "ANCMV2_PATH": "$(AspNetCoreModuleV2ShimDll)", - "ANCM_OUTOFPROCESS_HANDLER": "$(AspNetCoreModuleV2OutOfProcessHandlerDll)", - "LAUNCHER_ARGS": "$(TargetPath)", - "ASPNETCORE_ENVIRONMENT": "Development", - "LAUNCHER_PATH": "$(DotNetPath)", - "ASPNETCORE_MODULE_DEBUG": "console" - } - }, - "ANCM IIS": { - "commandName": "Executable", - "executablePath": "$(IISPath)", - "commandLineArgs": "$(IISArguments)", - "environmentVariables": { - "IIS_SITE_PATH": "$(MSBuildThisFileDirectory)", - "ANCM_PATH": "$(AspNetCoreModuleV1ShimDll)", - "ANCMV2_PATH": "$(AspNetCoreModuleV2ShimDll)", - "ASPNETCORE_MODULE_OUTOFPROCESS_HANDLER": "$(AspNetCoreModuleV2OutOfProcessHandlerDll)", - "LAUNCHER_ARGS": "$(TargetPath)", - "ASPNETCORE_ENVIRONMENT": "Development", - "LAUNCHER_PATH": "$(DotNetPath)", - "ASPNETCORE_MODULE_DEBUG": "console" - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/Startup.WebSockets.cs b/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/Startup.WebSockets.cs deleted file mode 100644 index d658ebd03f..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/Startup.WebSockets.cs +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Net.WebSockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Features; -using Microsoft.Extensions.DependencyInjection; -using Xunit; - -namespace TestSite -{ - public partial class Startup - { - - private void WebsocketRequest(IApplicationBuilder app) - { - app.Run(async context => - { - await context.Response.WriteAsync("test"); - }); - } - - private void WebReadBeforeUpgrade(IApplicationBuilder app) - { - app.Run(async context => { - - var singleByteArray = new byte[1]; - Assert.Equal(0, await context.Request.Body.ReadAsync(singleByteArray, 0, 1)); - - var ws = await Upgrade(context); - await SendMessages(ws, "Yay"); - }); - } - - private void WebSocketEcho(IApplicationBuilder app) - { - app.Run(async context => - { - var ws = await Upgrade(context); - - var appLifetime = app.ApplicationServices.GetRequiredService(); - - await Echo(ws, appLifetime.ApplicationStopping); - }); - } - - private void WebSocketLifetimeEvents(IApplicationBuilder app) - { - app.Run(async context => { - - var messages = new List(); - - context.Response.OnStarting(() => { - context.Response.Headers["custom-header"] = "value"; - messages.Add("OnStarting"); - return Task.CompletedTask; - }); - - var ws = await Upgrade(context); - messages.Add("Upgraded"); - - await SendMessages(ws, messages.ToArray()); - }); - } - - private static async Task SendMessages(WebSocket webSocket, params string[] messages) - { - foreach (var message in messages) - { - await webSocket.SendAsync(new ArraySegment(Encoding.ASCII.GetBytes(message)), WebSocketMessageType.Text, true, CancellationToken.None); - } - } - - private static async Task Upgrade(HttpContext context) - { - var upgradeFeature = context.Features.Get(); - - // Generate WebSocket response headers - string key = context.Request.Headers[Constants.Headers.SecWebSocketKey].ToString(); - var responseHeaders = HandshakeHelpers.GenerateResponseHeaders(key); - foreach (var headerPair in responseHeaders) - { - context.Response.Headers[headerPair.Key] = headerPair.Value; - } - - // Upgrade the connection - Stream opaqueTransport = await upgradeFeature.UpgradeAsync(); - - // Get the WebSocket object - var ws = WebSocketProtocol.CreateFromStream(opaqueTransport, isServer: true, subProtocol: null, keepAliveInterval: TimeSpan.FromMinutes(2)); - return ws; - } - - private async Task Echo(WebSocket webSocket, CancellationToken token) - { - var buffer = new byte[1024 * 4]; - var result = await webSocket.ReceiveAsync(new ArraySegment(buffer), token); - bool closeFromServer = false; - string closeFromServerCmd = "CloseFromServer"; - int closeFromServerLength = closeFromServerCmd.Length; - - while (!result.CloseStatus.HasValue && !token.IsCancellationRequested && !closeFromServer) - { - if (result.Count == closeFromServerLength && - Encoding.ASCII.GetString(buffer).Substring(0, result.Count) == closeFromServerCmd) - { - // The client sent "CloseFromServer" text message to request the server to close (a test scenario). - closeFromServer = true; - } - else - { - await webSocket.SendAsync(new ArraySegment(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, token); - result = await webSocket.ReceiveAsync(new ArraySegment(buffer), token); - } - } - - if (result.CloseStatus.HasValue) - { - // Client-initiated close handshake - await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); - } - else - { - // Server-initiated close handshake due to either of the two conditions: - // (1) The applicaton host is performing a graceful shutdown. - // (2) The client sent "CloseFromServer" text message to request the server to close (a test scenario). - await webSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, closeFromServerCmd, CancellationToken.None); - - // The server has sent the Close frame. - // Stop sending but keep receiving until we get the Close frame from the client. - while (!result.CloseStatus.HasValue) - { - result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); - } - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/Startup.cs b/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/Startup.cs deleted file mode 100644 index eb84272b76..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/Startup.cs +++ /dev/null @@ -1,699 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Linq; -using System.Net; -using System.Text; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Features; -using Microsoft.AspNetCore.IISIntegration.FunctionalTests; -using Microsoft.AspNetCore.Server.IIS; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Primitives; -using Xunit; - -namespace TestSite -{ - public partial class Startup - { - public void Configure(IApplicationBuilder app) - { - TestStartup.Register(app, this); - } - - private async Task ServerVariable(HttpContext ctx) - { - var varName = ctx.Request.Query["q"]; - var newValue = ctx.Request.Query["v"]; - var feature = ctx.Features.Get(); - if (newValue.Count != 0) - { - feature[varName] = newValue; - } - await ctx.Response.WriteAsync($"{varName}: {feature[varName] ?? "(null)"}"); - } - - private async Task AuthenticationAnonymous(HttpContext ctx) - { - await ctx.Response.WriteAsync("Anonymous?" + !ctx.User.Identity.IsAuthenticated); - } - - private async Task AuthenticationRestricted(HttpContext ctx) - { - if (ctx.User.Identity.IsAuthenticated) - { - await ctx.Response.WriteAsync(ctx.User.Identity.AuthenticationType); - } - else - { - await ctx.ChallengeAsync(IISServerDefaults.AuthenticationScheme); - } - } - - private async Task AuthenticationForbidden(HttpContext ctx) - { - await ctx.ForbidAsync(IISServerDefaults.AuthenticationScheme); - } - - private async Task AuthenticationRestrictedNTLM(HttpContext ctx) - { - if (string.Equals("NTLM", ctx.User.Identity.AuthenticationType, StringComparison.Ordinal)) - { - await ctx.Response.WriteAsync("NTLM"); - } - else - { - await ctx.ChallengeAsync(IISServerDefaults.AuthenticationScheme); - } - } - - private async Task FeatureCollectionSetRequestFeatures(HttpContext ctx) - { - try - { - Assert.Equal("GET", ctx.Request.Method); - ctx.Request.Method = "test"; - Assert.Equal("test", ctx.Request.Method); - - Assert.Equal("http", ctx.Request.Scheme); - ctx.Request.Scheme = "test"; - Assert.Equal("test", ctx.Request.Scheme); - - Assert.Equal("/FeatureCollectionSetRequestFeatures", ctx.Request.PathBase); - ctx.Request.PathBase = "/base"; - Assert.Equal("/base", ctx.Request.PathBase); - - Assert.Equal("/path", ctx.Request.Path); - ctx.Request.Path = "/path"; - Assert.Equal("/path", ctx.Request.Path); - - Assert.Equal("?query", ctx.Request.QueryString.Value); - ctx.Request.QueryString = QueryString.Empty; - Assert.Equal("", ctx.Request.QueryString.Value); - - Assert.Equal("HTTP/1.1", ctx.Request.Protocol); - ctx.Request.Protocol = "HTTP/1.0"; - Assert.Equal("HTTP/1.0", ctx.Request.Protocol); - - Assert.NotNull(ctx.Request.Headers); - var headers = new HeaderDictionary(); - ctx.Features.Get().Headers = headers; - Assert.Same(headers, ctx.Features.Get().Headers); - - Assert.NotNull(ctx.Request.Body); - var body = new MemoryStream(); - ctx.Request.Body = body; - Assert.Same(body, ctx.Request.Body); - - //Assert.NotNull(ctx.Features.Get().TraceIdentifier); - //Assert.NotEqual(CancellationToken.None, ctx.RequestAborted); - //var token = new CancellationTokenSource().Token; - //ctx.RequestAborted = token; - //Assert.Equal(token, ctx.RequestAborted); - - await ctx.Response.WriteAsync("Success"); - return; - } - catch (Exception exception) - { - ctx.Response.StatusCode = 500; - await ctx.Response.WriteAsync(exception.ToString()); - } - await ctx.Response.WriteAsync("_Failure"); - } - - private async Task FeatureCollectionSetResponseFeatures(HttpContext ctx) - { - try - { - Assert.Equal(200, ctx.Response.StatusCode); - ctx.Response.StatusCode = 404; - Assert.Equal(404, ctx.Response.StatusCode); - ctx.Response.StatusCode = 200; - - Assert.Null(ctx.Features.Get().ReasonPhrase); - ctx.Features.Get().ReasonPhrase = "Set Response"; - Assert.Equal("Set Response", ctx.Features.Get().ReasonPhrase); - - Assert.NotNull(ctx.Response.Headers); - var headers = new HeaderDictionary(); - ctx.Features.Get().Headers = headers; - Assert.Same(headers, ctx.Features.Get().Headers); - - var originalBody = ctx.Response.Body; - Assert.NotNull(originalBody); - var body = new MemoryStream(); - ctx.Response.Body = body; - Assert.Same(body, ctx.Response.Body); - ctx.Response.Body = originalBody; - - await ctx.Response.WriteAsync("Success"); - return; - } - catch (Exception exception) - { - ctx.Response.StatusCode = 500; - await ctx.Response.WriteAsync(exception.ToString()); - } - await ctx.Response.WriteAsync("_Failure"); - } - - private async Task FeatureCollectionSetConnectionFeatures(HttpContext ctx) - { - try - { - Assert.True(IPAddress.IsLoopback(ctx.Connection.LocalIpAddress)); - ctx.Connection.LocalIpAddress = IPAddress.IPv6Any; - Assert.Equal(IPAddress.IPv6Any, ctx.Connection.LocalIpAddress); - - Assert.True(IPAddress.IsLoopback(ctx.Connection.RemoteIpAddress)); - ctx.Connection.RemoteIpAddress = IPAddress.IPv6Any; - Assert.Equal(IPAddress.IPv6Any, ctx.Connection.RemoteIpAddress); - await ctx.Response.WriteAsync("Success"); - return; - } - catch (Exception exception) - { - ctx.Response.StatusCode = 500; - await ctx.Response.WriteAsync(exception.ToString()); - } - await ctx.Response.WriteAsync("_Failure"); - } - - private void Throw(HttpContext ctx) - { - throw new Exception(); - } - - private async Task SetCustomErorCode(HttpContext ctx) - { - var feature = ctx.Features.Get(); - feature.ReasonPhrase = ctx.Request.Query["reason"]; - feature.StatusCode = int.Parse(ctx.Request.Query["code"]); - if (ctx.Request.Query["writeBody"] == "True") - { - await ctx.Response.WriteAsync(ctx.Request.Query["body"]); - } - } - - private async Task HelloWorld(HttpContext ctx) - { - if (ctx.Request.Path.Value.StartsWith("/Path")) - { - await ctx.Response.WriteAsync(ctx.Request.Path.Value); - return; - } - if (ctx.Request.Path.Value.StartsWith("/Query")) - { - await ctx.Response.WriteAsync(ctx.Request.QueryString.Value); - return; - } - - await ctx.Response.WriteAsync("Hello World"); - } - - private async Task LargeResponseBody(HttpContext ctx) - { - if (int.TryParse(ctx.Request.Query["length"], out var length)) - { - await ctx.Response.WriteAsync(new string('a', length)); - } - } - - private async Task ResponseHeaders(HttpContext ctx) - { - ctx.Response.Headers["UnknownHeader"] = "test123=foo"; - ctx.Response.ContentType = "text/plain"; - ctx.Response.Headers["MultiHeader"] = new StringValues(new string[] { "1", "2" }); - await ctx.Response.WriteAsync("Request Complete"); - } - - private async Task ResponseInvalidOrdering(HttpContext ctx) - { - if (ctx.Request.Path.Equals("/SetStatusCodeAfterWrite")) - { - await ctx.Response.WriteAsync("Started_"); - try - { - ctx.Response.StatusCode = 200; - } - catch (InvalidOperationException) - { - await ctx.Response.WriteAsync("SetStatusCodeAfterWriteThrew_"); - } - await ctx.Response.WriteAsync("Finished"); - return; - } - else if (ctx.Request.Path.Equals("/SetHeaderAfterWrite")) - { - await ctx.Response.WriteAsync("Started_"); - try - { - ctx.Response.Headers["This will fail"] = "some value"; - } - catch (InvalidOperationException) - { - await ctx.Response.WriteAsync("SetHeaderAfterWriteThrew_"); - } - await ctx.Response.WriteAsync("Finished"); - return; - } - } - - private async Task CheckEnvironmentVariable(HttpContext ctx) - { - var variable = Environment.GetEnvironmentVariable("ASPNETCORE_INPROCESS_TESTING_VALUE"); - await ctx.Response.WriteAsync(variable); - } - - private async Task CheckEnvironmentLongValueVariable(HttpContext ctx) - { - var variable = Environment.GetEnvironmentVariable("ASPNETCORE_INPROCESS_TESTING_LONG_VALUE"); - await ctx.Response.WriteAsync(variable); - } - - private async Task CheckAppendedEnvironmentVariable(HttpContext ctx) - { - var variable = Environment.GetEnvironmentVariable("ProgramFiles"); - await ctx.Response.WriteAsync(variable); - } - - private async Task CheckRemoveAuthEnvironmentVariable(HttpContext ctx) - { - var variable = Environment.GetEnvironmentVariable("ASPNETCORE_IIS_HTTPAUTH"); - await ctx.Response.WriteAsync(variable); - } - private async Task ReadAndWriteSynchronously(HttpContext ctx) - { - var t2 = Task.Run(() => WriteManyTimesToResponseBody(ctx)); - var t1 = Task.Run(() => ReadRequestBody(ctx)); - await Task.WhenAll(t1, t2); - } - - private async Task ReadRequestBody(HttpContext ctx) - { - var readBuffer = new byte[1]; - var result = await ctx.Request.Body.ReadAsync(readBuffer, 0, 1); - while (result != 0) - { - result = await ctx.Request.Body.ReadAsync(readBuffer, 0, 1); - } - } - - private async Task WriteManyTimesToResponseBody(HttpContext ctx) - { - for (var i = 0; i < 10000; i++) - { - await ctx.Response.WriteAsync("hello world"); - } - } - - private async Task ReadAndWriteEcho(HttpContext ctx) - { - var readBuffer = new byte[4096]; - var result = await ctx.Request.Body.ReadAsync(readBuffer, 0, readBuffer.Length); - while (result != 0) - { - await ctx.Response.WriteAsync(Encoding.UTF8.GetString(readBuffer, 0, result)); - result = await ctx.Request.Body.ReadAsync(readBuffer, 0, readBuffer.Length); - } - } - private async Task ReadAndFlushEcho(HttpContext ctx) - { - var readBuffer = new byte[4096]; - var result = await ctx.Request.Body.ReadAsync(readBuffer, 0, readBuffer.Length); - while (result != 0) - { - await ctx.Response.WriteAsync(Encoding.UTF8.GetString(readBuffer, 0, result)); - await ctx.Response.Body.FlushAsync(); - result = await ctx.Request.Body.ReadAsync(readBuffer, 0, readBuffer.Length); - } - } - - private async Task ReadAndWriteEchoLines(HttpContext ctx) - { - if (ctx.Request.Headers.TryGetValue("Response-Content-Type", out var contentType)) - { - ctx.Response.ContentType = contentType; - } - - //Send headers - await ctx.Response.Body.FlushAsync(); - - var reader = new StreamReader(ctx.Request.Body); - while (!reader.EndOfStream) - { - var line = await reader.ReadLineAsync(); - if (line == "") - { - return; - } - await ctx.Response.WriteAsync(line + Environment.NewLine); - await ctx.Response.Body.FlushAsync(); - } - } - - private async Task ReadAndWriteEchoLinesNoBuffering(HttpContext ctx) - { - var feature = ctx.Features.Get(); - feature.DisableResponseBuffering(); - - if (ctx.Request.Headers.TryGetValue("Response-Content-Type", out var contentType)) - { - ctx.Response.ContentType = contentType; - } - - //Send headers - await ctx.Response.Body.FlushAsync(); - - var reader = new StreamReader(ctx.Request.Body); - while (!reader.EndOfStream) - { - var line = await reader.ReadLineAsync(); - if (line == "") - { - return; - } - await ctx.Response.WriteAsync(line + Environment.NewLine); - } - } - - private async Task ReadPartialBody(HttpContext ctx) - { - var data = new byte[5]; - var count = 0; - do - { - count += await ctx.Request.Body.ReadAsync(data, count, data.Length - count); - } while (count != data.Length); - await ctx.Response.Body.WriteAsync(data, 0, data.Length); - } - - private async Task SetHeaderFromBody(HttpContext ctx) - { - using (var reader = new StreamReader(ctx.Request.Body)) - { - var value = await reader.ReadToEndAsync(); - ctx.Response.Headers["BodyAsString"] = value; - await ctx.Response.WriteAsync(value); - } - } - - private async Task ReadAndWriteEchoTwice(HttpContext ctx) - { - var readBuffer = new byte[4096]; - var result = await ctx.Request.Body.ReadAsync(readBuffer, 0, readBuffer.Length); - while (result != 0) - { - await ctx.Response.WriteAsync(Encoding.UTF8.GetString(readBuffer, 0, result)); - await ctx.Response.Body.FlushAsync(); - await ctx.Response.WriteAsync(Encoding.UTF8.GetString(readBuffer, 0, result)); - await ctx.Response.Body.FlushAsync(); - result = await ctx.Request.Body.ReadAsync(readBuffer, 0, readBuffer.Length); - } - } - - private async Task ReadAndWriteSlowConnection(HttpContext ctx) - { - var t2 = Task.Run(() => WriteResponseBodyAFewTimes(ctx)); - var t1 = Task.Run(() => ReadRequestBody(ctx)); - await Task.WhenAll(t1, t2); - } - - private async Task WriteResponseBodyAFewTimes(HttpContext ctx) - { - for (var i = 0; i < 100; i++) - { - await ctx.Response.WriteAsync("hello world"); - } - } - - private async Task ReadAndWriteCopyToAsync(HttpContext ctx) - { - await ctx.Request.Body.CopyToAsync(ctx.Response.Body); - } - - private async Task UpgradeFeatureDetection(HttpContext ctx) - { - if (ctx.Features.Get() != null) - { - await ctx.Response.WriteAsync("Enabled"); - } - else - { - await ctx.Response.WriteAsync("Disabled"); - } - } - - private async Task TestReadOffsetWorks(HttpContext ctx) - { - var buffer = new byte[11]; - ctx.Request.Body.Read(buffer, 0, 6); - ctx.Request.Body.Read(buffer, 6, 5); - - await ctx.Response.WriteAsync(Encoding.UTF8.GetString(buffer)); - } - - private async Task TestInvalidReadOperations(HttpContext ctx) - { - var success = false; - if (ctx.Request.Path.StartsWithSegments("/NullBuffer")) - { - try - { - await ctx.Request.Body.ReadAsync(null, 0, 0); - } - catch (Exception) - { - success = true; - } - } - else if (ctx.Request.Path.StartsWithSegments("/InvalidOffsetSmall")) - { - try - { - await ctx.Request.Body.ReadAsync(new byte[1], -1, 0); - } - catch (ArgumentOutOfRangeException) - { - success = true; - } - } - else if (ctx.Request.Path.StartsWithSegments("/InvalidOffsetLarge")) - { - try - { - await ctx.Request.Body.ReadAsync(new byte[1], 2, 0); - } - catch (ArgumentOutOfRangeException) - { - success = true; - } - } - else if (ctx.Request.Path.StartsWithSegments("/InvalidCountSmall")) - { - try - { - await ctx.Request.Body.ReadAsync(new byte[1], 0, -1); - } - catch (ArgumentOutOfRangeException) - { - success = true; - } - } - else if (ctx.Request.Path.StartsWithSegments("/InvalidCountLarge")) - { - try - { - await ctx.Request.Body.ReadAsync(new byte[1], 0, -1); - } - catch (ArgumentOutOfRangeException) - { - success = true; - } - } - else if (ctx.Request.Path.StartsWithSegments("/InvalidCountWithOffset")) - { - try - { - await ctx.Request.Body.ReadAsync(new byte[3], 1, 3); - } - catch (ArgumentOutOfRangeException) - { - success = true; - } - } - - - await ctx.Response.WriteAsync(success ? "Success" : "Failure"); - } - - private async Task TestValidReadOperations(HttpContext ctx) - { - var count = -1; - - if (ctx.Request.Path.StartsWithSegments("/NullBuffer")) - { - count = await ctx.Request.Body.ReadAsync(null, 0, 0); - } - else if (ctx.Request.Path.StartsWithSegments("/NullBufferPost")) - { - count = await ctx.Request.Body.ReadAsync(null, 0, 0); - } - else if (ctx.Request.Path.StartsWithSegments("/InvalidCountZeroRead")) - { - count = await ctx.Request.Body.ReadAsync(new byte[1], 0, 0); - } - else if (ctx.Request.Path.StartsWithSegments("/InvalidCountZeroReadPost")) - { - count = await ctx.Request.Body.ReadAsync(new byte[1], 0, 0); - } - - await ctx.Response.WriteAsync(count == 0 ? "Success" : "Failure"); - } - - private async Task TestInvalidWriteOperations(HttpContext ctx) - { - var success = false; - - if (ctx.Request.Path.StartsWithSegments("/InvalidOffsetSmall")) - { - try - { - await ctx.Response.Body.WriteAsync(new byte[1], -1, 0); - } - catch (ArgumentOutOfRangeException) - { - success = true; - } - } - else if (ctx.Request.Path.StartsWithSegments("/InvalidOffsetLarge")) - { - try - { - await ctx.Response.Body.WriteAsync(new byte[1], 2, 0); - } - catch (ArgumentOutOfRangeException) - { - success = true; - } - } - else if (ctx.Request.Path.StartsWithSegments("/InvalidCountSmall")) - { - try - { - await ctx.Response.Body.WriteAsync(new byte[1], 0, -1); - } - catch (ArgumentOutOfRangeException) - { - success = true; - } - } - else if (ctx.Request.Path.StartsWithSegments("/InvalidCountLarge")) - { - try - { - await ctx.Response.Body.WriteAsync(new byte[1], 0, -1); - } - catch (ArgumentOutOfRangeException) - { - success = true; - } - } - else if (ctx.Request.Path.StartsWithSegments("/InvalidCountWithOffset")) - { - try - { - await ctx.Response.Body.WriteAsync(new byte[3], 1, 3); - } - catch (ArgumentOutOfRangeException) - { - success = true; - } - } - - await ctx.Response.WriteAsync(success ? "Success" : "Failure"); - } - - private async Task TestValidWriteOperations(HttpContext ctx) - { - if (ctx.Request.Path.StartsWithSegments("/NullBuffer")) - { - await ctx.Response.Body.WriteAsync(null, 0, 0); - } - else if (ctx.Request.Path.StartsWithSegments("/NullBufferPost")) - { - await ctx.Response.Body.WriteAsync(null, 0, 0); - } - - await ctx.Response.WriteAsync("Success"); - } - - private async Task LargeResponseFile(HttpContext ctx) - { - var tempFile = Path.GetTempFileName(); - var fileContent = new string('a', 200000); - var fileStream = File.OpenWrite(tempFile); - - for (var i = 0; i < 1000; i++) - { - await fileStream.WriteAsync(Encoding.UTF8.GetBytes(fileContent), 0, fileContent.Length); - } - fileStream.Close(); - - await ctx.Response.SendFileAsync(tempFile, 0, null); - - // Try to delete the file from the temp directory. If it fails, don't report an error - // to the application. File should eventually be cleaned up from the temp directory - // by OS. - try - { - File.Delete(tempFile); - } - catch (Exception) - { - } - } - - private async Task BasePath(HttpContext ctx) - { - await ctx.Response.WriteAsync(AppDomain.CurrentDomain.BaseDirectory); - } - - private async Task Shutdown(HttpContext ctx) - { - await ctx.Response.WriteAsync("Shutting down"); - ctx.RequestServices.GetService().StopApplication(); - } - - private async Task GetServerVariableStress(HttpContext ctx) - { - // This test simulates the scenario where native Flush call is being - // executed on background thread while request thread calls GetServerVariable - // concurrent native calls may cause native object corruption - - var serverVariableFeature = ctx.Features.Get(); - await ctx.Response.WriteAsync("Response Begin"); - for (int i = 0; i < 1000; i++) - { - await ctx.Response.WriteAsync(serverVariableFeature["REMOTE_PORT"]); - await ctx.Response.Body.FlushAsync(); - } - await ctx.Response.WriteAsync("Response End"); - } - - private async Task CommandLineArgs(HttpContext ctx) - { - await ctx.Response.WriteAsync(string.Join("|", Environment.GetCommandLineArgs().Skip(1))); - } - - public Task HttpsHelloWorld(HttpContext ctx) => - ctx.Response.WriteAsync("Scheme:" + ctx.Request.Scheme + "; Original:" + ctx.Request.Headers["x-original-proto"]); - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/web.config b/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/web.config deleted file mode 100644 index 2a9bd223c3..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/web.config +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/wwwroot/static.txt b/src/IISIntegration/src/IISIntegration/test/WebSites/InProcessWebSite/wwwroot/static.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/OutOfProcessWebSite/OutOfProcessWebSite.csproj b/src/IISIntegration/src/IISIntegration/test/WebSites/OutOfProcessWebSite/OutOfProcessWebSite.csproj deleted file mode 100644 index 14beb7394e..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/OutOfProcessWebSite/OutOfProcessWebSite.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - $(StandardTestTfms) - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/OutOfProcessWebSite/Program.cs b/src/IISIntegration/src/IISIntegration/test/WebSites/OutOfProcessWebSite/Program.cs deleted file mode 100644 index 90895237d2..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/OutOfProcessWebSite/Program.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.IO; -using System.Linq; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Logging; - -namespace TestSite -{ - public static class Program - { - public static int Main(string[] args) - { - var mode = args.FirstOrDefault(); - switch (mode) - { - case "CreateFile": - File.WriteAllText(args[1], ""); - return StartServer(); - } - - return StartServer(); - } - - private static int StartServer() - { - var host = new WebHostBuilder() - .ConfigureLogging( - (_, factory) => { - factory.AddConsole(); - factory.AddFilter("Console", level => level >= LogLevel.Information); - }) - .UseContentRoot(Directory.GetCurrentDirectory()) - .UseIISIntegration() - .UseStartup() - .UseKestrel() - .Build(); - - host.Run(); - return 0; - } - } -} - diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/OutOfProcessWebSite/Properties/launchSettings.json b/src/IISIntegration/src/IISIntegration/test/WebSites/OutOfProcessWebSite/Properties/launchSettings.json deleted file mode 100644 index 246b7a0b47..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/OutOfProcessWebSite/Properties/launchSettings.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "iisSettings": { - "windowsAuthentication": true, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:5762/", - "sslPort": 0 - } - }, - "profiles": { - "ANCM IIS Express": { - "commandName": "Executable", - "executablePath": "$(IISExpressPath)", - "commandLineArgs": "$(IISExpressArguments)", - "environmentVariables": { - "IIS_SITE_PATH": "$(MSBuildThisFileDirectory)", - "ANCM_PATH": "$(AspNetCoreModuleV1ShimDll)", - "ANCMV2_PATH": "$(AspNetCoreModuleV2ShimDll)", - "ANCM_OUTOFPROCESS_HANDLER": "$(AspNetCoreModuleV2OutOfProcessHandlerDll)", - "LAUNCHER_ARGS": "$(TargetPath)", - "ASPNETCORE_ENVIRONMENT": "Development", - "LAUNCHER_PATH": "$(DotNetPath)", - "ASPNETCORE_MODULE_DEBUG": "console" - } - }, - "ANCM IIS": { - "commandName": "Executable", - "executablePath": "$(IISPath)", - "commandLineArgs": "$(IISArguments)", - "environmentVariables": { - "IIS_SITE_PATH": "$(MSBuildThisFileDirectory)", - "ANCM_PATH": "$(AspNetCoreModuleV1ShimDll)", - "ANCMV2_PATH": "$(AspNetCoreModuleV2ShimDll)", - "ASPNETCORE_MODULE_OUTOFPROCESS_HANDLER": "$(AspNetCoreModuleV2OutOfProcessHandlerDll)", - "LAUNCHER_ARGS": "$(TargetPath)", - "ASPNETCORE_ENVIRONMENT": "Development", - "LAUNCHER_PATH": "$(DotNetPath)", - "ASPNETCORE_MODULE_DEBUG": "console" - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/OutOfProcessWebSite/Startup.cs b/src/IISIntegration/src/IISIntegration/test/WebSites/OutOfProcessWebSite/Startup.cs deleted file mode 100644 index de54a85a8a..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/OutOfProcessWebSite/Startup.cs +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Security.Principal; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting.Server.Features; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Features; -using Microsoft.AspNetCore.IISIntegration.FunctionalTests; -using Microsoft.AspNetCore.Server.IISIntegration; -using Microsoft.Extensions.DependencyInjection; -using Xunit; - -namespace TestSite -{ - public partial class Startup - { - private IServerAddressesFeature _serverAddresses; - - public void Configure(IApplicationBuilder app) - { - TestStartup.Register(app, this); - - _serverAddresses = app.ServerFeatures.Get(); - } - - public Task Path(HttpContext ctx) => ctx.Response.WriteAsync(ctx.Request.Path.Value); - - public Task Query(HttpContext ctx) => ctx.Response.WriteAsync(ctx.Request.QueryString.Value); - - public Task BodyLimit(HttpContext ctx) => ctx.Response.WriteAsync(ctx.Features.Get()?.MaxRequestBodySize?.ToString() ?? "null"); - - - public Task HelloWorld(HttpContext ctx) => ctx.Response.WriteAsync("Hello World"); - - public Task HttpsHelloWorld(HttpContext ctx) => - ctx.Response.WriteAsync("Scheme:" + ctx.Request.Scheme + "; Original:" + ctx.Request.Headers["x-original-proto"]); - - public Task Anonymous(HttpContext context) => context.Response.WriteAsync("Anonymous?" + !context.User.Identity.IsAuthenticated); - - public Task Restricted(HttpContext context) - { - if (context.User.Identity.IsAuthenticated) - { - Assert.IsType(context.User); - return context.Response.WriteAsync(context.User.Identity.AuthenticationType); - } - else - { - return context.ChallengeAsync(IISDefaults.AuthenticationScheme); - } - } - - public Task Forbidden(HttpContext context) => context.ForbidAsync(IISDefaults.AuthenticationScheme); - - public Task RestrictedNTLM(HttpContext context) - { - if (string.Equals("NTLM", context.User.Identity.AuthenticationType, StringComparison.Ordinal)) - { - return context.Response.WriteAsync("NTLM"); - } - else - { - return context.ChallengeAsync(IISDefaults.AuthenticationScheme); - } - } - - public Task UpgradeFeatureDetection(HttpContext context) => - context.Response.WriteAsync(context.Features.Get() != null? "Enabled": "Disabled"); - - public Task CheckRequestHandlerVersion(HttpContext context) - { - // We need to check if the aspnetcorev2_outofprocess dll is loaded by iisexpress.exe - // As they aren't in the same process, we will try to delete the file and expect a file - // in use error - try - { - File.Delete(context.Request.Headers["ANCMRHPath"]); - } - catch(UnauthorizedAccessException) - { - // TODO calling delete on the file will succeed when running with IIS - return context.Response.WriteAsync("Hello World"); - } - - return context.Response.WriteAsync(context.Request.Headers["ANCMRHPath"]); - } - - private async Task ProcessId(HttpContext context) - { - await context.Response.WriteAsync(Process.GetCurrentProcess().Id.ToString()); - } - - private async Task ServerAddresses(HttpContext context) - { - await context.Response.WriteAsync(string.Join(",", _serverAddresses.Addresses)); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/OutOfProcessWebSite/wwwroot/static.txt b/src/IISIntegration/src/IISIntegration/test/WebSites/OutOfProcessWebSite/wwwroot/static.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/StressTestWebSite/Program.cs b/src/IISIntegration/src/IISIntegration/test/WebSites/StressTestWebSite/Program.cs deleted file mode 100644 index e8e5392c2c..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/StressTestWebSite/Program.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Logging; - -namespace ANCMStressTestApp -{ - public class Program - { - public static void Main(string[] args) - { - var host = new WebHostBuilder() - .ConfigureLogging((_, factory) => - { - factory.AddConsole(); - }) - .UseKestrel() - .UseIISIntegration() - .UseStartup() - .Build(); - - host.Run(); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/StressTestWebSite/Properties/launchSettings.json b/src/IISIntegration/src/IISIntegration/test/WebSites/StressTestWebSite/Properties/launchSettings.json deleted file mode 100644 index 246b7a0b47..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/StressTestWebSite/Properties/launchSettings.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "iisSettings": { - "windowsAuthentication": true, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:5762/", - "sslPort": 0 - } - }, - "profiles": { - "ANCM IIS Express": { - "commandName": "Executable", - "executablePath": "$(IISExpressPath)", - "commandLineArgs": "$(IISExpressArguments)", - "environmentVariables": { - "IIS_SITE_PATH": "$(MSBuildThisFileDirectory)", - "ANCM_PATH": "$(AspNetCoreModuleV1ShimDll)", - "ANCMV2_PATH": "$(AspNetCoreModuleV2ShimDll)", - "ANCM_OUTOFPROCESS_HANDLER": "$(AspNetCoreModuleV2OutOfProcessHandlerDll)", - "LAUNCHER_ARGS": "$(TargetPath)", - "ASPNETCORE_ENVIRONMENT": "Development", - "LAUNCHER_PATH": "$(DotNetPath)", - "ASPNETCORE_MODULE_DEBUG": "console" - } - }, - "ANCM IIS": { - "commandName": "Executable", - "executablePath": "$(IISPath)", - "commandLineArgs": "$(IISArguments)", - "environmentVariables": { - "IIS_SITE_PATH": "$(MSBuildThisFileDirectory)", - "ANCM_PATH": "$(AspNetCoreModuleV1ShimDll)", - "ANCMV2_PATH": "$(AspNetCoreModuleV2ShimDll)", - "ASPNETCORE_MODULE_OUTOFPROCESS_HANDLER": "$(AspNetCoreModuleV2OutOfProcessHandlerDll)", - "LAUNCHER_ARGS": "$(TargetPath)", - "ASPNETCORE_ENVIRONMENT": "Development", - "LAUNCHER_PATH": "$(DotNetPath)", - "ASPNETCORE_MODULE_DEBUG": "console" - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/StressTestWebSite/Startup.cs b/src/IISIntegration/src/IISIntegration/test/WebSites/StressTestWebSite/Startup.cs deleted file mode 100644 index 68f6eb1f77..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/StressTestWebSite/Startup.cs +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using System.Threading; -using System.Text; -using System.Net.WebSockets; -using Microsoft.AspNetCore.Server.IIS.FunctionalTests; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Features; -using Microsoft.Net.Http.Headers; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Primitives; - -namespace ANCMStressTestApp -{ - public class Startup - { - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - } - - public void Configure(IApplicationBuilder app) - { - app.Map("/HelloWorld", HelloWorld); - app.Map("/ConnectionClose", ConnectionClose); - app.Map("/EchoPostData", EchoPostData); - app.Map("/LargeResponseBody", LargeResponseBody); - app.Map("/ResponseHeaders", ResponseHeaders); - app.Map("/EnvironmentVariables", EnvironmentVariables); - app.Map("/RequestInformation", RequestInformation); - app.Map("/WebSocket", WebSocket); - - app.Run(async context => - { - await context.Response.WriteAsync("Default Page"); - }); - } - - private void HelloWorld(IApplicationBuilder app) - { - app.Run(async context => - { - await context.Response.WriteAsync("Hello World"); - }); - } - - private void ConnectionClose(IApplicationBuilder app) - { - app.Run(async context => - { - context.Response.Headers[HeaderNames.Connection] = "close"; - await context.Response.WriteAsync("Connnection Close"); - await context.Response.Body.FlushAsync(); - }); - } - - private void EchoPostData(IApplicationBuilder app) - { - app.Run(async context => - { - string responseBody = string.Empty; - - if (string.Equals(context.Request.Method, "POST", StringComparison.OrdinalIgnoreCase)) - { - using (StreamReader reader = new StreamReader(context.Request.Body, Encoding.UTF8)) - { - responseBody = await reader.ReadToEndAsync(); - } - } - else - { - responseBody = "NoAction"; - } - - await context.Response.WriteAsync(responseBody); - }); - } - - private void LargeResponseBody(IApplicationBuilder app) - { - app.Run(async context => - { - if (int.TryParse(context.Request.Query["length"], out var length)) - { - await context.Response.WriteAsync(new string('a', length)); - } - }); - } - - private void ResponseHeaders(IApplicationBuilder app) - { - app.Run(async context => - { - context.Response.Headers["UnknownHeader"] = "test123=foo"; - context.Response.ContentType = "text/plain"; - context.Response.Headers["MultiHeader"] = new StringValues(new string[] { "1", "2" }); - await context.Response.WriteAsync("Request Complete"); - }); - } - - private void EnvironmentVariables(IApplicationBuilder app) - { - app.Run(async context => - { - context.Response.ContentType = "text/plain"; - await context.Response.WriteAsync("Environment Variables:" + Environment.NewLine); - var vars = Environment.GetEnvironmentVariables(); - foreach (var key in vars.Keys.Cast().OrderBy(key => key, StringComparer.OrdinalIgnoreCase)) - { - var value = vars[key]; - await context.Response.WriteAsync(key + ": " + value + Environment.NewLine); - } - await context.Response.WriteAsync(Environment.NewLine); - }); - } - - private void RequestInformation(IApplicationBuilder app) - { - app.Run(async context => - { - context.Response.ContentType = "text/plain"; - - await context.Response.WriteAsync("Address:" + Environment.NewLine); - await context.Response.WriteAsync("Scheme: " + context.Request.Scheme + Environment.NewLine); - await context.Response.WriteAsync("Host: " + context.Request.Headers["Host"] + Environment.NewLine); - await context.Response.WriteAsync("PathBase: " + context.Request.PathBase.Value + Environment.NewLine); - await context.Response.WriteAsync("Path: " + context.Request.Path.Value + Environment.NewLine); - await context.Response.WriteAsync("Query: " + context.Request.QueryString.Value + Environment.NewLine); - await context.Response.WriteAsync(Environment.NewLine); - - await context.Response.WriteAsync("Connection:" + Environment.NewLine); - await context.Response.WriteAsync("RemoteIp: " + context.Connection.RemoteIpAddress + Environment.NewLine); - await context.Response.WriteAsync("RemotePort: " + context.Connection.RemotePort + Environment.NewLine); - await context.Response.WriteAsync("LocalIp: " + context.Connection.LocalIpAddress + Environment.NewLine); - await context.Response.WriteAsync("LocalPort: " + context.Connection.LocalPort + Environment.NewLine); - await context.Response.WriteAsync(Environment.NewLine); - - await context.Response.WriteAsync("Headers:" + Environment.NewLine); - foreach (var header in context.Request.Headers) - { - await context.Response.WriteAsync(header.Key + ": " + header.Value + Environment.NewLine); - } - await context.Response.WriteAsync(Environment.NewLine); - }); - } - - private void WebSocket(IApplicationBuilder app) - { - app.Run(async context => - { - var upgradeFeature = context.Features.Get(); - - // Generate WebSocket response headers - string key = context.Request.Headers[Constants.Headers.SecWebSocketKey].ToString(); - var responseHeaders = HandshakeHelpers.GenerateResponseHeaders(key); - foreach (var headerPair in responseHeaders) - { - context.Response.Headers[headerPair.Key] = headerPair.Value; - } - - // Upgrade the connection - Stream opaqueTransport = await upgradeFeature.UpgradeAsync(); - - // Get the WebSocket object - var ws = WebSocketProtocol.CreateFromStream(opaqueTransport, isServer: true, subProtocol: null, keepAliveInterval: TimeSpan.FromMinutes(2)); - - var appLifetime = app.ApplicationServices.GetRequiredService(); - - await Echo(ws, appLifetime.ApplicationStopping); - }); - } - - private async Task Echo(WebSocket webSocket, CancellationToken token) - { - try - { - var buffer = new byte[1024 * 4]; - var result = await webSocket.ReceiveAsync(new ArraySegment(buffer), token); - bool closeFromServer = false; - string closeFromServerCmd = "CloseFromServer"; - int closeFromServerLength = closeFromServerCmd.Length; - - while (!result.CloseStatus.HasValue && !token.IsCancellationRequested && !closeFromServer) - { - if (result.Count == closeFromServerLength && - Encoding.ASCII.GetString(buffer).Substring(0, result.Count) == closeFromServerCmd) - { - // The client sent "CloseFromServer" text message to request the server to close (a test scenario). - closeFromServer = true; - } - else - { - await webSocket.SendAsync(new ArraySegment(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, token); - result = await webSocket.ReceiveAsync(new ArraySegment(buffer), token); - } - } - - if (result.CloseStatus.HasValue) - { - // Client-initiated close handshake - await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); - } - else - { - // Server-initiated close handshake due to either of the two conditions: - // (1) The applicaton host is performing a graceful shutdown. - // (2) The client sent "CloseFromServer" text message to request the server to close (a test scenario). - await webSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, closeFromServerCmd, CancellationToken.None); - - // The server has sent the Close frame. - // Stop sending but keep receiving until we get the Close frame from the client. - while (!result.CloseStatus.HasValue) - { - result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); - } - } - } - catch (Exception e) - { - Console.WriteLine("{0} Exception caught!", e); - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/StressTestWebSite/StressTestWebSite.csproj b/src/IISIntegration/src/IISIntegration/test/WebSites/StressTestWebSite/StressTestWebSite.csproj deleted file mode 100644 index 25ae032221..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/StressTestWebSite/StressTestWebSite.csproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - $(StandardTestTfms) - true - - - - - - - - - - - - - - - - - - diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/shared/SharedStartup/Startup.shared.cs b/src/IISIntegration/src/IISIntegration/test/WebSites/shared/SharedStartup/Startup.shared.cs deleted file mode 100644 index b5d7f0305f..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/shared/SharedStartup/Startup.shared.cs +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; - -namespace TestSite -{ - public partial class Startup - { - public void ConfigureServices(IServiceCollection serviceCollection) - { - serviceCollection.AddResponseCompression(); - } - - private async Task HostingEnvironment(HttpContext ctx) - { - var hostingEnv = ctx.RequestServices.GetService(); - - await ctx.Response.WriteAsync("ContentRootPath " + hostingEnv.ContentRootPath + Environment.NewLine); - await ctx.Response.WriteAsync("WebRootPath " + hostingEnv.WebRootPath + Environment.NewLine); - await ctx.Response.WriteAsync("CurrentDirectory " + Environment.CurrentDirectory); - } - - private async Task ConsoleWrite(HttpContext ctx) - { - Console.WriteLine("TEST MESSAGE"); - - await ctx.Response.WriteAsync("Hello World"); - } - - private async Task ConsoleErrorWrite(HttpContext ctx) - { - Console.Error.WriteLine("TEST MESSAGE"); - - await ctx.Response.WriteAsync("Hello World"); - } - - public async Task Auth(HttpContext ctx) - { - var authProvider = ctx.RequestServices.GetService(); - var authScheme = (await authProvider.GetAllSchemesAsync()).SingleOrDefault(); - - await ctx.Response.WriteAsync(authScheme?.Name ?? "null"); - if (ctx.User.Identity.Name != null) - { - await ctx.Response.WriteAsync(":" + ctx.User.Identity.Name); - } - } - - public async Task GetClientCert(HttpContext context) - { - var clientCert = context.Connection.ClientCertificate; - await context.Response.WriteAsync(clientCert != null ? $"Enabled;{clientCert.GetCertHashString()}" : "Disabled"); - } - - private static int _waitingRequestCount; - - public Task WaitForAbort(HttpContext context) - { - Interlocked.Increment(ref _waitingRequestCount); - try - { - context.RequestAborted.WaitHandle.WaitOne(); - return Task.CompletedTask; - } - finally - { - Interlocked.Decrement(ref _waitingRequestCount); - } - } - - public Task Abort(HttpContext context) - { - context.Abort(); - return Task.CompletedTask; - } - - public async Task WaitingRequestCount(HttpContext context) - { - await context.Response.WriteAsync(_waitingRequestCount.ToString()); - } - - public Task CreateFile(HttpContext context) - { - var hostingEnv = context.RequestServices.GetService(); - File.WriteAllText(System.IO.Path.Combine(hostingEnv.ContentRootPath, "Started.txt"), ""); - return Task.CompletedTask; - } - - public Task OverrideServer(HttpContext context) - { - context.Response.Headers["Server"] = "MyServer/7.8"; - return Task.CompletedTask; - } - - public void CompressedData(IApplicationBuilder builder) - { - builder.UseResponseCompression(); - // write random bytes to check that compressed data is passed through - builder.Run( - async context => - { - context.Response.ContentType = "text/html"; - await context.Response.Body.WriteAsync(new byte[100], 0, 100); - }); - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/shared/WebSockets/Constants.cs b/src/IISIntegration/src/IISIntegration/test/WebSites/shared/WebSockets/Constants.cs deleted file mode 100644 index 95b53003cc..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/shared/WebSockets/Constants.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests -{ - public static class Constants - { - public static class Headers - { - public const string Upgrade = "Upgrade"; - public const string UpgradeWebSocket = "websocket"; - public const string Connection = "Connection"; - public const string SecWebSocketKey = "Sec-WebSocket-Key"; - public const string SecWebSocketAccept = "Sec-WebSocket-Accept"; - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/shared/WebSockets/HandshakeHelpers.cs b/src/IISIntegration/src/IISIntegration/test/WebSites/shared/WebSockets/HandshakeHelpers.cs deleted file mode 100644 index b079ea3f85..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/shared/WebSockets/HandshakeHelpers.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Security.Cryptography; -using System.Text; - -namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests -{ - internal static class HandshakeHelpers - { - public static IEnumerable> GenerateResponseHeaders(string key) - { - yield return new KeyValuePair(Constants.Headers.Connection, Constants.Headers.Upgrade); - yield return new KeyValuePair(Constants.Headers.Upgrade, Constants.Headers.UpgradeWebSocket); - yield return new KeyValuePair(Constants.Headers.SecWebSocketAccept, CreateResponseKey(key)); - } - - public static string CreateResponseKey(string requestKey) - { - // "The value of this header field is constructed by concatenating /key/, defined above in step 4 - // in Section 4.2.2, with the string "258EAFA5- E914-47DA-95CA-C5AB0DC85B11", taking the SHA-1 hash of - // this concatenated value to obtain a 20-byte value and base64-encoding" - // https://tools.ietf.org/html/rfc6455#section-4.2.2 - - if (requestKey == null) - { - throw new ArgumentNullException(nameof(requestKey)); - } - - using (var algorithm = SHA1.Create()) - { - string merged = requestKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - byte[] mergedBytes = Encoding.UTF8.GetBytes(merged); - byte[] hashedBytes = algorithm.ComputeHash(mergedBytes); - return Convert.ToBase64String(hashedBytes); - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/WebSites/shared/WebSockets/TestStartup.cs b/src/IISIntegration/src/IISIntegration/test/WebSites/shared/WebSockets/TestStartup.cs deleted file mode 100644 index b1604e367a..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/WebSites/shared/WebSockets/TestStartup.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Reflection; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Http; - -namespace Microsoft.AspNetCore.IISIntegration.FunctionalTests -{ - public static class TestStartup - { - public static void Register(IApplicationBuilder app, object startup) - { - var type = startup.GetType(); - foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) - { - var parameters = method.GetParameters(); - if (method.Name != "Configure" && - parameters.Length == 1) - { - Action appfunc = null; - if (parameters[0].ParameterType == typeof(IApplicationBuilder)) - { - appfunc = innerAppBuilder => method.Invoke(startup, new[] { innerAppBuilder }); - } - else if (parameters[0].ParameterType == typeof(HttpContext)) - { - appfunc = innerAppBuilder => innerAppBuilder.Run(ctx => (Task)method.Invoke(startup, new[] { ctx })); - } - - if (appfunc != null) - { - app.Map("/" + method.Name, appfunc); - } - } - } - } - } -} diff --git a/src/IISIntegration/src/IISIntegration/test/gtest/gtest.vcxproj b/src/IISIntegration/src/IISIntegration/test/gtest/gtest.vcxproj deleted file mode 100644 index 924f26337d..0000000000 --- a/src/IISIntegration/src/IISIntegration/test/gtest/gtest.vcxproj +++ /dev/null @@ -1,180 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - - - - - 15.0 - {CAC1267B-8778-4257-AAC6-CAF481723B01} - Win32Proj - gtest - 10.0.15063.0 - - - - StaticLibrary - true - v141 - Unicode - gtestd - - - StaticLibrary - false - v141 - true - Unicode - gtest - - - StaticLibrary - true - v141 - Unicode - gtestd - - - StaticLibrary - false - v141 - true - Unicode - gtest - - - - - - - - - - - - - - - - - - - - - true - $(VC_IncludePath);$(WindowsSDK_IncludePath); - $(VC_SourcePath); - $(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\ - - - true - $(VC_IncludePath);$(WindowsSDK_IncludePath); - $(VC_SourcePath); - $(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\ - - - false - $(VC_IncludePath);$(WindowsSDK_IncludePath); - $(VC_SourcePath); - $(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\ - - - false - $(VC_IncludePath);$(WindowsSDK_IncludePath); - $(VC_SourcePath); - $(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\ - - - - NotUsing - Level3 - Disabled - true - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - true - googletest\googletest\include;googletest\googletest;googletest\googlemock;googletest\googlemock\include;%(AdditionalIncludeDirectories) - MultiThreadedDebug - - - Windows - true - - - - - NotUsing - Level3 - Disabled - true - _DEBUG;_LIB;%(PreprocessorDefinitions) - true - googletest\googletest\include;googletest\googletest;googletest\googlemock;googletest\googlemock\include;%(AdditionalIncludeDirectories) - MultiThreadedDebug - - - Windows - true - - - - - NotUsing - Level3 - MaxSpeed - true - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - googletest\googletest\include;googletest\googletest;googletest\googlemock;googletest\googlemock\include;%(AdditionalIncludeDirectories) - MultiThreaded - - - Windows - true - true - true - - - - - NotUsing - Level3 - MaxSpeed - true - true - true - NDEBUG;_LIB;%(PreprocessorDefinitions) - true - googletest\googletest\include;googletest\googletest;googletest\googlemock;googletest\googlemock\include;%(AdditionalIncludeDirectories) - MultiThreaded - - - Windows - true - true - true - - - - - - \ No newline at end of file From 21cf99994fc7a9c198d3aba820791cedc2cd4338 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Fri, 9 Nov 2018 20:04:20 +0000 Subject: [PATCH 1002/1029] Updating submodule(s) KestrelHttpServer => 4d2e68649f5d6ccd6339c04355a1f93734872aec [auto-updated: submodules] --- modules/KestrelHttpServer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/KestrelHttpServer b/modules/KestrelHttpServer index 2b87e7be85..4d2e68649f 160000 --- a/modules/KestrelHttpServer +++ b/modules/KestrelHttpServer @@ -1 +1 @@ -Subproject commit 2b87e7be8525ed7ae0aa57cbd94c3d1b522edaa3 +Subproject commit 4d2e68649f5d6ccd6339c04355a1f93734872aec From 7060d3a6c56ca835f7e7435e2d12a765e5293ac7 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Fri, 9 Nov 2018 20:46:08 +0000 Subject: [PATCH 1003/1029] Updating submodule(s) KestrelHttpServer => 5db6394769e229139cbf8538ec73253ce76e735b [auto-updated: submodules] --- modules/KestrelHttpServer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/KestrelHttpServer b/modules/KestrelHttpServer index 4d2e68649f..5db6394769 160000 --- a/modules/KestrelHttpServer +++ b/modules/KestrelHttpServer @@ -1 +1 @@ -Subproject commit 4d2e68649f5d6ccd6339c04355a1f93734872aec +Subproject commit 5db6394769e229139cbf8538ec73253ce76e735b From 74d9728e95b7ed2108e8e1974443ba286859de78 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 9 Nov 2018 12:49:58 -0800 Subject: [PATCH 1004/1029] Reorganize source code in preparation to move into aspnet/AspNetCore Prior to reorganization, this source code was found in https://github.com/aspnet/JsonPatch/tree/218064c300a7cf5a76669e133340a98a0c5517a5 --- .appveyor.yml | 17 -- .gitattributes | 52 ---- .github/ISSUE_TEMPLATE.md | 3 - .gitignore | 39 --- .travis.yml | 27 -- CONTRIBUTING.md | 4 - Directory.Build.props | 20 -- Directory.Build.targets | 7 - JsonPatch.sln | 63 ----- LICENSE.txt | 14 -- NuGet.config | 7 - NuGetPackageVerifier.json | 7 - README.md | 9 - build.cmd | 2 - build.sh | 8 - build/Key.snk | Bin 596 -> 0 bytes build/dependencies.props | 29 --- build/repo.props | 15 -- build/sources.props | 17 -- korebuild-lock.txt | 2 - korebuild.json | 4 - run.cmd | 2 - run.ps1 | 196 --------------- run.sh | 231 ------------------ src/Directory.Build.props | 7 - .../JsonPatch/src}/Adapters/IObjectAdapter.cs | 0 .../src}/Adapters/IObjectAdapterWithTest.cs | 0 .../JsonPatch/src}/Adapters/ObjectAdapter.cs | 0 .../Converters/JsonPatchDocumentConverter.cs | 0 .../TypedJsonPatchDocumentConverter.cs | 0 .../src}/Exceptions/JsonPatchException.cs | 0 .../JsonPatch/src}/Helpers/GetValueResult.cs | 0 .../src}/Helpers/JsonPatchProperty.cs | 0 .../JsonPatch/src}/IJsonPatchDocument.cs | 0 .../src}/Internal/ConversionResult.cs | 0 .../src}/Internal/ConversionResultProvider.cs | 0 .../src}/Internal/DictionaryAdapterOfTU.cs | 0 .../src}/Internal/DynamicObjectAdapter.cs | 0 .../JsonPatch/src}/Internal/ErrorReporter.cs | 0 .../JsonPatch/src}/Internal/IAdapter.cs | 0 .../JsonPatch/src}/Internal/ListAdapter.cs | 0 .../JsonPatch/src}/Internal/ObjectVisitor.cs | 0 .../JsonPatch/src}/Internal/ParsedPath.cs | 0 .../JsonPatch/src}/Internal/PathHelpers.cs | 0 .../JsonPatch/src}/Internal/PocoAdapter.cs | 0 .../JsonPatch/src}/JsonPatchDocument.cs | 0 .../JsonPatch/src}/JsonPatchDocumentOfT.cs | 0 .../JsonPatch/src}/JsonPatchError.cs | 0 .../Microsoft.AspNetCore.JsonPatch.csproj | 6 +- .../JsonPatch/src}/Operations/Operation.cs | 0 .../src}/Operations/OperationBase.cs | 0 .../JsonPatch/src}/Operations/OperationOfT.cs | 0 .../src}/Operations/OperationType.cs | 0 .../JsonPatch/src/Properties/AssemblyInfo.cs | 7 + .../src}/Properties/Resources.Designer.cs | 0 .../JsonPatch/src}/Resources.resx | 0 .../JsonPatch/src}/baseline.netcore.json | 0 .../test}/CustomNamingStrategyTests.cs | 0 .../AnonymousObjectIntegrationTest.cs | 0 .../DictionaryIntegrationTest.cs | 0 .../DynamicObjectIntegrationTest.cs | 0 .../ExpandoObjectIntegrationTest.cs | 0 .../IntegrationTests/ListIntegrationTest.cs | 0 .../NestedObjectIntegrationTest.cs | 0 .../SimpleObjectIntegrationTest.cs | 0 .../test}/Internal/DictionaryAdapterTest.cs | 0 .../Internal/DynamicObjectAdapterTest.cs | 0 .../test}/Internal/ListAdapterTest.cs | 0 .../test}/Internal/ObjectVisitorTest.cs | 0 .../test}/Internal/ParsedPathTests.cs | 0 .../test}/Internal/PocoAdapterTest.cs | 0 .../test}/JsonPatchDocumentGetPathTest.cs | 0 ...nPatchDocumentJsonPropertyAttributeTest.cs | 0 .../JsonPatch/test}/JsonPatchDocumentTest.cs | 0 ...icrosoft.AspNetCore.JsonPatch.Tests.csproj | 11 + .../JsonPatch/test}/OperationBaseTests.cs | 0 .../JsonPatch/test}/TestErrorLogger.cs | 0 .../test}/TestObjectModels/Customer.cs | 0 .../TestObjectModels/DynamicTestObject.cs | 0 .../test}/TestObjectModels/InheritedObject.cs | 0 .../test}/TestObjectModels/NestedObject.cs | 0 .../test}/TestObjectModels/SimpleObject.cs | 0 .../SimpleObjectWithNestedObject.cs | 0 .../Properties/AssemblyInfo.cs | 7 - test/Directory.Build.props | 18 -- ...Microsoft.AspNetCore.JsonPatch.Test.csproj | 20 -- version.props | 12 - 87 files changed, 21 insertions(+), 842 deletions(-) delete mode 100644 .appveyor.yml delete mode 100644 .gitattributes delete mode 100644 .github/ISSUE_TEMPLATE.md delete mode 100644 .gitignore delete mode 100644 .travis.yml delete mode 100644 CONTRIBUTING.md delete mode 100644 Directory.Build.props delete mode 100644 Directory.Build.targets delete mode 100644 JsonPatch.sln delete mode 100644 LICENSE.txt delete mode 100644 NuGet.config delete mode 100644 NuGetPackageVerifier.json delete mode 100644 README.md delete mode 100644 build.cmd delete mode 100755 build.sh delete mode 100644 build/Key.snk delete mode 100644 build/dependencies.props delete mode 100644 build/repo.props delete mode 100644 build/sources.props delete mode 100644 korebuild-lock.txt delete mode 100644 korebuild.json delete mode 100644 run.cmd delete mode 100644 run.ps1 delete mode 100755 run.sh delete mode 100644 src/Directory.Build.props rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Adapters/IObjectAdapter.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Adapters/IObjectAdapterWithTest.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Adapters/ObjectAdapter.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Converters/JsonPatchDocumentConverter.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Converters/TypedJsonPatchDocumentConverter.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Exceptions/JsonPatchException.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Helpers/GetValueResult.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Helpers/JsonPatchProperty.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/IJsonPatchDocument.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Internal/ConversionResult.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Internal/ConversionResultProvider.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Internal/DictionaryAdapterOfTU.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Internal/DynamicObjectAdapter.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Internal/ErrorReporter.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Internal/IAdapter.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Internal/ListAdapter.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Internal/ObjectVisitor.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Internal/ParsedPath.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Internal/PathHelpers.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Internal/PocoAdapter.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/JsonPatchDocument.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/JsonPatchDocumentOfT.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/JsonPatchError.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Microsoft.AspNetCore.JsonPatch.csproj (51%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Operations/Operation.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Operations/OperationBase.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Operations/OperationOfT.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Operations/OperationType.cs (100%) create mode 100644 src/Features/JsonPatch/src/Properties/AssemblyInfo.cs rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Properties/Resources.Designer.cs (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/Resources.resx (100%) rename src/{Microsoft.AspNetCore.JsonPatch => Features/JsonPatch/src}/baseline.netcore.json (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/CustomNamingStrategyTests.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/IntegrationTests/AnonymousObjectIntegrationTest.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/IntegrationTests/DictionaryIntegrationTest.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/IntegrationTests/DynamicObjectIntegrationTest.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/IntegrationTests/ExpandoObjectIntegrationTest.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/IntegrationTests/ListIntegrationTest.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/IntegrationTests/NestedObjectIntegrationTest.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/IntegrationTests/SimpleObjectIntegrationTest.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/Internal/DictionaryAdapterTest.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/Internal/DynamicObjectAdapterTest.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/Internal/ListAdapterTest.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/Internal/ObjectVisitorTest.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/Internal/ParsedPathTests.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/Internal/PocoAdapterTest.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/JsonPatchDocumentGetPathTest.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/JsonPatchDocumentJsonPropertyAttributeTest.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/JsonPatchDocumentTest.cs (100%) create mode 100644 src/Features/JsonPatch/test/Microsoft.AspNetCore.JsonPatch.Tests.csproj rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/OperationBaseTests.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/TestErrorLogger.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/TestObjectModels/Customer.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/TestObjectModels/DynamicTestObject.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/TestObjectModels/InheritedObject.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/TestObjectModels/NestedObject.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/TestObjectModels/SimpleObject.cs (100%) rename {test/Microsoft.AspNetCore.JsonPatch.Test => src/Features/JsonPatch/test}/TestObjectModels/SimpleObjectWithNestedObject.cs (100%) delete mode 100644 src/Microsoft.AspNetCore.JsonPatch/Properties/AssemblyInfo.cs delete mode 100644 test/Directory.Build.props delete mode 100644 test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj delete mode 100644 version.props diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index 4eea96ab69..0000000000 --- a/.appveyor.yml +++ /dev/null @@ -1,17 +0,0 @@ -init: -- git config --global core.autocrlf true -branches: - only: - - dev - - /^release\/.*$/ - - /^(.*\/)?ci-.*$/ -build_script: -- ps: .\run.ps1 default-build -clone_depth: 1 -environment: - global: - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - DOTNET_CLI_TELEMETRY_OPTOUT: 1 -test: 'off' -deploy: 'off' -os: Visual Studio 2017 diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index d4ee1cb7f3..0000000000 --- a/.gitattributes +++ /dev/null @@ -1,52 +0,0 @@ -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain - -*.jpg binary -*.png binary -*.gif binary - -*.cs text=auto diff=csharp -*.vb text=auto -*.resx text=auto -*.c text=auto -*.cpp text=auto -*.cxx text=auto -*.h text=auto -*.hxx text=auto -*.py text=auto -*.rb text=auto -*.java text=auto -*.html text=auto -*.htm text=auto -*.css text=auto -*.scss text=auto -*.sass text=auto -*.less text=auto -*.js text=auto -*.lisp text=auto -*.clj text=auto -*.sql text=auto -*.php text=auto -*.lua text=auto -*.m text=auto -*.asm text=auto -*.erl text=auto -*.fs text=auto -*.fsx text=auto -*.hs text=auto - -*.csproj text=auto -*.vbproj text=auto -*.fsproj text=auto -*.dbproj text=auto -*.sln text=auto eol=crlf - -*.sh eol=lf diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 101a084f0a..0000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,3 +0,0 @@ -THIS ISSUE TRACKER IS CLOSED - please log new issues here: https://github.com/aspnet/Home/issues - -For information about this change, see https://github.com/aspnet/Announcements/issues/283 diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 2e8ec28064..0000000000 --- a/.gitignore +++ /dev/null @@ -1,39 +0,0 @@ -[Oo]bj/ -[Bb]in/ -TestResults/ -.nuget/ -.build/ -.testPublish/ -*.sln.ide/ -_ReSharper.*/ -packages/ -artifacts/ -PublishProfiles/ -.vs/ -bower_components/ -node_modules/ -debugSettings.json -project.lock.json -*.user -*.suo -*.cache -*.docstates -_ReSharper.* -nuget.exe -*net45.csproj -*net451.csproj -*k10.csproj -*.psess -*.vsp -*.pidb -*.userprefs -*DS_Store -*.ncrunchsolution -*.*sdf -*.ipch -.settings -*.sln.ide -node_modules -*launchSettings.json -*.orig -global.json diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 64bdbb4441..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,27 +0,0 @@ -language: csharp -sudo: false -dist: trusty -env: - global: - - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - - DOTNET_CLI_TELEMETRY_OPTOUT: 1 -mono: none -os: -- linux -- osx -osx_image: xcode8.2 -addons: - apt: - packages: - - libunwind8 -branches: - only: - - dev - - /^release\/.*$/ - - /^(.*\/)?ci-.*$/ -before_install: -- if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s - /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib - /usr/local/lib/; fi -script: -- ./build.sh diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 64ff041d5c..0000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,4 +0,0 @@ -Contributing -====== - -Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/dev/CONTRIBUTING.md) in the Home repo. diff --git a/Directory.Build.props b/Directory.Build.props deleted file mode 100644 index 88b93729bb..0000000000 --- a/Directory.Build.props +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - Microsoft ASP.NET Core - https://github.com/aspnet/JsonPatch - git - $(MSBuildThisFileDirectory) - $(MSBuildThisFileDirectory)build\Key.snk - true - true - true - - diff --git a/Directory.Build.targets b/Directory.Build.targets deleted file mode 100644 index 53b3f6e1da..0000000000 --- a/Directory.Build.targets +++ /dev/null @@ -1,7 +0,0 @@ - - - $(MicrosoftNETCoreApp20PackageVersion) - $(MicrosoftNETCoreApp21PackageVersion) - $(NETStandardLibrary20PackageVersion) - - diff --git a/JsonPatch.sln b/JsonPatch.sln deleted file mode 100644 index f0b6a578f1..0000000000 --- a/JsonPatch.sln +++ /dev/null @@ -1,63 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26815.3 -MinimumVisualStudioVersion = 15.0.26730.03 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{430B59ED-F960-4D3A-8FFE-3370008E168D}" - ProjectSection(SolutionItems) = preProject - src\Directory.Build.props = src\Directory.Build.props - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{36CD6341-AB44-44EB-B3AA-BF98C89FECDD}" - ProjectSection(SolutionItems) = preProject - test\Directory.Build.props = test\Directory.Build.props - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.JsonPatch", "src\Microsoft.AspNetCore.JsonPatch\Microsoft.AspNetCore.JsonPatch.csproj", "{4D55F4D8-633B-462F-A5B1-FEB84BD2D534}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.JsonPatch.Test", "test\Microsoft.AspNetCore.JsonPatch.Test\Microsoft.AspNetCore.JsonPatch.Test.csproj", "{81C20848-E063-4E12-AC40-0B55A532C16C}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C430C499-382D-47BD-B351-CF8F89C08CD2}" - ProjectSection(SolutionItems) = preProject - .appveyor.yml = .appveyor.yml - .gitattributes = .gitattributes - .gitignore = .gitignore - .travis.yml = .travis.yml - build.cmd = build.cmd - build.ps1 = build.ps1 - build.sh = build.sh - CONTRIBUTING.md = CONTRIBUTING.md - Directory.Build.props = Directory.Build.props - Directory.Build.targets = Directory.Build.targets - LICENSE.txt = LICENSE.txt - NuGet.config = NuGet.config - NuGetPackageVerifier.json = NuGetPackageVerifier.json - README.md = README.md - version.xml = version.xml - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {4D55F4D8-633B-462F-A5B1-FEB84BD2D534}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4D55F4D8-633B-462F-A5B1-FEB84BD2D534}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4D55F4D8-633B-462F-A5B1-FEB84BD2D534}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4D55F4D8-633B-462F-A5B1-FEB84BD2D534}.Release|Any CPU.Build.0 = Release|Any CPU - {81C20848-E063-4E12-AC40-0B55A532C16C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {81C20848-E063-4E12-AC40-0B55A532C16C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {81C20848-E063-4E12-AC40-0B55A532C16C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {81C20848-E063-4E12-AC40-0B55A532C16C}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {4D55F4D8-633B-462F-A5B1-FEB84BD2D534} = {430B59ED-F960-4D3A-8FFE-3370008E168D} - {81C20848-E063-4E12-AC40-0B55A532C16C} = {36CD6341-AB44-44EB-B3AA-BF98C89FECDD} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {9FFA3EB9-8740-4434-BC8C-F3D595161B59} - EndGlobalSection -EndGlobal diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index 7b2956ecee..0000000000 --- a/LICENSE.txt +++ /dev/null @@ -1,14 +0,0 @@ -Copyright (c) .NET Foundation and Contributors - -All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed -under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -CONDITIONS OF ANY KIND, either express or implied. See the License for the -specific language governing permissions and limitations under the License. diff --git a/NuGet.config b/NuGet.config deleted file mode 100644 index e32bddfd51..0000000000 --- a/NuGet.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json deleted file mode 100644 index b153ab1515..0000000000 --- a/NuGetPackageVerifier.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "Default": { - "rules": [ - "DefaultCompositeRule" - ] - } -} \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 6c27b76d9d..0000000000 --- a/README.md +++ /dev/null @@ -1,9 +0,0 @@ -JsonPatch -=== -AppVeyor: [![AppVeyor](https://ci.appveyor.com/api/projects/status/51gggjks5k3q6pr5/branch/dev?svg=true)](https://ci.appveyor.com/project/aspnetci/JsonPatch/branch/dev) - -Travis: [![Travis](https://travis-ci.org/aspnet/JsonPatch.svg?branch=dev)](https://travis-ci.org/aspnet/JsonPatch) - -This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo. - - diff --git a/build.cmd b/build.cmd deleted file mode 100644 index c0050bda12..0000000000 --- a/build.cmd +++ /dev/null @@ -1,2 +0,0 @@ -@ECHO OFF -PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' default-build %*; exit $LASTEXITCODE" diff --git a/build.sh b/build.sh deleted file mode 100755 index 98a4b22765..0000000000 --- a/build.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -# Call "sync" between "chmod" and execution to prevent "text file busy" error in Docker (aufs) -chmod +x "$DIR/run.sh"; sync -"$DIR/run.sh" default-build "$@" diff --git a/build/Key.snk b/build/Key.snk deleted file mode 100644 index e10e4889c125d3120cd9e81582243d70f7cbb806..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098=Iw=HCsnz~#iVhm& zj%TU(_THUee?3yHBjk$37ysB?i5#7WD$={H zV4B!OxRPrb|8)HPg~A}8P>^=#y<)56#=E&NzcjOtPK~<4n6GHt=K$ro*T(lhby_@U zEk(hLzk1H)0yXj{A_5>fk-TgNoP|q6(tP2xo8zt8i%212CWM#AeCd?`hS|4~L({h~Moo(~vy&3Z z1uI}`fd^*>o=rwbAGymj6RM^pZm(*Kfhs+Y1#`-2JPWZMK8@;ZWCk2+9bX4YP);~fj-BU*R zQPvWv$89!{Rl9wM+zR>_TSkn^voYxA?2G iKnV#iZ6Ah`K>b=@=IjYJXrxL124zR(38)nxe+&q_$QXwJ diff --git a/build/dependencies.props b/build/dependencies.props deleted file mode 100644 index 55c598b536..0000000000 --- a/build/dependencies.props +++ /dev/null @@ -1,29 +0,0 @@ - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - - - - 2.1.3-rtm-15802 - 4.5.0 - 2.0.0 - 2.1.2 - 15.6.1 - 4.7.49 - 2.0.3 - 11.0.2 - 0.8.0 - 2.3.1 - 2.4.0-beta.1.build3945 - - - - - - - - 2.1.0 - 2.1.1 - - \ No newline at end of file diff --git a/build/repo.props b/build/repo.props deleted file mode 100644 index dab1601c88..0000000000 --- a/build/repo.props +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - Internal.AspNetCore.Universe.Lineup - 2.1.0-rc1-* - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json - - - - - - - diff --git a/build/sources.props b/build/sources.props deleted file mode 100644 index 9215df9751..0000000000 --- a/build/sources.props +++ /dev/null @@ -1,17 +0,0 @@ - - - - - $(DotNetRestoreSources) - - $(RestoreSources); - https://dotnet.myget.org/F/dotnet-core/api/v3/index.json; - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; - https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; - - - $(RestoreSources); - https://api.nuget.org/v3/index.json; - - - diff --git a/korebuild-lock.txt b/korebuild-lock.txt deleted file mode 100644 index 251c227c83..0000000000 --- a/korebuild-lock.txt +++ /dev/null @@ -1,2 +0,0 @@ -version:2.1.3-rtm-15802 -commithash:a7c08b45b440a7d2058a0aa1eaa3eb6ba811976a diff --git a/korebuild.json b/korebuild.json deleted file mode 100644 index 678d8bb948..0000000000 --- a/korebuild.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.1/tools/korebuild.schema.json", - "channel": "release/2.1" -} diff --git a/run.cmd b/run.cmd deleted file mode 100644 index d52d5c7e68..0000000000 --- a/run.cmd +++ /dev/null @@ -1,2 +0,0 @@ -@ECHO OFF -PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' %*; exit $LASTEXITCODE" diff --git a/run.ps1 b/run.ps1 deleted file mode 100644 index 27dcf848f8..0000000000 --- a/run.ps1 +++ /dev/null @@ -1,196 +0,0 @@ -#!/usr/bin/env powershell -#requires -version 4 - -<# -.SYNOPSIS -Executes KoreBuild commands. - -.DESCRIPTION -Downloads korebuild if required. Then executes the KoreBuild command. To see available commands, execute with `-Command help`. - -.PARAMETER Command -The KoreBuild command to run. - -.PARAMETER Path -The folder to build. Defaults to the folder containing this script. - -.PARAMETER Channel -The channel of KoreBuild to download. Overrides the value from the config file. - -.PARAMETER DotNetHome -The directory where .NET Core tools will be stored. - -.PARAMETER ToolsSource -The base url where build tools can be downloaded. Overrides the value from the config file. - -.PARAMETER Update -Updates KoreBuild to the latest version even if a lock file is present. - -.PARAMETER ConfigFile -The path to the configuration file that stores values. Defaults to korebuild.json. - -.PARAMETER ToolsSourceSuffix -The Suffix to append to the end of the ToolsSource. Useful for query strings in blob stores. - -.PARAMETER Arguments -Arguments to be passed to the command - -.NOTES -This function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be. -When the lockfile is not present, KoreBuild will create one using latest available version from $Channel. - -The $ConfigFile is expected to be an JSON file. It is optional, and the configuration values in it are optional as well. Any options set -in the file are overridden by command line parameters. - -.EXAMPLE -Example config file: -```json -{ - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev", - "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" -} -``` -#> -[CmdletBinding(PositionalBinding = $false)] -param( - [Parameter(Mandatory = $true, Position = 0)] - [string]$Command, - [string]$Path = $PSScriptRoot, - [Alias('c')] - [string]$Channel, - [Alias('d')] - [string]$DotNetHome, - [Alias('s')] - [string]$ToolsSource, - [Alias('u')] - [switch]$Update, - [string]$ConfigFile, - [string]$ToolsSourceSuffix, - [Parameter(ValueFromRemainingArguments = $true)] - [string[]]$Arguments -) - -Set-StrictMode -Version 2 -$ErrorActionPreference = 'Stop' - -# -# Functions -# - -function Get-KoreBuild { - - $lockFile = Join-Path $Path 'korebuild-lock.txt' - - if (!(Test-Path $lockFile) -or $Update) { - Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile $ToolsSourceSuffix - } - - $version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1 - if (!$version) { - Write-Error "Failed to parse version from $lockFile. Expected a line that begins with 'version:'" - } - $version = $version.TrimStart('version:').Trim() - $korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version) - - if (!(Test-Path $korebuildPath)) { - Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version" - New-Item -ItemType Directory -Path $korebuildPath | Out-Null - $remotePath = "$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip" - - try { - $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip" - Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix - if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) { - # Use built-in commands where possible as they are cross-plat compatible - Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath - } - else { - # Fallback to old approach for old installations of PowerShell - Add-Type -AssemblyName System.IO.Compression.FileSystem - [System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath) - } - } - catch { - Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore - throw - } - finally { - Remove-Item $tmpfile -ErrorAction Ignore - } - } - - return $korebuildPath -} - -function Join-Paths([string]$path, [string[]]$childPaths) { - $childPaths | ForEach-Object { $path = Join-Path $path $_ } - return $path -} - -function Get-RemoteFile([string]$RemotePath, [string]$LocalPath, [string]$RemoteSuffix) { - if ($RemotePath -notlike 'http*') { - Copy-Item $RemotePath $LocalPath - return - } - - $retries = 10 - while ($retries -gt 0) { - $retries -= 1 - try { - Invoke-WebRequest -UseBasicParsing -Uri $($RemotePath + $RemoteSuffix) -OutFile $LocalPath - return - } - catch { - Write-Verbose "Request failed. $retries retries remaining" - } - } - - Write-Error "Download failed: '$RemotePath'." -} - -# -# Main -# - -# Load configuration or set defaults - -$Path = Resolve-Path $Path -if (!$ConfigFile) { $ConfigFile = Join-Path $Path 'korebuild.json' } - -if (Test-Path $ConfigFile) { - try { - $config = Get-Content -Raw -Encoding UTF8 -Path $ConfigFile | ConvertFrom-Json - if ($config) { - if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel } - if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource} - } - } - catch { - Write-Warning "$ConfigFile could not be read. Its settings will be ignored." - Write-Warning $Error[0] - } -} - -if (!$DotNetHome) { - $DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } ` - elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} ` - elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}` - else { Join-Path $PSScriptRoot '.dotnet'} -} - -if (!$Channel) { $Channel = 'dev' } -if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } - -# Execute - -$korebuildPath = Get-KoreBuild -Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1') - -try { - Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile - Invoke-KoreBuildCommand $Command @Arguments -} -finally { - Remove-Module 'KoreBuild' -ErrorAction Ignore -} diff --git a/run.sh b/run.sh deleted file mode 100755 index 834961fc3a..0000000000 --- a/run.sh +++ /dev/null @@ -1,231 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -# -# variables -# - -RESET="\033[0m" -RED="\033[0;31m" -YELLOW="\033[0;33m" -MAGENTA="\033[0;95m" -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" -verbose=false -update=false -repo_path="$DIR" -channel='' -tools_source='' -tools_source_suffix='' - -# -# Functions -# -__usage() { - echo "Usage: $(basename "${BASH_SOURCE[0]}") command [options] [[--] ...]" - echo "" - echo "Arguments:" - echo " command The command to be run." - echo " ... Arguments passed to the command. Variable number of arguments allowed." - echo "" - echo "Options:" - echo " --verbose Show verbose output." - echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." - echo " --config-file The path to the configuration file that stores values. Defaults to korebuild.json." - echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." - echo " --path The directory to build. Defaults to the directory containing the script." - echo " -s|--tools-source|-ToolsSource The base url where build tools can be downloaded. Overrides the value from the config file." - echo " --tools-source-suffix|-ToolsSourceSuffix The suffix to append to tools-source. Useful for query strings." - echo " -u|--update Update to the latest KoreBuild even if the lock file is present." - echo "" - echo "Description:" - echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." - echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel." - - if [[ "${1:-}" != '--no-exit' ]]; then - exit 2 - fi -} - -get_korebuild() { - local version - local lock_file="$repo_path/korebuild-lock.txt" - if [ ! -f "$lock_file" ] || [ "$update" = true ]; then - __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" "$tools_source_suffix" - fi - version="$(grep 'version:*' -m 1 "$lock_file")" - if [[ "$version" == '' ]]; then - __error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'" - return 1 - fi - version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" - local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" - - { - if [ ! -d "$korebuild_path" ]; then - mkdir -p "$korebuild_path" - local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" - tmpfile="$(mktemp)" - echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" - if __get_remote_file "$remote_path" "$tmpfile" "$tools_source_suffix"; then - unzip -q -d "$korebuild_path" "$tmpfile" - fi - rm "$tmpfile" || true - fi - - source "$korebuild_path/KoreBuild.sh" - } || { - if [ -d "$korebuild_path" ]; then - echo "Cleaning up after failed installation" - rm -rf "$korebuild_path" || true - fi - return 1 - } -} - -__error() { - echo -e "${RED}error: $*${RESET}" 1>&2 -} - -__warn() { - echo -e "${YELLOW}warning: $*${RESET}" -} - -__machine_has() { - hash "$1" > /dev/null 2>&1 - return $? -} - -__get_remote_file() { - local remote_path=$1 - local local_path=$2 - local remote_path_suffix=$3 - - if [[ "$remote_path" != 'http'* ]]; then - cp "$remote_path" "$local_path" - return 0 - fi - - local failed=false - if __machine_has wget; then - wget --tries 10 --quiet -O "$local_path" "${remote_path}${remote_path_suffix}" || failed=true - else - failed=true - fi - - if [ "$failed" = true ] && __machine_has curl; then - failed=false - curl --retry 10 -sSL -f --create-dirs -o "$local_path" "${remote_path}${remote_path_suffix}" || failed=true - fi - - if [ "$failed" = true ]; then - __error "Download failed: $remote_path" 1>&2 - return 1 - fi -} - -# -# main -# - -command="${1:-}" -shift - -while [[ $# -gt 0 ]]; do - case $1 in - -\?|-h|--help) - __usage --no-exit - exit 0 - ;; - -c|--channel|-Channel) - shift - channel="${1:-}" - [ -z "$channel" ] && __usage - ;; - --config-file|-ConfigFile) - shift - config_file="${1:-}" - [ -z "$config_file" ] && __usage - if [ ! -f "$config_file" ]; then - __error "Invalid value for --config-file. $config_file does not exist." - exit 1 - fi - ;; - -d|--dotnet-home|-DotNetHome) - shift - DOTNET_HOME="${1:-}" - [ -z "$DOTNET_HOME" ] && __usage - ;; - --path|-Path) - shift - repo_path="${1:-}" - [ -z "$repo_path" ] && __usage - ;; - -s|--tools-source|-ToolsSource) - shift - tools_source="${1:-}" - [ -z "$tools_source" ] && __usage - ;; - --tools-source-suffix|-ToolsSourceSuffix) - shift - tools_source_suffix="${1:-}" - [ -z "$tools_source_suffix" ] && __usage - ;; - -u|--update|-Update) - update=true - ;; - --verbose|-Verbose) - verbose=true - ;; - --) - shift - break - ;; - *) - break - ;; - esac - shift -done - -if ! __machine_has unzip; then - __error 'Missing required command: unzip' - exit 1 -fi - -if ! __machine_has curl && ! __machine_has wget; then - __error 'Missing required command. Either wget or curl is required.' - exit 1 -fi - -[ -z "${config_file:-}" ] && config_file="$repo_path/korebuild.json" -if [ -f "$config_file" ]; then - if __machine_has jq ; then - if jq '.' "$config_file" >/dev/null ; then - config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" - config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")" - else - __warn "$config_file is invalid JSON. Its settings will be ignored." - fi - elif __machine_has python ; then - if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then - config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" - config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" - else - __warn "$config_file is invalid JSON. Its settings will be ignored." - fi - else - __warn 'Missing required command: jq or pyton. Could not parse the JSON file. Its settings will be ignored.' - fi - - [ ! -z "${config_channel:-}" ] && channel="$config_channel" - [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" -fi - -[ -z "$channel" ] && channel='dev' -[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' - -get_korebuild -set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file" -invoke_korebuild_command "$command" "$@" diff --git a/src/Directory.Build.props b/src/Directory.Build.props deleted file mode 100644 index 4b89a431e7..0000000000 --- a/src/Directory.Build.props +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/IObjectAdapter.cs b/src/Features/JsonPatch/src/Adapters/IObjectAdapter.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Adapters/IObjectAdapter.cs rename to src/Features/JsonPatch/src/Adapters/IObjectAdapter.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/IObjectAdapterWithTest.cs b/src/Features/JsonPatch/src/Adapters/IObjectAdapterWithTest.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Adapters/IObjectAdapterWithTest.cs rename to src/Features/JsonPatch/src/Adapters/IObjectAdapterWithTest.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs b/src/Features/JsonPatch/src/Adapters/ObjectAdapter.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Adapters/ObjectAdapter.cs rename to src/Features/JsonPatch/src/Adapters/ObjectAdapter.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Converters/JsonPatchDocumentConverter.cs b/src/Features/JsonPatch/src/Converters/JsonPatchDocumentConverter.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Converters/JsonPatchDocumentConverter.cs rename to src/Features/JsonPatch/src/Converters/JsonPatchDocumentConverter.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs b/src/Features/JsonPatch/src/Converters/TypedJsonPatchDocumentConverter.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Converters/TypedJsonPatchDocumentConverter.cs rename to src/Features/JsonPatch/src/Converters/TypedJsonPatchDocumentConverter.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Exceptions/JsonPatchException.cs b/src/Features/JsonPatch/src/Exceptions/JsonPatchException.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Exceptions/JsonPatchException.cs rename to src/Features/JsonPatch/src/Exceptions/JsonPatchException.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Helpers/GetValueResult.cs b/src/Features/JsonPatch/src/Helpers/GetValueResult.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Helpers/GetValueResult.cs rename to src/Features/JsonPatch/src/Helpers/GetValueResult.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Helpers/JsonPatchProperty.cs b/src/Features/JsonPatch/src/Helpers/JsonPatchProperty.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Helpers/JsonPatchProperty.cs rename to src/Features/JsonPatch/src/Helpers/JsonPatchProperty.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/IJsonPatchDocument.cs b/src/Features/JsonPatch/src/IJsonPatchDocument.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/IJsonPatchDocument.cs rename to src/Features/JsonPatch/src/IJsonPatchDocument.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ConversionResult.cs b/src/Features/JsonPatch/src/Internal/ConversionResult.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Internal/ConversionResult.cs rename to src/Features/JsonPatch/src/Internal/ConversionResult.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ConversionResultProvider.cs b/src/Features/JsonPatch/src/Internal/ConversionResultProvider.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Internal/ConversionResultProvider.cs rename to src/Features/JsonPatch/src/Internal/ConversionResultProvider.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapterOfTU.cs b/src/Features/JsonPatch/src/Internal/DictionaryAdapterOfTU.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Internal/DictionaryAdapterOfTU.cs rename to src/Features/JsonPatch/src/Internal/DictionaryAdapterOfTU.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs b/src/Features/JsonPatch/src/Internal/DynamicObjectAdapter.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Internal/DynamicObjectAdapter.cs rename to src/Features/JsonPatch/src/Internal/DynamicObjectAdapter.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ErrorReporter.cs b/src/Features/JsonPatch/src/Internal/ErrorReporter.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Internal/ErrorReporter.cs rename to src/Features/JsonPatch/src/Internal/ErrorReporter.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/IAdapter.cs b/src/Features/JsonPatch/src/Internal/IAdapter.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Internal/IAdapter.cs rename to src/Features/JsonPatch/src/Internal/IAdapter.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs b/src/Features/JsonPatch/src/Internal/ListAdapter.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Internal/ListAdapter.cs rename to src/Features/JsonPatch/src/Internal/ListAdapter.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs b/src/Features/JsonPatch/src/Internal/ObjectVisitor.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs rename to src/Features/JsonPatch/src/Internal/ObjectVisitor.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ParsedPath.cs b/src/Features/JsonPatch/src/Internal/ParsedPath.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Internal/ParsedPath.cs rename to src/Features/JsonPatch/src/Internal/ParsedPath.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/PathHelpers.cs b/src/Features/JsonPatch/src/Internal/PathHelpers.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Internal/PathHelpers.cs rename to src/Features/JsonPatch/src/Internal/PathHelpers.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs b/src/Features/JsonPatch/src/Internal/PocoAdapter.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Internal/PocoAdapter.cs rename to src/Features/JsonPatch/src/Internal/PocoAdapter.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs b/src/Features/JsonPatch/src/JsonPatchDocument.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocument.cs rename to src/Features/JsonPatch/src/JsonPatchDocument.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs b/src/Features/JsonPatch/src/JsonPatchDocumentOfT.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/JsonPatchDocumentOfT.cs rename to src/Features/JsonPatch/src/JsonPatchDocumentOfT.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/JsonPatchError.cs b/src/Features/JsonPatch/src/JsonPatchError.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/JsonPatchError.cs rename to src/Features/JsonPatch/src/JsonPatchError.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj b/src/Features/JsonPatch/src/Microsoft.AspNetCore.JsonPatch.csproj similarity index 51% rename from src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj rename to src/Features/JsonPatch/src/Microsoft.AspNetCore.JsonPatch.csproj index 9bd08214f6..3708e92927 100644 --- a/src/Microsoft.AspNetCore.JsonPatch/Microsoft.AspNetCore.JsonPatch.csproj +++ b/src/Features/JsonPatch/src/Microsoft.AspNetCore.JsonPatch.csproj @@ -9,9 +9,9 @@ - - - + + + diff --git a/src/Microsoft.AspNetCore.JsonPatch/Operations/Operation.cs b/src/Features/JsonPatch/src/Operations/Operation.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Operations/Operation.cs rename to src/Features/JsonPatch/src/Operations/Operation.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationBase.cs b/src/Features/JsonPatch/src/Operations/OperationBase.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Operations/OperationBase.cs rename to src/Features/JsonPatch/src/Operations/OperationBase.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationOfT.cs b/src/Features/JsonPatch/src/Operations/OperationOfT.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Operations/OperationOfT.cs rename to src/Features/JsonPatch/src/Operations/OperationOfT.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Operations/OperationType.cs b/src/Features/JsonPatch/src/Operations/OperationType.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Operations/OperationType.cs rename to src/Features/JsonPatch/src/Operations/OperationType.cs diff --git a/src/Features/JsonPatch/src/Properties/AssemblyInfo.cs b/src/Features/JsonPatch/src/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..11fa956b64 --- /dev/null +++ b/src/Features/JsonPatch/src/Properties/AssemblyInfo.cs @@ -0,0 +1,7 @@ + +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.JsonPatch.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs b/src/Features/JsonPatch/src/Properties/Resources.Designer.cs similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Properties/Resources.Designer.cs rename to src/Features/JsonPatch/src/Properties/Resources.Designer.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Resources.resx b/src/Features/JsonPatch/src/Resources.resx similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/Resources.resx rename to src/Features/JsonPatch/src/Resources.resx diff --git a/src/Microsoft.AspNetCore.JsonPatch/baseline.netcore.json b/src/Features/JsonPatch/src/baseline.netcore.json similarity index 100% rename from src/Microsoft.AspNetCore.JsonPatch/baseline.netcore.json rename to src/Features/JsonPatch/src/baseline.netcore.json diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/CustomNamingStrategyTests.cs b/src/Features/JsonPatch/test/CustomNamingStrategyTests.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/CustomNamingStrategyTests.cs rename to src/Features/JsonPatch/test/CustomNamingStrategyTests.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/AnonymousObjectIntegrationTest.cs b/src/Features/JsonPatch/test/IntegrationTests/AnonymousObjectIntegrationTest.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/AnonymousObjectIntegrationTest.cs rename to src/Features/JsonPatch/test/IntegrationTests/AnonymousObjectIntegrationTest.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DictionaryIntegrationTest.cs b/src/Features/JsonPatch/test/IntegrationTests/DictionaryIntegrationTest.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DictionaryIntegrationTest.cs rename to src/Features/JsonPatch/test/IntegrationTests/DictionaryIntegrationTest.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DynamicObjectIntegrationTest.cs b/src/Features/JsonPatch/test/IntegrationTests/DynamicObjectIntegrationTest.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/DynamicObjectIntegrationTest.cs rename to src/Features/JsonPatch/test/IntegrationTests/DynamicObjectIntegrationTest.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/ExpandoObjectIntegrationTest.cs b/src/Features/JsonPatch/test/IntegrationTests/ExpandoObjectIntegrationTest.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/ExpandoObjectIntegrationTest.cs rename to src/Features/JsonPatch/test/IntegrationTests/ExpandoObjectIntegrationTest.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/ListIntegrationTest.cs b/src/Features/JsonPatch/test/IntegrationTests/ListIntegrationTest.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/ListIntegrationTest.cs rename to src/Features/JsonPatch/test/IntegrationTests/ListIntegrationTest.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/NestedObjectIntegrationTest.cs b/src/Features/JsonPatch/test/IntegrationTests/NestedObjectIntegrationTest.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/NestedObjectIntegrationTest.cs rename to src/Features/JsonPatch/test/IntegrationTests/NestedObjectIntegrationTest.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/SimpleObjectIntegrationTest.cs b/src/Features/JsonPatch/test/IntegrationTests/SimpleObjectIntegrationTest.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/SimpleObjectIntegrationTest.cs rename to src/Features/JsonPatch/test/IntegrationTests/SimpleObjectIntegrationTest.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/DictionaryAdapterTest.cs b/src/Features/JsonPatch/test/Internal/DictionaryAdapterTest.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/Internal/DictionaryAdapterTest.cs rename to src/Features/JsonPatch/test/Internal/DictionaryAdapterTest.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/DynamicObjectAdapterTest.cs b/src/Features/JsonPatch/test/Internal/DynamicObjectAdapterTest.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/Internal/DynamicObjectAdapterTest.cs rename to src/Features/JsonPatch/test/Internal/DynamicObjectAdapterTest.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ListAdapterTest.cs b/src/Features/JsonPatch/test/Internal/ListAdapterTest.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ListAdapterTest.cs rename to src/Features/JsonPatch/test/Internal/ListAdapterTest.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ObjectVisitorTest.cs b/src/Features/JsonPatch/test/Internal/ObjectVisitorTest.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ObjectVisitorTest.cs rename to src/Features/JsonPatch/test/Internal/ObjectVisitorTest.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ParsedPathTests.cs b/src/Features/JsonPatch/test/Internal/ParsedPathTests.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ParsedPathTests.cs rename to src/Features/JsonPatch/test/Internal/ParsedPathTests.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/PocoAdapterTest.cs b/src/Features/JsonPatch/test/Internal/PocoAdapterTest.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/Internal/PocoAdapterTest.cs rename to src/Features/JsonPatch/test/Internal/PocoAdapterTest.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentGetPathTest.cs b/src/Features/JsonPatch/test/JsonPatchDocumentGetPathTest.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentGetPathTest.cs rename to src/Features/JsonPatch/test/JsonPatchDocumentGetPathTest.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs b/src/Features/JsonPatch/test/JsonPatchDocumentJsonPropertyAttributeTest.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentJsonPropertyAttributeTest.cs rename to src/Features/JsonPatch/test/JsonPatchDocumentJsonPropertyAttributeTest.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs b/src/Features/JsonPatch/test/JsonPatchDocumentTest.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/JsonPatchDocumentTest.cs rename to src/Features/JsonPatch/test/JsonPatchDocumentTest.cs diff --git a/src/Features/JsonPatch/test/Microsoft.AspNetCore.JsonPatch.Tests.csproj b/src/Features/JsonPatch/test/Microsoft.AspNetCore.JsonPatch.Tests.csproj new file mode 100644 index 0000000000..5aca855c9c --- /dev/null +++ b/src/Features/JsonPatch/test/Microsoft.AspNetCore.JsonPatch.Tests.csproj @@ -0,0 +1,11 @@ + + + + netcoreapp2.1;net461 + + + + + + + diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/OperationBaseTests.cs b/src/Features/JsonPatch/test/OperationBaseTests.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/OperationBaseTests.cs rename to src/Features/JsonPatch/test/OperationBaseTests.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/TestErrorLogger.cs b/src/Features/JsonPatch/test/TestErrorLogger.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/TestErrorLogger.cs rename to src/Features/JsonPatch/test/TestErrorLogger.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/Customer.cs b/src/Features/JsonPatch/test/TestObjectModels/Customer.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/Customer.cs rename to src/Features/JsonPatch/test/TestObjectModels/Customer.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/DynamicTestObject.cs b/src/Features/JsonPatch/test/TestObjectModels/DynamicTestObject.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/DynamicTestObject.cs rename to src/Features/JsonPatch/test/TestObjectModels/DynamicTestObject.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/InheritedObject.cs b/src/Features/JsonPatch/test/TestObjectModels/InheritedObject.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/InheritedObject.cs rename to src/Features/JsonPatch/test/TestObjectModels/InheritedObject.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/NestedObject.cs b/src/Features/JsonPatch/test/TestObjectModels/NestedObject.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/NestedObject.cs rename to src/Features/JsonPatch/test/TestObjectModels/NestedObject.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/SimpleObject.cs b/src/Features/JsonPatch/test/TestObjectModels/SimpleObject.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/SimpleObject.cs rename to src/Features/JsonPatch/test/TestObjectModels/SimpleObject.cs diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/SimpleObjectWithNestedObject.cs b/src/Features/JsonPatch/test/TestObjectModels/SimpleObjectWithNestedObject.cs similarity index 100% rename from test/Microsoft.AspNetCore.JsonPatch.Test/TestObjectModels/SimpleObjectWithNestedObject.cs rename to src/Features/JsonPatch/test/TestObjectModels/SimpleObjectWithNestedObject.cs diff --git a/src/Microsoft.AspNetCore.JsonPatch/Properties/AssemblyInfo.cs b/src/Microsoft.AspNetCore.JsonPatch/Properties/AssemblyInfo.cs deleted file mode 100644 index 08e6f5e01c..0000000000 --- a/src/Microsoft.AspNetCore.JsonPatch/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,7 +0,0 @@ - -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Microsoft.AspNetCore.JsonPatch.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/test/Directory.Build.props b/test/Directory.Build.props deleted file mode 100644 index 98685a5e13..0000000000 --- a/test/Directory.Build.props +++ /dev/null @@ -1,18 +0,0 @@ - - - - - netcoreapp2.1 - $(DeveloperBuildTestTfms) - $(StandardTestTfms);netcoreapp2.0 - $(StandardTestTfms);net461 - - - - - - - - - - diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj b/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj deleted file mode 100644 index ce1d92802d..0000000000 --- a/test/Microsoft.AspNetCore.JsonPatch.Test/Microsoft.AspNetCore.JsonPatch.Test.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - $(StandardTestTfms) - - - - - - - - - - - - - - - - diff --git a/version.props b/version.props deleted file mode 100644 index 669c874829..0000000000 --- a/version.props +++ /dev/null @@ -1,12 +0,0 @@ - - - 2.1.1 - rtm - $(VersionPrefix) - $(VersionPrefix)-$(VersionSuffix)-final - t000 - a- - $(FeatureBranchVersionPrefix)$(VersionSuffix)-$([System.Text.RegularExpressions.Regex]::Replace('$(FeatureBranchVersionSuffix)', '[^\w-]', '-')) - $(VersionSuffix)-$(BuildNumber) - - From 59ed8df382a76b8a0d1b19853318614b87ed171d Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 9 Nov 2018 13:05:31 -0800 Subject: [PATCH 1005/1029] Add targets and tools for ensuring consistent package versions between servicing builds --- Directory.Build.props | 8 ++ Directory.Build.targets | 31 ++++ build/SharedFx.targets | 2 +- build/buildorder.props | 2 - build/dependencies.props | 1 + build/repo.props | 15 +- build/repo.targets | 44 +++++- build/submodules.props | 1 - build/tasks/RepoTasks.csproj | 1 + ...ch-updates.md => PreparingPatchUpdates.md} | 10 +- eng/Baseline.props | 100 +++++++++++++ eng/Dependencies.props | 46 ++++++ eng/PatchConfig.props | 13 ++ eng/ProjectReferences.props | 7 + eng/targets/CSharp.Common.props | 14 ++ eng/targets/CSharp.Common.targets | 5 + eng/targets/Packaging.targets | 30 ++++ eng/targets/ResolveReferences.targets | 135 ++++++++++++++++++ .../BaselineGenerator.csproj | 15 ++ eng/tools/BaselineGenerator/Program.cs | 132 +++++++++++++++++ eng/tools/BaselineGenerator/README.md | 10 ++ eng/tools/BaselineGenerator/baseline.xml | 13 ++ eng/tools/Directory.Build.props | 3 + eng/tools/Directory.Build.targets | 2 + eng/tools/tools.sln | 34 +++++ src/DataProtection/Directory.Build.props | 16 --- src/Packages/Directory.Build.props | 4 +- version.props | 5 + 28 files changed, 665 insertions(+), 34 deletions(-) rename docs/{preparing-patch-updates.md => PreparingPatchUpdates.md} (74%) create mode 100644 eng/Baseline.props create mode 100644 eng/Dependencies.props create mode 100644 eng/PatchConfig.props create mode 100644 eng/ProjectReferences.props create mode 100644 eng/targets/CSharp.Common.props create mode 100644 eng/targets/CSharp.Common.targets create mode 100644 eng/targets/Packaging.targets create mode 100644 eng/targets/ResolveReferences.targets create mode 100644 eng/tools/BaselineGenerator/BaselineGenerator.csproj create mode 100644 eng/tools/BaselineGenerator/Program.cs create mode 100644 eng/tools/BaselineGenerator/README.md create mode 100644 eng/tools/BaselineGenerator/baseline.xml create mode 100644 eng/tools/Directory.Build.props create mode 100644 eng/tools/Directory.Build.targets create mode 100644 eng/tools/tools.sln diff --git a/Directory.Build.props b/Directory.Build.props index bdb885cd9f..c0f5b99d35 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -34,5 +34,13 @@ true + + netcoreapp2.1;net461 + + + + + + diff --git a/Directory.Build.targets b/Directory.Build.targets index 30ce3e3322..052fb09136 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,9 +1,39 @@ + + $(AssemblyName) + false + + + + + + + true + $(PackagesInPatch.Contains(' $(PackageId);')) + + + + + true + + false + + + + + $(BaselinePackageVersion).0 + $(BaselinePackageVersion).0 + $(BaselinePackageVersion) + + true + + false + $(IsImplementationProject) true false @@ -14,4 +44,5 @@ + diff --git a/build/SharedFx.targets b/build/SharedFx.targets index 84d2aee45c..2ab7352634 100644 --- a/build/SharedFx.targets +++ b/build/SharedFx.targets @@ -33,7 +33,7 @@ - + $(_MetapackageSrcRoot)$(MetapackageName)\ $(_WorkRoot)pkg\$(MetapackageName)\ diff --git a/build/buildorder.props b/build/buildorder.props index 1cb0f6cec8..55aceb0800 100644 --- a/build/buildorder.props +++ b/build/buildorder.props @@ -7,7 +7,6 @@ - @@ -30,7 +29,6 @@ - diff --git a/build/dependencies.props b/build/dependencies.props index dda2ffa595..e0fdd5fcc2 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -15,6 +15,7 @@ $(KoreBuildVersion) $(KoreBuildVersion) + 2.1.3-rtm-15842 diff --git a/build/repo.props b/build/repo.props index ec2fe7ab7f..a44dd76881 100644 --- a/build/repo.props +++ b/build/repo.props @@ -2,9 +2,8 @@ true - false - - public + true + false false true @@ -42,6 +41,16 @@ + + + + + + diff --git a/build/repo.targets b/build/repo.targets index cde696935c..0c1125bd51 100644 --- a/build/repo.targets +++ b/build/repo.targets @@ -16,18 +16,52 @@ SetTeamCityBuildNumberToVersion;$(PrepareDependsOn);VerifyPackageArtifactConfig;VerifyExternalDependencyConfig;PrepareOutputPaths $(CleanDependsOn);CleanArtifacts;CleanRepoArtifacts - $(RestoreDependsOn);InstallDotNet - $(CompileDependsOn);BuildRepositories + $(RestoreDependsOn);InstallDotNet;RestoreProjects + $(CompileDependsOn);BuildProjects;PackProjects;BuildRepositories $(PackageDependsOn);BuildMetapackages;CheckExpectedPackagesExist - $(TestDependsOn);_TestRepositories - $(GetArtifactInfoDependsOn);ResolveRepoInfo + $(TestDependsOn);TestProjects;_TestRepositories + $(GetArtifactInfoDependsOn);GetProjectArtifactInfo;ResolveRepoInfo - + + + + + + + + $(MSBuildThisFileDirectory)..\eng\ProjectReferences.props + + + + + @(_ProjectReferenceProvider->'', '%0A ') + + + ]]> + + + + + + + + + + + + + + MicrosoftNETCoreAppPackageVersion=$(MicrosoftNETCoreAppPackageVersion); diff --git a/build/submodules.props b/build/submodules.props index 8b30d5efcb..8030fb219f 100644 --- a/build/submodules.props +++ b/build/submodules.props @@ -77,6 +77,5 @@ - diff --git a/build/tasks/RepoTasks.csproj b/build/tasks/RepoTasks.csproj index 6be1f375d2..20cbf6cce8 100644 --- a/build/tasks/RepoTasks.csproj +++ b/build/tasks/RepoTasks.csproj @@ -6,6 +6,7 @@ + diff --git a/docs/preparing-patch-updates.md b/docs/PreparingPatchUpdates.md similarity index 74% rename from docs/preparing-patch-updates.md rename to docs/PreparingPatchUpdates.md index 87821935de..34813e8162 100644 --- a/docs/preparing-patch-updates.md +++ b/docs/PreparingPatchUpdates.md @@ -10,11 +10,15 @@ In order to prepare this repo to build a new servicing update, the following cha + 8 ``` -* Update the package archive baselines. This is used to make sure each build - of the package archives we give to Azure only contains new files and does +* Update the package archive baselines. This is used to make sure each build of the package archives we give to Azure only contains new files and does not require overwriting existing files. See [src/PackageArchive/ZipManifestGenerator/](/src/PackageArchive/ZipManifestGenerator/README.md) for instructions on how to run this tool. -* Update the list of repositories which will contain changes in [build/submodules.props](/build/submodules.props). +* Update the package baselines. This is used to ensure packages keep a consistent set of dependencies between releases. + See [eng/tools/BaselineGenerator/](/eng/tools/BaselineGenerator/README.md) for instructions on how to run this tool. + +* **For packages with source code in this repo (not a submodule):** Update the list of packages in [eng/PatchConfig.props](/eng/PatchConfig.props) to list which packages should be patching in this release. + +* **For packages still building from submodules:** Update the list of repositories which will contain changes in [build/submodules.props](/build/submodules.props). * `` items represent repos which were released in a previous patch, and will not contain servicing updates in the next patch. * `` items represent repos which will produce new packages in this patch. diff --git a/eng/Baseline.props b/eng/Baseline.props new file mode 100644 index 0000000000..acae8786c0 --- /dev/null +++ b/eng/Baseline.props @@ -0,0 +1,100 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + 2.1.6 + + + + 2.1.1 + + + + + 2.1.1 + + + + + + + + + + 2.1.1 + + + + + + + + + + + + + + + 2.1.1 + + + + + 2.1.1 + + + + + + + + + 2.1.1 + + + + + + + + 2.1.1 + + + + + + + + 0.4.1 + + + + + + + + 2.1.1 + + + + + + + + 2.1.1 + + + + + + + + 2.1.1 + + + + + + + \ No newline at end of file diff --git a/eng/Dependencies.props b/eng/Dependencies.props new file mode 100644 index 0000000000..917b401b0a --- /dev/null +++ b/eng/Dependencies.props @@ -0,0 +1,46 @@ + + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eng/PatchConfig.props b/eng/PatchConfig.props new file mode 100644 index 0000000000..91e93a17fe --- /dev/null +++ b/eng/PatchConfig.props @@ -0,0 +1,13 @@ + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + + + + Microsoft.AspNetCore; + Microsoft.AspNetCore.Server.IISIntegration; + + + + diff --git a/eng/ProjectReferences.props b/eng/ProjectReferences.props new file mode 100644 index 0000000000..7381583fb8 --- /dev/null +++ b/eng/ProjectReferences.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/eng/targets/CSharp.Common.props b/eng/targets/CSharp.Common.props new file mode 100644 index 0000000000..b3fc97e2d9 --- /dev/null +++ b/eng/targets/CSharp.Common.props @@ -0,0 +1,14 @@ + + + + 7.2 + + + SHA256 + + + + + + + diff --git a/eng/targets/CSharp.Common.targets b/eng/targets/CSharp.Common.targets new file mode 100644 index 0000000000..a7f7b610b6 --- /dev/null +++ b/eng/targets/CSharp.Common.targets @@ -0,0 +1,5 @@ + + + + + diff --git a/eng/targets/Packaging.targets b/eng/targets/Packaging.targets new file mode 100644 index 0000000000..69ad343564 --- /dev/null +++ b/eng/targets/Packaging.targets @@ -0,0 +1,30 @@ + + + + + + + + + + + $(PackageOutputPath)$(PackageId).$(PackageVersion).nupkg + + + + + NuGetPackage + $(PackageId) + $(PackageVersion) + $(RepositoryRoot) + true + + + + diff --git a/eng/targets/ResolveReferences.targets b/eng/targets/ResolveReferences.targets new file mode 100644 index 0000000000..caf44207ee --- /dev/null +++ b/eng/targets/ResolveReferences.targets @@ -0,0 +1,135 @@ + + + + + ResolveCustomReferences; + $(ResolveReferencesDependsOn); + + + + + + true + true + true + false + + + true + true + false + + + + <_ImplicitPackageReference Include="@(PackageReference->WithMetadataValue('IsImplicitlyDefined', 'true'))" /> + <_ExplicitPackageReference Include="@(PackageReference)" Exclude="@(_ImplicitPackageReference)" /> + <_ExplicitPackageReference Remove="Internal.AspNetCore.Sdk" /> + + + + + <_ProjectReferenceByAssemblyName Condition="'$(UseProjectReferences)' == 'true'" + Include="@(ProjectReferenceProvider)" + Exclude="@(UnusedProjectReferenceProvider)" /> + + + + + + + + + + + + <_LatestPackageReferenceWithVersion Include="@(Reference)" Condition=" '$(UseLatestPackageReferences)' == 'true' "> + %(LatestPackageReference.Identity) + %(LatestPackageReference.Version) + + <_LatestPackageReferenceWithVersion Remove="@(_LatestPackageReferenceWithVersion)" Condition="'%(Id)' != '%(Identity)' " /> + + + + + + + <_BaselinePackageReferenceWithVersion Include="@(Reference)" Condition=" '$(IsServicingBuild)' == 'true' OR '$(UseLatestPackageReferences)' != 'true' "> + %(BaselinePackageReference.Identity) + %(BaselinePackageReference.Version) + + + <_BaselinePackageReferenceWithVersion Remove="@(_BaselinePackageReferenceWithVersion)" Condition="'%(Id)' != '%(Identity)' " /> + + + + + + + <_PrivatePackageReferenceWithVersion Include="@(Reference->WithMetadataValue('PrivateAssets', 'All'))"> + %(LatestPackageReference.Identity) + %(LatestPackageReference.Version) + + + <_PrivatePackageReferenceWithVersion Remove="@(_PrivatePackageReferenceWithVersion)" Condition="'%(Id)' != '%(Identity)' " /> + + + + + + + <_LatestPackageReferenceWithVersion Remove="@(_LatestPackageReferenceWithVersion)" /> + <_BaselinePackageReferenceWithVersion Remove="@(_BaselinePackageReferenceWithVersion)" /> + <_PrivatePackageReferenceWithVersion Remove="@(_PrivatePackageReferenceWithVersion)" /> + <_ImplicitPackageReference Remove="@(_ImplicitPackageReference)" /> + + + + + <_ExplicitPackageReference Remove="@(_ExplicitPackageReference)" /> + + + + + + + + + + <_TargetFramework Remove="@(_TargetFramework)" /> + <_TargetFramework Include="$(TargetFramework)" Condition="'$(TargetFramework)' != '' "/> + <_TargetFramework Include="$(TargetFrameworks)" Condition="'$(TargetFramework)' == '' "/> + + + + + + + + + + + $([MSBuild]::MakeRelative($(RepositoryRoot), $(MSBuildProjectFullPath))) + + + + diff --git a/eng/tools/BaselineGenerator/BaselineGenerator.csproj b/eng/tools/BaselineGenerator/BaselineGenerator.csproj new file mode 100644 index 0000000000..625777dbd2 --- /dev/null +++ b/eng/tools/BaselineGenerator/BaselineGenerator.csproj @@ -0,0 +1,15 @@ + + + + Exe + netcoreapp2.1 + -o "$(MSBuildThisFileDirectory)../../Baseline.props" + $(MSBuildProjectDirectory) + + + + + + + + diff --git a/eng/tools/BaselineGenerator/Program.cs b/eng/tools/BaselineGenerator/Program.cs new file mode 100644 index 0000000000..d3d753a5ba --- /dev/null +++ b/eng/tools/BaselineGenerator/Program.cs @@ -0,0 +1,132 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using System.Xml.Linq; +using Microsoft.Extensions.CommandLineUtils; +using NuGet.Packaging; +using NuGet.Packaging.Core; + +namespace PackageBaselineGenerator +{ + /// + /// This generates Baseline.props with information about the last RTM release. + /// + class Program : CommandLineApplication + { + static void Main(string[] args) + { + new Program().Execute(args); + } + + private readonly CommandOption _source; + private readonly CommandOption _output; + + public Program() + { + _source = Option("-s|--source ", "The NuGet v2 source of the package to fetch", CommandOptionType.SingleValue); + _output = Option("-o|--output ", "The generated file output path", CommandOptionType.SingleValue); + + Invoke = () => Run().GetAwaiter().GetResult(); + } + + private async Task Run() + { + var source = _source.HasValue() + ? _source.Value() + : "https://www.nuget.org/api/v2/package"; + + var packageCache = Environment.GetEnvironmentVariable("NUGET_PACKAGES") != null + ? Environment.GetEnvironmentVariable("NUGET_PACKAGES") + : Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget", "packages"); + + var tempDir = Path.Combine(Directory.GetCurrentDirectory(), "obj", "tmp"); + Directory.CreateDirectory(tempDir); + + var input = XDocument.Load(Path.Combine(Directory.GetCurrentDirectory(), "baseline.xml")); + + var output = _output.HasValue() + ? _output.Value() + : Path.Combine(Directory.GetCurrentDirectory(), "Baseline.props"); + + var baselineVersion = input.Root.Attribute("Version").Value; + + var doc = new XDocument( + new XComment(" Auto generated. Do not edit manually, use eng/tools/BaselineGenerator/ to recreate. "), + new XElement("Project", + new XElement("PropertyGroup", + new XElement("MSBuildAllProjects", "$(MSBuildAllProjects);$(MSBuildThisFileFullPath)"), + new XElement("AspNetCoreBaselineVersion", baselineVersion)))); + + var client = new HttpClient(); + + foreach (var pkg in input.Root.Descendants("Package")) + { + var id = pkg.Attribute("Id").Value; + var version = pkg.Attribute("Version").Value; + var packageFileName = $"{id}.{version}.nupkg"; + var nupkgPath = Path.Combine(packageCache, id.ToLowerInvariant(), version, packageFileName); + if (!File.Exists(nupkgPath)) + { + nupkgPath = Path.Combine(tempDir, packageFileName); + } + + if (!File.Exists(nupkgPath)) + { + var url = $"{source}/{id}/{version}"; + using (var file = File.Create(nupkgPath)) + { + Console.WriteLine($"Downloading {url}"); + var response = await client.GetStreamAsync(url); + await response.CopyToAsync(file); + } + } + + + using (var reader = new PackageArchiveReader(nupkgPath)) + { + var first = true; + foreach (var group in reader.NuspecReader.GetDependencyGroups()) + { + if (first) + { + first = false; + doc.Root.Add(new XComment($" Package: {id}")); + + var propertyGroup = new XElement("PropertyGroup", + new XAttribute("Condition", $" '$(PackageId)' == '{id}' "), + new XElement("BaselinePackageVersion", version)); + doc.Root.Add(propertyGroup); + } + + var itemGroup = new XElement("ItemGroup", new XAttribute("Condition", $" '$(PackageId)' == '{id}' AND '$(TargetFramework)' == '{group.TargetFramework.GetShortFolderName()}' ")); + doc.Root.Add(itemGroup); + + foreach (var dependency in group.Packages) + { + itemGroup.Add(new XElement("BaselinePackageReference", new XAttribute("Include", dependency.Id), new XAttribute("Version", dependency.VersionRange.ToString()))); + } + } + } + } + + var settings = new XmlWriterSettings + { + OmitXmlDeclaration = true, + Encoding = Encoding.UTF8, + Indent = true, + }; + using (var writer = XmlWriter.Create(output, settings)) + { + doc.Save(writer); + } + + return 0; + } + } +} diff --git a/eng/tools/BaselineGenerator/README.md b/eng/tools/BaselineGenerator/README.md new file mode 100644 index 0000000000..1afd97d1b5 --- /dev/null +++ b/eng/tools/BaselineGenerator/README.md @@ -0,0 +1,10 @@ +BaselineGenerator +================= + +This tool is used to generate an MSBuild file which sets the "baseline" against which servicing updates are built. + +## Usage + +1. Add to the [baseline.xml](./baseline.xml) a list of package ID's and their latest released versions. The source of this information can typically + be found in the build.xml file generated during ProdCon builds. See https://github.com/dotnet/versions/blob/master/build-info/dotnet/product/cli/release/2.1.6/build.xml for example. +2. Run `dotnet run` on this project. diff --git a/eng/tools/BaselineGenerator/baseline.xml b/eng/tools/BaselineGenerator/baseline.xml new file mode 100644 index 0000000000..3687f918d6 --- /dev/null +++ b/eng/tools/BaselineGenerator/baseline.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/eng/tools/Directory.Build.props b/eng/tools/Directory.Build.props new file mode 100644 index 0000000000..fda3ea0cbe --- /dev/null +++ b/eng/tools/Directory.Build.props @@ -0,0 +1,3 @@ + + + diff --git a/eng/tools/Directory.Build.targets b/eng/tools/Directory.Build.targets new file mode 100644 index 0000000000..f75adf7e4d --- /dev/null +++ b/eng/tools/Directory.Build.targets @@ -0,0 +1,2 @@ + + diff --git a/eng/tools/tools.sln b/eng/tools/tools.sln new file mode 100644 index 0000000000..527e47cbc3 --- /dev/null +++ b/eng/tools/tools.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BaselineGenerator", "BaselineGenerator\BaselineGenerator.csproj", "{CF76A947-3A72-4824-87E6-BF029D84218B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CF76A947-3A72-4824-87E6-BF029D84218B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CF76A947-3A72-4824-87E6-BF029D84218B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CF76A947-3A72-4824-87E6-BF029D84218B}.Debug|x64.ActiveCfg = Debug|Any CPU + {CF76A947-3A72-4824-87E6-BF029D84218B}.Debug|x64.Build.0 = Debug|Any CPU + {CF76A947-3A72-4824-87E6-BF029D84218B}.Debug|x86.ActiveCfg = Debug|Any CPU + {CF76A947-3A72-4824-87E6-BF029D84218B}.Debug|x86.Build.0 = Debug|Any CPU + {CF76A947-3A72-4824-87E6-BF029D84218B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CF76A947-3A72-4824-87E6-BF029D84218B}.Release|Any CPU.Build.0 = Release|Any CPU + {CF76A947-3A72-4824-87E6-BF029D84218B}.Release|x64.ActiveCfg = Release|Any CPU + {CF76A947-3A72-4824-87E6-BF029D84218B}.Release|x64.Build.0 = Release|Any CPU + {CF76A947-3A72-4824-87E6-BF029D84218B}.Release|x86.ActiveCfg = Release|Any CPU + {CF76A947-3A72-4824-87E6-BF029D84218B}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/src/DataProtection/Directory.Build.props b/src/DataProtection/Directory.Build.props index b18bd3713f..deb7bb4ee6 100644 --- a/src/DataProtection/Directory.Build.props +++ b/src/DataProtection/Directory.Build.props @@ -5,20 +5,4 @@ - - false - - - - - - - - - - - - - - diff --git a/src/Packages/Directory.Build.props b/src/Packages/Directory.Build.props index b917f91a06..fe11cd2f09 100644 --- a/src/Packages/Directory.Build.props +++ b/src/Packages/Directory.Build.props @@ -3,9 +3,7 @@ false + true - - - diff --git a/version.props b/version.props index 3e4178aafa..f0cbed211d 100644 --- a/version.props +++ b/version.props @@ -11,6 +11,8 @@ $(PreReleaseLabel)-$(BuildNumber) $(PreReleaseBrandingLabel) Build $(BuildNumber) + + true false true @@ -32,6 +34,9 @@ $(VersionSuffix)+$(VersionMetadata) release/$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion) + + + $(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).$([MSBuild]::Subtract($(AspNetCorePatchVersion), 1)) From 27a47d07c55256368c2fa4b44c1eb7fda94a1a4f Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 9 Nov 2018 13:06:13 -0800 Subject: [PATCH 1006/1029] Reorganize the src/WebSockets/ folder to follow new source code organization conventions --- src/Middleware/Middleware.sln | 120 +++++++++++++++ src/Middleware/WebSockets/README.md | 12 ++ .../AutobahnTestAppAspNet4.csproj.aspnet4 | 0 .../AutobahnTestAppAspNet4/EchoSocket.ashx | 0 .../AutobahnTestAppAspNet4/EchoSocket.ashx.cs | 0 .../Properties/AssemblyInfo.cs | 0 .../AutobahnTestAppAspNet4/Web.Debug.config | 0 .../AutobahnTestAppAspNet4/Web.Release.config | 0 .../samples/AutobahnTestAppAspNet4/Web.config | 0 .../AutobahnTestAppAspNet4/packages.config | 0 .../AutobahnTestAppAspNet4/wstest-spec.json | 0 .../AutobahnTestAppHttpListener/App.config | 0 .../AutobahnTestAppHttpListener.csproj.net461 | 0 .../AutobahnTestAppHttpListener/Program.cs | 0 .../Properties/AssemblyInfo.cs | 0 .../WebSockets/samples/EchoApp/EchoApp.csproj | 16 ++ .../WebSockets/samples/EchoApp/Program.cs | 0 .../EchoApp/Properties/launchSettings.json | 0 .../WebSockets/samples/EchoApp/Startup.cs | 0 .../samples/EchoApp/wwwroot/index.html | 0 .../WebSockets/samples/TestServer/App.config | 0 .../WebSockets/samples/TestServer/Program.cs | 0 .../TestServer/Properties/AssemblyInfo.cs | 0 .../samples/TestServer/TestServer.csproj | 0 .../WebSockets}/setup-wstest.ps1 | 0 .../WebSockets}/setup-wstest.sh | 0 .../src}/ExtendedWebSocketAcceptContext.cs | 0 .../WebSockets/src}/Internal/Constants.cs | 0 .../src}/Internal/HandshakeHelpers.cs | 0 .../Microsoft.AspNetCore.WebSockets.csproj | 6 +- .../WebSockets/src}/WebSocketMiddleware.cs | 0 .../src}/WebSocketMiddlewareExtensions.cs | 0 .../WebSockets/src}/WebSocketOptions.cs | 0 .../WebSockets/src}/baseline.netcore.json | 0 .../AutobahnTestApp/AutobahnTestApp.csproj | 22 +-- .../test/AutobahnTestApp/Program.cs | 0 .../Properties/launchSettings.json | 0 .../WebSockets/test/AutobahnTestApp/README.md | 0 .../test/AutobahnTestApp/Startup.cs | 0 .../TestResources/testCert.pfx | Bin .../TestResources/testCert.txt | 0 .../scripts/RunAutobahnTests.ps1 | 0 .../scripts/autobahn.spec.json | 0 .../Autobahn/AutobahnCaseResult.cs | 0 .../Autobahn/AutobahnExpectations.cs | 0 .../Autobahn/AutobahnResult.cs | 0 .../Autobahn/AutobahnServerResult.cs | 0 .../Autobahn/AutobahnSpec.cs | 0 .../Autobahn/AutobahnTester.cs | 0 .../ConformanceTests}/Autobahn/Executable.cs | 0 .../ConformanceTests}/Autobahn/Expectation.cs | 0 .../ConformanceTests}/Autobahn/ServerSpec.cs | 0 .../test/ConformanceTests}/Autobahn/Wstest.cs | 0 .../test/ConformanceTests}/AutobahnTests.cs | 0 .../test/ConformanceTests}/Helpers.cs | 0 .../test/ConformanceTests}/Http.config | 0 ...NetCore.WebSockets.ConformanceTests.csproj | 15 ++ .../SkipIfWsTestNotPresentAttribute.cs | 0 .../WebSockets/test/Directory.Build.props | 27 ++++ .../test/UnitTests}/BufferStream.cs | 0 .../test/UnitTests}/DuplexStream.cs | 0 .../test/UnitTests}/IWebHostPortExtensions.cs | 0 .../UnitTests}/KestrelWebSocketHelpers.cs | 0 ...crosoft.AspNetCore.WebSockets.Tests.csproj | 14 ++ .../test/UnitTests}/SendReceiveTests.cs | 0 .../UnitTests}/WebSocketMiddlewareTests.cs | 0 .../test/UnitTests}/WebSocketPair.cs | 0 src/WebSockets/.gitignore | 31 ---- src/WebSockets/Directory.Build.props | 20 --- src/WebSockets/Directory.Build.targets | 7 - src/WebSockets/NuGetPackageVerifier.json | 7 - src/WebSockets/README.md | 19 --- src/WebSockets/WebSockets.sln | 145 ------------------ src/WebSockets/build.cmd | 3 - src/WebSockets/build.sh | 7 - src/WebSockets/build/Key.snk | Bin 596 -> 0 bytes src/WebSockets/build/dependencies.props | 39 ----- src/WebSockets/build/repo.props | 18 --- src/WebSockets/build/repo.targets | 9 -- src/WebSockets/build/sources.props | 17 -- src/WebSockets/samples/EchoApp/EchoApp.csproj | 19 --- src/WebSockets/src/Directory.Build.props | 7 - src/WebSockets/test/Directory.Build.props | 22 --- ...pNetCore.WebSockets.ConformanceTest.csproj | 18 --- ...icrosoft.AspNetCore.WebSockets.Test.csproj | 21 --- src/WebSockets/version.props | 12 -- 86 files changed, 218 insertions(+), 435 deletions(-) create mode 100644 src/Middleware/Middleware.sln create mode 100644 src/Middleware/WebSockets/README.md rename src/{ => Middleware}/WebSockets/samples/AutobahnTestAppAspNet4/AutobahnTestAppAspNet4.csproj.aspnet4 (100%) rename src/{ => Middleware}/WebSockets/samples/AutobahnTestAppAspNet4/EchoSocket.ashx (100%) rename src/{ => Middleware}/WebSockets/samples/AutobahnTestAppAspNet4/EchoSocket.ashx.cs (100%) rename src/{ => Middleware}/WebSockets/samples/AutobahnTestAppAspNet4/Properties/AssemblyInfo.cs (100%) rename src/{ => Middleware}/WebSockets/samples/AutobahnTestAppAspNet4/Web.Debug.config (100%) rename src/{ => Middleware}/WebSockets/samples/AutobahnTestAppAspNet4/Web.Release.config (100%) rename src/{ => Middleware}/WebSockets/samples/AutobahnTestAppAspNet4/Web.config (100%) rename src/{ => Middleware}/WebSockets/samples/AutobahnTestAppAspNet4/packages.config (100%) rename src/{ => Middleware}/WebSockets/samples/AutobahnTestAppAspNet4/wstest-spec.json (100%) rename src/{ => Middleware}/WebSockets/samples/AutobahnTestAppHttpListener/App.config (100%) rename src/{ => Middleware}/WebSockets/samples/AutobahnTestAppHttpListener/AutobahnTestAppHttpListener.csproj.net461 (100%) rename src/{ => Middleware}/WebSockets/samples/AutobahnTestAppHttpListener/Program.cs (100%) rename src/{ => Middleware}/WebSockets/samples/AutobahnTestAppHttpListener/Properties/AssemblyInfo.cs (100%) create mode 100644 src/Middleware/WebSockets/samples/EchoApp/EchoApp.csproj rename src/{ => Middleware}/WebSockets/samples/EchoApp/Program.cs (100%) rename src/{ => Middleware}/WebSockets/samples/EchoApp/Properties/launchSettings.json (100%) rename src/{ => Middleware}/WebSockets/samples/EchoApp/Startup.cs (100%) rename src/{ => Middleware}/WebSockets/samples/EchoApp/wwwroot/index.html (100%) rename src/{ => Middleware}/WebSockets/samples/TestServer/App.config (100%) rename src/{ => Middleware}/WebSockets/samples/TestServer/Program.cs (100%) rename src/{ => Middleware}/WebSockets/samples/TestServer/Properties/AssemblyInfo.cs (100%) rename src/{ => Middleware}/WebSockets/samples/TestServer/TestServer.csproj (100%) rename src/{WebSockets/build => Middleware/WebSockets}/setup-wstest.ps1 (100%) rename src/{WebSockets/build => Middleware/WebSockets}/setup-wstest.sh (100%) mode change 100755 => 100644 rename src/{WebSockets/src/Microsoft.AspNetCore.WebSockets => Middleware/WebSockets/src}/ExtendedWebSocketAcceptContext.cs (100%) rename src/{WebSockets/src/Microsoft.AspNetCore.WebSockets => Middleware/WebSockets/src}/Internal/Constants.cs (100%) rename src/{WebSockets/src/Microsoft.AspNetCore.WebSockets => Middleware/WebSockets/src}/Internal/HandshakeHelpers.cs (100%) rename src/{WebSockets/src/Microsoft.AspNetCore.WebSockets => Middleware/WebSockets/src}/Microsoft.AspNetCore.WebSockets.csproj (54%) rename src/{WebSockets/src/Microsoft.AspNetCore.WebSockets => Middleware/WebSockets/src}/WebSocketMiddleware.cs (100%) rename src/{WebSockets/src/Microsoft.AspNetCore.WebSockets => Middleware/WebSockets/src}/WebSocketMiddlewareExtensions.cs (100%) rename src/{WebSockets/src/Microsoft.AspNetCore.WebSockets => Middleware/WebSockets/src}/WebSocketOptions.cs (100%) rename src/{WebSockets/src/Microsoft.AspNetCore.WebSockets => Middleware/WebSockets/src}/baseline.netcore.json (100%) rename src/{ => Middleware}/WebSockets/test/AutobahnTestApp/AutobahnTestApp.csproj (75%) rename src/{ => Middleware}/WebSockets/test/AutobahnTestApp/Program.cs (100%) rename src/{ => Middleware}/WebSockets/test/AutobahnTestApp/Properties/launchSettings.json (100%) rename src/{ => Middleware}/WebSockets/test/AutobahnTestApp/README.md (100%) rename src/{ => Middleware}/WebSockets/test/AutobahnTestApp/Startup.cs (100%) rename src/{ => Middleware}/WebSockets/test/AutobahnTestApp/TestResources/testCert.pfx (100%) rename src/{ => Middleware}/WebSockets/test/AutobahnTestApp/TestResources/testCert.txt (100%) rename src/{ => Middleware}/WebSockets/test/AutobahnTestApp/scripts/RunAutobahnTests.ps1 (100%) rename src/{ => Middleware}/WebSockets/test/AutobahnTestApp/scripts/autobahn.spec.json (100%) rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest => Middleware/WebSockets/test/ConformanceTests}/Autobahn/AutobahnCaseResult.cs (100%) rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest => Middleware/WebSockets/test/ConformanceTests}/Autobahn/AutobahnExpectations.cs (100%) rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest => Middleware/WebSockets/test/ConformanceTests}/Autobahn/AutobahnResult.cs (100%) rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest => Middleware/WebSockets/test/ConformanceTests}/Autobahn/AutobahnServerResult.cs (100%) rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest => Middleware/WebSockets/test/ConformanceTests}/Autobahn/AutobahnSpec.cs (100%) rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest => Middleware/WebSockets/test/ConformanceTests}/Autobahn/AutobahnTester.cs (100%) rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest => Middleware/WebSockets/test/ConformanceTests}/Autobahn/Executable.cs (100%) rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest => Middleware/WebSockets/test/ConformanceTests}/Autobahn/Expectation.cs (100%) rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest => Middleware/WebSockets/test/ConformanceTests}/Autobahn/ServerSpec.cs (100%) rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest => Middleware/WebSockets/test/ConformanceTests}/Autobahn/Wstest.cs (100%) rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest => Middleware/WebSockets/test/ConformanceTests}/AutobahnTests.cs (100%) rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest => Middleware/WebSockets/test/ConformanceTests}/Helpers.cs (100%) rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest => Middleware/WebSockets/test/ConformanceTests}/Http.config (100%) create mode 100644 src/Middleware/WebSockets/test/ConformanceTests/Microsoft.AspNetCore.WebSockets.ConformanceTests.csproj rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest => Middleware/WebSockets/test/ConformanceTests}/SkipIfWsTestNotPresentAttribute.cs (100%) create mode 100644 src/Middleware/WebSockets/test/Directory.Build.props rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.Test => Middleware/WebSockets/test/UnitTests}/BufferStream.cs (100%) rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.Test => Middleware/WebSockets/test/UnitTests}/DuplexStream.cs (100%) rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.Test => Middleware/WebSockets/test/UnitTests}/IWebHostPortExtensions.cs (100%) rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.Test => Middleware/WebSockets/test/UnitTests}/KestrelWebSocketHelpers.cs (100%) create mode 100644 src/Middleware/WebSockets/test/UnitTests/Microsoft.AspNetCore.WebSockets.Tests.csproj rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.Test => Middleware/WebSockets/test/UnitTests}/SendReceiveTests.cs (100%) rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.Test => Middleware/WebSockets/test/UnitTests}/WebSocketMiddlewareTests.cs (100%) rename src/{WebSockets/test/Microsoft.AspNetCore.WebSockets.Test => Middleware/WebSockets/test/UnitTests}/WebSocketPair.cs (100%) delete mode 100644 src/WebSockets/.gitignore delete mode 100644 src/WebSockets/Directory.Build.props delete mode 100644 src/WebSockets/Directory.Build.targets delete mode 100644 src/WebSockets/NuGetPackageVerifier.json delete mode 100644 src/WebSockets/README.md delete mode 100644 src/WebSockets/WebSockets.sln delete mode 100644 src/WebSockets/build.cmd delete mode 100755 src/WebSockets/build.sh delete mode 100644 src/WebSockets/build/Key.snk delete mode 100644 src/WebSockets/build/dependencies.props delete mode 100644 src/WebSockets/build/repo.props delete mode 100644 src/WebSockets/build/repo.targets delete mode 100644 src/WebSockets/build/sources.props delete mode 100644 src/WebSockets/samples/EchoApp/EchoApp.csproj delete mode 100644 src/WebSockets/src/Directory.Build.props delete mode 100644 src/WebSockets/test/Directory.Build.props delete mode 100644 src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Microsoft.AspNetCore.WebSockets.ConformanceTest.csproj delete mode 100644 src/WebSockets/test/Microsoft.AspNetCore.WebSockets.Test/Microsoft.AspNetCore.WebSockets.Test.csproj delete mode 100644 src/WebSockets/version.props diff --git a/src/Middleware/Middleware.sln b/src/Middleware/Middleware.sln new file mode 100644 index 0000000000..28a99b57c6 --- /dev/null +++ b/src/Middleware/Middleware.sln @@ -0,0 +1,120 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebSockets", "WebSockets", "{E0D9867D-C23D-43EB-8D9C-DE0398A25432}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{A86EE055-ACD3-4BAC-A51D-1B3C71067AE0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EchoApp", "WebSockets\samples\EchoApp\EchoApp.csproj", "{0792C20B-1D18-4D7C-9C0F-A6F45A0F378E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestServer", "WebSockets\samples\TestServer\TestServer.csproj", "{4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.WebSockets", "WebSockets\src\Microsoft.AspNetCore.WebSockets.csproj", "{BECAA6A1-1AA4-415E-ADF3-07C103333826}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutobahnTestApp", "WebSockets\test\AutobahnTestApp\AutobahnTestApp.csproj", "{76B25812-AAFB-45BA-A71A-24F0C654ADFB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.WebSockets.ConformanceTests", "WebSockets\test\ConformanceTests\Microsoft.AspNetCore.WebSockets.ConformanceTests.csproj", "{88BDEE69-4DE3-40B5-A478-677EA355FB52}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.WebSockets.Tests", "WebSockets\test\UnitTests\Microsoft.AspNetCore.WebSockets.Tests.csproj", "{93970702-1BDB-4A8C-B7F6-020294464BB6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0792C20B-1D18-4D7C-9C0F-A6F45A0F378E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0792C20B-1D18-4D7C-9C0F-A6F45A0F378E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0792C20B-1D18-4D7C-9C0F-A6F45A0F378E}.Debug|x64.ActiveCfg = Debug|Any CPU + {0792C20B-1D18-4D7C-9C0F-A6F45A0F378E}.Debug|x64.Build.0 = Debug|Any CPU + {0792C20B-1D18-4D7C-9C0F-A6F45A0F378E}.Debug|x86.ActiveCfg = Debug|Any CPU + {0792C20B-1D18-4D7C-9C0F-A6F45A0F378E}.Debug|x86.Build.0 = Debug|Any CPU + {0792C20B-1D18-4D7C-9C0F-A6F45A0F378E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0792C20B-1D18-4D7C-9C0F-A6F45A0F378E}.Release|Any CPU.Build.0 = Release|Any CPU + {0792C20B-1D18-4D7C-9C0F-A6F45A0F378E}.Release|x64.ActiveCfg = Release|Any CPU + {0792C20B-1D18-4D7C-9C0F-A6F45A0F378E}.Release|x64.Build.0 = Release|Any CPU + {0792C20B-1D18-4D7C-9C0F-A6F45A0F378E}.Release|x86.ActiveCfg = Release|Any CPU + {0792C20B-1D18-4D7C-9C0F-A6F45A0F378E}.Release|x86.Build.0 = Release|Any CPU + {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Debug|x64.ActiveCfg = Debug|Any CPU + {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Debug|x64.Build.0 = Debug|Any CPU + {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Debug|x86.ActiveCfg = Debug|Any CPU + {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Debug|x86.Build.0 = Debug|Any CPU + {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Release|Any CPU.ActiveCfg = Debug|Any CPU + {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Release|Any CPU.Build.0 = Debug|Any CPU + {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Release|x64.ActiveCfg = Debug|Any CPU + {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Release|x64.Build.0 = Debug|Any CPU + {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Release|x86.ActiveCfg = Debug|Any CPU + {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Release|x86.Build.0 = Debug|Any CPU + {BECAA6A1-1AA4-415E-ADF3-07C103333826}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BECAA6A1-1AA4-415E-ADF3-07C103333826}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BECAA6A1-1AA4-415E-ADF3-07C103333826}.Debug|x64.ActiveCfg = Debug|Any CPU + {BECAA6A1-1AA4-415E-ADF3-07C103333826}.Debug|x64.Build.0 = Debug|Any CPU + {BECAA6A1-1AA4-415E-ADF3-07C103333826}.Debug|x86.ActiveCfg = Debug|Any CPU + {BECAA6A1-1AA4-415E-ADF3-07C103333826}.Debug|x86.Build.0 = Debug|Any CPU + {BECAA6A1-1AA4-415E-ADF3-07C103333826}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BECAA6A1-1AA4-415E-ADF3-07C103333826}.Release|Any CPU.Build.0 = Release|Any CPU + {BECAA6A1-1AA4-415E-ADF3-07C103333826}.Release|x64.ActiveCfg = Release|Any CPU + {BECAA6A1-1AA4-415E-ADF3-07C103333826}.Release|x64.Build.0 = Release|Any CPU + {BECAA6A1-1AA4-415E-ADF3-07C103333826}.Release|x86.ActiveCfg = Release|Any CPU + {BECAA6A1-1AA4-415E-ADF3-07C103333826}.Release|x86.Build.0 = Release|Any CPU + {76B25812-AAFB-45BA-A71A-24F0C654ADFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {76B25812-AAFB-45BA-A71A-24F0C654ADFB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {76B25812-AAFB-45BA-A71A-24F0C654ADFB}.Debug|x64.ActiveCfg = Debug|Any CPU + {76B25812-AAFB-45BA-A71A-24F0C654ADFB}.Debug|x64.Build.0 = Debug|Any CPU + {76B25812-AAFB-45BA-A71A-24F0C654ADFB}.Debug|x86.ActiveCfg = Debug|Any CPU + {76B25812-AAFB-45BA-A71A-24F0C654ADFB}.Debug|x86.Build.0 = Debug|Any CPU + {76B25812-AAFB-45BA-A71A-24F0C654ADFB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {76B25812-AAFB-45BA-A71A-24F0C654ADFB}.Release|Any CPU.Build.0 = Release|Any CPU + {76B25812-AAFB-45BA-A71A-24F0C654ADFB}.Release|x64.ActiveCfg = Release|Any CPU + {76B25812-AAFB-45BA-A71A-24F0C654ADFB}.Release|x64.Build.0 = Release|Any CPU + {76B25812-AAFB-45BA-A71A-24F0C654ADFB}.Release|x86.ActiveCfg = Release|Any CPU + {76B25812-AAFB-45BA-A71A-24F0C654ADFB}.Release|x86.Build.0 = Release|Any CPU + {88BDEE69-4DE3-40B5-A478-677EA355FB52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {88BDEE69-4DE3-40B5-A478-677EA355FB52}.Debug|Any CPU.Build.0 = Debug|Any CPU + {88BDEE69-4DE3-40B5-A478-677EA355FB52}.Debug|x64.ActiveCfg = Debug|Any CPU + {88BDEE69-4DE3-40B5-A478-677EA355FB52}.Debug|x64.Build.0 = Debug|Any CPU + {88BDEE69-4DE3-40B5-A478-677EA355FB52}.Debug|x86.ActiveCfg = Debug|Any CPU + {88BDEE69-4DE3-40B5-A478-677EA355FB52}.Debug|x86.Build.0 = Debug|Any CPU + {88BDEE69-4DE3-40B5-A478-677EA355FB52}.Release|Any CPU.ActiveCfg = Release|Any CPU + {88BDEE69-4DE3-40B5-A478-677EA355FB52}.Release|Any CPU.Build.0 = Release|Any CPU + {88BDEE69-4DE3-40B5-A478-677EA355FB52}.Release|x64.ActiveCfg = Release|Any CPU + {88BDEE69-4DE3-40B5-A478-677EA355FB52}.Release|x64.Build.0 = Release|Any CPU + {88BDEE69-4DE3-40B5-A478-677EA355FB52}.Release|x86.ActiveCfg = Release|Any CPU + {88BDEE69-4DE3-40B5-A478-677EA355FB52}.Release|x86.Build.0 = Release|Any CPU + {93970702-1BDB-4A8C-B7F6-020294464BB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {93970702-1BDB-4A8C-B7F6-020294464BB6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {93970702-1BDB-4A8C-B7F6-020294464BB6}.Debug|x64.ActiveCfg = Debug|Any CPU + {93970702-1BDB-4A8C-B7F6-020294464BB6}.Debug|x64.Build.0 = Debug|Any CPU + {93970702-1BDB-4A8C-B7F6-020294464BB6}.Debug|x86.ActiveCfg = Debug|Any CPU + {93970702-1BDB-4A8C-B7F6-020294464BB6}.Debug|x86.Build.0 = Debug|Any CPU + {93970702-1BDB-4A8C-B7F6-020294464BB6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {93970702-1BDB-4A8C-B7F6-020294464BB6}.Release|Any CPU.Build.0 = Release|Any CPU + {93970702-1BDB-4A8C-B7F6-020294464BB6}.Release|x64.ActiveCfg = Release|Any CPU + {93970702-1BDB-4A8C-B7F6-020294464BB6}.Release|x64.Build.0 = Release|Any CPU + {93970702-1BDB-4A8C-B7F6-020294464BB6}.Release|x86.ActiveCfg = Release|Any CPU + {93970702-1BDB-4A8C-B7F6-020294464BB6}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {A86EE055-ACD3-4BAC-A51D-1B3C71067AE0} = {E0D9867D-C23D-43EB-8D9C-DE0398A25432} + {0792C20B-1D18-4D7C-9C0F-A6F45A0F378E} = {A86EE055-ACD3-4BAC-A51D-1B3C71067AE0} + {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B} = {A86EE055-ACD3-4BAC-A51D-1B3C71067AE0} + {BECAA6A1-1AA4-415E-ADF3-07C103333826} = {E0D9867D-C23D-43EB-8D9C-DE0398A25432} + {76B25812-AAFB-45BA-A71A-24F0C654ADFB} = {E0D9867D-C23D-43EB-8D9C-DE0398A25432} + {88BDEE69-4DE3-40B5-A478-677EA355FB52} = {E0D9867D-C23D-43EB-8D9C-DE0398A25432} + {93970702-1BDB-4A8C-B7F6-020294464BB6} = {E0D9867D-C23D-43EB-8D9C-DE0398A25432} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {83786312-A93B-4BB4-AB06-7C6913A59AFA} + EndGlobalSection +EndGlobal diff --git a/src/Middleware/WebSockets/README.md b/src/Middleware/WebSockets/README.md new file mode 100644 index 0000000000..19061a2ad5 --- /dev/null +++ b/src/Middleware/WebSockets/README.md @@ -0,0 +1,12 @@ +WebSockets +========== + +Contains a managed implementation of the WebSocket protocol, along with server integration components. + +## System Requirements + +This repo has a few special system requirements/prerequisites. + +1. Windows IIS Express tests require IIS Express 10 and Windows 8 for WebSockets support +2. HttpListener/ASP.NET 4.6 samples require at least Windows 8 +3. Autobahn Test Suite requires special installation see the README.md in [test/AutobahnTestApp](./test/AutobahnTestApp/README.md) diff --git a/src/WebSockets/samples/AutobahnTestAppAspNet4/AutobahnTestAppAspNet4.csproj.aspnet4 b/src/Middleware/WebSockets/samples/AutobahnTestAppAspNet4/AutobahnTestAppAspNet4.csproj.aspnet4 similarity index 100% rename from src/WebSockets/samples/AutobahnTestAppAspNet4/AutobahnTestAppAspNet4.csproj.aspnet4 rename to src/Middleware/WebSockets/samples/AutobahnTestAppAspNet4/AutobahnTestAppAspNet4.csproj.aspnet4 diff --git a/src/WebSockets/samples/AutobahnTestAppAspNet4/EchoSocket.ashx b/src/Middleware/WebSockets/samples/AutobahnTestAppAspNet4/EchoSocket.ashx similarity index 100% rename from src/WebSockets/samples/AutobahnTestAppAspNet4/EchoSocket.ashx rename to src/Middleware/WebSockets/samples/AutobahnTestAppAspNet4/EchoSocket.ashx diff --git a/src/WebSockets/samples/AutobahnTestAppAspNet4/EchoSocket.ashx.cs b/src/Middleware/WebSockets/samples/AutobahnTestAppAspNet4/EchoSocket.ashx.cs similarity index 100% rename from src/WebSockets/samples/AutobahnTestAppAspNet4/EchoSocket.ashx.cs rename to src/Middleware/WebSockets/samples/AutobahnTestAppAspNet4/EchoSocket.ashx.cs diff --git a/src/WebSockets/samples/AutobahnTestAppAspNet4/Properties/AssemblyInfo.cs b/src/Middleware/WebSockets/samples/AutobahnTestAppAspNet4/Properties/AssemblyInfo.cs similarity index 100% rename from src/WebSockets/samples/AutobahnTestAppAspNet4/Properties/AssemblyInfo.cs rename to src/Middleware/WebSockets/samples/AutobahnTestAppAspNet4/Properties/AssemblyInfo.cs diff --git a/src/WebSockets/samples/AutobahnTestAppAspNet4/Web.Debug.config b/src/Middleware/WebSockets/samples/AutobahnTestAppAspNet4/Web.Debug.config similarity index 100% rename from src/WebSockets/samples/AutobahnTestAppAspNet4/Web.Debug.config rename to src/Middleware/WebSockets/samples/AutobahnTestAppAspNet4/Web.Debug.config diff --git a/src/WebSockets/samples/AutobahnTestAppAspNet4/Web.Release.config b/src/Middleware/WebSockets/samples/AutobahnTestAppAspNet4/Web.Release.config similarity index 100% rename from src/WebSockets/samples/AutobahnTestAppAspNet4/Web.Release.config rename to src/Middleware/WebSockets/samples/AutobahnTestAppAspNet4/Web.Release.config diff --git a/src/WebSockets/samples/AutobahnTestAppAspNet4/Web.config b/src/Middleware/WebSockets/samples/AutobahnTestAppAspNet4/Web.config similarity index 100% rename from src/WebSockets/samples/AutobahnTestAppAspNet4/Web.config rename to src/Middleware/WebSockets/samples/AutobahnTestAppAspNet4/Web.config diff --git a/src/WebSockets/samples/AutobahnTestAppAspNet4/packages.config b/src/Middleware/WebSockets/samples/AutobahnTestAppAspNet4/packages.config similarity index 100% rename from src/WebSockets/samples/AutobahnTestAppAspNet4/packages.config rename to src/Middleware/WebSockets/samples/AutobahnTestAppAspNet4/packages.config diff --git a/src/WebSockets/samples/AutobahnTestAppAspNet4/wstest-spec.json b/src/Middleware/WebSockets/samples/AutobahnTestAppAspNet4/wstest-spec.json similarity index 100% rename from src/WebSockets/samples/AutobahnTestAppAspNet4/wstest-spec.json rename to src/Middleware/WebSockets/samples/AutobahnTestAppAspNet4/wstest-spec.json diff --git a/src/WebSockets/samples/AutobahnTestAppHttpListener/App.config b/src/Middleware/WebSockets/samples/AutobahnTestAppHttpListener/App.config similarity index 100% rename from src/WebSockets/samples/AutobahnTestAppHttpListener/App.config rename to src/Middleware/WebSockets/samples/AutobahnTestAppHttpListener/App.config diff --git a/src/WebSockets/samples/AutobahnTestAppHttpListener/AutobahnTestAppHttpListener.csproj.net461 b/src/Middleware/WebSockets/samples/AutobahnTestAppHttpListener/AutobahnTestAppHttpListener.csproj.net461 similarity index 100% rename from src/WebSockets/samples/AutobahnTestAppHttpListener/AutobahnTestAppHttpListener.csproj.net461 rename to src/Middleware/WebSockets/samples/AutobahnTestAppHttpListener/AutobahnTestAppHttpListener.csproj.net461 diff --git a/src/WebSockets/samples/AutobahnTestAppHttpListener/Program.cs b/src/Middleware/WebSockets/samples/AutobahnTestAppHttpListener/Program.cs similarity index 100% rename from src/WebSockets/samples/AutobahnTestAppHttpListener/Program.cs rename to src/Middleware/WebSockets/samples/AutobahnTestAppHttpListener/Program.cs diff --git a/src/WebSockets/samples/AutobahnTestAppHttpListener/Properties/AssemblyInfo.cs b/src/Middleware/WebSockets/samples/AutobahnTestAppHttpListener/Properties/AssemblyInfo.cs similarity index 100% rename from src/WebSockets/samples/AutobahnTestAppHttpListener/Properties/AssemblyInfo.cs rename to src/Middleware/WebSockets/samples/AutobahnTestAppHttpListener/Properties/AssemblyInfo.cs diff --git a/src/Middleware/WebSockets/samples/EchoApp/EchoApp.csproj b/src/Middleware/WebSockets/samples/EchoApp/EchoApp.csproj new file mode 100644 index 0000000000..cc5ea2afc1 --- /dev/null +++ b/src/Middleware/WebSockets/samples/EchoApp/EchoApp.csproj @@ -0,0 +1,16 @@ + + + + netcoreapp2.1;net461 + + + + + + + + + + + + diff --git a/src/WebSockets/samples/EchoApp/Program.cs b/src/Middleware/WebSockets/samples/EchoApp/Program.cs similarity index 100% rename from src/WebSockets/samples/EchoApp/Program.cs rename to src/Middleware/WebSockets/samples/EchoApp/Program.cs diff --git a/src/WebSockets/samples/EchoApp/Properties/launchSettings.json b/src/Middleware/WebSockets/samples/EchoApp/Properties/launchSettings.json similarity index 100% rename from src/WebSockets/samples/EchoApp/Properties/launchSettings.json rename to src/Middleware/WebSockets/samples/EchoApp/Properties/launchSettings.json diff --git a/src/WebSockets/samples/EchoApp/Startup.cs b/src/Middleware/WebSockets/samples/EchoApp/Startup.cs similarity index 100% rename from src/WebSockets/samples/EchoApp/Startup.cs rename to src/Middleware/WebSockets/samples/EchoApp/Startup.cs diff --git a/src/WebSockets/samples/EchoApp/wwwroot/index.html b/src/Middleware/WebSockets/samples/EchoApp/wwwroot/index.html similarity index 100% rename from src/WebSockets/samples/EchoApp/wwwroot/index.html rename to src/Middleware/WebSockets/samples/EchoApp/wwwroot/index.html diff --git a/src/WebSockets/samples/TestServer/App.config b/src/Middleware/WebSockets/samples/TestServer/App.config similarity index 100% rename from src/WebSockets/samples/TestServer/App.config rename to src/Middleware/WebSockets/samples/TestServer/App.config diff --git a/src/WebSockets/samples/TestServer/Program.cs b/src/Middleware/WebSockets/samples/TestServer/Program.cs similarity index 100% rename from src/WebSockets/samples/TestServer/Program.cs rename to src/Middleware/WebSockets/samples/TestServer/Program.cs diff --git a/src/WebSockets/samples/TestServer/Properties/AssemblyInfo.cs b/src/Middleware/WebSockets/samples/TestServer/Properties/AssemblyInfo.cs similarity index 100% rename from src/WebSockets/samples/TestServer/Properties/AssemblyInfo.cs rename to src/Middleware/WebSockets/samples/TestServer/Properties/AssemblyInfo.cs diff --git a/src/WebSockets/samples/TestServer/TestServer.csproj b/src/Middleware/WebSockets/samples/TestServer/TestServer.csproj similarity index 100% rename from src/WebSockets/samples/TestServer/TestServer.csproj rename to src/Middleware/WebSockets/samples/TestServer/TestServer.csproj diff --git a/src/WebSockets/build/setup-wstest.ps1 b/src/Middleware/WebSockets/setup-wstest.ps1 similarity index 100% rename from src/WebSockets/build/setup-wstest.ps1 rename to src/Middleware/WebSockets/setup-wstest.ps1 diff --git a/src/WebSockets/build/setup-wstest.sh b/src/Middleware/WebSockets/setup-wstest.sh old mode 100755 new mode 100644 similarity index 100% rename from src/WebSockets/build/setup-wstest.sh rename to src/Middleware/WebSockets/setup-wstest.sh diff --git a/src/WebSockets/src/Microsoft.AspNetCore.WebSockets/ExtendedWebSocketAcceptContext.cs b/src/Middleware/WebSockets/src/ExtendedWebSocketAcceptContext.cs similarity index 100% rename from src/WebSockets/src/Microsoft.AspNetCore.WebSockets/ExtendedWebSocketAcceptContext.cs rename to src/Middleware/WebSockets/src/ExtendedWebSocketAcceptContext.cs diff --git a/src/WebSockets/src/Microsoft.AspNetCore.WebSockets/Internal/Constants.cs b/src/Middleware/WebSockets/src/Internal/Constants.cs similarity index 100% rename from src/WebSockets/src/Microsoft.AspNetCore.WebSockets/Internal/Constants.cs rename to src/Middleware/WebSockets/src/Internal/Constants.cs diff --git a/src/WebSockets/src/Microsoft.AspNetCore.WebSockets/Internal/HandshakeHelpers.cs b/src/Middleware/WebSockets/src/Internal/HandshakeHelpers.cs similarity index 100% rename from src/WebSockets/src/Microsoft.AspNetCore.WebSockets/Internal/HandshakeHelpers.cs rename to src/Middleware/WebSockets/src/Internal/HandshakeHelpers.cs diff --git a/src/WebSockets/src/Microsoft.AspNetCore.WebSockets/Microsoft.AspNetCore.WebSockets.csproj b/src/Middleware/WebSockets/src/Microsoft.AspNetCore.WebSockets.csproj similarity index 54% rename from src/WebSockets/src/Microsoft.AspNetCore.WebSockets/Microsoft.AspNetCore.WebSockets.csproj rename to src/Middleware/WebSockets/src/Microsoft.AspNetCore.WebSockets.csproj index c5c5c8fbfb..5ff6bed15f 100644 --- a/src/WebSockets/src/Microsoft.AspNetCore.WebSockets/Microsoft.AspNetCore.WebSockets.csproj +++ b/src/Middleware/WebSockets/src/Microsoft.AspNetCore.WebSockets.csproj @@ -10,9 +10,9 @@ - - - + + + diff --git a/src/WebSockets/src/Microsoft.AspNetCore.WebSockets/WebSocketMiddleware.cs b/src/Middleware/WebSockets/src/WebSocketMiddleware.cs similarity index 100% rename from src/WebSockets/src/Microsoft.AspNetCore.WebSockets/WebSocketMiddleware.cs rename to src/Middleware/WebSockets/src/WebSocketMiddleware.cs diff --git a/src/WebSockets/src/Microsoft.AspNetCore.WebSockets/WebSocketMiddlewareExtensions.cs b/src/Middleware/WebSockets/src/WebSocketMiddlewareExtensions.cs similarity index 100% rename from src/WebSockets/src/Microsoft.AspNetCore.WebSockets/WebSocketMiddlewareExtensions.cs rename to src/Middleware/WebSockets/src/WebSocketMiddlewareExtensions.cs diff --git a/src/WebSockets/src/Microsoft.AspNetCore.WebSockets/WebSocketOptions.cs b/src/Middleware/WebSockets/src/WebSocketOptions.cs similarity index 100% rename from src/WebSockets/src/Microsoft.AspNetCore.WebSockets/WebSocketOptions.cs rename to src/Middleware/WebSockets/src/WebSocketOptions.cs diff --git a/src/WebSockets/src/Microsoft.AspNetCore.WebSockets/baseline.netcore.json b/src/Middleware/WebSockets/src/baseline.netcore.json similarity index 100% rename from src/WebSockets/src/Microsoft.AspNetCore.WebSockets/baseline.netcore.json rename to src/Middleware/WebSockets/src/baseline.netcore.json diff --git a/src/WebSockets/test/AutobahnTestApp/AutobahnTestApp.csproj b/src/Middleware/WebSockets/test/AutobahnTestApp/AutobahnTestApp.csproj similarity index 75% rename from src/WebSockets/test/AutobahnTestApp/AutobahnTestApp.csproj rename to src/Middleware/WebSockets/test/AutobahnTestApp/AutobahnTestApp.csproj index 175f724c74..5cd27d8a7e 100644 --- a/src/WebSockets/test/AutobahnTestApp/AutobahnTestApp.csproj +++ b/src/Middleware/WebSockets/test/AutobahnTestApp/AutobahnTestApp.csproj @@ -3,6 +3,7 @@ netcoreapp2.1 $(TargetFrameworks);netcoreapp2.0 + true @@ -10,21 +11,20 @@ - + + + + + + + + + + - - - - - - - - - - diff --git a/src/WebSockets/test/AutobahnTestApp/Program.cs b/src/Middleware/WebSockets/test/AutobahnTestApp/Program.cs similarity index 100% rename from src/WebSockets/test/AutobahnTestApp/Program.cs rename to src/Middleware/WebSockets/test/AutobahnTestApp/Program.cs diff --git a/src/WebSockets/test/AutobahnTestApp/Properties/launchSettings.json b/src/Middleware/WebSockets/test/AutobahnTestApp/Properties/launchSettings.json similarity index 100% rename from src/WebSockets/test/AutobahnTestApp/Properties/launchSettings.json rename to src/Middleware/WebSockets/test/AutobahnTestApp/Properties/launchSettings.json diff --git a/src/WebSockets/test/AutobahnTestApp/README.md b/src/Middleware/WebSockets/test/AutobahnTestApp/README.md similarity index 100% rename from src/WebSockets/test/AutobahnTestApp/README.md rename to src/Middleware/WebSockets/test/AutobahnTestApp/README.md diff --git a/src/WebSockets/test/AutobahnTestApp/Startup.cs b/src/Middleware/WebSockets/test/AutobahnTestApp/Startup.cs similarity index 100% rename from src/WebSockets/test/AutobahnTestApp/Startup.cs rename to src/Middleware/WebSockets/test/AutobahnTestApp/Startup.cs diff --git a/src/WebSockets/test/AutobahnTestApp/TestResources/testCert.pfx b/src/Middleware/WebSockets/test/AutobahnTestApp/TestResources/testCert.pfx similarity index 100% rename from src/WebSockets/test/AutobahnTestApp/TestResources/testCert.pfx rename to src/Middleware/WebSockets/test/AutobahnTestApp/TestResources/testCert.pfx diff --git a/src/WebSockets/test/AutobahnTestApp/TestResources/testCert.txt b/src/Middleware/WebSockets/test/AutobahnTestApp/TestResources/testCert.txt similarity index 100% rename from src/WebSockets/test/AutobahnTestApp/TestResources/testCert.txt rename to src/Middleware/WebSockets/test/AutobahnTestApp/TestResources/testCert.txt diff --git a/src/WebSockets/test/AutobahnTestApp/scripts/RunAutobahnTests.ps1 b/src/Middleware/WebSockets/test/AutobahnTestApp/scripts/RunAutobahnTests.ps1 similarity index 100% rename from src/WebSockets/test/AutobahnTestApp/scripts/RunAutobahnTests.ps1 rename to src/Middleware/WebSockets/test/AutobahnTestApp/scripts/RunAutobahnTests.ps1 diff --git a/src/WebSockets/test/AutobahnTestApp/scripts/autobahn.spec.json b/src/Middleware/WebSockets/test/AutobahnTestApp/scripts/autobahn.spec.json similarity index 100% rename from src/WebSockets/test/AutobahnTestApp/scripts/autobahn.spec.json rename to src/Middleware/WebSockets/test/AutobahnTestApp/scripts/autobahn.spec.json diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Autobahn/AutobahnCaseResult.cs b/src/Middleware/WebSockets/test/ConformanceTests/Autobahn/AutobahnCaseResult.cs similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Autobahn/AutobahnCaseResult.cs rename to src/Middleware/WebSockets/test/ConformanceTests/Autobahn/AutobahnCaseResult.cs diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Autobahn/AutobahnExpectations.cs b/src/Middleware/WebSockets/test/ConformanceTests/Autobahn/AutobahnExpectations.cs similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Autobahn/AutobahnExpectations.cs rename to src/Middleware/WebSockets/test/ConformanceTests/Autobahn/AutobahnExpectations.cs diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Autobahn/AutobahnResult.cs b/src/Middleware/WebSockets/test/ConformanceTests/Autobahn/AutobahnResult.cs similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Autobahn/AutobahnResult.cs rename to src/Middleware/WebSockets/test/ConformanceTests/Autobahn/AutobahnResult.cs diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Autobahn/AutobahnServerResult.cs b/src/Middleware/WebSockets/test/ConformanceTests/Autobahn/AutobahnServerResult.cs similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Autobahn/AutobahnServerResult.cs rename to src/Middleware/WebSockets/test/ConformanceTests/Autobahn/AutobahnServerResult.cs diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Autobahn/AutobahnSpec.cs b/src/Middleware/WebSockets/test/ConformanceTests/Autobahn/AutobahnSpec.cs similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Autobahn/AutobahnSpec.cs rename to src/Middleware/WebSockets/test/ConformanceTests/Autobahn/AutobahnSpec.cs diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Autobahn/AutobahnTester.cs b/src/Middleware/WebSockets/test/ConformanceTests/Autobahn/AutobahnTester.cs similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Autobahn/AutobahnTester.cs rename to src/Middleware/WebSockets/test/ConformanceTests/Autobahn/AutobahnTester.cs diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Autobahn/Executable.cs b/src/Middleware/WebSockets/test/ConformanceTests/Autobahn/Executable.cs similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Autobahn/Executable.cs rename to src/Middleware/WebSockets/test/ConformanceTests/Autobahn/Executable.cs diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Autobahn/Expectation.cs b/src/Middleware/WebSockets/test/ConformanceTests/Autobahn/Expectation.cs similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Autobahn/Expectation.cs rename to src/Middleware/WebSockets/test/ConformanceTests/Autobahn/Expectation.cs diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Autobahn/ServerSpec.cs b/src/Middleware/WebSockets/test/ConformanceTests/Autobahn/ServerSpec.cs similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Autobahn/ServerSpec.cs rename to src/Middleware/WebSockets/test/ConformanceTests/Autobahn/ServerSpec.cs diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Autobahn/Wstest.cs b/src/Middleware/WebSockets/test/ConformanceTests/Autobahn/Wstest.cs similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Autobahn/Wstest.cs rename to src/Middleware/WebSockets/test/ConformanceTests/Autobahn/Wstest.cs diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/AutobahnTests.cs b/src/Middleware/WebSockets/test/ConformanceTests/AutobahnTests.cs similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/AutobahnTests.cs rename to src/Middleware/WebSockets/test/ConformanceTests/AutobahnTests.cs diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Helpers.cs b/src/Middleware/WebSockets/test/ConformanceTests/Helpers.cs similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Helpers.cs rename to src/Middleware/WebSockets/test/ConformanceTests/Helpers.cs diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Http.config b/src/Middleware/WebSockets/test/ConformanceTests/Http.config similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Http.config rename to src/Middleware/WebSockets/test/ConformanceTests/Http.config diff --git a/src/Middleware/WebSockets/test/ConformanceTests/Microsoft.AspNetCore.WebSockets.ConformanceTests.csproj b/src/Middleware/WebSockets/test/ConformanceTests/Microsoft.AspNetCore.WebSockets.ConformanceTests.csproj new file mode 100644 index 0000000000..76281207ee --- /dev/null +++ b/src/Middleware/WebSockets/test/ConformanceTests/Microsoft.AspNetCore.WebSockets.ConformanceTests.csproj @@ -0,0 +1,15 @@ + + + + netcoreapp2.1 + $(TargetFrameworks);netcoreapp2.0 + + + + + + + + + + diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/SkipIfWsTestNotPresentAttribute.cs b/src/Middleware/WebSockets/test/ConformanceTests/SkipIfWsTestNotPresentAttribute.cs similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/SkipIfWsTestNotPresentAttribute.cs rename to src/Middleware/WebSockets/test/ConformanceTests/SkipIfWsTestNotPresentAttribute.cs diff --git a/src/Middleware/WebSockets/test/Directory.Build.props b/src/Middleware/WebSockets/test/Directory.Build.props new file mode 100644 index 0000000000..3e2de2026d --- /dev/null +++ b/src/Middleware/WebSockets/test/Directory.Build.props @@ -0,0 +1,27 @@ + + + + + + + true + + + + + + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 0.5.1 + 2.1.2 + 2.1.2 + 2.1.1 + + + diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.Test/BufferStream.cs b/src/Middleware/WebSockets/test/UnitTests/BufferStream.cs similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.Test/BufferStream.cs rename to src/Middleware/WebSockets/test/UnitTests/BufferStream.cs diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.Test/DuplexStream.cs b/src/Middleware/WebSockets/test/UnitTests/DuplexStream.cs similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.Test/DuplexStream.cs rename to src/Middleware/WebSockets/test/UnitTests/DuplexStream.cs diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.Test/IWebHostPortExtensions.cs b/src/Middleware/WebSockets/test/UnitTests/IWebHostPortExtensions.cs similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.Test/IWebHostPortExtensions.cs rename to src/Middleware/WebSockets/test/UnitTests/IWebHostPortExtensions.cs diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.Test/KestrelWebSocketHelpers.cs b/src/Middleware/WebSockets/test/UnitTests/KestrelWebSocketHelpers.cs similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.Test/KestrelWebSocketHelpers.cs rename to src/Middleware/WebSockets/test/UnitTests/KestrelWebSocketHelpers.cs diff --git a/src/Middleware/WebSockets/test/UnitTests/Microsoft.AspNetCore.WebSockets.Tests.csproj b/src/Middleware/WebSockets/test/UnitTests/Microsoft.AspNetCore.WebSockets.Tests.csproj new file mode 100644 index 0000000000..fc5fb268d5 --- /dev/null +++ b/src/Middleware/WebSockets/test/UnitTests/Microsoft.AspNetCore.WebSockets.Tests.csproj @@ -0,0 +1,14 @@ + + + + $(StandardTestTfms) + + + + + + + + + + diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.Test/SendReceiveTests.cs b/src/Middleware/WebSockets/test/UnitTests/SendReceiveTests.cs similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.Test/SendReceiveTests.cs rename to src/Middleware/WebSockets/test/UnitTests/SendReceiveTests.cs diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.Test/WebSocketMiddlewareTests.cs b/src/Middleware/WebSockets/test/UnitTests/WebSocketMiddlewareTests.cs similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.Test/WebSocketMiddlewareTests.cs rename to src/Middleware/WebSockets/test/UnitTests/WebSocketMiddlewareTests.cs diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.Test/WebSocketPair.cs b/src/Middleware/WebSockets/test/UnitTests/WebSocketPair.cs similarity index 100% rename from src/WebSockets/test/Microsoft.AspNetCore.WebSockets.Test/WebSocketPair.cs rename to src/Middleware/WebSockets/test/UnitTests/WebSocketPair.cs diff --git a/src/WebSockets/.gitignore b/src/WebSockets/.gitignore deleted file mode 100644 index 0e10f4aa54..0000000000 --- a/src/WebSockets/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -[Oo]bj/ -[Bb]in/ -TestResults/ -.nuget/ -_ReSharper.*/ -packages/ -artifacts/ -PublishProfiles/ -*.user -*.suo -*.cache -*.docstates -_ReSharper.* -nuget.exe -*net45.csproj -*k10.csproj -*.psess -*.vsp -*.pidb -*.userprefs -*DS_Store -*.ncrunchsolution -*.*sdf -*.ipch -*.sln.ide -/.vs/ -.testPublish/ -.build/ -autobahnreports/ -.vscode/ -global.json diff --git a/src/WebSockets/Directory.Build.props b/src/WebSockets/Directory.Build.props deleted file mode 100644 index 6c76a5608f..0000000000 --- a/src/WebSockets/Directory.Build.props +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - Microsoft ASP.NET Core - https://github.com/aspnet/WebSockets - git - $(MSBuildThisFileDirectory) - $(MSBuildThisFileDirectory)build\Key.snk - true - true - true - - diff --git a/src/WebSockets/Directory.Build.targets b/src/WebSockets/Directory.Build.targets deleted file mode 100644 index 53b3f6e1da..0000000000 --- a/src/WebSockets/Directory.Build.targets +++ /dev/null @@ -1,7 +0,0 @@ - - - $(MicrosoftNETCoreApp20PackageVersion) - $(MicrosoftNETCoreApp21PackageVersion) - $(NETStandardLibrary20PackageVersion) - - diff --git a/src/WebSockets/NuGetPackageVerifier.json b/src/WebSockets/NuGetPackageVerifier.json deleted file mode 100644 index b153ab1515..0000000000 --- a/src/WebSockets/NuGetPackageVerifier.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "Default": { - "rules": [ - "DefaultCompositeRule" - ] - } -} \ No newline at end of file diff --git a/src/WebSockets/README.md b/src/WebSockets/README.md deleted file mode 100644 index c7c69ee89b..0000000000 --- a/src/WebSockets/README.md +++ /dev/null @@ -1,19 +0,0 @@ -WebSockets -================ - -AppVeyor: [![AppVeyor](https://ci.appveyor.com/api/projects/status/lk5hyg6gki03hdqe/branch/dev?svg=true)](https://ci.appveyor.com/project/aspnetci/WebSockets/branch/dev) - -Travis: [![Travis](https://travis-ci.org/aspnet/WebSockets.svg?branch=dev)](https://travis-ci.org/aspnet/WebSockets) - -Contains a managed implementation of the WebSocket protocol, along with server integration components. - -This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo. - - -## System Requirements - -This repo has a few special system requirements/prerequisites. - -1. Windows IIS Express tests require IIS Express 10 and Windows 8 for WebSockets support -2. HttpListener/ASP.NET 4.6 samples require at least Windows 8 -3. Autobahn Test Suite requires special installation see the README.md in test/AutobahnTestApp diff --git a/src/WebSockets/WebSockets.sln b/src/WebSockets/WebSockets.sln deleted file mode 100644 index 6977d2812e..0000000000 --- a/src/WebSockets/WebSockets.sln +++ /dev/null @@ -1,145 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26730.10 -MinimumVisualStudioVersion = 15.0.26730.03 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{2C7947A5-9FBD-4267-97C1-2D726D7B3BAF}" - ProjectSection(SolutionItems) = preProject - src\Directory.Build.props = src\Directory.Build.props - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{C45106D0-76C8-4776-A140-F7DD83CA2958}" - ProjectSection(SolutionItems) = preProject - test\Directory.Build.props = test\Directory.Build.props - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{9E55FC5B-FD9C-4266-AB24-F3AA649D7C8B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestServer", "samples\TestServer\TestServer.csproj", "{4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{19595D64-E42E-46FD-AB2E-BDC870724EE7}" - ProjectSection(SolutionItems) = preProject - scripts\UpdateCoreFxCode.ps1 = scripts\UpdateCoreFxCode.ps1 - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.WebSockets", "src\Microsoft.AspNetCore.WebSockets\Microsoft.AspNetCore.WebSockets.csproj", "{CDE16880-0374-46FA-8896-99F1B90B4B6F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.WebSockets.Test", "test\Microsoft.AspNetCore.WebSockets.Test\Microsoft.AspNetCore.WebSockets.Test.csproj", "{5AFA74F5-9B1D-4FC5-815F-EF471F5AC1EF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.WebSockets.ConformanceTest", "test\Microsoft.AspNetCore.WebSockets.ConformanceTest\Microsoft.AspNetCore.WebSockets.ConformanceTest.csproj", "{74F45408-1959-4FEE-9511-25D40F4913FD}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EchoApp", "samples\EchoApp\EchoApp.csproj", "{421954B0-5C6B-4092-8D4D-EACA4CE60AFB}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutobahnTestApp", "test\AutobahnTestApp\AutobahnTestApp.csproj", "{150DF5A8-87C6-42F7-8886-CE07BFD02FD2}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{92CE12E6-E127-433B-96D3-164C0113EA17}" - ProjectSection(SolutionItems) = preProject - build\dependencies.props = build\dependencies.props - build\Key.snk = build\Key.snk - build\repo.props = build\repo.props - build\repo.targets = build\repo.targets - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7A963B09-471B-4D67-B5C0-6039AF0C39EE}" - ProjectSection(SolutionItems) = preProject - Directory.Build.props = Directory.Build.props - Directory.Build.targets = Directory.Build.targets - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Debug|x64.ActiveCfg = Debug|Any CPU - {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Debug|x64.Build.0 = Debug|Any CPU - {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Debug|x86.ActiveCfg = Debug|Any CPU - {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Debug|x86.Build.0 = Debug|Any CPU - {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Release|Any CPU.Build.0 = Release|Any CPU - {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Release|x64.ActiveCfg = Release|Any CPU - {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Release|x64.Build.0 = Release|Any CPU - {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Release|x86.ActiveCfg = Release|Any CPU - {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B}.Release|x86.Build.0 = Release|Any CPU - {CDE16880-0374-46FA-8896-99F1B90B4B6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CDE16880-0374-46FA-8896-99F1B90B4B6F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CDE16880-0374-46FA-8896-99F1B90B4B6F}.Debug|x64.ActiveCfg = Debug|Any CPU - {CDE16880-0374-46FA-8896-99F1B90B4B6F}.Debug|x64.Build.0 = Debug|Any CPU - {CDE16880-0374-46FA-8896-99F1B90B4B6F}.Debug|x86.ActiveCfg = Debug|Any CPU - {CDE16880-0374-46FA-8896-99F1B90B4B6F}.Debug|x86.Build.0 = Debug|Any CPU - {CDE16880-0374-46FA-8896-99F1B90B4B6F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CDE16880-0374-46FA-8896-99F1B90B4B6F}.Release|Any CPU.Build.0 = Release|Any CPU - {CDE16880-0374-46FA-8896-99F1B90B4B6F}.Release|x64.ActiveCfg = Release|Any CPU - {CDE16880-0374-46FA-8896-99F1B90B4B6F}.Release|x64.Build.0 = Release|Any CPU - {CDE16880-0374-46FA-8896-99F1B90B4B6F}.Release|x86.ActiveCfg = Release|Any CPU - {CDE16880-0374-46FA-8896-99F1B90B4B6F}.Release|x86.Build.0 = Release|Any CPU - {5AFA74F5-9B1D-4FC5-815F-EF471F5AC1EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5AFA74F5-9B1D-4FC5-815F-EF471F5AC1EF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5AFA74F5-9B1D-4FC5-815F-EF471F5AC1EF}.Debug|x64.ActiveCfg = Debug|Any CPU - {5AFA74F5-9B1D-4FC5-815F-EF471F5AC1EF}.Debug|x64.Build.0 = Debug|Any CPU - {5AFA74F5-9B1D-4FC5-815F-EF471F5AC1EF}.Debug|x86.ActiveCfg = Debug|Any CPU - {5AFA74F5-9B1D-4FC5-815F-EF471F5AC1EF}.Debug|x86.Build.0 = Debug|Any CPU - {5AFA74F5-9B1D-4FC5-815F-EF471F5AC1EF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5AFA74F5-9B1D-4FC5-815F-EF471F5AC1EF}.Release|Any CPU.Build.0 = Release|Any CPU - {5AFA74F5-9B1D-4FC5-815F-EF471F5AC1EF}.Release|x64.ActiveCfg = Release|Any CPU - {5AFA74F5-9B1D-4FC5-815F-EF471F5AC1EF}.Release|x64.Build.0 = Release|Any CPU - {5AFA74F5-9B1D-4FC5-815F-EF471F5AC1EF}.Release|x86.ActiveCfg = Release|Any CPU - {5AFA74F5-9B1D-4FC5-815F-EF471F5AC1EF}.Release|x86.Build.0 = Release|Any CPU - {74F45408-1959-4FEE-9511-25D40F4913FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {74F45408-1959-4FEE-9511-25D40F4913FD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {74F45408-1959-4FEE-9511-25D40F4913FD}.Debug|x64.ActiveCfg = Debug|Any CPU - {74F45408-1959-4FEE-9511-25D40F4913FD}.Debug|x64.Build.0 = Debug|Any CPU - {74F45408-1959-4FEE-9511-25D40F4913FD}.Debug|x86.ActiveCfg = Debug|Any CPU - {74F45408-1959-4FEE-9511-25D40F4913FD}.Debug|x86.Build.0 = Debug|Any CPU - {74F45408-1959-4FEE-9511-25D40F4913FD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {74F45408-1959-4FEE-9511-25D40F4913FD}.Release|Any CPU.Build.0 = Release|Any CPU - {74F45408-1959-4FEE-9511-25D40F4913FD}.Release|x64.ActiveCfg = Release|Any CPU - {74F45408-1959-4FEE-9511-25D40F4913FD}.Release|x64.Build.0 = Release|Any CPU - {74F45408-1959-4FEE-9511-25D40F4913FD}.Release|x86.ActiveCfg = Release|Any CPU - {74F45408-1959-4FEE-9511-25D40F4913FD}.Release|x86.Build.0 = Release|Any CPU - {421954B0-5C6B-4092-8D4D-EACA4CE60AFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {421954B0-5C6B-4092-8D4D-EACA4CE60AFB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {421954B0-5C6B-4092-8D4D-EACA4CE60AFB}.Debug|x64.ActiveCfg = Debug|Any CPU - {421954B0-5C6B-4092-8D4D-EACA4CE60AFB}.Debug|x64.Build.0 = Debug|Any CPU - {421954B0-5C6B-4092-8D4D-EACA4CE60AFB}.Debug|x86.ActiveCfg = Debug|Any CPU - {421954B0-5C6B-4092-8D4D-EACA4CE60AFB}.Debug|x86.Build.0 = Debug|Any CPU - {421954B0-5C6B-4092-8D4D-EACA4CE60AFB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {421954B0-5C6B-4092-8D4D-EACA4CE60AFB}.Release|Any CPU.Build.0 = Release|Any CPU - {421954B0-5C6B-4092-8D4D-EACA4CE60AFB}.Release|x64.ActiveCfg = Release|Any CPU - {421954B0-5C6B-4092-8D4D-EACA4CE60AFB}.Release|x64.Build.0 = Release|Any CPU - {421954B0-5C6B-4092-8D4D-EACA4CE60AFB}.Release|x86.ActiveCfg = Release|Any CPU - {421954B0-5C6B-4092-8D4D-EACA4CE60AFB}.Release|x86.Build.0 = Release|Any CPU - {150DF5A8-87C6-42F7-8886-CE07BFD02FD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {150DF5A8-87C6-42F7-8886-CE07BFD02FD2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {150DF5A8-87C6-42F7-8886-CE07BFD02FD2}.Debug|x64.ActiveCfg = Debug|Any CPU - {150DF5A8-87C6-42F7-8886-CE07BFD02FD2}.Debug|x64.Build.0 = Debug|Any CPU - {150DF5A8-87C6-42F7-8886-CE07BFD02FD2}.Debug|x86.ActiveCfg = Debug|Any CPU - {150DF5A8-87C6-42F7-8886-CE07BFD02FD2}.Debug|x86.Build.0 = Debug|Any CPU - {150DF5A8-87C6-42F7-8886-CE07BFD02FD2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {150DF5A8-87C6-42F7-8886-CE07BFD02FD2}.Release|Any CPU.Build.0 = Release|Any CPU - {150DF5A8-87C6-42F7-8886-CE07BFD02FD2}.Release|x64.ActiveCfg = Release|Any CPU - {150DF5A8-87C6-42F7-8886-CE07BFD02FD2}.Release|x64.Build.0 = Release|Any CPU - {150DF5A8-87C6-42F7-8886-CE07BFD02FD2}.Release|x86.ActiveCfg = Release|Any CPU - {150DF5A8-87C6-42F7-8886-CE07BFD02FD2}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {4E5F5FCC-172C-44D9-BEA0-39098A79CD0B} = {9E55FC5B-FD9C-4266-AB24-F3AA649D7C8B} - {CDE16880-0374-46FA-8896-99F1B90B4B6F} = {2C7947A5-9FBD-4267-97C1-2D726D7B3BAF} - {5AFA74F5-9B1D-4FC5-815F-EF471F5AC1EF} = {C45106D0-76C8-4776-A140-F7DD83CA2958} - {74F45408-1959-4FEE-9511-25D40F4913FD} = {C45106D0-76C8-4776-A140-F7DD83CA2958} - {421954B0-5C6B-4092-8D4D-EACA4CE60AFB} = {9E55FC5B-FD9C-4266-AB24-F3AA649D7C8B} - {150DF5A8-87C6-42F7-8886-CE07BFD02FD2} = {C45106D0-76C8-4776-A140-F7DD83CA2958} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {D3542868-F8C6-401B-8071-37FE3C981604} - EndGlobalSection -EndGlobal diff --git a/src/WebSockets/build.cmd b/src/WebSockets/build.cmd deleted file mode 100644 index f4169ea5e4..0000000000 --- a/src/WebSockets/build.cmd +++ /dev/null @@ -1,3 +0,0 @@ -@ECHO OFF -SET RepoRoot="%~dp0..\.." -%RepoRoot%\build.cmd -LockFile %RepoRoot%\korebuild-lock.txt -Path %~dp0 %* diff --git a/src/WebSockets/build.sh b/src/WebSockets/build.sh deleted file mode 100755 index d5bb0cf631..0000000000 --- a/src/WebSockets/build.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -repo_root="$DIR/../.." -"$repo_root/build.sh" --path "$DIR" --lockfile "$repo_root/korebuild-lock.txt" "$@" diff --git a/src/WebSockets/build/Key.snk b/src/WebSockets/build/Key.snk deleted file mode 100644 index e10e4889c125d3120cd9e81582243d70f7cbb806..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098=Iw=HCsnz~#iVhm& zj%TU(_THUee?3yHBjk$37ysB?i5#7WD$={H zV4B!OxRPrb|8)HPg~A}8P>^=#y<)56#=E&NzcjOtPK~<4n6GHt=K$ro*T(lhby_@U zEk(hLzk1H)0yXj{A_5>fk-TgNoP|q6(tP2xo8zt8i%212CWM#AeCd?`hS|4~L({h~Moo(~vy&3Z z1uI}`fd^*>o=rwbAGymj6RM^pZm(*Kfhs+Y1#`-2JPWZMK8@;ZWCk2+9bX4YP);~fj-BU*R zQPvWv$89!{Rl9wM+zR>_TSkn^voYxA?2G iKnV#iZ6Ah`K>b=@=IjYJXrxL124zR(38)nxe+&q_$QXwJ diff --git a/src/WebSockets/build/dependencies.props b/src/WebSockets/build/dependencies.props deleted file mode 100644 index 6d1c938c0c..0000000000 --- a/src/WebSockets/build/dependencies.props +++ /dev/null @@ -1,39 +0,0 @@ - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - - - - 2.1.3-rtm-15802 - 2.0.0 - 2.1.2 - 15.6.1 - 2.0.3 - 4.5.1 - 2.3.1 - 2.4.0-beta.1.build3945 - - - - - - - - 2.1.1 - 2.1.1 - 2.1.1 - 2.1.1 - 2.1.1 - 0.5.1 - 2.1.2 - 2.1.2 - 2.1.1 - 2.1.0 - 2.1.1 - 2.1.1 - 2.1.1 - 2.1.1 - 2.1.1 - - \ No newline at end of file diff --git a/src/WebSockets/build/repo.props b/src/WebSockets/build/repo.props deleted file mode 100644 index de99df697a..0000000000 --- a/src/WebSockets/build/repo.props +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - Internal.AspNetCore.Universe.Lineup - 2.1.0-rc1-* - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json - - - - - - - diff --git a/src/WebSockets/build/repo.targets b/src/WebSockets/build/repo.targets deleted file mode 100644 index 1767331014..0000000000 --- a/src/WebSockets/build/repo.targets +++ /dev/null @@ -1,9 +0,0 @@ - - - $(ArtifactsDir)autobahnreports\ - - - - - - diff --git a/src/WebSockets/build/sources.props b/src/WebSockets/build/sources.props deleted file mode 100644 index 9215df9751..0000000000 --- a/src/WebSockets/build/sources.props +++ /dev/null @@ -1,17 +0,0 @@ - - - - - $(DotNetRestoreSources) - - $(RestoreSources); - https://dotnet.myget.org/F/dotnet-core/api/v3/index.json; - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; - https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; - - - $(RestoreSources); - https://api.nuget.org/v3/index.json; - - - diff --git a/src/WebSockets/samples/EchoApp/EchoApp.csproj b/src/WebSockets/samples/EchoApp/EchoApp.csproj deleted file mode 100644 index f5696ccf03..0000000000 --- a/src/WebSockets/samples/EchoApp/EchoApp.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - netcoreapp2.1;net461 - - - - - - - - - - - - - - - diff --git a/src/WebSockets/src/Directory.Build.props b/src/WebSockets/src/Directory.Build.props deleted file mode 100644 index 1e0980f663..0000000000 --- a/src/WebSockets/src/Directory.Build.props +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/WebSockets/test/Directory.Build.props b/src/WebSockets/test/Directory.Build.props deleted file mode 100644 index be781a6b15..0000000000 --- a/src/WebSockets/test/Directory.Build.props +++ /dev/null @@ -1,22 +0,0 @@ - - - - - netcoreapp2.1 - $(DeveloperBuildTestTfms) - netcoreapp2.1;netcoreapp2.0 - $(StandardTestTfms);net461 - - - - - true - - - - - - diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Microsoft.AspNetCore.WebSockets.ConformanceTest.csproj b/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Microsoft.AspNetCore.WebSockets.ConformanceTest.csproj deleted file mode 100644 index 79e3839b12..0000000000 --- a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.ConformanceTest/Microsoft.AspNetCore.WebSockets.ConformanceTest.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - netcoreapp2.1 - $(TargetFrameworks);netcoreapp2.0 - - - - - - - - - - - - - diff --git a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.Test/Microsoft.AspNetCore.WebSockets.Test.csproj b/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.Test/Microsoft.AspNetCore.WebSockets.Test.csproj deleted file mode 100644 index c906aa0f91..0000000000 --- a/src/WebSockets/test/Microsoft.AspNetCore.WebSockets.Test/Microsoft.AspNetCore.WebSockets.Test.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - $(StandardTestTfms) - - - - - - - - - - - - - - - - - diff --git a/src/WebSockets/version.props b/src/WebSockets/version.props deleted file mode 100644 index 669c874829..0000000000 --- a/src/WebSockets/version.props +++ /dev/null @@ -1,12 +0,0 @@ - - - 2.1.1 - rtm - $(VersionPrefix) - $(VersionPrefix)-$(VersionSuffix)-final - t000 - a- - $(FeatureBranchVersionPrefix)$(VersionSuffix)-$([System.Text.RegularExpressions.Regex]::Replace('$(FeatureBranchVersionSuffix)', '[^\w-]', '-')) - $(VersionSuffix)-$(BuildNumber) - - From 32622d1a0afdd4387e89d454c555a85729451933 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 9 Nov 2018 13:06:34 -0800 Subject: [PATCH 1007/1029] Remove the JsonPatch git submodule --- .gitmodules | 4 ---- modules/JsonPatch | 1 - 2 files changed, 5 deletions(-) delete mode 160000 modules/JsonPatch diff --git a/.gitmodules b/.gitmodules index 76458daf89..5eaf7683cc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -66,10 +66,6 @@ path = modules/JavaScriptServices url = https://github.com/aspnet/JavaScriptServices.git branch = release/2.1 -[submodule "modules/JsonPatch"] - path = modules/JsonPatch - url = https://github.com/aspnet/JsonPatch.git - branch = release/2.1 [submodule "modules/KestrelHttpServer"] path = modules/KestrelHttpServer url = https://github.com/aspnet/KestrelHttpServer.git diff --git a/modules/JsonPatch b/modules/JsonPatch deleted file mode 160000 index 218064c300..0000000000 --- a/modules/JsonPatch +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 218064c300a7cf5a76669e133340a98a0c5517a5 From 979f72a839dcdc96f74326e2e7086efb9811231d Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 9 Nov 2018 13:08:02 -0800 Subject: [PATCH 1008/1029] Update PR validation to run a real build --- .azure/pipelines/fast-pr-validation.yml | 31 ++++++++----------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/.azure/pipelines/fast-pr-validation.yml b/.azure/pipelines/fast-pr-validation.yml index c88e0a520a..b634a55889 100644 --- a/.azure/pipelines/fast-pr-validation.yml +++ b/.azure/pipelines/fast-pr-validation.yml @@ -3,28 +3,17 @@ trigger: - release/* jobs: -- template: project-ci.yml +- template: jobs/default-build.yml parameters: - buildArgs: "/t:FastCheck" -- job: RepoBuilds - pool: - vmImage: vs2017-win2016 - strategy: - maxParallel: 3 - matrix: - DataProtection: - _FolderName: DataProtection - WebSockets: - _FolderName: WebSockets - steps: - - script: src/$(_FolderName)/build.cmd -ci - displayName: Run src/$(_FolderName)/build.cmd - - task: PublishTestResults@2 - displayName: Publish test results - condition: always() - inputs: - testRunner: vstest - testResultsFiles: 'src/$(_FolderName)/artifacts/logs/**/*.trx' + jobName: PR_FastCheck + jobDisplayName: Fast Check + agentOs: Windows + buildArgs: "/p:FastCheck" +- template: jobs/default-build.yml + parameters: + jobName: Windows_Build + jobDisplayName: "Build: Windows" + agentOs: Windows - template: jobs/iisintegration-job.yml parameters: variables: From fd5156e88b88d3736c08ce3305fe9212d227edfc Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Fri, 9 Nov 2018 14:05:43 -0800 Subject: [PATCH 1009/1029] Updating BuildTools from 2.1.3-rtm-15842 to 2.1.3-rtm-15843 [auto-updated: buildtools] --- korebuild-lock.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 08f95645f0..7e1e575c87 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.3-rtm-15842 -commithash:b631cb7a2b982cbbfc4d2e02be66c6612f9e3afd +version:2.1.3-rtm-15843 +commithash:651ca3c2d8f764b0b36be231cf45f19b1dd4bd2c From 1c8df01d09984b528b79747f1a5f8faf36cc4df4 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 9 Nov 2018 14:09:09 -0800 Subject: [PATCH 1010/1029] Update PR validation to fix the FastCheck config and IIS tests --- .azure/pipelines/fast-pr-validation.yml | 5 ++++- .azure/pipelines/jobs/default-build.yml | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.azure/pipelines/fast-pr-validation.yml b/.azure/pipelines/fast-pr-validation.yml index b634a55889..5449521778 100644 --- a/.azure/pipelines/fast-pr-validation.yml +++ b/.azure/pipelines/fast-pr-validation.yml @@ -8,12 +8,15 @@ jobs: jobName: PR_FastCheck jobDisplayName: Fast Check agentOs: Windows - buildArgs: "/p:FastCheck" + buildArgs: "/t:FastCheck" - template: jobs/default-build.yml parameters: jobName: Windows_Build jobDisplayName: "Build: Windows" agentOs: Windows + beforeBuild: + - powershell: "& ./src/IISIntegration/tools/UpdateIISExpressCertificate.ps1" + displayName: Setup IISExpress test certificates" - template: jobs/iisintegration-job.yml parameters: variables: diff --git a/.azure/pipelines/jobs/default-build.yml b/.azure/pipelines/jobs/default-build.yml index d39a7e1e22..065e4d1770 100644 --- a/.azure/pipelines/jobs/default-build.yml +++ b/.azure/pipelines/jobs/default-build.yml @@ -63,6 +63,7 @@ jobs: - job: ${{ coalesce(parameters.jobName, parameters.agentOs) }} displayName: ${{ coalesce(parameters.jobDisplayName, parameters.agentOs) }} dependsOn: ${{ parameters.dependsOn }} + timeoutInMinutes: 90 workspace: clean: all strategy: From dfacde4deee8520bd3c5c165863f426a726e2bb0 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 9 Nov 2018 14:23:04 -0800 Subject: [PATCH 1011/1029] Fix /t:FastCheck for local-projects --- build/repo.targets | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/build/repo.targets b/build/repo.targets index 0c1125bd51..9e7e303327 100644 --- a/build/repo.targets +++ b/build/repo.targets @@ -250,7 +250,7 @@ - + + + + $(BuildProperties);DesignTimeBuild=true + + + + DependsOnTargets="_SetDesignTimeBuild;ComputeGraph;VerifyPackageArtifactConfig;VerifyAllReposHaveNuGetPackageVerifier" /> From 7338d749d05d885bba924c432ec03699f531dece Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Fri, 9 Nov 2018 14:52:25 -0800 Subject: [PATCH 1012/1029] Updating BuildTools from 2.1.3-rtm-15843 to 2.1.3-rtm-15844 [auto-updated: buildtools] --- korebuild-lock.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 7e1e575c87..7d2ac1cf8c 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.3-rtm-15843 -commithash:651ca3c2d8f764b0b36be231cf45f19b1dd4bd2c +version:2.1.3-rtm-15844 +commithash:8d031079e81ea30446712d48f7e8e9539fb92907 From f64d6a2b501047af3ac9d76f221909700b95337d Mon Sep 17 00:00:00 2001 From: dotnet-maestro-bot Date: Fri, 9 Nov 2018 15:48:44 -0800 Subject: [PATCH 1013/1029] Updating dependencies (#3996) --- build/dependencies.props | 128 +++++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 0d6109cbeb..ffc4e9b097 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -2,71 +2,71 @@ - 2.2.0-rtm-27105-02 - 2.2.0-rtm-27105-02 - 4.6.0-rtm-27105-02 + 2.2.0-rtm-27109-04 + 2.2.0-rtm-27109-04 + 4.6.0-rtm-27109-02 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 - 2.2.0-rtm-181106-13 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 + 2.2.0-rtm-181109-01 From 1fa7c5b91c070a1c6590c93553d25f324863959d Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sat, 10 Nov 2018 00:15:24 +0000 Subject: [PATCH 1014/1029] Updating submodule(s) SignalR => df668017eebf98f8d724177d220712c0e6218114 [auto-updated: submodules] --- modules/SignalR | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/SignalR b/modules/SignalR index d0dac557ac..df668017ee 160000 --- a/modules/SignalR +++ b/modules/SignalR @@ -1 +1 @@ -Subproject commit d0dac557ac9c2ce00fea0cc418df68974282f263 +Subproject commit df668017eebf98f8d724177d220712c0e6218114 From a87f3ff4a01d58530a73f85c5186a413501c34eb Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sat, 10 Nov 2018 00:15:34 +0000 Subject: [PATCH 1015/1029] Updating BuildTools from 2.2.0-preview2-20181108.7 to 2.2.0-preview2-20181109.5 [auto-updated: buildtools] --- global.json | 2 +- korebuild-lock.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/global.json b/global.json index 10f2dc6bc5..5c2b5c9e77 100644 --- a/global.json +++ b/global.json @@ -3,6 +3,6 @@ "version": "2.2.100-rtm-009578" }, "msbuild-sdks": { - "Internal.AspNetCore.Sdk": "2.2.0-preview2-20181108.7" + "Internal.AspNetCore.Sdk": "2.2.0-preview2-20181109.5" } } diff --git a/korebuild-lock.txt b/korebuild-lock.txt index a48863b8c5..268c275813 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.2.0-preview2-20181108.7 -commithash:4b09b2475059642a0e304427fbc6515cb8052fca +version:2.2.0-preview2-20181109.5 +commithash:f736f491e6a372b52791e094f8b93e176c2f98c2 From 1ab08d70ef462dddcf71f3b419493b10db081eae Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 9 Nov 2018 16:17:15 -0800 Subject: [PATCH 1016/1029] Reorganize source code in preparation to move into aspnet/AspNetCore Prior to reorganization, this source code was found in https://github.com/aspnet/HtmlAbstractions/tree/252ae0c434d93f5bfaf949c35edb9ef59730d0a3 --- .appveyor.yml | 17 - .gitattributes | 51 -- .github/ISSUE_TEMPLATE.md | 3 - .gitignore | 40 -- .travis.yml | 27 - CONTRIBUTING.md | 4 - Directory.Build.props | 24 - Directory.Build.targets | 7 - HtmlAbstractions.sln | 90 --- LICENSE.txt | 14 - NuGet.config | 7 - NuGetPackageVerifier.json | 7 - README.md | 9 - build.cmd | 2 - build.sh | 8 - build/Key.snk | Bin 596 -> 0 bytes build/dependencies.props | 28 - build/repo.props | 15 - build/sources.props | 17 - korebuild-lock.txt | 2 - korebuild.json | 4 - run.cmd | 2 - run.ps1 | 196 ------ run.sh | 231 ------- .../Abstractions/src}/HtmlContentBuilder.cs | 0 .../src}/HtmlContentBuilderExtensions.cs | 0 .../src}/HtmlFormattableString.cs | 0 .../Abstractions/src}/HtmlString.cs | 0 .../Abstractions/src}/IHtmlContent.cs | 0 .../Abstractions/src}/IHtmlContentBuilder.cs | 0 .../src}/IHtmlContentContainer.cs | 0 ...rosoft.AspNetCore.Html.Abstractions.csproj | 4 +- .../src/Properties/AssemblyInfo.cs | 8 + .../Abstractions/src}/baseline.netcore.json | 0 .../test}/HtmlContentBuilderExtensionsTest.cs | 0 .../test}/HtmlContentBuilderTest.cs | 0 .../test}/HtmlFormattableStringTest.cs | 0 ....AspNetCore.Html.Abstractions.Tests.csproj | 12 + .../Properties/AssemblyInfo.cs | 8 - .../EncoderServiceCollectionExtensions.cs | 83 --- .../Microsoft.Extensions.WebEncoders.csproj | 19 - .../Testing/HtmlTestEncoder.cs | 104 ---- .../Testing/JavaScriptTestEncoder.cs | 104 ---- .../Testing/UrlTestEncoder.cs | 104 ---- .../WebEncoderOptions.cs | 21 - .../baseline.netcore.json | 564 ------------------ test/Directory.Build.props | 17 - ...t.AspNetCore.Html.Abstractions.Test.csproj | 12 - ...EncoderServiceCollectionExtensionsTests.cs | 90 --- .../HtmlTestEncoderTest.cs | 26 - ...rosoft.Extensions.WebEncoders.Tests.csproj | 15 - version.props | 12 - 52 files changed, 22 insertions(+), 1986 deletions(-) delete mode 100644 .appveyor.yml delete mode 100644 .gitattributes delete mode 100644 .github/ISSUE_TEMPLATE.md delete mode 100644 .gitignore delete mode 100644 .travis.yml delete mode 100644 CONTRIBUTING.md delete mode 100644 Directory.Build.props delete mode 100644 Directory.Build.targets delete mode 100644 HtmlAbstractions.sln delete mode 100644 LICENSE.txt delete mode 100644 NuGet.config delete mode 100644 NuGetPackageVerifier.json delete mode 100644 README.md delete mode 100644 build.cmd delete mode 100755 build.sh delete mode 100644 build/Key.snk delete mode 100644 build/dependencies.props delete mode 100644 build/repo.props delete mode 100644 build/sources.props delete mode 100644 korebuild-lock.txt delete mode 100644 korebuild.json delete mode 100644 run.cmd delete mode 100644 run.ps1 delete mode 100755 run.sh rename src/{Microsoft.AspNetCore.Html.Abstractions => Html/Abstractions/src}/HtmlContentBuilder.cs (100%) rename src/{Microsoft.AspNetCore.Html.Abstractions => Html/Abstractions/src}/HtmlContentBuilderExtensions.cs (100%) rename src/{Microsoft.AspNetCore.Html.Abstractions => Html/Abstractions/src}/HtmlFormattableString.cs (100%) rename src/{Microsoft.AspNetCore.Html.Abstractions => Html/Abstractions/src}/HtmlString.cs (100%) rename src/{Microsoft.AspNetCore.Html.Abstractions => Html/Abstractions/src}/IHtmlContent.cs (100%) rename src/{Microsoft.AspNetCore.Html.Abstractions => Html/Abstractions/src}/IHtmlContentBuilder.cs (100%) rename src/{Microsoft.AspNetCore.Html.Abstractions => Html/Abstractions/src}/IHtmlContentContainer.cs (100%) rename src/{Microsoft.AspNetCore.Html.Abstractions => Html/Abstractions/src}/Microsoft.AspNetCore.Html.Abstractions.csproj (74%) mode change 100755 => 100644 create mode 100644 src/Html/Abstractions/src/Properties/AssemblyInfo.cs rename src/{Microsoft.AspNetCore.Html.Abstractions => Html/Abstractions/src}/baseline.netcore.json (100%) rename {test/Microsoft.AspNetCore.Html.Abstractions.Test => src/Html/Abstractions/test}/HtmlContentBuilderExtensionsTest.cs (100%) rename {test/Microsoft.AspNetCore.Html.Abstractions.Test => src/Html/Abstractions/test}/HtmlContentBuilderTest.cs (100%) rename {test/Microsoft.AspNetCore.Html.Abstractions.Test => src/Html/Abstractions/test}/HtmlFormattableStringTest.cs (100%) create mode 100644 src/Html/Abstractions/test/Microsoft.AspNetCore.Html.Abstractions.Tests.csproj delete mode 100644 src/Microsoft.AspNetCore.Html.Abstractions/Properties/AssemblyInfo.cs delete mode 100644 src/Microsoft.Extensions.WebEncoders/EncoderServiceCollectionExtensions.cs delete mode 100755 src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj delete mode 100644 src/Microsoft.Extensions.WebEncoders/Testing/HtmlTestEncoder.cs delete mode 100644 src/Microsoft.Extensions.WebEncoders/Testing/JavaScriptTestEncoder.cs delete mode 100644 src/Microsoft.Extensions.WebEncoders/Testing/UrlTestEncoder.cs delete mode 100644 src/Microsoft.Extensions.WebEncoders/WebEncoderOptions.cs delete mode 100644 src/Microsoft.Extensions.WebEncoders/baseline.netcore.json delete mode 100644 test/Directory.Build.props delete mode 100755 test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj delete mode 100644 test/Microsoft.Extensions.WebEncoders.Tests/EncoderServiceCollectionExtensionsTests.cs delete mode 100644 test/Microsoft.Extensions.WebEncoders.Tests/HtmlTestEncoderTest.cs delete mode 100755 test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj delete mode 100644 version.props diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index 4eea96ab69..0000000000 --- a/.appveyor.yml +++ /dev/null @@ -1,17 +0,0 @@ -init: -- git config --global core.autocrlf true -branches: - only: - - dev - - /^release\/.*$/ - - /^(.*\/)?ci-.*$/ -build_script: -- ps: .\run.ps1 default-build -clone_depth: 1 -environment: - global: - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - DOTNET_CLI_TELEMETRY_OPTOUT: 1 -test: 'off' -deploy: 'off' -os: Visual Studio 2017 diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 66abdf279e..0000000000 --- a/.gitattributes +++ /dev/null @@ -1,51 +0,0 @@ -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain - -*.jpg binary -*.png binary -*.gif binary - -*.cs text=auto diff=csharp -*.vb text=auto -*.resx text=auto -*.c text=auto -*.cpp text=auto -*.cxx text=auto -*.h text=auto -*.hxx text=auto -*.py text=auto -*.rb text=auto -*.java text=auto -*.html text=auto -*.htm text=auto -*.css text=auto -*.scss text=auto -*.sass text=auto -*.less text=auto -*.js text=auto -*.lisp text=auto -*.clj text=auto -*.sql text=auto -*.php text=auto -*.lua text=auto -*.m text=auto -*.asm text=auto -*.erl text=auto -*.fs text=auto -*.fsx text=auto -*.hs text=auto - -*.csproj text=auto -*.vbproj text=auto -*.fsproj text=auto -*.dbproj text=auto -*.sln text=auto eol=crlf -*.sh eol=lf \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 101a084f0a..0000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,3 +0,0 @@ -THIS ISSUE TRACKER IS CLOSED - please log new issues here: https://github.com/aspnet/Home/issues - -For information about this change, see https://github.com/aspnet/Announcements/issues/283 diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 6da3c6a3e9..0000000000 --- a/.gitignore +++ /dev/null @@ -1,40 +0,0 @@ -[Oo]bj/ -[Bb]in/ -TestResults/ -.nuget/ -*.sln.ide/ -_ReSharper.*/ -packages/ -artifacts/ -PublishProfiles/ -.vs/ -bower_components/ -node_modules/ -**/wwwroot/lib/ -debugSettings.json -project.lock.json -*.user -*.suo -*.cache -*.docstates -_ReSharper.* -nuget.exe -*net45.csproj -*net451.csproj -*k10.csproj -*.psess -*.vsp -*.pidb -*.userprefs -*DS_Store -*.ncrunchsolution -*.*sdf -*.ipch -.settings -*.sln.ide -node_modules -**/[Cc]ompiler/[Rr]esources/**/*.js -*launchSettings.json -.build/ -.testPublish/ -global.json diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 64bdbb4441..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,27 +0,0 @@ -language: csharp -sudo: false -dist: trusty -env: - global: - - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - - DOTNET_CLI_TELEMETRY_OPTOUT: 1 -mono: none -os: -- linux -- osx -osx_image: xcode8.2 -addons: - apt: - packages: - - libunwind8 -branches: - only: - - dev - - /^release\/.*$/ - - /^(.*\/)?ci-.*$/ -before_install: -- if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s - /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib - /usr/local/lib/; fi -script: -- ./build.sh diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 64ff041d5c..0000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,4 +0,0 @@ -Contributing -====== - -Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/dev/CONTRIBUTING.md) in the Home repo. diff --git a/Directory.Build.props b/Directory.Build.props deleted file mode 100644 index b7176c688d..0000000000 --- a/Directory.Build.props +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - https://github.com/aspnet/HtmlAbstractions - git - $(MSBuildThisFileDirectory) - $(MSBuildThisFileDirectory)build\Key.snk - true - true - true - - - - - - - diff --git a/Directory.Build.targets b/Directory.Build.targets deleted file mode 100644 index 53b3f6e1da..0000000000 --- a/Directory.Build.targets +++ /dev/null @@ -1,7 +0,0 @@ - - - $(MicrosoftNETCoreApp20PackageVersion) - $(MicrosoftNETCoreApp21PackageVersion) - $(NETStandardLibrary20PackageVersion) - - diff --git a/HtmlAbstractions.sln b/HtmlAbstractions.sln deleted file mode 100644 index 5ee1cb4612..0000000000 --- a/HtmlAbstractions.sln +++ /dev/null @@ -1,90 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26127.0 -MinimumVisualStudioVersion = 15.0.26730.03 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A5A15F1C-885A-452A-A731-B0173DDBD913}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F31FF137-390C-49BF-A3BD-7C6ED3597C21}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Html.Abstractions", "src\Microsoft.AspNetCore.Html.Abstractions\Microsoft.AspNetCore.Html.Abstractions.csproj", "{68A28E4A-3ADE-4187-9625-4FF185887CB3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Html.Abstractions.Test", "test\Microsoft.AspNetCore.Html.Abstractions.Test\Microsoft.AspNetCore.Html.Abstractions.Test.csproj", "{2D187B88-94BD-4A39-AC97-F8F8B9363301}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B4962A29-BE69-4A18-9B4F-B803EEE31EAA}" - ProjectSection(SolutionItems) = preProject - NuGetPackageVerifier.json = NuGetPackageVerifier.json - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Extensions.WebEncoders", "src\Microsoft.Extensions.WebEncoders\Microsoft.Extensions.WebEncoders.csproj", "{DD2CE416-765E-4000-A03E-C2FF165DA1B6}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Extensions.WebEncoders.Tests", "test\Microsoft.Extensions.WebEncoders.Tests\Microsoft.Extensions.WebEncoders.Tests.csproj", "{7AE2731D-43CD-4CF8-850A-4914DE2CE930}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|Mixed Platforms = Debug|Mixed Platforms - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|Mixed Platforms = Release|Mixed Platforms - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Debug|x86.ActiveCfg = Debug|Any CPU - {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Debug|x86.Build.0 = Debug|Any CPU - {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|Any CPU.Build.0 = Release|Any CPU - {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|x86.ActiveCfg = Release|Any CPU - {68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|x86.Build.0 = Release|Any CPU - {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Debug|x86.ActiveCfg = Debug|Any CPU - {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Debug|x86.Build.0 = Debug|Any CPU - {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|Any CPU.Build.0 = Release|Any CPU - {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|x86.ActiveCfg = Release|Any CPU - {2D187B88-94BD-4A39-AC97-F8F8B9363301}.Release|x86.Build.0 = Release|Any CPU - {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Debug|x86.ActiveCfg = Debug|Any CPU - {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Debug|x86.Build.0 = Debug|Any CPU - {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Release|Any CPU.Build.0 = Release|Any CPU - {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Release|x86.ActiveCfg = Release|Any CPU - {DD2CE416-765E-4000-A03E-C2FF165DA1B6}.Release|x86.Build.0 = Release|Any CPU - {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Debug|x86.ActiveCfg = Debug|Any CPU - {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Debug|x86.Build.0 = Debug|Any CPU - {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Release|Any CPU.Build.0 = Release|Any CPU - {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Release|x86.ActiveCfg = Release|Any CPU - {7AE2731D-43CD-4CF8-850A-4914DE2CE930}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {68A28E4A-3ADE-4187-9625-4FF185887CB3} = {A5A15F1C-885A-452A-A731-B0173DDBD913} - {2D187B88-94BD-4A39-AC97-F8F8B9363301} = {F31FF137-390C-49BF-A3BD-7C6ED3597C21} - {DD2CE416-765E-4000-A03E-C2FF165DA1B6} = {A5A15F1C-885A-452A-A731-B0173DDBD913} - {7AE2731D-43CD-4CF8-850A-4914DE2CE930} = {F31FF137-390C-49BF-A3BD-7C6ED3597C21} - EndGlobalSection -EndGlobal diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index 7b2956ecee..0000000000 --- a/LICENSE.txt +++ /dev/null @@ -1,14 +0,0 @@ -Copyright (c) .NET Foundation and Contributors - -All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed -under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -CONDITIONS OF ANY KIND, either express or implied. See the License for the -specific language governing permissions and limitations under the License. diff --git a/NuGet.config b/NuGet.config deleted file mode 100644 index e32bddfd51..0000000000 --- a/NuGet.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json deleted file mode 100644 index b153ab1515..0000000000 --- a/NuGetPackageVerifier.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "Default": { - "rules": [ - "DefaultCompositeRule" - ] - } -} \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index a1e3579e7a..0000000000 --- a/README.md +++ /dev/null @@ -1,9 +0,0 @@ -HtmlAbstractions -========== -AppVeyor: [![AppVeyor](https://ci.appveyor.com/api/projects/status/cu9y78vsdp19e5on/branch/dev?svg=true)](https://ci.appveyor.com/project/aspnetci/htmlabstractions/branch/dev) - -Travis: [![Travis](https://travis-ci.org/aspnet/HtmlAbstractions.svg?branch=dev)](https://travis-ci.org/aspnet/HtmlAbstractions) - -HTML abstractions used for building HTML content, including types such as `HtmlString` and `IHtmlContent`. - -This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo. diff --git a/build.cmd b/build.cmd deleted file mode 100644 index c0050bda12..0000000000 --- a/build.cmd +++ /dev/null @@ -1,2 +0,0 @@ -@ECHO OFF -PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' default-build %*; exit $LASTEXITCODE" diff --git a/build.sh b/build.sh deleted file mode 100755 index 98a4b22765..0000000000 --- a/build.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -# Call "sync" between "chmod" and execution to prevent "text file busy" error in Docker (aufs) -chmod +x "$DIR/run.sh"; sync -"$DIR/run.sh" default-build "$@" diff --git a/build/Key.snk b/build/Key.snk deleted file mode 100644 index e10e4889c125d3120cd9e81582243d70f7cbb806..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098=Iw=HCsnz~#iVhm& zj%TU(_THUee?3yHBjk$37ysB?i5#7WD$={H zV4B!OxRPrb|8)HPg~A}8P>^=#y<)56#=E&NzcjOtPK~<4n6GHt=K$ro*T(lhby_@U zEk(hLzk1H)0yXj{A_5>fk-TgNoP|q6(tP2xo8zt8i%212CWM#AeCd?`hS|4~L({h~Moo(~vy&3Z z1uI}`fd^*>o=rwbAGymj6RM^pZm(*Kfhs+Y1#`-2JPWZMK8@;ZWCk2+9bX4YP);~fj-BU*R zQPvWv$89!{Rl9wM+zR>_TSkn^voYxA?2G iKnV#iZ6Ah`K>b=@=IjYJXrxL124zR(38)nxe+&q_$QXwJ diff --git a/build/dependencies.props b/build/dependencies.props deleted file mode 100644 index 3c314a3476..0000000000 --- a/build/dependencies.props +++ /dev/null @@ -1,28 +0,0 @@ - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - - - - 2.1.3-rtm-15802 - 2.0.0 - 2.1.2 - 15.6.1 - 2.0.3 - 4.5.0 - 2.3.1 - 2.4.0-beta.1.build3945 - - - - - - - - 2.1.0 - 2.1.1 - 2.1.1 - 2.1.1 - - \ No newline at end of file diff --git a/build/repo.props b/build/repo.props deleted file mode 100644 index dab1601c88..0000000000 --- a/build/repo.props +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - Internal.AspNetCore.Universe.Lineup - 2.1.0-rc1-* - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json - - - - - - - diff --git a/build/sources.props b/build/sources.props deleted file mode 100644 index 9215df9751..0000000000 --- a/build/sources.props +++ /dev/null @@ -1,17 +0,0 @@ - - - - - $(DotNetRestoreSources) - - $(RestoreSources); - https://dotnet.myget.org/F/dotnet-core/api/v3/index.json; - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; - https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; - - - $(RestoreSources); - https://api.nuget.org/v3/index.json; - - - diff --git a/korebuild-lock.txt b/korebuild-lock.txt deleted file mode 100644 index 251c227c83..0000000000 --- a/korebuild-lock.txt +++ /dev/null @@ -1,2 +0,0 @@ -version:2.1.3-rtm-15802 -commithash:a7c08b45b440a7d2058a0aa1eaa3eb6ba811976a diff --git a/korebuild.json b/korebuild.json deleted file mode 100644 index 678d8bb948..0000000000 --- a/korebuild.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.1/tools/korebuild.schema.json", - "channel": "release/2.1" -} diff --git a/run.cmd b/run.cmd deleted file mode 100644 index d52d5c7e68..0000000000 --- a/run.cmd +++ /dev/null @@ -1,2 +0,0 @@ -@ECHO OFF -PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' %*; exit $LASTEXITCODE" diff --git a/run.ps1 b/run.ps1 deleted file mode 100644 index 27dcf848f8..0000000000 --- a/run.ps1 +++ /dev/null @@ -1,196 +0,0 @@ -#!/usr/bin/env powershell -#requires -version 4 - -<# -.SYNOPSIS -Executes KoreBuild commands. - -.DESCRIPTION -Downloads korebuild if required. Then executes the KoreBuild command. To see available commands, execute with `-Command help`. - -.PARAMETER Command -The KoreBuild command to run. - -.PARAMETER Path -The folder to build. Defaults to the folder containing this script. - -.PARAMETER Channel -The channel of KoreBuild to download. Overrides the value from the config file. - -.PARAMETER DotNetHome -The directory where .NET Core tools will be stored. - -.PARAMETER ToolsSource -The base url where build tools can be downloaded. Overrides the value from the config file. - -.PARAMETER Update -Updates KoreBuild to the latest version even if a lock file is present. - -.PARAMETER ConfigFile -The path to the configuration file that stores values. Defaults to korebuild.json. - -.PARAMETER ToolsSourceSuffix -The Suffix to append to the end of the ToolsSource. Useful for query strings in blob stores. - -.PARAMETER Arguments -Arguments to be passed to the command - -.NOTES -This function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be. -When the lockfile is not present, KoreBuild will create one using latest available version from $Channel. - -The $ConfigFile is expected to be an JSON file. It is optional, and the configuration values in it are optional as well. Any options set -in the file are overridden by command line parameters. - -.EXAMPLE -Example config file: -```json -{ - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", - "channel": "dev", - "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" -} -``` -#> -[CmdletBinding(PositionalBinding = $false)] -param( - [Parameter(Mandatory = $true, Position = 0)] - [string]$Command, - [string]$Path = $PSScriptRoot, - [Alias('c')] - [string]$Channel, - [Alias('d')] - [string]$DotNetHome, - [Alias('s')] - [string]$ToolsSource, - [Alias('u')] - [switch]$Update, - [string]$ConfigFile, - [string]$ToolsSourceSuffix, - [Parameter(ValueFromRemainingArguments = $true)] - [string[]]$Arguments -) - -Set-StrictMode -Version 2 -$ErrorActionPreference = 'Stop' - -# -# Functions -# - -function Get-KoreBuild { - - $lockFile = Join-Path $Path 'korebuild-lock.txt' - - if (!(Test-Path $lockFile) -or $Update) { - Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile $ToolsSourceSuffix - } - - $version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1 - if (!$version) { - Write-Error "Failed to parse version from $lockFile. Expected a line that begins with 'version:'" - } - $version = $version.TrimStart('version:').Trim() - $korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version) - - if (!(Test-Path $korebuildPath)) { - Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version" - New-Item -ItemType Directory -Path $korebuildPath | Out-Null - $remotePath = "$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip" - - try { - $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip" - Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix - if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) { - # Use built-in commands where possible as they are cross-plat compatible - Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath - } - else { - # Fallback to old approach for old installations of PowerShell - Add-Type -AssemblyName System.IO.Compression.FileSystem - [System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath) - } - } - catch { - Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore - throw - } - finally { - Remove-Item $tmpfile -ErrorAction Ignore - } - } - - return $korebuildPath -} - -function Join-Paths([string]$path, [string[]]$childPaths) { - $childPaths | ForEach-Object { $path = Join-Path $path $_ } - return $path -} - -function Get-RemoteFile([string]$RemotePath, [string]$LocalPath, [string]$RemoteSuffix) { - if ($RemotePath -notlike 'http*') { - Copy-Item $RemotePath $LocalPath - return - } - - $retries = 10 - while ($retries -gt 0) { - $retries -= 1 - try { - Invoke-WebRequest -UseBasicParsing -Uri $($RemotePath + $RemoteSuffix) -OutFile $LocalPath - return - } - catch { - Write-Verbose "Request failed. $retries retries remaining" - } - } - - Write-Error "Download failed: '$RemotePath'." -} - -# -# Main -# - -# Load configuration or set defaults - -$Path = Resolve-Path $Path -if (!$ConfigFile) { $ConfigFile = Join-Path $Path 'korebuild.json' } - -if (Test-Path $ConfigFile) { - try { - $config = Get-Content -Raw -Encoding UTF8 -Path $ConfigFile | ConvertFrom-Json - if ($config) { - if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel } - if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource} - } - } - catch { - Write-Warning "$ConfigFile could not be read. Its settings will be ignored." - Write-Warning $Error[0] - } -} - -if (!$DotNetHome) { - $DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } ` - elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} ` - elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}` - else { Join-Path $PSScriptRoot '.dotnet'} -} - -if (!$Channel) { $Channel = 'dev' } -if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } - -# Execute - -$korebuildPath = Get-KoreBuild -Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1') - -try { - Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile - Invoke-KoreBuildCommand $Command @Arguments -} -finally { - Remove-Module 'KoreBuild' -ErrorAction Ignore -} diff --git a/run.sh b/run.sh deleted file mode 100755 index 834961fc3a..0000000000 --- a/run.sh +++ /dev/null @@ -1,231 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -# -# variables -# - -RESET="\033[0m" -RED="\033[0;31m" -YELLOW="\033[0;33m" -MAGENTA="\033[0;95m" -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" -verbose=false -update=false -repo_path="$DIR" -channel='' -tools_source='' -tools_source_suffix='' - -# -# Functions -# -__usage() { - echo "Usage: $(basename "${BASH_SOURCE[0]}") command [options] [[--] ...]" - echo "" - echo "Arguments:" - echo " command The command to be run." - echo " ... Arguments passed to the command. Variable number of arguments allowed." - echo "" - echo "Options:" - echo " --verbose Show verbose output." - echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." - echo " --config-file The path to the configuration file that stores values. Defaults to korebuild.json." - echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." - echo " --path The directory to build. Defaults to the directory containing the script." - echo " -s|--tools-source|-ToolsSource The base url where build tools can be downloaded. Overrides the value from the config file." - echo " --tools-source-suffix|-ToolsSourceSuffix The suffix to append to tools-source. Useful for query strings." - echo " -u|--update Update to the latest KoreBuild even if the lock file is present." - echo "" - echo "Description:" - echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." - echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel." - - if [[ "${1:-}" != '--no-exit' ]]; then - exit 2 - fi -} - -get_korebuild() { - local version - local lock_file="$repo_path/korebuild-lock.txt" - if [ ! -f "$lock_file" ] || [ "$update" = true ]; then - __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" "$tools_source_suffix" - fi - version="$(grep 'version:*' -m 1 "$lock_file")" - if [[ "$version" == '' ]]; then - __error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'" - return 1 - fi - version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" - local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" - - { - if [ ! -d "$korebuild_path" ]; then - mkdir -p "$korebuild_path" - local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" - tmpfile="$(mktemp)" - echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" - if __get_remote_file "$remote_path" "$tmpfile" "$tools_source_suffix"; then - unzip -q -d "$korebuild_path" "$tmpfile" - fi - rm "$tmpfile" || true - fi - - source "$korebuild_path/KoreBuild.sh" - } || { - if [ -d "$korebuild_path" ]; then - echo "Cleaning up after failed installation" - rm -rf "$korebuild_path" || true - fi - return 1 - } -} - -__error() { - echo -e "${RED}error: $*${RESET}" 1>&2 -} - -__warn() { - echo -e "${YELLOW}warning: $*${RESET}" -} - -__machine_has() { - hash "$1" > /dev/null 2>&1 - return $? -} - -__get_remote_file() { - local remote_path=$1 - local local_path=$2 - local remote_path_suffix=$3 - - if [[ "$remote_path" != 'http'* ]]; then - cp "$remote_path" "$local_path" - return 0 - fi - - local failed=false - if __machine_has wget; then - wget --tries 10 --quiet -O "$local_path" "${remote_path}${remote_path_suffix}" || failed=true - else - failed=true - fi - - if [ "$failed" = true ] && __machine_has curl; then - failed=false - curl --retry 10 -sSL -f --create-dirs -o "$local_path" "${remote_path}${remote_path_suffix}" || failed=true - fi - - if [ "$failed" = true ]; then - __error "Download failed: $remote_path" 1>&2 - return 1 - fi -} - -# -# main -# - -command="${1:-}" -shift - -while [[ $# -gt 0 ]]; do - case $1 in - -\?|-h|--help) - __usage --no-exit - exit 0 - ;; - -c|--channel|-Channel) - shift - channel="${1:-}" - [ -z "$channel" ] && __usage - ;; - --config-file|-ConfigFile) - shift - config_file="${1:-}" - [ -z "$config_file" ] && __usage - if [ ! -f "$config_file" ]; then - __error "Invalid value for --config-file. $config_file does not exist." - exit 1 - fi - ;; - -d|--dotnet-home|-DotNetHome) - shift - DOTNET_HOME="${1:-}" - [ -z "$DOTNET_HOME" ] && __usage - ;; - --path|-Path) - shift - repo_path="${1:-}" - [ -z "$repo_path" ] && __usage - ;; - -s|--tools-source|-ToolsSource) - shift - tools_source="${1:-}" - [ -z "$tools_source" ] && __usage - ;; - --tools-source-suffix|-ToolsSourceSuffix) - shift - tools_source_suffix="${1:-}" - [ -z "$tools_source_suffix" ] && __usage - ;; - -u|--update|-Update) - update=true - ;; - --verbose|-Verbose) - verbose=true - ;; - --) - shift - break - ;; - *) - break - ;; - esac - shift -done - -if ! __machine_has unzip; then - __error 'Missing required command: unzip' - exit 1 -fi - -if ! __machine_has curl && ! __machine_has wget; then - __error 'Missing required command. Either wget or curl is required.' - exit 1 -fi - -[ -z "${config_file:-}" ] && config_file="$repo_path/korebuild.json" -if [ -f "$config_file" ]; then - if __machine_has jq ; then - if jq '.' "$config_file" >/dev/null ; then - config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" - config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")" - else - __warn "$config_file is invalid JSON. Its settings will be ignored." - fi - elif __machine_has python ; then - if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then - config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" - config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" - else - __warn "$config_file is invalid JSON. Its settings will be ignored." - fi - else - __warn 'Missing required command: jq or pyton. Could not parse the JSON file. Its settings will be ignored.' - fi - - [ ! -z "${config_channel:-}" ] && channel="$config_channel" - [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" -fi - -[ -z "$channel" ] && channel='dev' -[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' - -get_korebuild -set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file" -invoke_korebuild_command "$command" "$@" diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilder.cs b/src/Html/Abstractions/src/HtmlContentBuilder.cs similarity index 100% rename from src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilder.cs rename to src/Html/Abstractions/src/HtmlContentBuilder.cs diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilderExtensions.cs b/src/Html/Abstractions/src/HtmlContentBuilderExtensions.cs similarity index 100% rename from src/Microsoft.AspNetCore.Html.Abstractions/HtmlContentBuilderExtensions.cs rename to src/Html/Abstractions/src/HtmlContentBuilderExtensions.cs diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlFormattableString.cs b/src/Html/Abstractions/src/HtmlFormattableString.cs similarity index 100% rename from src/Microsoft.AspNetCore.Html.Abstractions/HtmlFormattableString.cs rename to src/Html/Abstractions/src/HtmlFormattableString.cs diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/HtmlString.cs b/src/Html/Abstractions/src/HtmlString.cs similarity index 100% rename from src/Microsoft.AspNetCore.Html.Abstractions/HtmlString.cs rename to src/Html/Abstractions/src/HtmlString.cs diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContent.cs b/src/Html/Abstractions/src/IHtmlContent.cs similarity index 100% rename from src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContent.cs rename to src/Html/Abstractions/src/IHtmlContent.cs diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContentBuilder.cs b/src/Html/Abstractions/src/IHtmlContentBuilder.cs similarity index 100% rename from src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContentBuilder.cs rename to src/Html/Abstractions/src/IHtmlContentBuilder.cs diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContentContainer.cs b/src/Html/Abstractions/src/IHtmlContentContainer.cs similarity index 100% rename from src/Microsoft.AspNetCore.Html.Abstractions/IHtmlContentContainer.cs rename to src/Html/Abstractions/src/IHtmlContentContainer.cs diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj b/src/Html/Abstractions/src/Microsoft.AspNetCore.Html.Abstractions.csproj old mode 100755 new mode 100644 similarity index 74% rename from src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj rename to src/Html/Abstractions/src/Microsoft.AspNetCore.Html.Abstractions.csproj index 271cc6c7fa..f914769d17 --- a/src/Microsoft.AspNetCore.Html.Abstractions/Microsoft.AspNetCore.Html.Abstractions.csproj +++ b/src/Html/Abstractions/src/Microsoft.AspNetCore.Html.Abstractions.csproj @@ -1,8 +1,8 @@  - Microsoft ASP.NET Core ASP.NET Core HTML abstractions used for building HTML content. + Commonly used types: Microsoft.AspNetCore.Html.HtmlString Microsoft.AspNetCore.Html.IHtmlContent @@ -12,7 +12,7 @@ Microsoft.AspNetCore.Html.IHtmlContent - + diff --git a/src/Html/Abstractions/src/Properties/AssemblyInfo.cs b/src/Html/Abstractions/src/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..cb0b47442c --- /dev/null +++ b/src/Html/Abstractions/src/Properties/AssemblyInfo.cs @@ -0,0 +1,8 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Html.Abstractions.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/baseline.netcore.json b/src/Html/Abstractions/src/baseline.netcore.json similarity index 100% rename from src/Microsoft.AspNetCore.Html.Abstractions/baseline.netcore.json rename to src/Html/Abstractions/src/baseline.netcore.json diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs b/src/Html/Abstractions/test/HtmlContentBuilderExtensionsTest.cs similarity index 100% rename from test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderExtensionsTest.cs rename to src/Html/Abstractions/test/HtmlContentBuilderExtensionsTest.cs diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderTest.cs b/src/Html/Abstractions/test/HtmlContentBuilderTest.cs similarity index 100% rename from test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlContentBuilderTest.cs rename to src/Html/Abstractions/test/HtmlContentBuilderTest.cs diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlFormattableStringTest.cs b/src/Html/Abstractions/test/HtmlFormattableStringTest.cs similarity index 100% rename from test/Microsoft.AspNetCore.Html.Abstractions.Test/HtmlFormattableStringTest.cs rename to src/Html/Abstractions/test/HtmlFormattableStringTest.cs diff --git a/src/Html/Abstractions/test/Microsoft.AspNetCore.Html.Abstractions.Tests.csproj b/src/Html/Abstractions/test/Microsoft.AspNetCore.Html.Abstractions.Tests.csproj new file mode 100644 index 0000000000..0e77dbbfb3 --- /dev/null +++ b/src/Html/Abstractions/test/Microsoft.AspNetCore.Html.Abstractions.Tests.csproj @@ -0,0 +1,12 @@ + + + + $(StandardTestTfms) + + + + + + + + diff --git a/src/Microsoft.AspNetCore.Html.Abstractions/Properties/AssemblyInfo.cs b/src/Microsoft.AspNetCore.Html.Abstractions/Properties/AssemblyInfo.cs deleted file mode 100644 index bde0132dbb..0000000000 --- a/src/Microsoft.AspNetCore.Html.Abstractions/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Reflection; -using System.Resources; -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Html.Abstractions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/Microsoft.Extensions.WebEncoders/EncoderServiceCollectionExtensions.cs b/src/Microsoft.Extensions.WebEncoders/EncoderServiceCollectionExtensions.cs deleted file mode 100644 index 72f5e369a1..0000000000 --- a/src/Microsoft.Extensions.WebEncoders/EncoderServiceCollectionExtensions.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Text.Encodings.Web; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Options; -using Microsoft.Extensions.WebEncoders; - -namespace Microsoft.Extensions.DependencyInjection -{ - /// - /// Extension methods for setting up web encoding services in an . - /// - public static class EncoderServiceCollectionExtensions - { - /// - /// Adds , and - /// to the specified . - /// - /// The . - /// The so that additional calls can be chained. - public static IServiceCollection AddWebEncoders(this IServiceCollection services) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - services.AddOptions(); - - // Register the default encoders - // We want to call the 'Default' property getters lazily since they perform static caching - services.TryAddSingleton( - CreateFactory(() => HtmlEncoder.Default, settings => HtmlEncoder.Create(settings))); - services.TryAddSingleton( - CreateFactory(() => JavaScriptEncoder.Default, settings => JavaScriptEncoder.Create(settings))); - services.TryAddSingleton( - CreateFactory(() => UrlEncoder.Default, settings => UrlEncoder.Create(settings))); - - return services; - } - - /// - /// Adds , and - /// to the specified . - /// - /// The . - /// An to configure the provided . - /// The so that additional calls can be chained. - public static IServiceCollection AddWebEncoders(this IServiceCollection services, Action setupAction) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - if (setupAction == null) - { - throw new ArgumentNullException(nameof(setupAction)); - } - - services.AddWebEncoders(); - services.Configure(setupAction); - - return services; - } - - private static Func CreateFactory( - Func defaultFactory, - Func customSettingsFactory) - { - return serviceProvider => - { - var settings = serviceProvider - ?.GetService>() - ?.Value - ?.TextEncoderSettings; - return (settings != null) ? customSettingsFactory(settings) : defaultFactory(); - }; - } - } -} diff --git a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj b/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj deleted file mode 100755 index 5e6b3392b5..0000000000 --- a/src/Microsoft.Extensions.WebEncoders/Microsoft.Extensions.WebEncoders.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - Microsoft .NET Extensions - Contains registration and configuration APIs to add the core framework encoders to a dependency injection container. - netstandard2.0 - $(NoWarn);CS1591 - true - true - aspnetcore - - - - - - - - - diff --git a/src/Microsoft.Extensions.WebEncoders/Testing/HtmlTestEncoder.cs b/src/Microsoft.Extensions.WebEncoders/Testing/HtmlTestEncoder.cs deleted file mode 100644 index 162ce4f6c1..0000000000 --- a/src/Microsoft.Extensions.WebEncoders/Testing/HtmlTestEncoder.cs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Text.Encodings.Web; - -namespace Microsoft.Extensions.WebEncoders.Testing -{ - /// - /// Encoder used for unit testing. - /// - public sealed class HtmlTestEncoder : HtmlEncoder - { - public override int MaxOutputCharactersPerInputCharacter - { - get { return 1; } - } - - public override string Encode(string value) - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (value.Length == 0) - { - return string.Empty; - } - - return $"HtmlEncode[[{value}]]"; - } - - public override void Encode(TextWriter output, char[] value, int startIndex, int characterCount) - { - if (output == null) - { - throw new ArgumentNullException(nameof(output)); - } - - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (characterCount == 0) - { - return; - } - - output.Write("HtmlEncode[["); - output.Write(value, startIndex, characterCount); - output.Write("]]"); - } - - public override void Encode(TextWriter output, string value, int startIndex, int characterCount) - { - if (output == null) - { - throw new ArgumentNullException(nameof(output)); - } - - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (characterCount == 0) - { - return; - } - - output.Write("HtmlEncode[["); - output.Write(value.Substring(startIndex, characterCount)); - output.Write("]]"); - } - - public override bool WillEncode(int unicodeScalar) - { - return false; - } - - public override unsafe int FindFirstCharacterToEncode(char* text, int textLength) - { - return -1; - } - - public override unsafe bool TryEncodeUnicodeScalar( - int unicodeScalar, - char* buffer, - int bufferLength, - out int numberOfCharactersWritten) - { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - - numberOfCharactersWritten = 0; - return false; - } - } -} \ No newline at end of file diff --git a/src/Microsoft.Extensions.WebEncoders/Testing/JavaScriptTestEncoder.cs b/src/Microsoft.Extensions.WebEncoders/Testing/JavaScriptTestEncoder.cs deleted file mode 100644 index bef4461676..0000000000 --- a/src/Microsoft.Extensions.WebEncoders/Testing/JavaScriptTestEncoder.cs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Text.Encodings.Web; - -namespace Microsoft.Extensions.WebEncoders.Testing -{ - /// - /// Encoder used for unit testing. - /// - public class JavaScriptTestEncoder : JavaScriptEncoder - { - public override int MaxOutputCharactersPerInputCharacter - { - get { return 1; } - } - - public override string Encode(string value) - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (value.Length == 0) - { - return string.Empty; - } - - return $"JavaScriptEncode[[{value}]]"; - } - - public override void Encode(TextWriter output, char[] value, int startIndex, int characterCount) - { - if (output == null) - { - throw new ArgumentNullException(nameof(output)); - } - - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (characterCount == 0) - { - return; - } - - output.Write("JavaScriptEncode[["); - output.Write(value, startIndex, characterCount); - output.Write("]]"); - } - - public override void Encode(TextWriter output, string value, int startIndex, int characterCount) - { - if (output == null) - { - throw new ArgumentNullException(nameof(output)); - } - - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (characterCount == 0) - { - return; - } - - output.Write("JavaScriptEncode[["); - output.Write(value.Substring(startIndex, characterCount)); - output.Write("]]"); - } - - public override bool WillEncode(int unicodeScalar) - { - return false; - } - - public override unsafe int FindFirstCharacterToEncode(char* text, int textLength) - { - return -1; - } - - public override unsafe bool TryEncodeUnicodeScalar( - int unicodeScalar, - char* buffer, - int bufferLength, - out int numberOfCharactersWritten) - { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - - numberOfCharactersWritten = 0; - return false; - } - } -} \ No newline at end of file diff --git a/src/Microsoft.Extensions.WebEncoders/Testing/UrlTestEncoder.cs b/src/Microsoft.Extensions.WebEncoders/Testing/UrlTestEncoder.cs deleted file mode 100644 index 295bda63e8..0000000000 --- a/src/Microsoft.Extensions.WebEncoders/Testing/UrlTestEncoder.cs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Text.Encodings.Web; - -namespace Microsoft.Extensions.WebEncoders.Testing -{ - /// - /// Encoder used for unit testing. - /// - public class UrlTestEncoder : UrlEncoder - { - public override int MaxOutputCharactersPerInputCharacter - { - get { return 1; } - } - - public override string Encode(string value) - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (value.Length == 0) - { - return string.Empty; - } - - return $"UrlEncode[[{value}]]"; - } - - public override void Encode(TextWriter output, char[] value, int startIndex, int characterCount) - { - if (output == null) - { - throw new ArgumentNullException(nameof(output)); - } - - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (characterCount == 0) - { - return; - } - - output.Write("UrlEncode[["); - output.Write(value, startIndex, characterCount); - output.Write("]]"); - } - - public override void Encode(TextWriter output, string value, int startIndex, int characterCount) - { - if (output == null) - { - throw new ArgumentNullException(nameof(output)); - } - - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (characterCount == 0) - { - return; - } - - output.Write("UrlEncode[["); - output.Write(value.Substring(startIndex, characterCount)); - output.Write("]]"); - } - - public override bool WillEncode(int unicodeScalar) - { - return false; - } - - public override unsafe int FindFirstCharacterToEncode(char* text, int textLength) - { - return -1; - } - - public override unsafe bool TryEncodeUnicodeScalar( - int unicodeScalar, - char* buffer, - int bufferLength, - out int numberOfCharactersWritten) - { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - - numberOfCharactersWritten = 0; - return false; - } - } -} \ No newline at end of file diff --git a/src/Microsoft.Extensions.WebEncoders/WebEncoderOptions.cs b/src/Microsoft.Extensions.WebEncoders/WebEncoderOptions.cs deleted file mode 100644 index 2f5e770a0c..0000000000 --- a/src/Microsoft.Extensions.WebEncoders/WebEncoderOptions.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Text.Encodings.Web; - -namespace Microsoft.Extensions.WebEncoders -{ - /// - /// Specifies options common to all three encoders (HtmlEncode, JavaScriptEncode, UrlEncode). - /// - public sealed class WebEncoderOptions - { - /// - /// Specifies which code points are allowed to be represented unescaped by the encoders. - /// - /// - /// If this property is null, then the encoders will use their default allow lists. - /// - public TextEncoderSettings TextEncoderSettings { get; set; } - } -} diff --git a/src/Microsoft.Extensions.WebEncoders/baseline.netcore.json b/src/Microsoft.Extensions.WebEncoders/baseline.netcore.json deleted file mode 100644 index 6da0ae0754..0000000000 --- a/src/Microsoft.Extensions.WebEncoders/baseline.netcore.json +++ /dev/null @@ -1,564 +0,0 @@ -{ - "AssemblyIdentity": "Microsoft.Extensions.WebEncoders, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", - "Types": [ - { - "Name": "Microsoft.Extensions.WebEncoders.WebEncoderOptions", - "Visibility": "Public", - "Kind": "Class", - "Sealed": true, - "ImplementedInterfaces": [], - "Members": [ - { - "Kind": "Method", - "Name": "get_TextEncoderSettings", - "Parameters": [], - "ReturnType": "System.Text.Encodings.Web.TextEncoderSettings", - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "set_TextEncoderSettings", - "Parameters": [ - { - "Name": "value", - "Type": "System.Text.Encodings.Web.TextEncoderSettings" - } - ], - "ReturnType": "System.Void", - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Constructor", - "Name": ".ctor", - "Parameters": [], - "Visibility": "Public", - "GenericParameter": [] - } - ], - "GenericParameters": [] - }, - { - "Name": "Microsoft.Extensions.WebEncoders.Testing.HtmlTestEncoder", - "Visibility": "Public", - "Kind": "Class", - "Sealed": true, - "BaseType": "System.Text.Encodings.Web.HtmlEncoder", - "ImplementedInterfaces": [], - "Members": [ - { - "Kind": "Method", - "Name": "get_MaxOutputCharactersPerInputCharacter", - "Parameters": [], - "ReturnType": "System.Int32", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "Encode", - "Parameters": [ - { - "Name": "value", - "Type": "System.String" - } - ], - "ReturnType": "System.String", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "Encode", - "Parameters": [ - { - "Name": "output", - "Type": "System.IO.TextWriter" - }, - { - "Name": "value", - "Type": "System.Char[]" - }, - { - "Name": "startIndex", - "Type": "System.Int32" - }, - { - "Name": "characterCount", - "Type": "System.Int32" - } - ], - "ReturnType": "System.Void", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "Encode", - "Parameters": [ - { - "Name": "output", - "Type": "System.IO.TextWriter" - }, - { - "Name": "value", - "Type": "System.String" - }, - { - "Name": "startIndex", - "Type": "System.Int32" - }, - { - "Name": "characterCount", - "Type": "System.Int32" - } - ], - "ReturnType": "System.Void", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "WillEncode", - "Parameters": [ - { - "Name": "unicodeScalar", - "Type": "System.Int32" - } - ], - "ReturnType": "System.Boolean", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "FindFirstCharacterToEncode", - "Parameters": [ - { - "Name": "text", - "Type": "System.Char*" - }, - { - "Name": "textLength", - "Type": "System.Int32" - } - ], - "ReturnType": "System.Int32", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "TryEncodeUnicodeScalar", - "Parameters": [ - { - "Name": "unicodeScalar", - "Type": "System.Int32" - }, - { - "Name": "buffer", - "Type": "System.Char*" - }, - { - "Name": "bufferLength", - "Type": "System.Int32" - }, - { - "Name": "numberOfCharactersWritten", - "Type": "System.Int32", - "Direction": "Out" - } - ], - "ReturnType": "System.Boolean", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Constructor", - "Name": ".ctor", - "Parameters": [], - "Visibility": "Public", - "GenericParameter": [] - } - ], - "GenericParameters": [] - }, - { - "Name": "Microsoft.Extensions.WebEncoders.Testing.JavaScriptTestEncoder", - "Visibility": "Public", - "Kind": "Class", - "BaseType": "System.Text.Encodings.Web.JavaScriptEncoder", - "ImplementedInterfaces": [], - "Members": [ - { - "Kind": "Method", - "Name": "get_MaxOutputCharactersPerInputCharacter", - "Parameters": [], - "ReturnType": "System.Int32", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "Encode", - "Parameters": [ - { - "Name": "value", - "Type": "System.String" - } - ], - "ReturnType": "System.String", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "Encode", - "Parameters": [ - { - "Name": "output", - "Type": "System.IO.TextWriter" - }, - { - "Name": "value", - "Type": "System.Char[]" - }, - { - "Name": "startIndex", - "Type": "System.Int32" - }, - { - "Name": "characterCount", - "Type": "System.Int32" - } - ], - "ReturnType": "System.Void", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "Encode", - "Parameters": [ - { - "Name": "output", - "Type": "System.IO.TextWriter" - }, - { - "Name": "value", - "Type": "System.String" - }, - { - "Name": "startIndex", - "Type": "System.Int32" - }, - { - "Name": "characterCount", - "Type": "System.Int32" - } - ], - "ReturnType": "System.Void", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "WillEncode", - "Parameters": [ - { - "Name": "unicodeScalar", - "Type": "System.Int32" - } - ], - "ReturnType": "System.Boolean", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "FindFirstCharacterToEncode", - "Parameters": [ - { - "Name": "text", - "Type": "System.Char*" - }, - { - "Name": "textLength", - "Type": "System.Int32" - } - ], - "ReturnType": "System.Int32", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "TryEncodeUnicodeScalar", - "Parameters": [ - { - "Name": "unicodeScalar", - "Type": "System.Int32" - }, - { - "Name": "buffer", - "Type": "System.Char*" - }, - { - "Name": "bufferLength", - "Type": "System.Int32" - }, - { - "Name": "numberOfCharactersWritten", - "Type": "System.Int32", - "Direction": "Out" - } - ], - "ReturnType": "System.Boolean", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Constructor", - "Name": ".ctor", - "Parameters": [], - "Visibility": "Public", - "GenericParameter": [] - } - ], - "GenericParameters": [] - }, - { - "Name": "Microsoft.Extensions.WebEncoders.Testing.UrlTestEncoder", - "Visibility": "Public", - "Kind": "Class", - "BaseType": "System.Text.Encodings.Web.UrlEncoder", - "ImplementedInterfaces": [], - "Members": [ - { - "Kind": "Method", - "Name": "get_MaxOutputCharactersPerInputCharacter", - "Parameters": [], - "ReturnType": "System.Int32", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "Encode", - "Parameters": [ - { - "Name": "value", - "Type": "System.String" - } - ], - "ReturnType": "System.String", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "Encode", - "Parameters": [ - { - "Name": "output", - "Type": "System.IO.TextWriter" - }, - { - "Name": "value", - "Type": "System.Char[]" - }, - { - "Name": "startIndex", - "Type": "System.Int32" - }, - { - "Name": "characterCount", - "Type": "System.Int32" - } - ], - "ReturnType": "System.Void", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "Encode", - "Parameters": [ - { - "Name": "output", - "Type": "System.IO.TextWriter" - }, - { - "Name": "value", - "Type": "System.String" - }, - { - "Name": "startIndex", - "Type": "System.Int32" - }, - { - "Name": "characterCount", - "Type": "System.Int32" - } - ], - "ReturnType": "System.Void", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "WillEncode", - "Parameters": [ - { - "Name": "unicodeScalar", - "Type": "System.Int32" - } - ], - "ReturnType": "System.Boolean", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "FindFirstCharacterToEncode", - "Parameters": [ - { - "Name": "text", - "Type": "System.Char*" - }, - { - "Name": "textLength", - "Type": "System.Int32" - } - ], - "ReturnType": "System.Int32", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "TryEncodeUnicodeScalar", - "Parameters": [ - { - "Name": "unicodeScalar", - "Type": "System.Int32" - }, - { - "Name": "buffer", - "Type": "System.Char*" - }, - { - "Name": "bufferLength", - "Type": "System.Int32" - }, - { - "Name": "numberOfCharactersWritten", - "Type": "System.Int32", - "Direction": "Out" - } - ], - "ReturnType": "System.Boolean", - "Virtual": true, - "Override": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Constructor", - "Name": ".ctor", - "Parameters": [], - "Visibility": "Public", - "GenericParameter": [] - } - ], - "GenericParameters": [] - }, - { - "Name": "Microsoft.Extensions.DependencyInjection.EncoderServiceCollectionExtensions", - "Visibility": "Public", - "Kind": "Class", - "Abstract": true, - "Static": true, - "Sealed": true, - "ImplementedInterfaces": [], - "Members": [ - { - "Kind": "Method", - "Name": "AddWebEncoders", - "Parameters": [ - { - "Name": "services", - "Type": "Microsoft.Extensions.DependencyInjection.IServiceCollection" - } - ], - "ReturnType": "Microsoft.Extensions.DependencyInjection.IServiceCollection", - "Static": true, - "Extension": true, - "Visibility": "Public", - "GenericParameter": [] - }, - { - "Kind": "Method", - "Name": "AddWebEncoders", - "Parameters": [ - { - "Name": "services", - "Type": "Microsoft.Extensions.DependencyInjection.IServiceCollection" - }, - { - "Name": "setupAction", - "Type": "System.Action" - } - ], - "ReturnType": "Microsoft.Extensions.DependencyInjection.IServiceCollection", - "Static": true, - "Extension": true, - "Visibility": "Public", - "GenericParameter": [] - } - ], - "GenericParameters": [] - } - ] -} \ No newline at end of file diff --git a/test/Directory.Build.props b/test/Directory.Build.props deleted file mode 100644 index 0b706cbca5..0000000000 --- a/test/Directory.Build.props +++ /dev/null @@ -1,17 +0,0 @@ - - - - - netcoreapp2.1 - $(DeveloperBuildTestTfms) - netcoreapp2.1;netcoreapp2.0 - $(StandardTestTfms);net461 - - - - - - - - - diff --git a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj b/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj deleted file mode 100755 index 1577693497..0000000000 --- a/test/Microsoft.AspNetCore.Html.Abstractions.Test/Microsoft.AspNetCore.Html.Abstractions.Test.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - $(StandardTestTfms) - - - - - - - - diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/EncoderServiceCollectionExtensionsTests.cs b/test/Microsoft.Extensions.WebEncoders.Tests/EncoderServiceCollectionExtensionsTests.cs deleted file mode 100644 index 0178bba2d5..0000000000 --- a/test/Microsoft.Extensions.WebEncoders.Tests/EncoderServiceCollectionExtensionsTests.cs +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Text.Encodings.Web; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.WebEncoders.Testing; -using Xunit; - -namespace Microsoft.Extensions.WebEncoders -{ - public class EncoderServiceCollectionExtensionsTests - { - [Fact] - public void AddWebEncoders_WithoutOptions_RegistersDefaultEncoders() - { - // Arrange - var serviceCollection = new ServiceCollection(); - - // Act - serviceCollection.AddWebEncoders(); - - // Assert - var serviceProvider = serviceCollection.BuildServiceProvider(); - Assert.Same(HtmlEncoder.Default, serviceProvider.GetRequiredService()); // default encoder - Assert.Same(HtmlEncoder.Default, serviceProvider.GetRequiredService()); // as singleton instance - Assert.Same(JavaScriptEncoder.Default, serviceProvider.GetRequiredService()); // default encoder - Assert.Same(JavaScriptEncoder.Default, serviceProvider.GetRequiredService()); // as singleton instance - Assert.Same(UrlEncoder.Default, serviceProvider.GetRequiredService()); // default encoder - Assert.Same(UrlEncoder.Default, serviceProvider.GetRequiredService()); // as singleton instance - } - - [Fact] - public void AddWebEncoders_WithOptions_RegistersEncodersWithCustomCodeFilter() - { - // Arrange - var serviceCollection = new ServiceCollection(); - - // Act - serviceCollection.AddWebEncoders(options => - { - options.TextEncoderSettings = new TextEncoderSettings(); - options.TextEncoderSettings.AllowCharacters("ace".ToCharArray()); // only these three chars are allowed - }); - - // Assert - var serviceProvider = serviceCollection.BuildServiceProvider(); - - var htmlEncoder = serviceProvider.GetRequiredService(); - Assert.Equal("abcde", htmlEncoder.Encode("abcde")); - Assert.Same(htmlEncoder, serviceProvider.GetRequiredService()); // as singleton instance - - var javaScriptEncoder = serviceProvider.GetRequiredService(); - Assert.Equal(@"a\u0062c\u0064e", javaScriptEncoder.Encode("abcde")); - Assert.Same(javaScriptEncoder, serviceProvider.GetRequiredService()); // as singleton instance - - var urlEncoder = serviceProvider.GetRequiredService(); - Assert.Equal("a%62c%64e", urlEncoder.Encode("abcde")); - Assert.Same(urlEncoder, serviceProvider.GetRequiredService()); // as singleton instance - } - - [Fact] - public void AddWebEncoders_DoesNotOverrideExistingRegisteredEncoders() - { - // Arrange - var serviceCollection = new ServiceCollection(); - - // Act - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - // we don't register an existing URL encoder - serviceCollection.AddWebEncoders(options => - { - options.TextEncoderSettings = new TextEncoderSettings(); - options.TextEncoderSettings.AllowCharacters("ace".ToCharArray()); // only these three chars are allowed - }); - - // Assert - var serviceProvider = serviceCollection.BuildServiceProvider(); - - var htmlEncoder = serviceProvider.GetRequiredService(); - Assert.Equal("HtmlEncode[[abcde]]", htmlEncoder.Encode("abcde")); - - var javaScriptEncoder = serviceProvider.GetRequiredService(); - Assert.Equal("JavaScriptEncode[[abcde]]", javaScriptEncoder.Encode("abcde")); - - var urlEncoder = serviceProvider.GetRequiredService(); - Assert.Equal("a%62c%64e", urlEncoder.Encode("abcde")); - } - } -} diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/HtmlTestEncoderTest.cs b/test/Microsoft.Extensions.WebEncoders.Tests/HtmlTestEncoderTest.cs deleted file mode 100644 index baafedc4de..0000000000 --- a/test/Microsoft.Extensions.WebEncoders.Tests/HtmlTestEncoderTest.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Xunit; - -namespace Microsoft.Extensions.WebEncoders.Testing -{ - public class HtmlTestEncoderTest - { - [Theory] - [InlineData("", "")] - [InlineData("abcd", "HtmlEncode[[abcd]]")] - [InlineData("<<''\"\">>", "HtmlEncode[[<<''\"\">>]]")] - public void StringEncode_EncodesAsExpected(string input, string expectedOutput) - { - // Arrange - var encoder = new HtmlTestEncoder(); - - // Act - var output = encoder.Encode(input); - - // Assert - Assert.Equal(expectedOutput, output); - } - } -} diff --git a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj b/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj deleted file mode 100755 index 247ccd19b3..0000000000 --- a/test/Microsoft.Extensions.WebEncoders.Tests/Microsoft.Extensions.WebEncoders.Tests.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - $(StandardTestTfms) - - - - - - - - - - - diff --git a/version.props b/version.props deleted file mode 100644 index 669c874829..0000000000 --- a/version.props +++ /dev/null @@ -1,12 +0,0 @@ - - - 2.1.1 - rtm - $(VersionPrefix) - $(VersionPrefix)-$(VersionSuffix)-final - t000 - a- - $(FeatureBranchVersionPrefix)$(VersionSuffix)-$([System.Text.RegularExpressions.Regex]::Replace('$(FeatureBranchVersionSuffix)', '[^\w-]', '-')) - $(VersionSuffix)-$(BuildNumber) - - From 140cf62b569cc968325237117f31a6a50bce6601 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 9 Nov 2018 17:29:24 -0800 Subject: [PATCH 1017/1029] Re-enable SignCheck --- build/repo.props | 2 -- 1 file changed, 2 deletions(-) diff --git a/build/repo.props b/build/repo.props index 799ff45854..2c14e6176a 100644 --- a/build/repo.props +++ b/build/repo.props @@ -13,8 +13,6 @@ $(RepositoryRoot).deps\build\ $(RepositoryRoot).deps\Signed\Packages\ - - true $(RepositoryRoot)eng\signcheck.exclusions.txt true From 2fee09506e6810f56d28b6707e053ae0af99257c Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Sun, 11 Nov 2018 17:14:16 -0800 Subject: [PATCH 1018/1029] Update the SignalR module to correct code signing config --- modules/SignalR | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/SignalR b/modules/SignalR index df668017ee..a242dc726d 160000 --- a/modules/SignalR +++ b/modules/SignalR @@ -1 +1 @@ -Subproject commit df668017eebf98f8d724177d220712c0e6218114 +Subproject commit a242dc726d714e0a10ed423e1e526e8902b0fc2c From ce8cf65589734f82b0536c543aba5bd60d0a5a98 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Sun, 11 Nov 2018 20:24:57 -0800 Subject: [PATCH 1019/1029] Update SignalR submodule --- modules/SignalR | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/SignalR b/modules/SignalR index a242dc726d..a9def470e3 160000 --- a/modules/SignalR +++ b/modules/SignalR @@ -1 +1 @@ -Subproject commit a242dc726d714e0a10ed423e1e526e8902b0fc2c +Subproject commit a9def470e3b8e1480c55d1c311e4b37472140307 From de9609b34388d5472a84f4fe968d7d5d3a359e98 Mon Sep 17 00:00:00 2001 From: Justin Kotalik Date: Mon, 12 Nov 2018 09:05:17 -0800 Subject: [PATCH 1020/1029] Remove implicit reference to InteralAspNetCoreSdk (#3998) --- .../ANCMPackageResolver/ANCMPackageResolver.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMPackageResolver/ANCMPackageResolver.csproj b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMPackageResolver/ANCMPackageResolver.csproj index 591599ecca..561936aeaf 100644 --- a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMPackageResolver/ANCMPackageResolver.csproj +++ b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMPackageResolver/ANCMPackageResolver.csproj @@ -7,6 +7,7 @@ + From ee3e71e6bae52965c39e16fee4db70280528f46f Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Mon, 12 Nov 2018 20:03:45 +0000 Subject: [PATCH 1021/1029] Updating submodule(s) SignalR => b476df9acd22a403d9fe46ecb0feedf052035e39 [auto-updated: submodules] --- modules/SignalR | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/SignalR b/modules/SignalR index a9def470e3..b476df9acd 160000 --- a/modules/SignalR +++ b/modules/SignalR @@ -1 +1 @@ -Subproject commit a9def470e3b8e1480c55d1c311e4b37472140307 +Subproject commit b476df9acd22a403d9fe46ecb0feedf052035e39 From ed1976b8627ced537e1aa354b017faa5a0b90619 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 13 Nov 2018 10:02:59 -0800 Subject: [PATCH 1022/1029] Update BuildTools to 2.1.3-rtm-15845 --- build/repo.targets | 8 +------- korebuild-lock.txt | 4 ++-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/build/repo.targets b/build/repo.targets index 9e7e303327..602356a33f 100644 --- a/build/repo.targets +++ b/build/repo.targets @@ -306,14 +306,8 @@ Condition=" @(ExternalDependency->WithMetadataValue('Version', '')->Count()) != 0 " /> - - - $(BuildProperties);DesignTimeBuild=true - - - + DependsOnTargets="ComputeGraph;VerifyPackageArtifactConfig;VerifyAllReposHaveNuGetPackageVerifier" /> diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 7d2ac1cf8c..65061b1d21 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.3-rtm-15844 -commithash:8d031079e81ea30446712d48f7e8e9539fb92907 +version:2.1.3-rtm-15845 +commithash:c808c3c16cbc75c88ee39abd2e15569657312474 From ccd098ecad2dfb3404410a6d6eee629dbff3d9a8 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 13 Nov 2018 10:28:42 -0800 Subject: [PATCH 1023/1029] Update DataProtection to use custom reference resolution This changes DataProtection to build as projects instead of a pseudo-submodule. It replaces Package and ProjectReference with items which custom targets then resolve. --- .azure/pipelines/fast-pr-validation.yml | 2 +- Directory.Build.targets | 11 +++++-- build/PackageArchive.targets | 4 +-- build/buildorder.props | 1 - build/repo.props | 1 + build/repo.targets | 17 +++++++---- build/submodules.props | 1 - eng/Dependencies.props | 10 +++++-- eng/ProjectReferences.props | 9 ++++++ ...NetCore.DataProtection.Abstractions.csproj | 2 +- ...e.DataProtection.Abstractions.Tests.csproj | 4 +-- ...etCore.DataProtection.AzureKeyVault.csproj | 9 ++---- ....DataProtection.AzureKeyVault.Tests.csproj | 9 ++---- ...NetCore.DataProtection.AzureStorage.csproj | 7 ++--- ...e.DataProtection.AzureStorage.Tests.csproj | 9 ++---- ...NetCore.Cryptography.Internal.Tests.csproj | 2 +- ...pNetCore.Cryptography.KeyDerivation.csproj | 2 +- ...re.Cryptography.KeyDerivation.Tests.csproj | 4 +-- ...Microsoft.AspNetCore.DataProtection.csproj | 21 ++++++-------- ...oft.AspNetCore.DataProtection.Tests.csproj | 10 +++---- src/DataProtection/Directory.Build.props | 8 ----- ...spNetCore.DataProtection.Extensions.csproj | 7 ++--- ...ore.DataProtection.Extensions.Tests.csproj | 5 ++-- ...oft.AspNetCore.DataProtection.Redis.csproj | 7 ++--- ...pNetCore.DataProtection.Redis.Tests.csproj | 7 ++--- ...AspNetCore.DataProtection.SystemWeb.csproj | 7 ++--- src/DataProtection/dependencies.props | 29 ------------------- .../samples/AzureBlob/AzureBlob.csproj | 13 ++++----- .../AzureKeyVault/AzureKeyVault.csproj | 15 ++++------ .../CustomEncryptorSample.csproj | 11 +++---- .../KeyManagementSample.csproj | 4 +-- .../samples/NonDISample/NonDISample.csproj | 2 +- src/DataProtection/samples/Redis/Redis.csproj | 11 +++---- src/DataProtection/version.props | 18 ------------ 34 files changed, 104 insertions(+), 175 deletions(-) delete mode 100644 src/DataProtection/Directory.Build.props delete mode 100644 src/DataProtection/dependencies.props delete mode 100644 src/DataProtection/version.props diff --git a/.azure/pipelines/fast-pr-validation.yml b/.azure/pipelines/fast-pr-validation.yml index 5449521778..216f257ef1 100644 --- a/.azure/pipelines/fast-pr-validation.yml +++ b/.azure/pipelines/fast-pr-validation.yml @@ -16,7 +16,7 @@ jobs: agentOs: Windows beforeBuild: - powershell: "& ./src/IISIntegration/tools/UpdateIISExpressCertificate.ps1" - displayName: Setup IISExpress test certificates" + displayName: Setup IISExpress test certificates - template: jobs/iisintegration-job.yml parameters: variables: diff --git a/Directory.Build.targets b/Directory.Build.targets index a382d031d9..eea5ccac3a 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -22,9 +22,16 @@ - $(BaselinePackageVersion).0 $(BaselinePackageVersion).0 - $(BaselinePackageVersion) + + $(BaselinePackageVersion) + $(BaselinePackageVersion) diff --git a/build/PackageArchive.targets b/build/PackageArchive.targets index 5ba1cadcf8..c92c5455d3 100644 --- a/build/PackageArchive.targets +++ b/build/PackageArchive.targets @@ -8,9 +8,7 @@ - - - + DotNetRestoreSourcePropsPath=$(GeneratedRestoreSourcesPropsPath); diff --git a/build/buildorder.props b/build/buildorder.props index d3dd091d55..89ee48312e 100644 --- a/build/buildorder.props +++ b/build/buildorder.props @@ -12,7 +12,6 @@ - diff --git a/build/repo.props b/build/repo.props index 9023800398..dbda0b55d0 100644 --- a/build/repo.props +++ b/build/repo.props @@ -46,6 +46,7 @@ $(IntermediateDir)sources.g.props $(IntermediateDir)branding.g.props - SetTeamCityBuildNumberToVersion;$(PrepareDependsOn);VerifyPackageArtifactConfig;VerifyExternalDependencyConfig;PrepareOutputPaths + SetTeamCityBuildNumberToVersion;$(PrepareDependsOn) + $(PrepareDependsOn);VerifyPackageArtifactConfig;VerifyExternalDependencyConfig;PrepareOutputPaths $(CleanDependsOn);CleanArtifacts;CleanRepoArtifacts $(RestoreDependsOn);InstallDotNet;RestoreProjects - $(CompileDependsOn);BuildProjects;PackProjects;BuildRepositories - $(PackageDependsOn);BuildMetapackages;CheckExpectedPackagesExist - $(TestDependsOn);TestProjects;_TestRepositories - $(GetArtifactInfoDependsOn);GetProjectArtifactInfo;ResolveRepoInfo + $(CompileDependsOn);BuildProjects + $(CompileDependsOn);PackProjects;BuildRepositories + $(PackageDependsOn);PackProjects + $(PackageDependsOn);BuildMetapackages;CheckExpectedPackagesExist + $(TestDependsOn);TestProjects + $(TestDependsOn);_TestRepositories + $(GetArtifactInfoDependsOn);GetProjectArtifactInfo + $(GetArtifactInfoDependsOn);ResolveRepoInfo @@ -246,7 +251,7 @@ - + diff --git a/build/submodules.props b/build/submodules.props index d921cff07f..8db8e4fe1f 100644 --- a/build/submodules.props +++ b/build/submodules.props @@ -54,7 +54,6 @@ - diff --git a/eng/Dependencies.props b/eng/Dependencies.props index 6df8435a82..a8a2f8543d 100644 --- a/eng/Dependencies.props +++ b/eng/Dependencies.props @@ -11,11 +11,15 @@ - - - + + + + + + + diff --git a/eng/ProjectReferences.props b/eng/ProjectReferences.props index de8f54f37a..7d310275de 100644 --- a/eng/ProjectReferences.props +++ b/eng/ProjectReferences.props @@ -2,6 +2,15 @@ + + + + + + + + + diff --git a/src/DataProtection/Abstractions/src/Microsoft.AspNetCore.DataProtection.Abstractions.csproj b/src/DataProtection/Abstractions/src/Microsoft.AspNetCore.DataProtection.Abstractions.csproj index 94dc1366dd..021b3fde2c 100644 --- a/src/DataProtection/Abstractions/src/Microsoft.AspNetCore.DataProtection.Abstractions.csproj +++ b/src/DataProtection/Abstractions/src/Microsoft.AspNetCore.DataProtection.Abstractions.csproj @@ -15,7 +15,7 @@ Microsoft.AspNetCore.DataProtection.IDataProtector - + diff --git a/src/DataProtection/Abstractions/test/Microsoft.AspNetCore.DataProtection.Abstractions.Tests.csproj b/src/DataProtection/Abstractions/test/Microsoft.AspNetCore.DataProtection.Abstractions.Tests.csproj index 94ea16f046..6199bd2b24 100644 --- a/src/DataProtection/Abstractions/test/Microsoft.AspNetCore.DataProtection.Abstractions.Tests.csproj +++ b/src/DataProtection/Abstractions/test/Microsoft.AspNetCore.DataProtection.Abstractions.Tests.csproj @@ -5,8 +5,8 @@ - - + + diff --git a/src/DataProtection/AzureKeyVault/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault.csproj b/src/DataProtection/AzureKeyVault/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault.csproj index 86b9195c60..42aa2edb13 100644 --- a/src/DataProtection/AzureKeyVault/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault.csproj +++ b/src/DataProtection/AzureKeyVault/src/Microsoft.AspNetCore.DataProtection.AzureKeyVault.csproj @@ -9,12 +9,9 @@ - - - - - - + + + diff --git a/src/DataProtection/AzureKeyVault/test/Microsoft.AspNetCore.DataProtection.AzureKeyVault.Tests.csproj b/src/DataProtection/AzureKeyVault/test/Microsoft.AspNetCore.DataProtection.AzureKeyVault.Tests.csproj index 8a3e7b2de7..95a7d299fc 100644 --- a/src/DataProtection/AzureKeyVault/test/Microsoft.AspNetCore.DataProtection.AzureKeyVault.Tests.csproj +++ b/src/DataProtection/AzureKeyVault/test/Microsoft.AspNetCore.DataProtection.AzureKeyVault.Tests.csproj @@ -6,12 +6,9 @@ - - - - - - + + + diff --git a/src/DataProtection/AzureStorage/src/Microsoft.AspNetCore.DataProtection.AzureStorage.csproj b/src/DataProtection/AzureStorage/src/Microsoft.AspNetCore.DataProtection.AzureStorage.csproj index 368e6a9934..d65f55a425 100644 --- a/src/DataProtection/AzureStorage/src/Microsoft.AspNetCore.DataProtection.AzureStorage.csproj +++ b/src/DataProtection/AzureStorage/src/Microsoft.AspNetCore.DataProtection.AzureStorage.csproj @@ -9,11 +9,8 @@ - - - - - + + diff --git a/src/DataProtection/AzureStorage/test/Microsoft.AspNetCore.DataProtection.AzureStorage.Tests.csproj b/src/DataProtection/AzureStorage/test/Microsoft.AspNetCore.DataProtection.AzureStorage.Tests.csproj index be4ade7f7a..a8b6486901 100644 --- a/src/DataProtection/AzureStorage/test/Microsoft.AspNetCore.DataProtection.AzureStorage.Tests.csproj +++ b/src/DataProtection/AzureStorage/test/Microsoft.AspNetCore.DataProtection.AzureStorage.Tests.csproj @@ -6,12 +6,9 @@ - - - - - - + + + diff --git a/src/DataProtection/Cryptography.Internal/test/Microsoft.AspNetCore.Cryptography.Internal.Tests.csproj b/src/DataProtection/Cryptography.Internal/test/Microsoft.AspNetCore.Cryptography.Internal.Tests.csproj index 2a67e3345b..9bc42b1842 100644 --- a/src/DataProtection/Cryptography.Internal/test/Microsoft.AspNetCore.Cryptography.Internal.Tests.csproj +++ b/src/DataProtection/Cryptography.Internal/test/Microsoft.AspNetCore.Cryptography.Internal.Tests.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/DataProtection/Cryptography.KeyDerivation/src/Microsoft.AspNetCore.Cryptography.KeyDerivation.csproj b/src/DataProtection/Cryptography.KeyDerivation/src/Microsoft.AspNetCore.Cryptography.KeyDerivation.csproj index ac98d14665..668f7ca459 100644 --- a/src/DataProtection/Cryptography.KeyDerivation/src/Microsoft.AspNetCore.Cryptography.KeyDerivation.csproj +++ b/src/DataProtection/Cryptography.KeyDerivation/src/Microsoft.AspNetCore.Cryptography.KeyDerivation.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/DataProtection/Cryptography.KeyDerivation/test/Microsoft.AspNetCore.Cryptography.KeyDerivation.Tests.csproj b/src/DataProtection/Cryptography.KeyDerivation/test/Microsoft.AspNetCore.Cryptography.KeyDerivation.Tests.csproj index 3f6b273467..46b39d41bd 100644 --- a/src/DataProtection/Cryptography.KeyDerivation/test/Microsoft.AspNetCore.Cryptography.KeyDerivation.Tests.csproj +++ b/src/DataProtection/Cryptography.KeyDerivation/test/Microsoft.AspNetCore.Cryptography.KeyDerivation.Tests.csproj @@ -10,8 +10,8 @@ - - + + diff --git a/src/DataProtection/DataProtection/src/Microsoft.AspNetCore.DataProtection.csproj b/src/DataProtection/DataProtection/src/Microsoft.AspNetCore.DataProtection.csproj index 1428564533..18aa5ddc40 100644 --- a/src/DataProtection/DataProtection/src/Microsoft.AspNetCore.DataProtection.csproj +++ b/src/DataProtection/DataProtection/src/Microsoft.AspNetCore.DataProtection.csproj @@ -14,18 +14,15 @@ - - - - - - - - - - - - + + + + + + + + + diff --git a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests.csproj b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests.csproj index 7f505ef53a..81986fba41 100644 --- a/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests.csproj +++ b/src/DataProtection/DataProtection/test/Microsoft.AspNetCore.DataProtection.Tests.csproj @@ -11,12 +11,12 @@ - - + + - - - + + + diff --git a/src/DataProtection/Directory.Build.props b/src/DataProtection/Directory.Build.props deleted file mode 100644 index deb7bb4ee6..0000000000 --- a/src/DataProtection/Directory.Build.props +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/src/DataProtection/Extensions/src/Microsoft.AspNetCore.DataProtection.Extensions.csproj b/src/DataProtection/Extensions/src/Microsoft.AspNetCore.DataProtection.Extensions.csproj index e8335310e4..c106a52961 100644 --- a/src/DataProtection/Extensions/src/Microsoft.AspNetCore.DataProtection.Extensions.csproj +++ b/src/DataProtection/Extensions/src/Microsoft.AspNetCore.DataProtection.Extensions.csproj @@ -12,11 +12,8 @@ - - - - - + + diff --git a/src/DataProtection/Extensions/test/Microsoft.AspNetCore.DataProtection.Extensions.Tests.csproj b/src/DataProtection/Extensions/test/Microsoft.AspNetCore.DataProtection.Extensions.Tests.csproj index 24bd4c8933..da0be5fc69 100644 --- a/src/DataProtection/Extensions/test/Microsoft.AspNetCore.DataProtection.Extensions.Tests.csproj +++ b/src/DataProtection/Extensions/test/Microsoft.AspNetCore.DataProtection.Extensions.Tests.csproj @@ -10,8 +10,9 @@ - - + + + diff --git a/src/DataProtection/Redis/src/Microsoft.AspNetCore.DataProtection.Redis.csproj b/src/DataProtection/Redis/src/Microsoft.AspNetCore.DataProtection.Redis.csproj index 45ed6e5bc3..c5742bf3de 100644 --- a/src/DataProtection/Redis/src/Microsoft.AspNetCore.DataProtection.Redis.csproj +++ b/src/DataProtection/Redis/src/Microsoft.AspNetCore.DataProtection.Redis.csproj @@ -14,11 +14,8 @@ - - - - - + + diff --git a/src/DataProtection/Redis/test/Microsoft.AspNetCore.DataProtection.Redis.Tests.csproj b/src/DataProtection/Redis/test/Microsoft.AspNetCore.DataProtection.Redis.Tests.csproj index 426f2c2681..6bf56165bd 100644 --- a/src/DataProtection/Redis/test/Microsoft.AspNetCore.DataProtection.Redis.Tests.csproj +++ b/src/DataProtection/Redis/test/Microsoft.AspNetCore.DataProtection.Redis.Tests.csproj @@ -5,11 +5,8 @@ - - - - - + + diff --git a/src/DataProtection/SystemWeb/src/Microsoft.AspNetCore.DataProtection.SystemWeb.csproj b/src/DataProtection/SystemWeb/src/Microsoft.AspNetCore.DataProtection.SystemWeb.csproj index 03629c1de3..603fe68cc8 100644 --- a/src/DataProtection/SystemWeb/src/Microsoft.AspNetCore.DataProtection.SystemWeb.csproj +++ b/src/DataProtection/SystemWeb/src/Microsoft.AspNetCore.DataProtection.SystemWeb.csproj @@ -13,11 +13,8 @@ - - - - - + + diff --git a/src/DataProtection/dependencies.props b/src/DataProtection/dependencies.props deleted file mode 100644 index 7a7089d81f..0000000000 --- a/src/DataProtection/dependencies.props +++ /dev/null @@ -1,29 +0,0 @@ - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - - - - 2.1.3-rtm-15822 - - - - - 2.1.1 - 2.1.1 - 2.1.0 - 2.1.1 - 2.1.1 - 2.1.1 - 2.1.1 - 2.1.1 - 2.1.1 - 2.1.1 - 2.1.1 - 2.1.1 - - diff --git a/src/DataProtection/samples/AzureBlob/AzureBlob.csproj b/src/DataProtection/samples/AzureBlob/AzureBlob.csproj index 5863e186ab..226c012c96 100644 --- a/src/DataProtection/samples/AzureBlob/AzureBlob.csproj +++ b/src/DataProtection/samples/AzureBlob/AzureBlob.csproj @@ -6,14 +6,11 @@ - - - - - - - - + + + + + diff --git a/src/DataProtection/samples/AzureKeyVault/AzureKeyVault.csproj b/src/DataProtection/samples/AzureKeyVault/AzureKeyVault.csproj index cd9e5cd193..05fe9a940b 100644 --- a/src/DataProtection/samples/AzureKeyVault/AzureKeyVault.csproj +++ b/src/DataProtection/samples/AzureKeyVault/AzureKeyVault.csproj @@ -6,15 +6,12 @@ - - - - - - - - - + + + + + + diff --git a/src/DataProtection/samples/CustomEncryptorSample/CustomEncryptorSample.csproj b/src/DataProtection/samples/CustomEncryptorSample/CustomEncryptorSample.csproj index 3fd8400239..5dfda97978 100644 --- a/src/DataProtection/samples/CustomEncryptorSample/CustomEncryptorSample.csproj +++ b/src/DataProtection/samples/CustomEncryptorSample/CustomEncryptorSample.csproj @@ -6,13 +6,10 @@ - - - - - - - + + + + diff --git a/src/DataProtection/samples/KeyManagementSample/KeyManagementSample.csproj b/src/DataProtection/samples/KeyManagementSample/KeyManagementSample.csproj index 89141c6a0e..dffd36b3d5 100644 --- a/src/DataProtection/samples/KeyManagementSample/KeyManagementSample.csproj +++ b/src/DataProtection/samples/KeyManagementSample/KeyManagementSample.csproj @@ -6,8 +6,8 @@ - - + + diff --git a/src/DataProtection/samples/NonDISample/NonDISample.csproj b/src/DataProtection/samples/NonDISample/NonDISample.csproj index b305f80bf0..1573ddc7b1 100644 --- a/src/DataProtection/samples/NonDISample/NonDISample.csproj +++ b/src/DataProtection/samples/NonDISample/NonDISample.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/DataProtection/samples/Redis/Redis.csproj b/src/DataProtection/samples/Redis/Redis.csproj index 22e398ef9f..eae640279c 100644 --- a/src/DataProtection/samples/Redis/Redis.csproj +++ b/src/DataProtection/samples/Redis/Redis.csproj @@ -6,13 +6,10 @@ - - - - - - - + + + + diff --git a/src/DataProtection/version.props b/src/DataProtection/version.props deleted file mode 100644 index 6ecf2553b6..0000000000 --- a/src/DataProtection/version.props +++ /dev/null @@ -1,18 +0,0 @@ - - - 2.1.1 - rtm - $(VersionPrefix) - $(VersionPrefix)-$(VersionSuffix)-final - t000 - a- - $(FeatureBranchVersionPrefix)$(VersionSuffix)-$([System.Text.RegularExpressions.Regex]::Replace('$(FeatureBranchVersionSuffix)', '[^\w-]', '-')) - $(VersionSuffix)-$(BuildNumber) - - 0.4.1 - rtm - $(ExperimentalVersionPrefix) - $(ExperimentalVersionPrefix)-$(ExperimentalVersionSuffix)-final - $(ExperimentalVersionSuffix)-$(BuildNumber) - - From 25812764031111560a7585fbd4eee4ab5f5092f8 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 13 Nov 2018 18:34:13 +0000 Subject: [PATCH 1024/1029] Updating BuildTools from 2.1.3-rtm-15845 to 2.1.3-rtm-15846 [auto-updated: buildtools] --- korebuild-lock.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 65061b1d21..c662868420 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.1.3-rtm-15845 -commithash:c808c3c16cbc75c88ee39abd2e15569657312474 +version:2.1.3-rtm-15846 +commithash:2444fbdf4f909c90222129d39cc2f588bb14b414 From a2d855406b837c17f4119bfc9767e32182969194 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 13 Nov 2018 15:30:21 -0800 Subject: [PATCH 1025/1029] Reorganize source code in preparation to move into aspnet/AspNetCore Prior to reorganization, this source code was found in https://github.com/aspnet/DotNetTools/tree/eba014d534ef34ea88ce6c3879b92743b825a7fe --- .appveyor.yml | 17 -- .editorconfig | 24 -- .gitattributes | 52 ---- .gitignore | 37 --- .travis.yml | 27 -- .vsts-pipelines/builds/ci-internal.yml | 13 - .vsts-pipelines/builds/ci-public.yml | 15 - CONTRIBUTING.md | 4 - Directory.Build.props | 25 -- Directory.Build.targets | 6 - DotNetTools.sln | 162 ----------- LICENSE.txt | 14 - NuGet.config | 11 - README.md | 39 --- build.cmd | 2 - build.sh | 8 - build/Key.snk | Bin 596 -> 0 bytes build/VSIX.props | 9 - build/VSIX.targets | 120 -------- build/dependencies.props | 29 -- build/repo.props | 15 - build/repo.targets | 10 - build/sources.props | 18 -- .../NuGetPackageVerifier.json | 204 +++++++------- korebuild-lock.txt | 2 - korebuild.json | 16 -- run.cmd | 2 - run.ps1 | 210 -------------- run.sh | 259 ------------------ samples/dotnet-watch/Directory.Build.props | 2 - samples/dotnet-watch/Directory.Build.targets | 2 - .../LaunchAnyCommand/LaunchAnyCommand.csproj | 13 - .../dotnet-watch/LaunchAnyCommand/README.md | 17 -- .../LaunchAnyCommand/package.json | 8 - .../LaunchAnyCommand/say-hello.js | 1 - samples/dotnet-watch/README.md | 5 - .../WatchJavascriptFiles/Program.cs | 28 -- .../WatchJavascriptFiles/README.md | 16 -- .../WatchJavascriptFiles.csproj | 16 -- .../WatchJavascriptFiles/wwwroot/app.js | 1 - .../WatchMultipleProjects/README.md | 18 -- .../WatchMultipleProjects/Test/Test.csproj | 13 - .../WatchMultipleProjects/Test/UnitTest1.cs | 17 -- .../WatchMultipleProjects/Web/Program.cs | 28 -- .../WatchMultipleProjects/Web/Web.csproj | 15 - .../WatchMultipleProjects/watch.csproj | 17 -- src/Directory.Build.props | 7 - src/Directory.Build.targets | 7 - src/Tools/Directory.Build.targets | 7 + .../src}/CertificateGenerator.cs | 0 ...NetCore.DeveloperCertificates.XPlat.csproj | 2 +- src/Tools/README.md | 32 +++ src/{ => Tools}/dotnet-dev-certs/README.md | 0 .../dotnet-dev-certs/src}/Program.cs | 0 .../src/dotnet-dev-certs.csproj | 32 +++ src/{ => Tools}/dotnet-sql-cache/README.md | 0 .../dotnet-sql-cache/src}/Program.cs | 0 .../dotnet-sql-cache/src}/SqlQueries.cs | 0 .../src/dotnet-sql-cache.csproj | 30 ++ src/{ => Tools}/dotnet-user-secrets/README.md | 0 .../src}/CommandLineOptions.cs | 0 .../src}/Internal/ClearCommand.cs | 0 .../src}/Internal/CommandContext.cs | 0 .../src}/Internal/ICommand.cs | 0 .../src}/Internal/ListCommand.cs | 0 .../src}/Internal/MsBuildProjectFinder.cs | 0 .../src}/Internal/ProjectIdResolver.cs | 0 .../ReadableJsonConfigurationSource.cs | 0 .../src}/Internal/RemoveCommand.cs | 0 .../src}/Internal/SecretsStore.cs | 0 .../src}/Internal/SetCommand.cs | 0 .../dotnet-user-secrets/src}/Program.cs | 0 .../src}/Properties/AssemblyInfo.cs | 0 .../src}/Properties/Resources.Designer.cs | 0 .../dotnet-user-secrets/src}/Resources.resx | 0 .../src}/assets/SecretManager.targets | 0 .../src/dotnet-user-secrets.csproj | 42 +++ .../test}/MsBuildProjectFinderTest.cs | 0 .../test}/SecretManagerTests.cs | 0 .../test}/SetCommandTest.cs | 0 .../test}/TemporaryFileProvider.cs | 0 .../test}/UserSecretsTestFixture.cs | 0 .../test/dotnet-user-secrets.Tests.csproj | 21 ++ src/{ => Tools}/dotnet-watch/README.md | 0 .../dotnet-watch/src}/CommandLineOptions.cs | 0 .../dotnet-watch/src}/DotNetWatcher.cs | 0 .../dotnet-watch/src}/IFileSet.cs | 0 .../dotnet-watch/src}/IFileSetFactory.cs | 0 .../dotnet-watch/src}/Internal/FileSet.cs | 0 .../src}/Internal/FileSetWatcher.cs | 0 .../dotnet-watch/src}/Internal/FileWatcher.cs | 0 .../Internal/FileWatcher/DotnetFileWatcher.cs | 0 .../FileWatcher/FileWatcherFactory.cs | 0 .../FileWatcher/IFileSystemWatcher.cs | 0 .../FileWatcher/PollingFileWatcher.cs | 0 .../src}/Internal/MsBuildFileSetFactory.cs | 0 .../src}/Internal/MsBuildProjectFinder.cs | 0 .../src}/Internal/OutputCapture.cs | 0 .../dotnet-watch/src}/Internal/OutputSink.cs | 0 .../src}/Internal/ProcessRunner.cs | 0 .../src}/PrefixConsoleReporter.cs | 0 .../dotnet-watch/src}/ProcessSpec.cs | 0 .../dotnet-watch/src}/Program.cs | 0 .../src}/Properties/AssemblyInfo.cs | 0 .../src}/Properties/Resources.Designer.cs | 0 .../dotnet-watch/src}/Resources.resx | 0 .../src}/assets/DotNetWatch.targets | 0 .../dotnet-watch/src}/dotnet-watch.csproj | 0 .../dotnet-watch/test}/AppWithDepsTests.cs | 0 .../Tools/dotnet-watch/test}/AssertEx.cs | 0 .../dotnet-watch/test}/AwaitableProcess.cs | 0 .../test}/CommandLineOptionsTests.cs | 0 .../test}/ConsoleReporterTests.cs | 0 .../dotnet-watch/test}/DotNetWatcherTests.cs | 0 .../dotnet-watch/test}/FileWatcherTests.cs | 0 .../dotnet-watch/test}/GlobbingAppTests.cs | 0 .../test}/MsBuildFileSetFactoryTest.cs | 0 .../dotnet-watch/test}/NoDepsAppTests.cs | 0 .../Tools/dotnet-watch/test}/ProgramTests.cs | 0 .../test}/Scenario/ProjectToolScenario.cs | 0 .../test}/Scenario/WatchableApp.cs | 0 .../AppWithDeps/AppWithDeps.csproj | 0 .../test}/TestProjects/AppWithDeps/Program.cs | 0 .../TestProjects/Dependency/Dependency.csproj | 0 .../test}/TestProjects/Dependency/Foo.cs | 0 .../GlobbingApp/GlobbingApp.csproj | 0 .../test}/TestProjects/GlobbingApp/Program.cs | 0 .../TestProjects/GlobbingApp/exclude/Baz.cs | 0 .../TestProjects/GlobbingApp/include/Foo.cs | 0 .../KitchenSink/KitchenSink.csproj | 0 .../test}/TestProjects/KitchenSink/Program.cs | 0 .../TestProjects/NoDepsApp/NoDepsApp.csproj | 0 .../test}/TestProjects/NoDepsApp/Program.cs | 0 .../test}/Utilities/TemporaryCSharpProject.cs | 0 .../test}/Utilities/TemporaryDirectory.cs | 0 .../test}/Utilities/TestProjectGraph.cs | 0 .../test/dotnet-watch.Tests.csproj | 13 +- .../Tools/shared/src}/CliContext.cs | 0 .../src}/CommandLineApplicationExtensions.cs | 0 .../Tools/shared/src}/ConsoleReporter.cs | 0 .../Tools/shared/src}/DebugHelper.cs | 0 {shared => src/Tools/shared/src}/Ensure.cs | 0 {shared => src/Tools/shared/src}/IConsole.cs | 0 {shared => src/Tools/shared/src}/IReporter.cs | 0 .../Tools/shared/src}/NullReporter.cs | 0 .../Tools/shared/src}/PhysicalConsole.cs | 0 .../Tools/shared/test}/TestConsole.cs | 0 .../Tools/shared/test}/TestReporter.cs | 0 src/dotnet-dev-certs/dotnet-dev-certs.csproj | 32 --- src/dotnet-sql-cache/dotnet-sql-cache.csproj | 35 --- .../dotnet-user-secrets.csproj | 42 --- test/Directory.Build.props | 11 - .../dotnet-user-secrets.Tests.csproj | 21 -- .../dotnet-watch.Tests.csproj | 16 -- .../Key.snk | Bin 596 -> 0 bytes ...lStudio.SecretManager.TestExtension.csproj | 149 ---------- .../NotifyPropertyChanged.cs | 18 -- .../ProjectViewModel.cs | 20 -- .../Properties/AssemblyInfo.cs | 33 --- .../RelayCommand.cs | 44 --- .../Resources/SecretManagerTestCommand.png | Bin 1172 -> 0 bytes .../Resources/SecretManagerTestPackage.ico | Bin 428446 -> 0 bytes .../SecretManagerTestCommand.cs | 100 ------- .../SecretManagerTestControl.xaml | 87 ------ .../SecretManagerTestControl.xaml.cs | 37 --- .../SecretManagerTestPackage.cs | 27 -- .../SecretManagerTestPackage.vsct | 83 ------ .../SecretManagerTestWindow.cs | 31 --- .../SecretManagerViewModel.cs | 214 --------------- .../VSPackage.resx | 140 ---------- .../app.config | 27 -- .../source.extension.vsixmanifest | 21 -- ...icrosoft.VisualStudio.SecretManager.csproj | 117 -------- .../ProjectLocalSecretsManager.cs | 148 ---------- .../Properties/AssemblyInfo.cs | 16 -- .../Resources.Designer.cs | 140 ---------- .../Resources.resx | 146 ---------- .../SecretManagerFactory.cs | 37 --- .../SecretStore.cs | 169 ------------ .../Sources/ConfigurationPath.cs | 79 ------ .../Sources/JsonConfigurationFileParser.cs | 120 -------- .../Sources/PathHelper.cs | 57 ---- .../source.extension.vsixmanifest | 22 -- version.props | 15 - 184 files changed, 273 insertions(+), 3741 deletions(-) delete mode 100644 .appveyor.yml delete mode 100644 .editorconfig delete mode 100644 .gitattributes delete mode 100644 .gitignore delete mode 100644 .travis.yml delete mode 100644 .vsts-pipelines/builds/ci-internal.yml delete mode 100644 .vsts-pipelines/builds/ci-public.yml delete mode 100644 CONTRIBUTING.md delete mode 100644 Directory.Build.props delete mode 100644 Directory.Build.targets delete mode 100644 DotNetTools.sln delete mode 100644 LICENSE.txt delete mode 100644 NuGet.config delete mode 100644 README.md delete mode 100644 build.cmd delete mode 100755 build.sh delete mode 100644 build/Key.snk delete mode 100644 build/VSIX.props delete mode 100644 build/VSIX.targets delete mode 100644 build/dependencies.props delete mode 100644 build/repo.props delete mode 100644 build/repo.targets delete mode 100644 build/sources.props rename NuGetPackageVerifier.json => eng/NuGetPackageVerifier.json (98%) delete mode 100644 korebuild-lock.txt delete mode 100644 korebuild.json delete mode 100644 run.cmd delete mode 100644 run.ps1 delete mode 100755 run.sh delete mode 100644 samples/dotnet-watch/Directory.Build.props delete mode 100644 samples/dotnet-watch/Directory.Build.targets delete mode 100644 samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj delete mode 100644 samples/dotnet-watch/LaunchAnyCommand/README.md delete mode 100644 samples/dotnet-watch/LaunchAnyCommand/package.json delete mode 100644 samples/dotnet-watch/LaunchAnyCommand/say-hello.js delete mode 100644 samples/dotnet-watch/README.md delete mode 100755 samples/dotnet-watch/WatchJavascriptFiles/Program.cs delete mode 100644 samples/dotnet-watch/WatchJavascriptFiles/README.md delete mode 100755 samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj delete mode 100644 samples/dotnet-watch/WatchJavascriptFiles/wwwroot/app.js delete mode 100644 samples/dotnet-watch/WatchMultipleProjects/README.md delete mode 100755 samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj delete mode 100755 samples/dotnet-watch/WatchMultipleProjects/Test/UnitTest1.cs delete mode 100755 samples/dotnet-watch/WatchMultipleProjects/Web/Program.cs delete mode 100755 samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj delete mode 100644 samples/dotnet-watch/WatchMultipleProjects/watch.csproj delete mode 100644 src/Directory.Build.props delete mode 100644 src/Directory.Build.targets create mode 100644 src/Tools/Directory.Build.targets rename src/{Microsoft.AspNetCore.DeveloperCertificates.XPlat => Tools/FirstRunCertGenerator/src}/CertificateGenerator.cs (100%) rename src/{Microsoft.AspNetCore.DeveloperCertificates.XPlat => Tools/FirstRunCertGenerator/src}/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj (65%) create mode 100644 src/Tools/README.md rename src/{ => Tools}/dotnet-dev-certs/README.md (100%) rename src/{dotnet-dev-certs => Tools/dotnet-dev-certs/src}/Program.cs (100%) create mode 100644 src/Tools/dotnet-dev-certs/src/dotnet-dev-certs.csproj rename src/{ => Tools}/dotnet-sql-cache/README.md (100%) rename src/{dotnet-sql-cache => Tools/dotnet-sql-cache/src}/Program.cs (100%) rename src/{dotnet-sql-cache => Tools/dotnet-sql-cache/src}/SqlQueries.cs (100%) create mode 100644 src/Tools/dotnet-sql-cache/src/dotnet-sql-cache.csproj rename src/{ => Tools}/dotnet-user-secrets/README.md (100%) rename src/{dotnet-user-secrets => Tools/dotnet-user-secrets/src}/CommandLineOptions.cs (100%) rename src/{dotnet-user-secrets => Tools/dotnet-user-secrets/src}/Internal/ClearCommand.cs (100%) rename src/{dotnet-user-secrets => Tools/dotnet-user-secrets/src}/Internal/CommandContext.cs (100%) rename src/{dotnet-user-secrets => Tools/dotnet-user-secrets/src}/Internal/ICommand.cs (100%) rename src/{dotnet-user-secrets => Tools/dotnet-user-secrets/src}/Internal/ListCommand.cs (100%) rename src/{dotnet-user-secrets => Tools/dotnet-user-secrets/src}/Internal/MsBuildProjectFinder.cs (100%) rename src/{dotnet-user-secrets => Tools/dotnet-user-secrets/src}/Internal/ProjectIdResolver.cs (100%) rename src/{dotnet-user-secrets => Tools/dotnet-user-secrets/src}/Internal/ReadableJsonConfigurationSource.cs (100%) rename src/{dotnet-user-secrets => Tools/dotnet-user-secrets/src}/Internal/RemoveCommand.cs (100%) rename src/{dotnet-user-secrets => Tools/dotnet-user-secrets/src}/Internal/SecretsStore.cs (100%) rename src/{dotnet-user-secrets => Tools/dotnet-user-secrets/src}/Internal/SetCommand.cs (100%) rename src/{dotnet-user-secrets => Tools/dotnet-user-secrets/src}/Program.cs (100%) rename src/{dotnet-user-secrets => Tools/dotnet-user-secrets/src}/Properties/AssemblyInfo.cs (100%) rename src/{dotnet-user-secrets => Tools/dotnet-user-secrets/src}/Properties/Resources.Designer.cs (100%) rename src/{dotnet-user-secrets => Tools/dotnet-user-secrets/src}/Resources.resx (100%) rename src/{dotnet-user-secrets => Tools/dotnet-user-secrets/src}/assets/SecretManager.targets (100%) create mode 100644 src/Tools/dotnet-user-secrets/src/dotnet-user-secrets.csproj rename {test/dotnet-user-secrets.Tests => src/Tools/dotnet-user-secrets/test}/MsBuildProjectFinderTest.cs (100%) rename {test/dotnet-user-secrets.Tests => src/Tools/dotnet-user-secrets/test}/SecretManagerTests.cs (100%) rename {test/dotnet-user-secrets.Tests => src/Tools/dotnet-user-secrets/test}/SetCommandTest.cs (100%) rename {test/dotnet-user-secrets.Tests => src/Tools/dotnet-user-secrets/test}/TemporaryFileProvider.cs (100%) rename {test/dotnet-user-secrets.Tests => src/Tools/dotnet-user-secrets/test}/UserSecretsTestFixture.cs (100%) create mode 100644 src/Tools/dotnet-user-secrets/test/dotnet-user-secrets.Tests.csproj rename src/{ => Tools}/dotnet-watch/README.md (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/CommandLineOptions.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/DotNetWatcher.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/IFileSet.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/IFileSetFactory.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/Internal/FileSet.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/Internal/FileSetWatcher.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/Internal/FileWatcher.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/Internal/FileWatcher/DotnetFileWatcher.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/Internal/FileWatcher/FileWatcherFactory.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/Internal/FileWatcher/IFileSystemWatcher.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/Internal/FileWatcher/PollingFileWatcher.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/Internal/MsBuildFileSetFactory.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/Internal/MsBuildProjectFinder.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/Internal/OutputCapture.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/Internal/OutputSink.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/Internal/ProcessRunner.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/PrefixConsoleReporter.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/ProcessSpec.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/Program.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/Properties/AssemblyInfo.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/Properties/Resources.Designer.cs (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/Resources.resx (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/assets/DotNetWatch.targets (100%) rename src/{dotnet-watch => Tools/dotnet-watch/src}/dotnet-watch.csproj (100%) rename {test/dotnet-watch.FunctionalTests => src/Tools/dotnet-watch/test}/AppWithDepsTests.cs (100%) rename {test/dotnet-watch.Tests => src/Tools/dotnet-watch/test}/AssertEx.cs (100%) rename {test/dotnet-watch.FunctionalTests => src/Tools/dotnet-watch/test}/AwaitableProcess.cs (100%) rename {test/dotnet-watch.Tests => src/Tools/dotnet-watch/test}/CommandLineOptionsTests.cs (100%) rename {test/dotnet-watch.Tests => src/Tools/dotnet-watch/test}/ConsoleReporterTests.cs (100%) rename {test/dotnet-watch.FunctionalTests => src/Tools/dotnet-watch/test}/DotNetWatcherTests.cs (100%) rename {test/dotnet-watch.FunctionalTests => src/Tools/dotnet-watch/test}/FileWatcherTests.cs (100%) rename {test/dotnet-watch.FunctionalTests => src/Tools/dotnet-watch/test}/GlobbingAppTests.cs (100%) rename {test/dotnet-watch.Tests => src/Tools/dotnet-watch/test}/MsBuildFileSetFactoryTest.cs (100%) rename {test/dotnet-watch.FunctionalTests => src/Tools/dotnet-watch/test}/NoDepsAppTests.cs (100%) rename {test/dotnet-watch.Tests => src/Tools/dotnet-watch/test}/ProgramTests.cs (100%) rename {test/dotnet-watch.FunctionalTests => src/Tools/dotnet-watch/test}/Scenario/ProjectToolScenario.cs (100%) rename {test/dotnet-watch.FunctionalTests => src/Tools/dotnet-watch/test}/Scenario/WatchableApp.cs (100%) rename {test/dotnet-watch.FunctionalTests => src/Tools/dotnet-watch/test}/TestProjects/AppWithDeps/AppWithDeps.csproj (100%) rename {test/dotnet-watch.FunctionalTests => src/Tools/dotnet-watch/test}/TestProjects/AppWithDeps/Program.cs (100%) rename {test/dotnet-watch.FunctionalTests => src/Tools/dotnet-watch/test}/TestProjects/Dependency/Dependency.csproj (100%) rename {test/dotnet-watch.FunctionalTests => src/Tools/dotnet-watch/test}/TestProjects/Dependency/Foo.cs (100%) rename {test/dotnet-watch.FunctionalTests => src/Tools/dotnet-watch/test}/TestProjects/GlobbingApp/GlobbingApp.csproj (100%) rename {test/dotnet-watch.FunctionalTests => src/Tools/dotnet-watch/test}/TestProjects/GlobbingApp/Program.cs (100%) rename {test/dotnet-watch.FunctionalTests => src/Tools/dotnet-watch/test}/TestProjects/GlobbingApp/exclude/Baz.cs (100%) rename {test/dotnet-watch.FunctionalTests => src/Tools/dotnet-watch/test}/TestProjects/GlobbingApp/include/Foo.cs (100%) rename {test/dotnet-watch.FunctionalTests => src/Tools/dotnet-watch/test}/TestProjects/KitchenSink/KitchenSink.csproj (100%) rename {test/dotnet-watch.FunctionalTests => src/Tools/dotnet-watch/test}/TestProjects/KitchenSink/Program.cs (100%) rename {test/dotnet-watch.FunctionalTests => src/Tools/dotnet-watch/test}/TestProjects/NoDepsApp/NoDepsApp.csproj (100%) rename {test/dotnet-watch.FunctionalTests => src/Tools/dotnet-watch/test}/TestProjects/NoDepsApp/Program.cs (100%) rename {test/dotnet-watch.Tests => src/Tools/dotnet-watch/test}/Utilities/TemporaryCSharpProject.cs (100%) rename {test/dotnet-watch.Tests => src/Tools/dotnet-watch/test}/Utilities/TemporaryDirectory.cs (100%) rename {test/dotnet-watch.Tests => src/Tools/dotnet-watch/test}/Utilities/TestProjectGraph.cs (100%) rename test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj => src/Tools/dotnet-watch/test/dotnet-watch.Tests.csproj (64%) rename {shared => src/Tools/shared/src}/CliContext.cs (100%) rename {shared => src/Tools/shared/src}/CommandLineApplicationExtensions.cs (100%) rename {shared => src/Tools/shared/src}/ConsoleReporter.cs (100%) rename {shared => src/Tools/shared/src}/DebugHelper.cs (100%) rename {shared => src/Tools/shared/src}/Ensure.cs (100%) rename {shared => src/Tools/shared/src}/IConsole.cs (100%) rename {shared => src/Tools/shared/src}/IReporter.cs (100%) rename {shared => src/Tools/shared/src}/NullReporter.cs (100%) rename {shared => src/Tools/shared/src}/PhysicalConsole.cs (100%) rename {test/Shared => src/Tools/shared/test}/TestConsole.cs (100%) rename {test/Shared => src/Tools/shared/test}/TestReporter.cs (100%) delete mode 100644 src/dotnet-dev-certs/dotnet-dev-certs.csproj delete mode 100644 src/dotnet-sql-cache/dotnet-sql-cache.csproj delete mode 100644 src/dotnet-user-secrets/dotnet-user-secrets.csproj delete mode 100644 test/Directory.Build.props delete mode 100644 test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj delete mode 100644 test/dotnet-watch.Tests/dotnet-watch.Tests.csproj delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Key.snk delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Microsoft.VisualStudio.SecretManager.TestExtension.csproj delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/NotifyPropertyChanged.cs delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/ProjectViewModel.cs delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Properties/AssemblyInfo.cs delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/RelayCommand.cs delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Resources/SecretManagerTestCommand.png delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Resources/SecretManagerTestPackage.ico delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestCommand.cs delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestControl.xaml delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestControl.xaml.cs delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestPackage.cs delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestPackage.vsct delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestWindow.cs delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerViewModel.cs delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/VSPackage.resx delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/app.config delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager.TestExtension/source.extension.vsixmanifest delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager/ProjectLocalSecretsManager.cs delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager/Properties/AssemblyInfo.cs delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager/Resources.Designer.cs delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager/Resources.resx delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager/SecretManagerFactory.cs delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager/SecretStore.cs delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager/Sources/ConfigurationPath.cs delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager/Sources/JsonConfigurationFileParser.cs delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager/Sources/PathHelper.cs delete mode 100644 tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest delete mode 100644 version.props diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index 4eea96ab69..0000000000 --- a/.appveyor.yml +++ /dev/null @@ -1,17 +0,0 @@ -init: -- git config --global core.autocrlf true -branches: - only: - - dev - - /^release\/.*$/ - - /^(.*\/)?ci-.*$/ -build_script: -- ps: .\run.ps1 default-build -clone_depth: 1 -environment: - global: - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - DOTNET_CLI_TELEMETRY_OPTOUT: 1 -test: 'off' -deploy: 'off' -os: Visual Studio 2017 diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index e2566a262e..0000000000 --- a/.editorconfig +++ /dev/null @@ -1,24 +0,0 @@ -# EditorConfig is awesome:http://EditorConfig.org - -# top-most EditorConfig file -root = true - -[*] -indent_style = space -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true - -[*.cs] -indent_size = 4 -dotnet_sort_system_directives_first = true:warning - -# Xml files -[*.{csproj,config,props,targets,ruleset,config,resx,xml}] -indent_size = 2 - -[*.{json, yml}] -indent_size = 2 - -[*.{ps1,sh}] -indent_size = 4 \ No newline at end of file diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index c2f0f84273..0000000000 --- a/.gitattributes +++ /dev/null @@ -1,52 +0,0 @@ -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain - -*.jpg binary -*.png binary -*.gif binary - -*.cs text=auto diff=csharp -*.vb text=auto -*.resx text=auto -*.c text=auto -*.cpp text=auto -*.cxx text=auto -*.h text=auto -*.hxx text=auto -*.py text=auto -*.rb text=auto -*.java text=auto -*.html text=auto -*.htm text=auto -*.css text=auto -*.scss text=auto -*.sass text=auto -*.less text=auto -*.js text=auto -*.lisp text=auto -*.clj text=auto -*.sql text=auto -*.php text=auto -*.lua text=auto -*.m text=auto -*.asm text=auto -*.erl text=auto -*.fs text=auto -*.fsx text=auto -*.hs text=auto - -*.csproj text=auto -*.vbproj text=auto -*.fsproj text=auto -*.dbproj text=auto -*.sln text=auto eol=crlf - -*.sh eol=lf \ No newline at end of file diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 01ed76be4f..0000000000 --- a/.gitignore +++ /dev/null @@ -1,37 +0,0 @@ -[Oo]bj/ -[Bb]in/ -TestResults/ -.nuget/ -_ReSharper.*/ -packages/ -artifacts/ -PublishProfiles/ -*.user -*.suo -*.cache -*.docstates -_ReSharper.* -nuget.exe -*net45.csproj -*net451.csproj -*k10.csproj -*.psess -*.vsp -*.pidb -*.userprefs -*DS_Store -*.ncrunchsolution -*.*sdf -*.ipch -*.sln.ide -project.lock.json -.testPublish/ -.build/ -/.vs/ -.vscode/ -*.nuget.props -*.nuget.targets -.idea/ -.dotnet/ -global.json -*.binlog diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 64bdbb4441..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,27 +0,0 @@ -language: csharp -sudo: false -dist: trusty -env: - global: - - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - - DOTNET_CLI_TELEMETRY_OPTOUT: 1 -mono: none -os: -- linux -- osx -osx_image: xcode8.2 -addons: - apt: - packages: - - libunwind8 -branches: - only: - - dev - - /^release\/.*$/ - - /^(.*\/)?ci-.*$/ -before_install: -- if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s - /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib - /usr/local/lib/; fi -script: -- ./build.sh diff --git a/.vsts-pipelines/builds/ci-internal.yml b/.vsts-pipelines/builds/ci-internal.yml deleted file mode 100644 index 3693598d93..0000000000 --- a/.vsts-pipelines/builds/ci-internal.yml +++ /dev/null @@ -1,13 +0,0 @@ -trigger: -- master -- release/* - -resources: - repositories: - - repository: buildtools - type: git - name: aspnet-BuildTools - ref: refs/heads/release/2.1 - -phases: -- template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/.vsts-pipelines/builds/ci-public.yml b/.vsts-pipelines/builds/ci-public.yml deleted file mode 100644 index c459e62eb6..0000000000 --- a/.vsts-pipelines/builds/ci-public.yml +++ /dev/null @@ -1,15 +0,0 @@ -trigger: -- master -- release/* - -# See https://github.com/aspnet/BuildTools -resources: - repositories: - - repository: buildtools - type: github - endpoint: DotNet-Bot GitHub Connection - name: aspnet/BuildTools - ref: refs/heads/release/2.1 - -phases: -- template: .vsts-pipelines/templates/project-ci.yml@buildtools diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 64ff041d5c..0000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,4 +0,0 @@ -Contributing -====== - -Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/dev/CONTRIBUTING.md) in the Home repo. diff --git a/Directory.Build.props b/Directory.Build.props deleted file mode 100644 index 8c12d37b2d..0000000000 --- a/Directory.Build.props +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - Microsoft .NET - https://github.com/aspnet/DotNetTools - git - $(MSBuildThisFileDirectory) - $(MSBuildThisFileDirectory)build\Key.snk - true - true - - - false - $(MSBuildThisFileDirectory)obj\$(MSBuildProjectName)\ - $(MSBuildThisFileDirectory)bin\$(MSBuildProjectName)\ - - - diff --git a/Directory.Build.targets b/Directory.Build.targets deleted file mode 100644 index eb03b2565f..0000000000 --- a/Directory.Build.targets +++ /dev/null @@ -1,6 +0,0 @@ - - - $(MicrosoftNETCoreApp21PackageVersion) - $(NETStandardLibrary20PackageVersion) - - diff --git a/DotNetTools.sln b/DotNetTools.sln deleted file mode 100644 index 82fefe40d0..0000000000 --- a/DotNetTools.sln +++ /dev/null @@ -1,162 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27120.0 -MinimumVisualStudioVersion = 15.0.26730.03 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66517987-2A5A-4330-B130-207039378FD4}" - ProjectSection(SolutionItems) = preProject - src\Directory.Build.props = src\Directory.Build.props - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-watch", "src\dotnet-watch\dotnet-watch.csproj", "{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8321E0D1-9A47-4D2F-AED8-3AE636D44E35}" - ProjectSection(SolutionItems) = preProject - .appveyor.yml = .appveyor.yml - .editorconfig = .editorconfig - .gitattributes = .gitattributes - .gitignore = .gitignore - .travis.yml = .travis.yml - build.cmd = build.cmd - build.ps1 = build.ps1 - build.sh = build.sh - CONTRIBUTING.md = CONTRIBUTING.md - build\dependencies.props = build\dependencies.props - Directory.Build.props = Directory.Build.props - Directory.Build.targets = Directory.Build.targets - LICENSE.txt = LICENSE.txt - NuGet.config = NuGet.config - NuGetPackageVerifier.json = NuGetPackageVerifier.json - README.md = README.md - build\sources.props = build\sources.props - version.props = version.props - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F5B382BC-258F-46E1-AC3D-10E5CCD55134}" - ProjectSection(SolutionItems) = preProject - test\Directory.Build.props = test\Directory.Build.props - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-watch.FunctionalTests", "test\dotnet-watch.FunctionalTests\dotnet-watch.FunctionalTests.csproj", "{16BADE2F-1184-4518-8A70-B68A19D0805B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-user-secrets", "src\dotnet-user-secrets\dotnet-user-secrets.csproj", "{8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-user-secrets.Tests", "test\dotnet-user-secrets.Tests\dotnet-user-secrets.Tests.csproj", "{7B331122-83B1-4F08-A119-DC846959844C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-watch.Tests", "test\dotnet-watch.Tests\dotnet-watch.Tests.csproj", "{8A2E6961-6B12-4A8E-8215-3E7301D52EAC}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-sql-cache", "src\dotnet-sql-cache\dotnet-sql-cache.csproj", "{53F3B53D-303A-4DAA-9C38-4F55195FA5B9}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-dev-certs", "src\dotnet-dev-certs\dotnet-dev-certs.csproj", "{4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.VisualStudio.SecretManager", "tooling\Microsoft.VisualStudio.SecretManager\Microsoft.VisualStudio.SecretManager.csproj", "{5E117F2E-7152-447F-BF47-59F759EEF3A7}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tooling", "tooling", "{62826851-7D74-4F1E-B7D1-12553B789CD8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.VisualStudio.SecretManager.TestExtension", "tooling\Microsoft.VisualStudio.SecretManager.TestExtension\Microsoft.VisualStudio.SecretManager.TestExtension.csproj", "{965F8820-F809-4081-9090-1AEC903F291B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DeveloperCertificates.XPlat", "src\Microsoft.AspNetCore.DeveloperCertificates.XPlat\Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj", "{96E71881-1465-44F5-B4B7-DF9B370FFD02}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - DebugNoVSIX|Any CPU = DebugNoVSIX|Any CPU - Release|Any CPU = Release|Any CPU - ReleaseNoVSIX|Any CPU = ReleaseNoVSIX|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU - {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU - {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.Release|Any CPU.Build.0 = Release|Any CPU - {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU - {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU - {16BADE2F-1184-4518-8A70-B68A19D0805B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {16BADE2F-1184-4518-8A70-B68A19D0805B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {16BADE2F-1184-4518-8A70-B68A19D0805B}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU - {16BADE2F-1184-4518-8A70-B68A19D0805B}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU - {16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {16BADE2F-1184-4518-8A70-B68A19D0805B}.Release|Any CPU.Build.0 = Release|Any CPU - {16BADE2F-1184-4518-8A70-B68A19D0805B}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU - {16BADE2F-1184-4518-8A70-B68A19D0805B}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU - {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU - {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU - {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.Release|Any CPU.Build.0 = Release|Any CPU - {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU - {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU - {7B331122-83B1-4F08-A119-DC846959844C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7B331122-83B1-4F08-A119-DC846959844C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7B331122-83B1-4F08-A119-DC846959844C}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU - {7B331122-83B1-4F08-A119-DC846959844C}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU - {7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7B331122-83B1-4F08-A119-DC846959844C}.Release|Any CPU.Build.0 = Release|Any CPU - {7B331122-83B1-4F08-A119-DC846959844C}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU - {7B331122-83B1-4F08-A119-DC846959844C}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU - {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU - {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU - {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.Release|Any CPU.Build.0 = Release|Any CPU - {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU - {8A2E6961-6B12-4A8E-8215-3E7301D52EAC}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU - {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU - {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU - {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.Release|Any CPU.Build.0 = Release|Any CPU - {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU - {53F3B53D-303A-4DAA-9C38-4F55195FA5B9}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU - {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU - {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU - {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.Release|Any CPU.Build.0 = Release|Any CPU - {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU - {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU - {5E117F2E-7152-447F-BF47-59F759EEF3A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5E117F2E-7152-447F-BF47-59F759EEF3A7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5E117F2E-7152-447F-BF47-59F759EEF3A7}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU - {5E117F2E-7152-447F-BF47-59F759EEF3A7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5E117F2E-7152-447F-BF47-59F759EEF3A7}.Release|Any CPU.Build.0 = Release|Any CPU - {5E117F2E-7152-447F-BF47-59F759EEF3A7}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU - {965F8820-F809-4081-9090-1AEC903F291B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {965F8820-F809-4081-9090-1AEC903F291B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {965F8820-F809-4081-9090-1AEC903F291B}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU - {965F8820-F809-4081-9090-1AEC903F291B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {965F8820-F809-4081-9090-1AEC903F291B}.Release|Any CPU.Build.0 = Release|Any CPU - {965F8820-F809-4081-9090-1AEC903F291B}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU - {96E71881-1465-44F5-B4B7-DF9B370FFD02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {96E71881-1465-44F5-B4B7-DF9B370FFD02}.Debug|Any CPU.Build.0 = Debug|Any CPU - {96E71881-1465-44F5-B4B7-DF9B370FFD02}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU - {96E71881-1465-44F5-B4B7-DF9B370FFD02}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU - {96E71881-1465-44F5-B4B7-DF9B370FFD02}.Release|Any CPU.ActiveCfg = Release|Any CPU - {96E71881-1465-44F5-B4B7-DF9B370FFD02}.Release|Any CPU.Build.0 = Release|Any CPU - {96E71881-1465-44F5-B4B7-DF9B370FFD02}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU - {96E71881-1465-44F5-B4B7-DF9B370FFD02}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {8A8CEABC-AC47-43FF-A5DF-69224F7E1F46} = {66517987-2A5A-4330-B130-207039378FD4} - {16BADE2F-1184-4518-8A70-B68A19D0805B} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} - {8730E848-CA0F-4E0A-9A2F-BC22AD0B2C4E} = {66517987-2A5A-4330-B130-207039378FD4} - {7B331122-83B1-4F08-A119-DC846959844C} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} - {8A2E6961-6B12-4A8E-8215-3E7301D52EAC} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134} - {53F3B53D-303A-4DAA-9C38-4F55195FA5B9} = {66517987-2A5A-4330-B130-207039378FD4} - {4FED5119-EE5C-4753-88A4-D61BDEB4D6C8} = {66517987-2A5A-4330-B130-207039378FD4} - {5E117F2E-7152-447F-BF47-59F759EEF3A7} = {62826851-7D74-4F1E-B7D1-12553B789CD8} - {965F8820-F809-4081-9090-1AEC903F291B} = {62826851-7D74-4F1E-B7D1-12553B789CD8} - {96E71881-1465-44F5-B4B7-DF9B370FFD02} = {66517987-2A5A-4330-B130-207039378FD4} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {57C07F14-2EAC-44FF-A277-B9221B4B2BF7} - EndGlobalSection -EndGlobal diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index 7b2956ecee..0000000000 --- a/LICENSE.txt +++ /dev/null @@ -1,14 +0,0 @@ -Copyright (c) .NET Foundation and Contributors - -All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software distributed -under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -CONDITIONS OF ANY KIND, either express or implied. See the License for the -specific language governing permissions and limitations under the License. diff --git a/NuGet.config b/NuGet.config deleted file mode 100644 index 8c30f1c84e..0000000000 --- a/NuGet.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - diff --git a/README.md b/README.md deleted file mode 100644 index 0eb8eb3be8..0000000000 --- a/README.md +++ /dev/null @@ -1,39 +0,0 @@ -DotNetTools -=========== - -[![Travis build status](https://img.shields.io/travis/aspnet/DotNetTools.svg?label=travis-ci&branch=dev&style=flat-square)](https://travis-ci.org/aspnet/DotNetTools/branches) -[![AppVeyor build status](https://img.shields.io/appveyor/ci/aspnetci/DotNetTools/dev.svg?label=appveyor&style=flat-square)](https://ci.appveyor.com/project/aspnetci/DotNetTools/branch/dev) - -This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at . - -## Projects - -The repository contains command-line tools for ASP.NET Core that are bundled* in the .NET Core CLI. Follow the links below for more details on each tool. - - - [dotnet-watch](src/dotnet-watch/README.md) - - [dotnet-user-secrets](src/dotnet-user-secrets/README.md) - - [dotnet-sql-cache](src/dotnet-sql-cache/README.md) - - [dotnet-dev-certs](src/dotnet-dev-certs/README.md) - -*\*This applies to .NET Core CLI 2.1.300-preview2 and up. For earlier versions of the CLI, these tools must be installed separately.* - -*For 2.0 CLI and earlier, see for details.* - -*For 2.1.300-preview1 CLI, see for details.* - -## Usage - -The command line tools can be invoked as a subcommand of `dotnet`. - -```sh -dotnet watch -dotnet user-secrets -dotnet sql-cache -dotnet dev-certs -``` - -Add `--help` to see more details. For example, - -``` -dotnet watch --help -``` diff --git a/build.cmd b/build.cmd deleted file mode 100644 index c0050bda12..0000000000 --- a/build.cmd +++ /dev/null @@ -1,2 +0,0 @@ -@ECHO OFF -PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' default-build %*; exit $LASTEXITCODE" diff --git a/build.sh b/build.sh deleted file mode 100755 index 98a4b22765..0000000000 --- a/build.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -# Call "sync" between "chmod" and execution to prevent "text file busy" error in Docker (aufs) -chmod +x "$DIR/run.sh"; sync -"$DIR/run.sh" default-build "$@" diff --git a/build/Key.snk b/build/Key.snk deleted file mode 100644 index e10e4889c125d3120cd9e81582243d70f7cbb806..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098=Iw=HCsnz~#iVhm& zj%TU(_THUee?3yHBjk$37ysB?i5#7WD$={H zV4B!OxRPrb|8)HPg~A}8P>^=#y<)56#=E&NzcjOtPK~<4n6GHt=K$ro*T(lhby_@U zEk(hLzk1H)0yXj{A_5>fk-TgNoP|q6(tP2xo8zt8i%212CWM#AeCd?`hS|4~L({h~Moo(~vy&3Z z1uI}`fd^*>o=rwbAGymj6RM^pZm(*Kfhs+Y1#`-2JPWZMK8@;ZWCk2+9bX4YP);~fj-BU*R zQPvWv$89!{Rl9wM+zR>_TSkn^voYxA?2G iKnV#iZ6Ah`K>b=@=IjYJXrxL124zR(38)nxe+&q_$QXwJ diff --git a/build/VSIX.props b/build/VSIX.props deleted file mode 100644 index 9640955a99..0000000000 --- a/build/VSIX.props +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/build/VSIX.targets b/build/VSIX.targets deleted file mode 100644 index ccafe5bf76..0000000000 --- a/build/VSIX.targets +++ /dev/null @@ -1,120 +0,0 @@ - - - true - $(RestoreDependsOn);RestoreVSIX - $(PackageDependsOn);PackageVSIX - $(GetArtifactInfoDependsOn);GetVSIXArtifactInfo - Microsoft.VisualStudio.SecretManager - $(RepositoryRoot)tooling\$(VSIXName)\$(VSIXName).csproj - $(BuildDir)$(VSIXName).vsix - $(BuildDir)$(VSIXName).json - $(BuildDir)$(VSIXName).pdb - shipoob - - - - - - - - VsixPackage - $(PackageVersion) - $(VSIXArtifactCategory) - $(VSIXName) - - - - VsixPackageManifestFile - $(VSIXArtifactCategory) - $(VSIXName).vsix - $(VSIXName) - - - - SymbolsFile - $(VSIXArtifactCategory) - $(VSIXName).vsix - full - - - - - - - - - - - - - - $(LogOutputDir)vsix-restore.rsp - - - - - - - - - - - - - - - - - - - - - - $(LogOutputDir)vsix.log - $(LogOutputDir)vsix-build.rsp - - - - - - - - - - - - - - - diff --git a/build/dependencies.props b/build/dependencies.props deleted file mode 100644 index 2ffa03acd5..0000000000 --- a/build/dependencies.props +++ /dev/null @@ -1,29 +0,0 @@ - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - - - - 2.1.3-rtm-15833 - 2.1.1 - 2.1.0 - 2.1.1 - 2.1.1 - 2.1.1 - 2.1.2 - 15.9.0 - 2.0.3 - 4.5.1 - 4.5.0 - 9.0.1 - 2.4.0 - 2.4.0 - - - - - - - - diff --git a/build/repo.props b/build/repo.props deleted file mode 100644 index 571c6712c0..0000000000 --- a/build/repo.props +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - Internal.AspNetCore.Universe.Lineup - 2.1.0-* - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json - - - diff --git a/build/repo.targets b/build/repo.targets deleted file mode 100644 index 1183428580..0000000000 --- a/build/repo.targets +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - Configuration=$(Configuration)NoVSIX - - - diff --git a/build/sources.props b/build/sources.props deleted file mode 100644 index cada42ba91..0000000000 --- a/build/sources.props +++ /dev/null @@ -1,18 +0,0 @@ - - - - - $(DotNetRestoreSources) - - $(RestoreSources); - https://dotnet.myget.org/F/dotnet-core/api/v3/index.json; - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; - https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; - https://vside.myget.org/F/vssdk/api/v3/index.json; - - - $(RestoreSources); - https://api.nuget.org/v3/index.json; - - - diff --git a/NuGetPackageVerifier.json b/eng/NuGetPackageVerifier.json similarity index 98% rename from NuGetPackageVerifier.json rename to eng/NuGetPackageVerifier.json index 3e59aeb910..4ce6d1a168 100644 --- a/NuGetPackageVerifier.json +++ b/eng/NuGetPackageVerifier.json @@ -1,102 +1,102 @@ -{ - "adx": { - "rules": [ - "AdxVerificationCompositeRule" - ], - "packages": { - "dotnet-watch": { - "packageTypes": [ - "DotnetTool" - ] - }, - "dotnet-sql-cache": { - "packageTypes": [ - "DotnetTool" - ], - "Exclusions": { - "NEUTRAL_RESOURCES_LANGUAGE": { - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." - }, - "WRONG_PUBLICKEYTOKEN": { - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." - }, - "ASSEMBLY_INFORMATIONAL_VERSION_MISMATCH": { - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." - }, - "ASSEMBLY_FILE_VERSION_MISMATCH": { - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." - }, - "ASSEMBLY_VERSION_MISMATCH": { - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." - } - } - }, - "dotnet-user-secrets": { - "packageTypes": [ - "DotnetTool" - ], - "Exclusions": { - "NEUTRAL_RESOURCES_LANGUAGE": { - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." - }, - "SERVICING_ATTRIBUTE": { - "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg." - }, - "WRONG_PUBLICKEYTOKEN": { - "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." - }, - "ASSEMBLY_INFORMATIONAL_VERSION_MISMATCH": { - "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." - }, - "ASSEMBLY_FILE_VERSION_MISMATCH": { - "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." - }, - "ASSEMBLY_VERSION_MISMATCH": { - "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", - "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." - } - } - }, - "dotnet-dev-certs": { - "packageTypes": [ - "DotnetTool" - ] - }, - "Microsoft.AspNetCore.DeveloperCertificates.XPlat": { - "Exclusions": { - "DOC_MISSING": { - "lib/netcoreapp2.1/Microsoft.AspNetCore.DeveloperCertificates.XPlat.dll": "Docs not required to shipoob package" - } - } - } - } - }, - "Default": { - "rules": [ - "DefaultCompositeRule" - ] - } -} +{ + "adx": { + "rules": [ + "AdxVerificationCompositeRule" + ], + "packages": { + "dotnet-watch": { + "packageTypes": [ + "DotnetTool" + ] + }, + "dotnet-sql-cache": { + "packageTypes": [ + "DotnetTool" + ], + "Exclusions": { + "NEUTRAL_RESOURCES_LANGUAGE": { + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + }, + "WRONG_PUBLICKEYTOKEN": { + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + }, + "ASSEMBLY_INFORMATIONAL_VERSION_MISMATCH": { + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + }, + "ASSEMBLY_FILE_VERSION_MISMATCH": { + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + }, + "ASSEMBLY_VERSION_MISMATCH": { + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": "Assembly is built by another project but bundled in our nupkg." + } + } + }, + "dotnet-user-secrets": { + "packageTypes": [ + "DotnetTool" + ], + "Exclusions": { + "NEUTRAL_RESOURCES_LANGUAGE": { + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + }, + "SERVICING_ATTRIBUTE": { + "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg." + }, + "WRONG_PUBLICKEYTOKEN": { + "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + }, + "ASSEMBLY_INFORMATIONAL_VERSION_MISMATCH": { + "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + }, + "ASSEMBLY_FILE_VERSION_MISMATCH": { + "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + }, + "ASSEMBLY_VERSION_MISMATCH": { + "tools/netcoreapp2.1/any/Newtonsoft.Json.dll": "Assembly is built by another project but bundled in our nupkg.", + "tools/netcoreapp2.1/any/System.Runtime.CompilerServices.Unsafe.dll": "Assembly is built by another project but bundled in our nupkg." + } + } + }, + "dotnet-dev-certs": { + "packageTypes": [ + "DotnetTool" + ] + }, + "Microsoft.AspNetCore.DeveloperCertificates.XPlat": { + "Exclusions": { + "DOC_MISSING": { + "lib/netcoreapp2.1/Microsoft.AspNetCore.DeveloperCertificates.XPlat.dll": "Docs not required to shipoob package" + } + } + } + } + }, + "Default": { + "rules": [ + "DefaultCompositeRule" + ] + } +} diff --git a/korebuild-lock.txt b/korebuild-lock.txt deleted file mode 100644 index 04cce2fca7..0000000000 --- a/korebuild-lock.txt +++ /dev/null @@ -1,2 +0,0 @@ -version:2.1.3-rtm-15833 -commithash:42bee65743476deedda53948fa3e84a0ac4c0360 diff --git a/korebuild.json b/korebuild.json deleted file mode 100644 index 196a3ca537..0000000000 --- a/korebuild.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.1/tools/korebuild.schema.json", - "channel": "release/2.1", - "toolsets": { - "visualstudio": { - "required": [ - "windows" - ], - "includePrerelease": true, - "minVersion": "15.0.26730.03", - "requiredWorkloads": [ - "Microsoft.VisualStudio.Component.VSSDK" - ] - } - } -} diff --git a/run.cmd b/run.cmd deleted file mode 100644 index d52d5c7e68..0000000000 --- a/run.cmd +++ /dev/null @@ -1,2 +0,0 @@ -@ECHO OFF -PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' %*; exit $LASTEXITCODE" diff --git a/run.ps1 b/run.ps1 deleted file mode 100644 index 2f892843e0..0000000000 --- a/run.ps1 +++ /dev/null @@ -1,210 +0,0 @@ -#!/usr/bin/env powershell -#requires -version 4 - -<# -.SYNOPSIS -Executes KoreBuild commands. - -.DESCRIPTION -Downloads korebuild if required. Then executes the KoreBuild command. To see available commands, execute with `-Command help`. - -.PARAMETER Command -The KoreBuild command to run. - -.PARAMETER Path -The folder to build. Defaults to the folder containing this script. - -.PARAMETER Channel -The channel of KoreBuild to download. Overrides the value from the config file. - -.PARAMETER DotNetHome -The directory where .NET Core tools will be stored. - -.PARAMETER ToolsSource -The base url where build tools can be downloaded. Overrides the value from the config file. - -.PARAMETER Update -Updates KoreBuild to the latest version even if a lock file is present. - -.PARAMETER Reinstall -Re-installs KoreBuild - -.PARAMETER ConfigFile -The path to the configuration file that stores values. Defaults to korebuild.json. - -.PARAMETER ToolsSourceSuffix -The Suffix to append to the end of the ToolsSource. Useful for query strings in blob stores. - -.PARAMETER CI -Sets up CI specific settings and variables. - -.PARAMETER Arguments -Arguments to be passed to the command - -.NOTES -This function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be. -When the lockfile is not present, KoreBuild will create one using latest available version from $Channel. - -The $ConfigFile is expected to be an JSON file. It is optional, and the configuration values in it are optional as well. Any options set -in the file are overridden by command line parameters. - -.EXAMPLE -Example config file: -```json -{ - "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", - "channel": "master", - "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" -} -``` -#> -[CmdletBinding(PositionalBinding = $false)] -param( - [Parameter(Mandatory = $true, Position = 0)] - [string]$Command, - [string]$Path = $PSScriptRoot, - [Alias('c')] - [string]$Channel, - [Alias('d')] - [string]$DotNetHome, - [Alias('s')] - [string]$ToolsSource, - [Alias('u')] - [switch]$Update, - [switch]$Reinstall, - [string]$ToolsSourceSuffix, - [string]$ConfigFile = $null, - [switch]$CI, - [Parameter(ValueFromRemainingArguments = $true)] - [string[]]$Arguments -) - -Set-StrictMode -Version 2 -$ErrorActionPreference = 'Stop' - -# -# Functions -# - -function Get-KoreBuild { - - $lockFile = Join-Path $Path 'korebuild-lock.txt' - - if (!(Test-Path $lockFile) -or $Update) { - Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile $ToolsSourceSuffix - } - - $version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1 - if (!$version) { - Write-Error "Failed to parse version from $lockFile. Expected a line that begins with 'version:'" - } - $version = $version.TrimStart('version:').Trim() - $korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version) - - if ($Reinstall -and (Test-Path $korebuildPath)) { - Remove-Item -Force -Recurse $korebuildPath - } - - if (!(Test-Path $korebuildPath)) { - Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version" - New-Item -ItemType Directory -Path $korebuildPath | Out-Null - $remotePath = "$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip" - - try { - $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip" - Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix - if (Get-Command -Name 'Microsoft.PowerShell.Archive\Expand-Archive' -ErrorAction Ignore) { - # Use built-in commands where possible as they are cross-plat compatible - Microsoft.PowerShell.Archive\Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath - } - else { - # Fallback to old approach for old installations of PowerShell - Add-Type -AssemblyName System.IO.Compression.FileSystem - [System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath) - } - } - catch { - Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore - throw - } - finally { - Remove-Item $tmpfile -ErrorAction Ignore - } - } - - return $korebuildPath -} - -function Join-Paths([string]$path, [string[]]$childPaths) { - $childPaths | ForEach-Object { $path = Join-Path $path $_ } - return $path -} - -function Get-RemoteFile([string]$RemotePath, [string]$LocalPath, [string]$RemoteSuffix) { - if ($RemotePath -notlike 'http*') { - Copy-Item $RemotePath $LocalPath - return - } - - $retries = 10 - while ($retries -gt 0) { - $retries -= 1 - try { - Invoke-WebRequest -UseBasicParsing -Uri $($RemotePath + $RemoteSuffix) -OutFile $LocalPath - return - } - catch { - Write-Verbose "Request failed. $retries retries remaining" - } - } - - Write-Error "Download failed: '$RemotePath'." -} - -# -# Main -# - -# Load configuration or set defaults - -$Path = Resolve-Path $Path -if (!$ConfigFile) { $ConfigFile = Join-Path $Path 'korebuild.json' } - -if (Test-Path $ConfigFile) { - try { - $config = Get-Content -Raw -Encoding UTF8 -Path $ConfigFile | ConvertFrom-Json - if ($config) { - if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel } - if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource} - } - } - catch { - Write-Host -ForegroundColor Red $Error[0] - Write-Error "$ConfigFile contains invalid JSON." - exit 1 - } -} - -if (!$DotNetHome) { - $DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } ` - elseif ($CI) { Join-Path $PSScriptRoot '.dotnet' } ` - elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} ` - elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}` - else { Join-Path $PSScriptRoot '.dotnet'} -} - -if (!$Channel) { $Channel = 'master' } -if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } - -# Execute - -$korebuildPath = Get-KoreBuild -Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1') - -try { - Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile -CI:$CI - Invoke-KoreBuildCommand $Command @Arguments -} -finally { - Remove-Module 'KoreBuild' -ErrorAction Ignore -} diff --git a/run.sh b/run.sh deleted file mode 100755 index 129b0b9576..0000000000 --- a/run.sh +++ /dev/null @@ -1,259 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -# -# variables -# - -RESET="\033[0m" -RED="\033[0;31m" -YELLOW="\033[0;33m" -MAGENTA="\033[0;95m" -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -verbose=false -update=false -reinstall=false -repo_path="$DIR" -channel='' -tools_source='' -tools_source_suffix='' -ci=false - -# -# Functions -# -__usage() { - echo "Usage: $(basename "${BASH_SOURCE[0]}") command [options] [[--] ...]" - echo "" - echo "Arguments:" - echo " command The command to be run." - echo " ... Arguments passed to the command. Variable number of arguments allowed." - echo "" - echo "Options:" - echo " --verbose Show verbose output." - echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.." - echo " --config-file The path to the configuration file that stores values. Defaults to korebuild.json." - echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet." - echo " --path The directory to build. Defaults to the directory containing the script." - echo " -s|--tools-source|-ToolsSource The base url where build tools can be downloaded. Overrides the value from the config file." - echo " --tools-source-suffix|-ToolsSourceSuffix The suffix to append to tools-source. Useful for query strings." - echo " -u|--update Update to the latest KoreBuild even if the lock file is present." - echo " --reinstall Reinstall KoreBuild." - echo " --ci Apply CI specific settings and environment variables." - echo "" - echo "Description:" - echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be." - echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel." - - if [[ "${1:-}" != '--no-exit' ]]; then - exit 2 - fi -} - -get_korebuild() { - local version - local lock_file="$repo_path/korebuild-lock.txt" - if [ ! -f "$lock_file" ] || [ "$update" = true ]; then - __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" "$tools_source_suffix" - fi - version="$(grep 'version:*' -m 1 "$lock_file")" - if [[ "$version" == '' ]]; then - __error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'" - return 1 - fi - version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" - local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version" - - if [ "$reinstall" = true ] && [ -d "$korebuild_path" ]; then - rm -rf "$korebuild_path" - fi - - { - if [ ! -d "$korebuild_path" ]; then - mkdir -p "$korebuild_path" - local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip" - tmpfile="$(mktemp)" - echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}" - if __get_remote_file "$remote_path" "$tmpfile" "$tools_source_suffix"; then - unzip -q -d "$korebuild_path" "$tmpfile" - fi - rm "$tmpfile" || true - fi - - source "$korebuild_path/KoreBuild.sh" - } || { - if [ -d "$korebuild_path" ]; then - echo "Cleaning up after failed installation" - rm -rf "$korebuild_path" || true - fi - return 1 - } -} - -__error() { - echo -e "${RED}error: $*${RESET}" 1>&2 -} - -__warn() { - echo -e "${YELLOW}warning: $*${RESET}" -} - -__machine_has() { - hash "$1" > /dev/null 2>&1 - return $? -} - -__get_remote_file() { - local remote_path=$1 - local local_path=$2 - local remote_path_suffix=$3 - - if [[ "$remote_path" != 'http'* ]]; then - cp "$remote_path" "$local_path" - return 0 - fi - - local failed=false - if __machine_has wget; then - wget --tries 10 --quiet -O "$local_path" "${remote_path}${remote_path_suffix}" || failed=true - else - failed=true - fi - - if [ "$failed" = true ] && __machine_has curl; then - failed=false - curl --retry 10 -sSL -f --create-dirs -o "$local_path" "${remote_path}${remote_path_suffix}" || failed=true - fi - - if [ "$failed" = true ]; then - __error "Download failed: $remote_path" 1>&2 - return 1 - fi -} - -# -# main -# - -command="${1:-}" -shift - -while [[ $# -gt 0 ]]; do - case $1 in - -\?|-h|--help) - __usage --no-exit - exit 0 - ;; - -c|--channel|-Channel) - shift - channel="${1:-}" - [ -z "$channel" ] && __usage - ;; - --config-file|-ConfigFile) - shift - config_file="${1:-}" - [ -z "$config_file" ] && __usage - if [ ! -f "$config_file" ]; then - __error "Invalid value for --config-file. $config_file does not exist." - exit 1 - fi - ;; - -d|--dotnet-home|-DotNetHome) - shift - DOTNET_HOME="${1:-}" - [ -z "$DOTNET_HOME" ] && __usage - ;; - --path|-Path) - shift - repo_path="${1:-}" - [ -z "$repo_path" ] && __usage - ;; - -s|--tools-source|-ToolsSource) - shift - tools_source="${1:-}" - [ -z "$tools_source" ] && __usage - ;; - --tools-source-suffix|-ToolsSourceSuffix) - shift - tools_source_suffix="${1:-}" - [ -z "$tools_source_suffix" ] && __usage - ;; - -u|--update|-Update) - update=true - ;; - --reinstall|-[Rr]einstall) - reinstall=true - ;; - --ci|-[Cc][Ii]) - ci=true - if [[ -z "${DOTNET_HOME:-}" ]]; then - DOTNET_HOME="$DIR/.dotnet" - fi - ;; - --verbose|-Verbose) - verbose=true - ;; - --) - shift - break - ;; - *) - break - ;; - esac - shift -done - -if ! __machine_has unzip; then - __error 'Missing required command: unzip' - exit 1 -fi - -if ! __machine_has curl && ! __machine_has wget; then - __error 'Missing required command. Either wget or curl is required.' - exit 1 -fi - -[ -z "${config_file:-}" ] && config_file="$repo_path/korebuild.json" -if [ -f "$config_file" ]; then - if __machine_has jq ; then - if jq '.' "$config_file" >/dev/null ; then - config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" - config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")" - else - __error "$config_file contains invalid JSON." - exit 1 - fi - elif __machine_has python ; then - if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then - config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" - config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" - else - __error "$config_file contains invalid JSON." - exit 1 - fi - elif __machine_has python3 ; then - if python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then - config_channel="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" - config_tools_source="$(python3 -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" - else - __error "$config_file contains invalid JSON." - exit 1 - fi - else - __error 'Missing required command: jq or python. Could not parse the JSON file.' - exit 1 - fi - - [ ! -z "${config_channel:-}" ] && channel="$config_channel" - [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source" -fi - -[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet" -[ -z "$channel" ] && channel='master' -[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools' - -get_korebuild -set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file" "$ci" -invoke_korebuild_command "$command" "$@" diff --git a/samples/dotnet-watch/Directory.Build.props b/samples/dotnet-watch/Directory.Build.props deleted file mode 100644 index 76c9003a6b..0000000000 --- a/samples/dotnet-watch/Directory.Build.props +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/samples/dotnet-watch/Directory.Build.targets b/samples/dotnet-watch/Directory.Build.targets deleted file mode 100644 index 76c9003a6b..0000000000 --- a/samples/dotnet-watch/Directory.Build.targets +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj b/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj deleted file mode 100644 index 1dc6efedd6..0000000000 --- a/samples/dotnet-watch/LaunchAnyCommand/LaunchAnyCommand.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - netcoreapp2.1 - - - - - - - - - - diff --git a/samples/dotnet-watch/LaunchAnyCommand/README.md b/samples/dotnet-watch/LaunchAnyCommand/README.md deleted file mode 100644 index fa52f4073e..0000000000 --- a/samples/dotnet-watch/LaunchAnyCommand/README.md +++ /dev/null @@ -1,17 +0,0 @@ -Launch any command with dotnet-watch -==================================== - -## Prerequisites - -1. Install .NET Core command line. -2. Install NodeJS. - -## Usage - -Open a terminal to the directory containing this project. - -``` -dotnet watch msbuild /t:RunMyNpmCommand -``` - -Changing the .csproj file, or the say-hello.js file will cause dotnet-watch to re-run the 'RunMyNpmCommand' target in MyApp.csproj. diff --git a/samples/dotnet-watch/LaunchAnyCommand/package.json b/samples/dotnet-watch/LaunchAnyCommand/package.json deleted file mode 100644 index 61e25fb082..0000000000 --- a/samples/dotnet-watch/LaunchAnyCommand/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "any-command", - "version": "0.0.0", - "private": true, - "scripts": { - "custom": "node say-hello.js" - } -} diff --git a/samples/dotnet-watch/LaunchAnyCommand/say-hello.js b/samples/dotnet-watch/LaunchAnyCommand/say-hello.js deleted file mode 100644 index c35728f5a1..0000000000 --- a/samples/dotnet-watch/LaunchAnyCommand/say-hello.js +++ /dev/null @@ -1 +0,0 @@ -console.log("Hello from Javascript"); diff --git a/samples/dotnet-watch/README.md b/samples/dotnet-watch/README.md deleted file mode 100644 index 5988ab77ba..0000000000 --- a/samples/dotnet-watch/README.md +++ /dev/null @@ -1,5 +0,0 @@ -dotnet-watch samples -==================== - -The samples in this folder show some ways to customize dotnet-watch. For full details on -available settings and configuration, see the [README for the dotnet-watch](../../src/dotnet-watch/README.md) project. diff --git a/samples/dotnet-watch/WatchJavascriptFiles/Program.cs b/samples/dotnet-watch/WatchJavascriptFiles/Program.cs deleted file mode 100755 index f71a9e073d..0000000000 --- a/samples/dotnet-watch/WatchJavascriptFiles/Program.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.IO; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; - -namespace WatchJavascriptFiles -{ - public class Program - { - public static void Main(string[] args) - { - var host = new WebHostBuilder() - .UseKestrel() - .UseContentRoot(Directory.GetCurrentDirectory()) - .Configure(app => - app.Run(async (context) => - { - await context.Response.WriteAsync("Hello World!"); - })) - .Build(); - - host.Run(); - } - } -} diff --git a/samples/dotnet-watch/WatchJavascriptFiles/README.md b/samples/dotnet-watch/WatchJavascriptFiles/README.md deleted file mode 100644 index 3b0a148cd0..0000000000 --- a/samples/dotnet-watch/WatchJavascriptFiles/README.md +++ /dev/null @@ -1,16 +0,0 @@ -Watch JavaScript files with dotnet-watch -======================================== - -## Prerequisites - -Install .NET Core command line. - -## Usage - -Open a terminal to the directory containing this project. - -``` -dotnet watch run -``` - -Changing the .csproj file, or \*.js file in wwwroot, or any \*.cs file will cause dotnet-watch to restart the website. diff --git a/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj b/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj deleted file mode 100755 index 008b0322e6..0000000000 --- a/samples/dotnet-watch/WatchJavascriptFiles/WatchJavascriptFiles.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - netcoreapp2.1 - - - - - - - - - - - - diff --git a/samples/dotnet-watch/WatchJavascriptFiles/wwwroot/app.js b/samples/dotnet-watch/WatchJavascriptFiles/wwwroot/app.js deleted file mode 100644 index a94cbdc370..0000000000 --- a/samples/dotnet-watch/WatchJavascriptFiles/wwwroot/app.js +++ /dev/null @@ -1 +0,0 @@ -document.title = "My awesome website"; diff --git a/samples/dotnet-watch/WatchMultipleProjects/README.md b/samples/dotnet-watch/WatchMultipleProjects/README.md deleted file mode 100644 index 46d7a7904c..0000000000 --- a/samples/dotnet-watch/WatchMultipleProjects/README.md +++ /dev/null @@ -1,18 +0,0 @@ -Watch multiple projects with dotnet-watch -========================================= - -## Prerequisites - -Install .NET Core command line. - -## Usage - -Open a terminal to the directory containing this project. - -``` -dotnet watch msbuild /t:TestAndRun -``` - -The "TestAndRun" target in watch.proj will execute "dotnet test" on Test.csproj and then launch the website by calling "dotnet run" on Web.csproj. - -Changing any \*.cs file in Test/ or Web/, any \*.csproj file, or watch.proj, will cause dotnet-watch to relaunch the "TestAndRun" target from watch.proj. diff --git a/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj b/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj deleted file mode 100755 index 0ffd10766a..0000000000 --- a/samples/dotnet-watch/WatchMultipleProjects/Test/Test.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - netcoreapp2.1 - - - - - - - - - diff --git a/samples/dotnet-watch/WatchMultipleProjects/Test/UnitTest1.cs b/samples/dotnet-watch/WatchMultipleProjects/Test/UnitTest1.cs deleted file mode 100755 index 0da9a7f234..0000000000 --- a/samples/dotnet-watch/WatchMultipleProjects/Test/UnitTest1.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using Xunit; - -namespace Test -{ - public class UnitTest1 - { - [Fact] - public void Test1() - { - Assert.True(true); - } - } -} diff --git a/samples/dotnet-watch/WatchMultipleProjects/Web/Program.cs b/samples/dotnet-watch/WatchMultipleProjects/Web/Program.cs deleted file mode 100755 index 6a02b1f332..0000000000 --- a/samples/dotnet-watch/WatchMultipleProjects/Web/Program.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.IO; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; - -namespace Web -{ - public class Program - { - public static void Main(string[] args) - { - var host = new WebHostBuilder() - .UseKestrel() - .UseContentRoot(Directory.GetCurrentDirectory()) - .Configure(app => - app.Run(async (context) => - { - await context.Response.WriteAsync("Hello World!"); - })) - .Build(); - - host.Run(); - } - } -} diff --git a/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj b/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj deleted file mode 100755 index ec2a93ed3a..0000000000 --- a/samples/dotnet-watch/WatchMultipleProjects/Web/Web.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - netcoreapp2.1 - - - - - - - - - - - diff --git a/samples/dotnet-watch/WatchMultipleProjects/watch.csproj b/samples/dotnet-watch/WatchMultipleProjects/watch.csproj deleted file mode 100644 index d890295d39..0000000000 --- a/samples/dotnet-watch/WatchMultipleProjects/watch.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - netcoreapp2.1 - false - - - - - - - - - - - - - diff --git a/src/Directory.Build.props b/src/Directory.Build.props deleted file mode 100644 index 4b89a431e7..0000000000 --- a/src/Directory.Build.props +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets deleted file mode 100644 index c7b5f24861..0000000000 --- a/src/Directory.Build.targets +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/Tools/Directory.Build.targets b/src/Tools/Directory.Build.targets new file mode 100644 index 0000000000..3d2647b41b --- /dev/null +++ b/src/Tools/Directory.Build.targets @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/CertificateGenerator.cs b/src/Tools/FirstRunCertGenerator/src/CertificateGenerator.cs similarity index 100% rename from src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/CertificateGenerator.cs rename to src/Tools/FirstRunCertGenerator/src/CertificateGenerator.cs diff --git a/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj b/src/Tools/FirstRunCertGenerator/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj similarity index 65% rename from src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj rename to src/Tools/FirstRunCertGenerator/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj index 81c90a297c..ce61b3ab62 100644 --- a/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj +++ b/src/Tools/FirstRunCertGenerator/src/Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/Tools/README.md b/src/Tools/README.md new file mode 100644 index 0000000000..e13c6ec6e3 --- /dev/null +++ b/src/Tools/README.md @@ -0,0 +1,32 @@ +DotNetTools +=========== + +## Projects + +The folder contains command-line tools for ASP.NET Core that are bundled* in the .NET Core CLI. Follow the links below for more details on each tool. + + - [dotnet-watch](dotnet-watch/README.md) + - [dotnet-user-secrets](dotnet-user-secrets/README.md) + - [dotnet-sql-cache](dotnet-sql-cache/README.md) + - [dotnet-dev-certs](dotnet-dev-certs/README.md) + +*\*This applies to .NET Core CLI 2.1.300-preview2 and up. For earlier versions of the CLI, these tools must be installed separately.* + +*For 2.0 CLI and earlier, see for details.* + +## Usage + +The command line tools can be invoked as a subcommand of `dotnet`. + +```sh +dotnet watch +dotnet user-secrets +dotnet sql-cache +dotnet dev-certs +``` + +Add `--help` to see more details. For example, + +``` +dotnet watch --help +``` diff --git a/src/dotnet-dev-certs/README.md b/src/Tools/dotnet-dev-certs/README.md similarity index 100% rename from src/dotnet-dev-certs/README.md rename to src/Tools/dotnet-dev-certs/README.md diff --git a/src/dotnet-dev-certs/Program.cs b/src/Tools/dotnet-dev-certs/src/Program.cs similarity index 100% rename from src/dotnet-dev-certs/Program.cs rename to src/Tools/dotnet-dev-certs/src/Program.cs diff --git a/src/Tools/dotnet-dev-certs/src/dotnet-dev-certs.csproj b/src/Tools/dotnet-dev-certs/src/dotnet-dev-certs.csproj new file mode 100644 index 0000000000..1f0f906e50 --- /dev/null +++ b/src/Tools/dotnet-dev-certs/src/dotnet-dev-certs.csproj @@ -0,0 +1,32 @@ + + + + netcoreapp2.1 + exe + Command line tool to generate certificates used in ASP.NET Core during development. + Microsoft.AspNetCore.DeveloperCertificates.Tools + dotnet;developercertificates + true + + win-x64;win-x86 + + + + + + + + + + + + + + + + + + + + + diff --git a/src/dotnet-sql-cache/README.md b/src/Tools/dotnet-sql-cache/README.md similarity index 100% rename from src/dotnet-sql-cache/README.md rename to src/Tools/dotnet-sql-cache/README.md diff --git a/src/dotnet-sql-cache/Program.cs b/src/Tools/dotnet-sql-cache/src/Program.cs similarity index 100% rename from src/dotnet-sql-cache/Program.cs rename to src/Tools/dotnet-sql-cache/src/Program.cs diff --git a/src/dotnet-sql-cache/SqlQueries.cs b/src/Tools/dotnet-sql-cache/src/SqlQueries.cs similarity index 100% rename from src/dotnet-sql-cache/SqlQueries.cs rename to src/Tools/dotnet-sql-cache/src/SqlQueries.cs diff --git a/src/Tools/dotnet-sql-cache/src/dotnet-sql-cache.csproj b/src/Tools/dotnet-sql-cache/src/dotnet-sql-cache.csproj new file mode 100644 index 0000000000..3856c4877c --- /dev/null +++ b/src/Tools/dotnet-sql-cache/src/dotnet-sql-cache.csproj @@ -0,0 +1,30 @@ + + + + netcoreapp2.1 + exe + Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching. + cache;distributedcache;sqlserver + true + + win-x64;win-x86 + + + + + + + + + + + + + + + + + + + + diff --git a/src/dotnet-user-secrets/README.md b/src/Tools/dotnet-user-secrets/README.md similarity index 100% rename from src/dotnet-user-secrets/README.md rename to src/Tools/dotnet-user-secrets/README.md diff --git a/src/dotnet-user-secrets/CommandLineOptions.cs b/src/Tools/dotnet-user-secrets/src/CommandLineOptions.cs similarity index 100% rename from src/dotnet-user-secrets/CommandLineOptions.cs rename to src/Tools/dotnet-user-secrets/src/CommandLineOptions.cs diff --git a/src/dotnet-user-secrets/Internal/ClearCommand.cs b/src/Tools/dotnet-user-secrets/src/Internal/ClearCommand.cs similarity index 100% rename from src/dotnet-user-secrets/Internal/ClearCommand.cs rename to src/Tools/dotnet-user-secrets/src/Internal/ClearCommand.cs diff --git a/src/dotnet-user-secrets/Internal/CommandContext.cs b/src/Tools/dotnet-user-secrets/src/Internal/CommandContext.cs similarity index 100% rename from src/dotnet-user-secrets/Internal/CommandContext.cs rename to src/Tools/dotnet-user-secrets/src/Internal/CommandContext.cs diff --git a/src/dotnet-user-secrets/Internal/ICommand.cs b/src/Tools/dotnet-user-secrets/src/Internal/ICommand.cs similarity index 100% rename from src/dotnet-user-secrets/Internal/ICommand.cs rename to src/Tools/dotnet-user-secrets/src/Internal/ICommand.cs diff --git a/src/dotnet-user-secrets/Internal/ListCommand.cs b/src/Tools/dotnet-user-secrets/src/Internal/ListCommand.cs similarity index 100% rename from src/dotnet-user-secrets/Internal/ListCommand.cs rename to src/Tools/dotnet-user-secrets/src/Internal/ListCommand.cs diff --git a/src/dotnet-user-secrets/Internal/MsBuildProjectFinder.cs b/src/Tools/dotnet-user-secrets/src/Internal/MsBuildProjectFinder.cs similarity index 100% rename from src/dotnet-user-secrets/Internal/MsBuildProjectFinder.cs rename to src/Tools/dotnet-user-secrets/src/Internal/MsBuildProjectFinder.cs diff --git a/src/dotnet-user-secrets/Internal/ProjectIdResolver.cs b/src/Tools/dotnet-user-secrets/src/Internal/ProjectIdResolver.cs similarity index 100% rename from src/dotnet-user-secrets/Internal/ProjectIdResolver.cs rename to src/Tools/dotnet-user-secrets/src/Internal/ProjectIdResolver.cs diff --git a/src/dotnet-user-secrets/Internal/ReadableJsonConfigurationSource.cs b/src/Tools/dotnet-user-secrets/src/Internal/ReadableJsonConfigurationSource.cs similarity index 100% rename from src/dotnet-user-secrets/Internal/ReadableJsonConfigurationSource.cs rename to src/Tools/dotnet-user-secrets/src/Internal/ReadableJsonConfigurationSource.cs diff --git a/src/dotnet-user-secrets/Internal/RemoveCommand.cs b/src/Tools/dotnet-user-secrets/src/Internal/RemoveCommand.cs similarity index 100% rename from src/dotnet-user-secrets/Internal/RemoveCommand.cs rename to src/Tools/dotnet-user-secrets/src/Internal/RemoveCommand.cs diff --git a/src/dotnet-user-secrets/Internal/SecretsStore.cs b/src/Tools/dotnet-user-secrets/src/Internal/SecretsStore.cs similarity index 100% rename from src/dotnet-user-secrets/Internal/SecretsStore.cs rename to src/Tools/dotnet-user-secrets/src/Internal/SecretsStore.cs diff --git a/src/dotnet-user-secrets/Internal/SetCommand.cs b/src/Tools/dotnet-user-secrets/src/Internal/SetCommand.cs similarity index 100% rename from src/dotnet-user-secrets/Internal/SetCommand.cs rename to src/Tools/dotnet-user-secrets/src/Internal/SetCommand.cs diff --git a/src/dotnet-user-secrets/Program.cs b/src/Tools/dotnet-user-secrets/src/Program.cs similarity index 100% rename from src/dotnet-user-secrets/Program.cs rename to src/Tools/dotnet-user-secrets/src/Program.cs diff --git a/src/dotnet-user-secrets/Properties/AssemblyInfo.cs b/src/Tools/dotnet-user-secrets/src/Properties/AssemblyInfo.cs similarity index 100% rename from src/dotnet-user-secrets/Properties/AssemblyInfo.cs rename to src/Tools/dotnet-user-secrets/src/Properties/AssemblyInfo.cs diff --git a/src/dotnet-user-secrets/Properties/Resources.Designer.cs b/src/Tools/dotnet-user-secrets/src/Properties/Resources.Designer.cs similarity index 100% rename from src/dotnet-user-secrets/Properties/Resources.Designer.cs rename to src/Tools/dotnet-user-secrets/src/Properties/Resources.Designer.cs diff --git a/src/dotnet-user-secrets/Resources.resx b/src/Tools/dotnet-user-secrets/src/Resources.resx similarity index 100% rename from src/dotnet-user-secrets/Resources.resx rename to src/Tools/dotnet-user-secrets/src/Resources.resx diff --git a/src/dotnet-user-secrets/assets/SecretManager.targets b/src/Tools/dotnet-user-secrets/src/assets/SecretManager.targets similarity index 100% rename from src/dotnet-user-secrets/assets/SecretManager.targets rename to src/Tools/dotnet-user-secrets/src/assets/SecretManager.targets diff --git a/src/Tools/dotnet-user-secrets/src/dotnet-user-secrets.csproj b/src/Tools/dotnet-user-secrets/src/dotnet-user-secrets.csproj new file mode 100644 index 0000000000..a66a31dd7e --- /dev/null +++ b/src/Tools/dotnet-user-secrets/src/dotnet-user-secrets.csproj @@ -0,0 +1,42 @@ + + + + netcoreapp2.1 + exe + Command line tool to manage user secrets for Microsoft.Extensions.Configuration. + false + Microsoft.Extensions.SecretManager.Tools + configuration;secrets;usersecrets + true + + win-x64;win-x86 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/dotnet-user-secrets.Tests/MsBuildProjectFinderTest.cs b/src/Tools/dotnet-user-secrets/test/MsBuildProjectFinderTest.cs similarity index 100% rename from test/dotnet-user-secrets.Tests/MsBuildProjectFinderTest.cs rename to src/Tools/dotnet-user-secrets/test/MsBuildProjectFinderTest.cs diff --git a/test/dotnet-user-secrets.Tests/SecretManagerTests.cs b/src/Tools/dotnet-user-secrets/test/SecretManagerTests.cs similarity index 100% rename from test/dotnet-user-secrets.Tests/SecretManagerTests.cs rename to src/Tools/dotnet-user-secrets/test/SecretManagerTests.cs diff --git a/test/dotnet-user-secrets.Tests/SetCommandTest.cs b/src/Tools/dotnet-user-secrets/test/SetCommandTest.cs similarity index 100% rename from test/dotnet-user-secrets.Tests/SetCommandTest.cs rename to src/Tools/dotnet-user-secrets/test/SetCommandTest.cs diff --git a/test/dotnet-user-secrets.Tests/TemporaryFileProvider.cs b/src/Tools/dotnet-user-secrets/test/TemporaryFileProvider.cs similarity index 100% rename from test/dotnet-user-secrets.Tests/TemporaryFileProvider.cs rename to src/Tools/dotnet-user-secrets/test/TemporaryFileProvider.cs diff --git a/test/dotnet-user-secrets.Tests/UserSecretsTestFixture.cs b/src/Tools/dotnet-user-secrets/test/UserSecretsTestFixture.cs similarity index 100% rename from test/dotnet-user-secrets.Tests/UserSecretsTestFixture.cs rename to src/Tools/dotnet-user-secrets/test/UserSecretsTestFixture.cs diff --git a/src/Tools/dotnet-user-secrets/test/dotnet-user-secrets.Tests.csproj b/src/Tools/dotnet-user-secrets/test/dotnet-user-secrets.Tests.csproj new file mode 100644 index 0000000000..0254a866e8 --- /dev/null +++ b/src/Tools/dotnet-user-secrets/test/dotnet-user-secrets.Tests.csproj @@ -0,0 +1,21 @@ + + + + netcoreapp2.1 + Microsoft.Extensions.SecretManager.Tools.Tests + + + + + + + + + + + + + + + + diff --git a/src/dotnet-watch/README.md b/src/Tools/dotnet-watch/README.md similarity index 100% rename from src/dotnet-watch/README.md rename to src/Tools/dotnet-watch/README.md diff --git a/src/dotnet-watch/CommandLineOptions.cs b/src/Tools/dotnet-watch/src/CommandLineOptions.cs similarity index 100% rename from src/dotnet-watch/CommandLineOptions.cs rename to src/Tools/dotnet-watch/src/CommandLineOptions.cs diff --git a/src/dotnet-watch/DotNetWatcher.cs b/src/Tools/dotnet-watch/src/DotNetWatcher.cs similarity index 100% rename from src/dotnet-watch/DotNetWatcher.cs rename to src/Tools/dotnet-watch/src/DotNetWatcher.cs diff --git a/src/dotnet-watch/IFileSet.cs b/src/Tools/dotnet-watch/src/IFileSet.cs similarity index 100% rename from src/dotnet-watch/IFileSet.cs rename to src/Tools/dotnet-watch/src/IFileSet.cs diff --git a/src/dotnet-watch/IFileSetFactory.cs b/src/Tools/dotnet-watch/src/IFileSetFactory.cs similarity index 100% rename from src/dotnet-watch/IFileSetFactory.cs rename to src/Tools/dotnet-watch/src/IFileSetFactory.cs diff --git a/src/dotnet-watch/Internal/FileSet.cs b/src/Tools/dotnet-watch/src/Internal/FileSet.cs similarity index 100% rename from src/dotnet-watch/Internal/FileSet.cs rename to src/Tools/dotnet-watch/src/Internal/FileSet.cs diff --git a/src/dotnet-watch/Internal/FileSetWatcher.cs b/src/Tools/dotnet-watch/src/Internal/FileSetWatcher.cs similarity index 100% rename from src/dotnet-watch/Internal/FileSetWatcher.cs rename to src/Tools/dotnet-watch/src/Internal/FileSetWatcher.cs diff --git a/src/dotnet-watch/Internal/FileWatcher.cs b/src/Tools/dotnet-watch/src/Internal/FileWatcher.cs similarity index 100% rename from src/dotnet-watch/Internal/FileWatcher.cs rename to src/Tools/dotnet-watch/src/Internal/FileWatcher.cs diff --git a/src/dotnet-watch/Internal/FileWatcher/DotnetFileWatcher.cs b/src/Tools/dotnet-watch/src/Internal/FileWatcher/DotnetFileWatcher.cs similarity index 100% rename from src/dotnet-watch/Internal/FileWatcher/DotnetFileWatcher.cs rename to src/Tools/dotnet-watch/src/Internal/FileWatcher/DotnetFileWatcher.cs diff --git a/src/dotnet-watch/Internal/FileWatcher/FileWatcherFactory.cs b/src/Tools/dotnet-watch/src/Internal/FileWatcher/FileWatcherFactory.cs similarity index 100% rename from src/dotnet-watch/Internal/FileWatcher/FileWatcherFactory.cs rename to src/Tools/dotnet-watch/src/Internal/FileWatcher/FileWatcherFactory.cs diff --git a/src/dotnet-watch/Internal/FileWatcher/IFileSystemWatcher.cs b/src/Tools/dotnet-watch/src/Internal/FileWatcher/IFileSystemWatcher.cs similarity index 100% rename from src/dotnet-watch/Internal/FileWatcher/IFileSystemWatcher.cs rename to src/Tools/dotnet-watch/src/Internal/FileWatcher/IFileSystemWatcher.cs diff --git a/src/dotnet-watch/Internal/FileWatcher/PollingFileWatcher.cs b/src/Tools/dotnet-watch/src/Internal/FileWatcher/PollingFileWatcher.cs similarity index 100% rename from src/dotnet-watch/Internal/FileWatcher/PollingFileWatcher.cs rename to src/Tools/dotnet-watch/src/Internal/FileWatcher/PollingFileWatcher.cs diff --git a/src/dotnet-watch/Internal/MsBuildFileSetFactory.cs b/src/Tools/dotnet-watch/src/Internal/MsBuildFileSetFactory.cs similarity index 100% rename from src/dotnet-watch/Internal/MsBuildFileSetFactory.cs rename to src/Tools/dotnet-watch/src/Internal/MsBuildFileSetFactory.cs diff --git a/src/dotnet-watch/Internal/MsBuildProjectFinder.cs b/src/Tools/dotnet-watch/src/Internal/MsBuildProjectFinder.cs similarity index 100% rename from src/dotnet-watch/Internal/MsBuildProjectFinder.cs rename to src/Tools/dotnet-watch/src/Internal/MsBuildProjectFinder.cs diff --git a/src/dotnet-watch/Internal/OutputCapture.cs b/src/Tools/dotnet-watch/src/Internal/OutputCapture.cs similarity index 100% rename from src/dotnet-watch/Internal/OutputCapture.cs rename to src/Tools/dotnet-watch/src/Internal/OutputCapture.cs diff --git a/src/dotnet-watch/Internal/OutputSink.cs b/src/Tools/dotnet-watch/src/Internal/OutputSink.cs similarity index 100% rename from src/dotnet-watch/Internal/OutputSink.cs rename to src/Tools/dotnet-watch/src/Internal/OutputSink.cs diff --git a/src/dotnet-watch/Internal/ProcessRunner.cs b/src/Tools/dotnet-watch/src/Internal/ProcessRunner.cs similarity index 100% rename from src/dotnet-watch/Internal/ProcessRunner.cs rename to src/Tools/dotnet-watch/src/Internal/ProcessRunner.cs diff --git a/src/dotnet-watch/PrefixConsoleReporter.cs b/src/Tools/dotnet-watch/src/PrefixConsoleReporter.cs similarity index 100% rename from src/dotnet-watch/PrefixConsoleReporter.cs rename to src/Tools/dotnet-watch/src/PrefixConsoleReporter.cs diff --git a/src/dotnet-watch/ProcessSpec.cs b/src/Tools/dotnet-watch/src/ProcessSpec.cs similarity index 100% rename from src/dotnet-watch/ProcessSpec.cs rename to src/Tools/dotnet-watch/src/ProcessSpec.cs diff --git a/src/dotnet-watch/Program.cs b/src/Tools/dotnet-watch/src/Program.cs similarity index 100% rename from src/dotnet-watch/Program.cs rename to src/Tools/dotnet-watch/src/Program.cs diff --git a/src/dotnet-watch/Properties/AssemblyInfo.cs b/src/Tools/dotnet-watch/src/Properties/AssemblyInfo.cs similarity index 100% rename from src/dotnet-watch/Properties/AssemblyInfo.cs rename to src/Tools/dotnet-watch/src/Properties/AssemblyInfo.cs diff --git a/src/dotnet-watch/Properties/Resources.Designer.cs b/src/Tools/dotnet-watch/src/Properties/Resources.Designer.cs similarity index 100% rename from src/dotnet-watch/Properties/Resources.Designer.cs rename to src/Tools/dotnet-watch/src/Properties/Resources.Designer.cs diff --git a/src/dotnet-watch/Resources.resx b/src/Tools/dotnet-watch/src/Resources.resx similarity index 100% rename from src/dotnet-watch/Resources.resx rename to src/Tools/dotnet-watch/src/Resources.resx diff --git a/src/dotnet-watch/assets/DotNetWatch.targets b/src/Tools/dotnet-watch/src/assets/DotNetWatch.targets similarity index 100% rename from src/dotnet-watch/assets/DotNetWatch.targets rename to src/Tools/dotnet-watch/src/assets/DotNetWatch.targets diff --git a/src/dotnet-watch/dotnet-watch.csproj b/src/Tools/dotnet-watch/src/dotnet-watch.csproj similarity index 100% rename from src/dotnet-watch/dotnet-watch.csproj rename to src/Tools/dotnet-watch/src/dotnet-watch.csproj diff --git a/test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs b/src/Tools/dotnet-watch/test/AppWithDepsTests.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs rename to src/Tools/dotnet-watch/test/AppWithDepsTests.cs diff --git a/test/dotnet-watch.Tests/AssertEx.cs b/src/Tools/dotnet-watch/test/AssertEx.cs similarity index 100% rename from test/dotnet-watch.Tests/AssertEx.cs rename to src/Tools/dotnet-watch/test/AssertEx.cs diff --git a/test/dotnet-watch.FunctionalTests/AwaitableProcess.cs b/src/Tools/dotnet-watch/test/AwaitableProcess.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/AwaitableProcess.cs rename to src/Tools/dotnet-watch/test/AwaitableProcess.cs diff --git a/test/dotnet-watch.Tests/CommandLineOptionsTests.cs b/src/Tools/dotnet-watch/test/CommandLineOptionsTests.cs similarity index 100% rename from test/dotnet-watch.Tests/CommandLineOptionsTests.cs rename to src/Tools/dotnet-watch/test/CommandLineOptionsTests.cs diff --git a/test/dotnet-watch.Tests/ConsoleReporterTests.cs b/src/Tools/dotnet-watch/test/ConsoleReporterTests.cs similarity index 100% rename from test/dotnet-watch.Tests/ConsoleReporterTests.cs rename to src/Tools/dotnet-watch/test/ConsoleReporterTests.cs diff --git a/test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs b/src/Tools/dotnet-watch/test/DotNetWatcherTests.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/DotNetWatcherTests.cs rename to src/Tools/dotnet-watch/test/DotNetWatcherTests.cs diff --git a/test/dotnet-watch.FunctionalTests/FileWatcherTests.cs b/src/Tools/dotnet-watch/test/FileWatcherTests.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/FileWatcherTests.cs rename to src/Tools/dotnet-watch/test/FileWatcherTests.cs diff --git a/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs b/src/Tools/dotnet-watch/test/GlobbingAppTests.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs rename to src/Tools/dotnet-watch/test/GlobbingAppTests.cs diff --git a/test/dotnet-watch.Tests/MsBuildFileSetFactoryTest.cs b/src/Tools/dotnet-watch/test/MsBuildFileSetFactoryTest.cs similarity index 100% rename from test/dotnet-watch.Tests/MsBuildFileSetFactoryTest.cs rename to src/Tools/dotnet-watch/test/MsBuildFileSetFactoryTest.cs diff --git a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs b/src/Tools/dotnet-watch/test/NoDepsAppTests.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs rename to src/Tools/dotnet-watch/test/NoDepsAppTests.cs diff --git a/test/dotnet-watch.Tests/ProgramTests.cs b/src/Tools/dotnet-watch/test/ProgramTests.cs similarity index 100% rename from test/dotnet-watch.Tests/ProgramTests.cs rename to src/Tools/dotnet-watch/test/ProgramTests.cs diff --git a/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs b/src/Tools/dotnet-watch/test/Scenario/ProjectToolScenario.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs rename to src/Tools/dotnet-watch/test/Scenario/ProjectToolScenario.cs diff --git a/test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs b/src/Tools/dotnet-watch/test/Scenario/WatchableApp.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/Scenario/WatchableApp.cs rename to src/Tools/dotnet-watch/test/Scenario/WatchableApp.cs diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj b/src/Tools/dotnet-watch/test/TestProjects/AppWithDeps/AppWithDeps.csproj similarity index 100% rename from test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/AppWithDeps.csproj rename to src/Tools/dotnet-watch/test/TestProjects/AppWithDeps/AppWithDeps.csproj diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/Program.cs b/src/Tools/dotnet-watch/test/TestProjects/AppWithDeps/Program.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/TestProjects/AppWithDeps/Program.cs rename to src/Tools/dotnet-watch/test/TestProjects/AppWithDeps/Program.cs diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/Dependency/Dependency.csproj b/src/Tools/dotnet-watch/test/TestProjects/Dependency/Dependency.csproj similarity index 100% rename from test/dotnet-watch.FunctionalTests/TestProjects/Dependency/Dependency.csproj rename to src/Tools/dotnet-watch/test/TestProjects/Dependency/Dependency.csproj diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/Dependency/Foo.cs b/src/Tools/dotnet-watch/test/TestProjects/Dependency/Foo.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/TestProjects/Dependency/Foo.cs rename to src/Tools/dotnet-watch/test/TestProjects/Dependency/Foo.cs diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj b/src/Tools/dotnet-watch/test/TestProjects/GlobbingApp/GlobbingApp.csproj similarity index 100% rename from test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/GlobbingApp.csproj rename to src/Tools/dotnet-watch/test/TestProjects/GlobbingApp/GlobbingApp.csproj diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/Program.cs b/src/Tools/dotnet-watch/test/TestProjects/GlobbingApp/Program.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/Program.cs rename to src/Tools/dotnet-watch/test/TestProjects/GlobbingApp/Program.cs diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/exclude/Baz.cs b/src/Tools/dotnet-watch/test/TestProjects/GlobbingApp/exclude/Baz.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/exclude/Baz.cs rename to src/Tools/dotnet-watch/test/TestProjects/GlobbingApp/exclude/Baz.cs diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/include/Foo.cs b/src/Tools/dotnet-watch/test/TestProjects/GlobbingApp/include/Foo.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/TestProjects/GlobbingApp/include/Foo.cs rename to src/Tools/dotnet-watch/test/TestProjects/GlobbingApp/include/Foo.cs diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj b/src/Tools/dotnet-watch/test/TestProjects/KitchenSink/KitchenSink.csproj similarity index 100% rename from test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj rename to src/Tools/dotnet-watch/test/TestProjects/KitchenSink/KitchenSink.csproj diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/Program.cs b/src/Tools/dotnet-watch/test/TestProjects/KitchenSink/Program.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/TestProjects/KitchenSink/Program.cs rename to src/Tools/dotnet-watch/test/TestProjects/KitchenSink/Program.cs diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj b/src/Tools/dotnet-watch/test/TestProjects/NoDepsApp/NoDepsApp.csproj similarity index 100% rename from test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/NoDepsApp.csproj rename to src/Tools/dotnet-watch/test/TestProjects/NoDepsApp/NoDepsApp.csproj diff --git a/test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/Program.cs b/src/Tools/dotnet-watch/test/TestProjects/NoDepsApp/Program.cs similarity index 100% rename from test/dotnet-watch.FunctionalTests/TestProjects/NoDepsApp/Program.cs rename to src/Tools/dotnet-watch/test/TestProjects/NoDepsApp/Program.cs diff --git a/test/dotnet-watch.Tests/Utilities/TemporaryCSharpProject.cs b/src/Tools/dotnet-watch/test/Utilities/TemporaryCSharpProject.cs similarity index 100% rename from test/dotnet-watch.Tests/Utilities/TemporaryCSharpProject.cs rename to src/Tools/dotnet-watch/test/Utilities/TemporaryCSharpProject.cs diff --git a/test/dotnet-watch.Tests/Utilities/TemporaryDirectory.cs b/src/Tools/dotnet-watch/test/Utilities/TemporaryDirectory.cs similarity index 100% rename from test/dotnet-watch.Tests/Utilities/TemporaryDirectory.cs rename to src/Tools/dotnet-watch/test/Utilities/TemporaryDirectory.cs diff --git a/test/dotnet-watch.Tests/Utilities/TestProjectGraph.cs b/src/Tools/dotnet-watch/test/Utilities/TestProjectGraph.cs similarity index 100% rename from test/dotnet-watch.Tests/Utilities/TestProjectGraph.cs rename to src/Tools/dotnet-watch/test/Utilities/TestProjectGraph.cs diff --git a/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj b/src/Tools/dotnet-watch/test/dotnet-watch.Tests.csproj similarity index 64% rename from test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj rename to src/Tools/dotnet-watch/test/dotnet-watch.Tests.csproj index d7c0a3fdac..ce23611f24 100644 --- a/test/dotnet-watch.FunctionalTests/dotnet-watch.FunctionalTests.csproj +++ b/src/Tools/dotnet-watch/test/dotnet-watch.Tests.csproj @@ -2,23 +2,22 @@ netcoreapp2.1 + Microsoft.DotNet.Watcher.Tools.Tests $(DefaultItemExcludes);TestProjects\**\* - Microsoft.DotNet.Watcher.Tools.FunctionalTests - + - - + - - + + @@ -37,7 +36,7 @@ - diff --git a/shared/CliContext.cs b/src/Tools/shared/src/CliContext.cs similarity index 100% rename from shared/CliContext.cs rename to src/Tools/shared/src/CliContext.cs diff --git a/shared/CommandLineApplicationExtensions.cs b/src/Tools/shared/src/CommandLineApplicationExtensions.cs similarity index 100% rename from shared/CommandLineApplicationExtensions.cs rename to src/Tools/shared/src/CommandLineApplicationExtensions.cs diff --git a/shared/ConsoleReporter.cs b/src/Tools/shared/src/ConsoleReporter.cs similarity index 100% rename from shared/ConsoleReporter.cs rename to src/Tools/shared/src/ConsoleReporter.cs diff --git a/shared/DebugHelper.cs b/src/Tools/shared/src/DebugHelper.cs similarity index 100% rename from shared/DebugHelper.cs rename to src/Tools/shared/src/DebugHelper.cs diff --git a/shared/Ensure.cs b/src/Tools/shared/src/Ensure.cs similarity index 100% rename from shared/Ensure.cs rename to src/Tools/shared/src/Ensure.cs diff --git a/shared/IConsole.cs b/src/Tools/shared/src/IConsole.cs similarity index 100% rename from shared/IConsole.cs rename to src/Tools/shared/src/IConsole.cs diff --git a/shared/IReporter.cs b/src/Tools/shared/src/IReporter.cs similarity index 100% rename from shared/IReporter.cs rename to src/Tools/shared/src/IReporter.cs diff --git a/shared/NullReporter.cs b/src/Tools/shared/src/NullReporter.cs similarity index 100% rename from shared/NullReporter.cs rename to src/Tools/shared/src/NullReporter.cs diff --git a/shared/PhysicalConsole.cs b/src/Tools/shared/src/PhysicalConsole.cs similarity index 100% rename from shared/PhysicalConsole.cs rename to src/Tools/shared/src/PhysicalConsole.cs diff --git a/test/Shared/TestConsole.cs b/src/Tools/shared/test/TestConsole.cs similarity index 100% rename from test/Shared/TestConsole.cs rename to src/Tools/shared/test/TestConsole.cs diff --git a/test/Shared/TestReporter.cs b/src/Tools/shared/test/TestReporter.cs similarity index 100% rename from test/Shared/TestReporter.cs rename to src/Tools/shared/test/TestReporter.cs diff --git a/src/dotnet-dev-certs/dotnet-dev-certs.csproj b/src/dotnet-dev-certs/dotnet-dev-certs.csproj deleted file mode 100644 index 59dc5b5eab..0000000000 --- a/src/dotnet-dev-certs/dotnet-dev-certs.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - netcoreapp2.1 - exe - Command line tool to generate certificates used in ASP.NET Core during development. - Microsoft.AspNetCore.DeveloperCertificates.Tools - dotnet;developercertificates - true - - win-x64;win-x86 - - - - - - - - - - - - - - - - - - - - - diff --git a/src/dotnet-sql-cache/dotnet-sql-cache.csproj b/src/dotnet-sql-cache/dotnet-sql-cache.csproj deleted file mode 100644 index 15c3229544..0000000000 --- a/src/dotnet-sql-cache/dotnet-sql-cache.csproj +++ /dev/null @@ -1,35 +0,0 @@ - - - - netcoreapp2.1 - exe - Command line tool to create tables and indexes in a Microsoft SQL Server database for distributed caching. - cache;distributedcache;sqlserver - true - - win-x64;win-x86 - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/dotnet-user-secrets/dotnet-user-secrets.csproj b/src/dotnet-user-secrets/dotnet-user-secrets.csproj deleted file mode 100644 index 99258ea0f6..0000000000 --- a/src/dotnet-user-secrets/dotnet-user-secrets.csproj +++ /dev/null @@ -1,42 +0,0 @@ - - - - netcoreapp2.1 - exe - Command line tool to manage user secrets for Microsoft.Extensions.Configuration. - false - Microsoft.Extensions.SecretManager.Tools - configuration;secrets;usersecrets - true - - win-x64;win-x86 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/Directory.Build.props b/test/Directory.Build.props deleted file mode 100644 index c79812719a..0000000000 --- a/test/Directory.Build.props +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj b/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj deleted file mode 100644 index fd8be34db7..0000000000 --- a/test/dotnet-user-secrets.Tests/dotnet-user-secrets.Tests.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - netcoreapp2.1 - Microsoft.Extensions.SecretManager.Tools.Tests - - - - - - - - - - - - - - - - diff --git a/test/dotnet-watch.Tests/dotnet-watch.Tests.csproj b/test/dotnet-watch.Tests/dotnet-watch.Tests.csproj deleted file mode 100644 index ce5349ad3e..0000000000 --- a/test/dotnet-watch.Tests/dotnet-watch.Tests.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - netcoreapp2.1 - Microsoft.DotNet.Watcher.Tools.Tests - - - - - - - - - - - diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Key.snk b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Key.snk deleted file mode 100644 index 2181a1627bf841f91b220de8258de4591629d169..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098eLAD9Hsv)-@LYruqYXoq*$CbcyqhF9_ zJNINE4KwxCc=zqW)Jwkn`UV}^Y(IMBUm{xgCv_L2E)Wkc$U2dxKX7}>;DDK-YyBR0 zv=7PjBU$b1ek&UiLnaZH0)Abxi^KRk>d3t73-A?lyM6?EoG?NRqitAMj2X3Z%u&|E zrwKH+r+S(9p=O{cvKd2`xM2&?bvfd7`75k&O%+r%^Y9Y((vA%FwT9CHDc1YIm z?bKQ;eA=^ehw|6kYCr#+^U@%^KVmW;jWR>>>52Qp(#(u)JQMZntn)LxTf^YaEopg% zSwCw!kXHvf`Yi5*iHA|n^xZiW`Vs!)erHg)_=wmuq`=R*E1(2vKuV7Aqfi;Z_JV}) zocdzFRoQ|X~Wz-;7of>%3oHo1{Tr@ar%xdF&hy6Cdrd z#Vr5nWd2vx^_sX>r<(q0{qfHrRw{Oq(R~1V%Y)_)X+3Kn8cf$)`f?|$rnz~wob0mw z!!?6FA|Ksdn;(hg$rFCTIa5M7;@1K!FJEr&5h+UyX% i)<83a5xbDB8Z - - - 15.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - False - False - False - True - True - ..\..\build\Key.snk - True - - - - - - - Debug - AnyCPU - 2.0 - {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {965F8820-F809-4081-9090-1AEC903F291B} - Library - Properties - Microsoft.VisualStudio.SecretManager.TestExtension - Microsoft.VisualStudio.SecretManager.TestExtension - v4.6.1 - true - true - true - true - true - false - Program - $(DevEnvDir)devenv.exe - /rootsuffix Exp - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - SecretManagerTestControl.xaml - - - - - - - Designer - - - - - - - - - Designer - MSBuild:Compile - - - - - - - - False - - - - - - - - - - - - - - - - - - - 7.10.6071 - - - - - - 11.0.61030 - - - 12.0.30110 - - - 15.0.26606 - - - 8.0.50727 - - - 9.0.30729 - - - - 4.4.0 - - - - - - - Menus.ctmenu - - - - - true - VSPackage - - - - - - diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/NotifyPropertyChanged.cs b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/NotifyPropertyChanged.cs deleted file mode 100644 index 720593d469..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/NotifyPropertyChanged.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.ComponentModel; -using System.Runtime.CompilerServices; - -namespace Microsoft.VisualStudio.SecretManager.TestExtension -{ - public abstract class NotifyPropertyChanged : INotifyPropertyChanged - { - public event PropertyChangedEventHandler PropertyChanged; - - protected void OnPropertyChanged([CallerMemberName] string propertyName = null) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - } -} diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/ProjectViewModel.cs b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/ProjectViewModel.cs deleted file mode 100644 index f667db5267..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/ProjectViewModel.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.IO; -using Microsoft.VisualStudio.ProjectSystem; - -namespace Microsoft.VisualStudio.SecretManager.TestExtension -{ - public class ProjectViewModel : NotifyPropertyChanged - { - public ProjectViewModel(UnconfiguredProject project) - { - Project = project; - } - - internal UnconfiguredProject Project { get; } - - public string ProjectName => Path.GetFileNameWithoutExtension(Project.FullPath); - } -} diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Properties/AssemblyInfo.cs b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Properties/AssemblyInfo.cs deleted file mode 100644 index 9999a9ba7e..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Microsoft.VisualStudio.SecretManager.TestExtension")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Microsoft.VisualStudio.SecretManager.TestExtension")] -[assembly: AssemblyCopyright("")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/RelayCommand.cs b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/RelayCommand.cs deleted file mode 100644 index e12b2bd622..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/RelayCommand.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Windows.Input; - -namespace Microsoft.VisualStudio.SecretManager.TestExtension -{ - public class RelayCommand : ICommand - { - readonly Action _execute = null; - readonly Predicate _canExecute = null; - - public RelayCommand(Action execute) - : this(execute, null) - { - } - - public RelayCommand(Action execute, Predicate canExecute) - { - if (execute == null) - throw new ArgumentNullException("execute"); - - _execute = execute; - _canExecute = canExecute; - } - - public bool CanExecute(object parameter) - { - return _canExecute == null ? true : _canExecute((T)parameter); - } - - public event EventHandler CanExecuteChanged - { - add { CommandManager.RequerySuggested += value; } - remove { CommandManager.RequerySuggested -= value; } - } - - public void Execute(object parameter) - { - _execute((T)parameter); - } - } -} diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Resources/SecretManagerTestCommand.png b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/Resources/SecretManagerTestCommand.png deleted file mode 100644 index b22d975cbf00eda60e37587614e0677d0bfb525d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1172 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

N3mPu2mM3; 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 - /// Command ID. - /// - public const int CommandId = 0x0100; - - ///

- /// Command menu group (command set GUID). - /// - public static readonly Guid CommandSet = new Guid("e415a3f4-f2a8-4834-b7f7-f89844b2505c"); - - /// - /// VS Package that provides this command, not null. - /// - private readonly Package package; - - /// - /// Initializes a new instance of the class. - /// Adds our command handlers for menu (commands must exist in the command table file) - /// - /// Owner package, not null. - private SecretManagerTestCommand(Package package) - { - if (package == null) - { - throw new ArgumentNullException("package"); - } - - this.package = package; - - OleMenuCommandService commandService = this.ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService; - if (commandService != null) - { - var menuCommandID = new CommandID(CommandSet, CommandId); - var menuItem = new MenuCommand(this.ShowToolWindow, menuCommandID); - commandService.AddCommand(menuItem); - } - } - - /// - /// Gets the instance of the command. - /// - public static SecretManagerTestCommand Instance - { - get; - private set; - } - - /// - /// Gets the service provider from the owner package. - /// - private IServiceProvider ServiceProvider - { - get - { - return this.package; - } - } - - /// - /// Initializes the singleton instance of the command. - /// - /// Owner package, not null. - public static void Initialize(Package package) - { - Instance = new SecretManagerTestCommand(package); - } - - /// - /// Shows the tool window when the menu item is clicked. - /// - /// The event sender. - /// The event args. - private void ShowToolWindow(object sender, EventArgs e) - { - // Get the instance number 0 of this tool window. This window is single instance so this instance - // is actually the only one. - // The last flag is set to true so that if the tool window does not exists it will be created. - ToolWindowPane window = this.package.FindToolWindow(typeof(SecretManagerTestWindow), 0, true); - if ((null == window) || (null == window.Frame)) - { - throw new NotSupportedException("Cannot create tool window"); - } - - IVsWindowFrame windowFrame = (IVsWindowFrame)window.Frame; - Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(windowFrame.Show()); - } - } -} diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestControl.xaml b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestControl.xaml deleted file mode 100644 index 201144b7e1..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestControl.xaml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestControl.xaml.cs b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestControl.xaml.cs deleted file mode 100644 index b39c208ddf..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestControl.xaml.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.VisualStudio.SecretManager.TestExtension -{ - using System.Diagnostics.CodeAnalysis; - using System.Windows; - using System.Windows.Controls; - - /// - /// Interaction logic for SecretManagerTestControl. - /// - public partial class SecretManagerTestControl : UserControl - { - /// - /// Initializes a new instance of the class. - /// - public SecretManagerTestControl() - { - this.InitializeComponent(); - } - - /// - /// Handles click on the button by displaying a message box. - /// - /// The event sender. - /// The event args. - [SuppressMessage("Microsoft.Globalization", "CA1300:SpecifyMessageBoxOptions", Justification = "Sample code")] - [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:ElementMustBeginWithUpperCaseLetter", Justification = "Default event handler naming pattern")] - private void button1_Click(object sender, RoutedEventArgs e) - { - MessageBox.Show( - string.Format(System.Globalization.CultureInfo.CurrentUICulture, "Invoked '{0}'", this.ToString()), - "SecretManagerTest"); - } - } -} diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestPackage.cs b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestPackage.cs deleted file mode 100644 index ada842d9cb..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestPackage.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.InteropServices; -using Microsoft.VisualStudio.Shell; - -namespace Microsoft.VisualStudio.SecretManager.TestExtension -{ - [PackageRegistration(UseManagedResourcesOnly = true)] - [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] // Info on this package for Help/About - [ProvideMenuResource("Menus.ctmenu", 1)] - [ProvideToolWindow(typeof(SecretManagerTestWindow))] - [Guid(SecretManagerTestPackage.PackageGuidString)] - [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "pkgdef, VS and vsixmanifest are valid VS terms")] - public sealed class SecretManagerTestPackage : Package - { - public const string PackageGuidString = "7b771e3e-f599-4fde-95a9-e35019e705f7"; - - protected override void Initialize() - { - SecretManagerTestCommand.Initialize(this); - base.Initialize(); - } - } -} diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestPackage.vsct b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestPackage.vsct deleted file mode 100644 index 554ae60164..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestPackage.vsct +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestWindow.cs b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestWindow.cs deleted file mode 100644 index 240a8fb935..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerTestWindow.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Runtime.InteropServices; -using Microsoft.VisualStudio.ComponentModelHost; -using Microsoft.VisualStudio.ProjectSystem; -using Microsoft.VisualStudio.Shell; - -namespace Microsoft.VisualStudio.SecretManager.TestExtension -{ - [Guid("6afffd63-17b6-4ef2-b515-fee22d767631")] - public class SecretManagerTestWindow : ToolWindowPane - { - public SecretManagerTestWindow() - : base(null) - { - this.Caption = "SecretManager Test Window"; - this.Content = new SecretManagerTestControl(); - } - - protected override void Initialize() - { - base.Initialize(); - - var component = (IComponentModel)GetService(typeof(SComponentModel)); - var projectService = component.GetService().GetProjectService(); - ((SecretManagerTestControl)Content).DataContext = new SecretManagerViewModel(projectService); - } - } -} diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerViewModel.cs b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerViewModel.cs deleted file mode 100644 index 3a4d5cbf61..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/SecretManagerViewModel.cs +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Runtime.InteropServices; -using System.Threading.Tasks; -using System.Windows; -using Microsoft.VisualStudio.ProjectSystem; -using Microsoft.VisualStudio.Shell; -using Microsoft.VisualStudio.Shell.Interop; -using Microsoft.VisualStudio.Threading; -using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider; -using Task = System.Threading.Tasks.Task; - -namespace Microsoft.VisualStudio.SecretManager.TestExtension -{ - public class SecretManagerViewModel : NotifyPropertyChanged - { - private readonly IProjectService _projectService; - private readonly Random _rand; - private string _error; - private bool _isLoaded; - private ProjectViewModel _selectedProject; - - public SecretManagerViewModel(IProjectService projectService) - { - _projectService = projectService; - - RefreshCommand = new RelayCommand(Refresh, RefreshIsEnabled); - AddCommand = new RelayCommand(Add, IsProjectLoaded); - SaveCommand = new RelayCommand(Save, IsProjectLoaded); - Refresh(null); - _rand = new Random(); - } - - public RelayCommand RefreshCommand { get; } - - public RelayCommand AddCommand { get; } - public RelayCommand SaveCommand { get; } - - public ObservableCollection Projects { get; } = new ObservableCollection(); - - public ProjectViewModel SelectedProject - { - get => _selectedProject; - set - { - if (value == _selectedProject) - { - return; - } - - _selectedProject = value; - OnSelectedProjectChanged(); - OnPropertyChanged(); - } - } - - public bool IsLoaded - { - get => _isLoaded; - set - { - if (value == _isLoaded) - { - return; - } - - _isLoaded = value; - OnPropertyChanged(); - } - } - - public string Error - { - get => _error; - set - { - if (value == _error) - { - return; - } - - _error = value; - OnPropertyChanged(); - OnPropertyChanged(nameof(ErrorVisibility)); - } - } - - public Visibility ErrorVisibility => Error == null ? Visibility.Collapsed : Visibility.Visible; - - public ObservableCollection> Secrets { get; } = new ObservableCollection>(); - - private bool RefreshIsEnabled(object obj) => IsLoaded || SelectedProject == null; - - private void Refresh(object obj) - { - Projects.Clear(); - - foreach (var project in _projectService.LoadedUnconfiguredProjects) - { - Projects.Add(new ProjectViewModel(project)); - } - } - - private bool IsProjectLoaded(object obj) => IsLoaded && SelectedProject != null; - - private void Add(object obj) - { - Secrets.Add(new KeyValuePair("NewKey" + _rand.Next(10_000), "My new totally random and secret test value")); - } - - private async void Save(object obj) - { - Exception exception; - - try - { - IOleServiceProvider oleServices; - var project = (IVsProject)_selectedProject.Project.Services.HostObject; - Marshal.ThrowExceptionForHR(project.GetItemContext((uint)VSConstants.VSITEMID.Root, out oleServices)); - var services = new ServiceProvider(oleServices); - - var projectSecrets = (IVsProjectSecrets)services.GetService(typeof(SVsProjectLocalSecrets)); - await TaskScheduler.Default; - - if (projectSecrets == null) - { - exception = null; - } - else - { - foreach (var secret in Secrets) - { - await projectSecrets.SetSecretAsync(secret.Key, secret.Value).ConfigureAwait(false); - } - - exception = null; - } - } - catch (Exception ex) - { - exception = ex; - } - - if (exception != null) - { - Error = exception.ToString(); - } - } - - private async void OnSelectedProjectChanged() - { - Secrets.Clear(); - IsLoaded = false; - - if (_selectedProject == null) - { - return; - } - - KeyValuePair[] results; - Exception exception; - - try - { - IOleServiceProvider oleServices; - var project = (IVsProject)_selectedProject.Project.Services.HostObject; - Marshal.ThrowExceptionForHR(project.GetItemContext((uint)VSConstants.VSITEMID.Root, out oleServices)); - var services = new ServiceProvider(oleServices); - - var projectSecrets = (IVsProjectSecrets)services.GetService(typeof(SVsProjectLocalSecrets)); - await TaskScheduler.Default; - - if (projectSecrets == null) - { - results = null; - exception = null; - } - else - { - var secrets = await projectSecrets.GetSecretsAsync().ConfigureAwait(false); - - results = secrets.ToArray(); - exception = null; - } - } - catch (Exception ex) - { - results = null; - exception = ex; - } - - await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); - - if (exception != null) - { - Error = exception.ToString(); - } - else if (results != null) - { - for (var i = 0; i < results.Length; i++) - { - Secrets.Add(results[i]); - } - } - - IsLoaded = true; - } - } -} diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/VSPackage.resx b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/VSPackage.resx deleted file mode 100644 index ca1c752309..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/VSPackage.resx +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - SecretManagerTest Extension - - - SecretManagerTest Visual Studio Extension Detailed Info - - - Resources\SecretManagerTestPackage.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - \ No newline at end of file diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/app.config b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/app.config deleted file mode 100644 index 4bac29887b..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/app.config +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/source.extension.vsixmanifest b/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/source.extension.vsixmanifest deleted file mode 100644 index 3b8e971651..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager.TestExtension/source.extension.vsixmanifest +++ /dev/null @@ -1,21 +0,0 @@ - - - - - Microsoft.VisualStudio.SecretManager.TestExtension - A test extension for Microsoft.VisualStudio.TestExtension - - - - - - - - - - - - - - - diff --git a/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj b/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj deleted file mode 100644 index b178075251..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager/Microsoft.VisualStudio.SecretManager.csproj +++ /dev/null @@ -1,117 +0,0 @@ - - - - 15.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - CommonExtensions - Microsoft\ASP.NET Core\UserSecrets - true - - False - False - False - True - True - ..\..\build\Key.snk - True - - - - - - - Debug - AnyCPU - 2.0 - {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {5E117F2E-7152-447F-BF47-59F759EEF3A7} - Library - Properties - Microsoft.VisualStudio.SecretManager - Microsoft.VisualStudio.SecretManager - v4.6.1 - true - true - false - true - true - true - Program - $(DevEnvDir)devenv.exe - /rootsuffix Exp - - - true - full - false - bin\Debug\ - TRACE;DEBUG;EXTENSION_DEVELOPER_MODE - prompt - 4 - latest - - - true - full - true - bin\Release\ - TRACE - prompt - 4 - latest - - - - - - - - - - - - - - Designer - - - - - - - - - - - - - - - - - - - - - - - - - - - Designer - - - - - - - - - - diff --git a/tooling/Microsoft.VisualStudio.SecretManager/ProjectLocalSecretsManager.cs b/tooling/Microsoft.VisualStudio.SecretManager/ProjectLocalSecretsManager.cs deleted file mode 100644 index e516a85ffb..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager/ProjectLocalSecretsManager.cs +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.VisualStudio.ProjectSystem.Properties; -using Microsoft.VisualStudio.Threading; -using Task = System.Threading.Tasks.Task; - -namespace Microsoft.VisualStudio.SecretManager -{ - /// - /// Provides an thread-safe access the secrets.json file based on the UserSecretsId property in a configured project. - /// - internal class ProjectLocalSecretsManager : Shell.IVsProjectSecrets, Shell.SVsProjectLocalSecrets - { - private const string UserSecretsPropertyName = "UserSecretsId"; - - private readonly AsyncSemaphore _semaphore; - private readonly IProjectPropertiesProvider _propertiesProvider; - private readonly Lazy _services; - - public ProjectLocalSecretsManager(IProjectPropertiesProvider propertiesProvider, Lazy serviceProvider) - { - _propertiesProvider = propertiesProvider ?? throw new ArgumentNullException(nameof(propertiesProvider)); - _services = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); - _semaphore = new AsyncSemaphore(1); - } - - public string SanitizeName(string name) => name; - - public IReadOnlyCollection GetInvalidCharactersFrom(string name) => Array.Empty(); - - public async Task AddSecretAsync(string name, string value, CancellationToken cancellationToken = default) - { - EnsureKeyNameIsValid(name); - await TaskScheduler.Default; - - using (await _semaphore.EnterAsync(cancellationToken)) - using (var store = await GetOrCreateStoreAsync(cancellationToken)) - { - if (store.ContainsKey(name)) - { - throw new ArgumentException(Resources.Error_SecretAlreadyExists, nameof(name)); - } - - store.Set(name, value); - await store.SaveAsync(cancellationToken); - } - } - - public async Task SetSecretAsync(string name, string value, CancellationToken cancellationToken = default) - { - EnsureKeyNameIsValid(name); - await TaskScheduler.Default; - - using (await _semaphore.EnterAsync(cancellationToken)) - using (var store = await GetOrCreateStoreAsync(cancellationToken)) - { - store.Set(name, value); - await store.SaveAsync(cancellationToken); - } - } - - public async Task GetSecretAsync(string name, CancellationToken cancellationToken = default) - { - EnsureKeyNameIsValid(name); - await TaskScheduler.Default; - - using (await _semaphore.EnterAsync(cancellationToken)) - using (var store = await GetOrCreateStoreAsync(cancellationToken)) - { - return store.Get(name); - } - } - - public async Task> GetSecretNamesAsync(CancellationToken cancellationToken = default) - { - await TaskScheduler.Default; - - using (await _semaphore.EnterAsync(cancellationToken)) - using (var store = await GetOrCreateStoreAsync(cancellationToken)) - { - return store.ReadOnlyKeys; - } - } - - - public async Task> GetSecretsAsync(CancellationToken cancellationToken = default) - { - await TaskScheduler.Default; - - using (await _semaphore.EnterAsync(cancellationToken)) - using (var store = await GetOrCreateStoreAsync(cancellationToken)) - { - return store.Values; - } - } - - public async Task RemoveSecretAsync(string name, CancellationToken cancellationToken = default) - { - EnsureKeyNameIsValid(name); - await TaskScheduler.Default; - - using (await _semaphore.EnterAsync(cancellationToken)) - using (var store = await GetOrCreateStoreAsync(cancellationToken)) - { - if (store.Remove(name)) - { - await store.SaveAsync(cancellationToken); - return true; - } - - return false; - } - } - - private void EnsureKeyNameIsValid(string name) - { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - if (name.Length == 0) - { - throw new ArgumentException(nameof(name)); - } - } - - private async Task GetOrCreateStoreAsync(CancellationToken cancellationToken) - { - var userSecretsId = await _propertiesProvider.GetCommonProperties().GetEvaluatedPropertyValueAsync(UserSecretsPropertyName); - - if (string.IsNullOrEmpty(userSecretsId)) - { - userSecretsId = Guid.NewGuid().ToString(); - await _propertiesProvider.GetCommonProperties().SetPropertyValueAsync(UserSecretsPropertyName, userSecretsId); - } - - var store = new SecretStore(userSecretsId); - await store.LoadAsync(cancellationToken); - return store; - } - } -} diff --git a/tooling/Microsoft.VisualStudio.SecretManager/Properties/AssemblyInfo.cs b/tooling/Microsoft.VisualStudio.SecretManager/Properties/AssemblyInfo.cs deleted file mode 100644 index 56a9841165..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Reflection; -using Microsoft.VisualStudio.Shell; - -// required for VS to generate the pkgdef -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: ProvideCodeBase(CodeBase = @"$PackageFolder$\Microsoft.VisualStudio.SecretManager.dll")] -[assembly: ProvideBindingRedirection( - AssemblyName = "Microsoft.VisualStudio.SecretManager", - GenerateCodeBase = true, - PublicKeyToken = "adb9793829ddae60", - OldVersionLowerBound = "0.0.0.0", - OldVersionUpperBound = "1.0.0.0", - NewVersion = "1.0.0.0")] diff --git a/tooling/Microsoft.VisualStudio.SecretManager/Resources.Designer.cs b/tooling/Microsoft.VisualStudio.SecretManager/Resources.Designer.cs deleted file mode 100644 index bd79af4b8c..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager/Resources.Designer.cs +++ /dev/null @@ -1,140 +0,0 @@ -// -namespace Microsoft.VisualStudio.SecretManager -{ - using System.Globalization; - using System.Reflection; - using System.Resources; - - internal static class Resources - { - private static readonly ResourceManager _resourceManager - = new ResourceManager("Microsoft.VisualStudio.SecretManager.Resources", typeof(Resources).GetTypeInfo().Assembly); - - /// - /// A secret with this name already exists. - /// - internal static string Error_SecretAlreadyExists - { - get => GetString("Error_SecretAlreadyExists"); - } - - /// - /// Value cannot be null or an empty string. - /// - internal static string Common_StringNullOrEmpty - { - get => GetString("Common_StringNullOrEmpty"); - } - - /// - /// Value cannot be null or an empty string. - /// - internal static string FormatCommon_StringNullOrEmpty() - => GetString("Common_StringNullOrEmpty"); - - /// - /// Invalid character '{0}' found in the user secrets ID at index '{1}'. - /// - internal static string Error_Invalid_Character_In_UserSecrets_Id - { - get => GetString("Error_Invalid_Character_In_UserSecrets_Id"); - } - - /// - /// Invalid character '{0}' found in the user secrets ID at index '{1}'. - /// - internal static string FormatError_Invalid_Character_In_UserSecrets_Id(object p0, object p1) - => string.Format(CultureInfo.CurrentCulture, GetString("Error_Invalid_Character_In_UserSecrets_Id"), p0, p1); - - /// - /// Could not find 'UserSecretsIdAttribute' on assembly '{0}'. - /// Check that the project for '{0}' has set the 'UserSecretsId' build property. - /// If the 'UserSecretsId' property is already set then add a reference to the Microsoft.Extensions.Configuration.UserSecrets package. - /// - internal static string Error_Missing_UserSecretsIdAttribute - { - get => GetString("Error_Missing_UserSecretsIdAttribute"); - } - - /// - /// Could not find 'UserSecretsIdAttribute' on assembly '{0}'. - /// Check that the project for '{0}' has set the 'UserSecretsId' build property. - /// If the 'UserSecretsId' property is already set then add a reference to the Microsoft.Extensions.Configuration.UserSecrets package. - /// - internal static string FormatError_Missing_UserSecretsIdAttribute(object p0) - => string.Format(CultureInfo.CurrentCulture, GetString("Error_Missing_UserSecretsIdAttribute"), p0); - - /// - /// File path must be a non-empty string. - /// - internal static string Error_InvalidFilePath - { - get => GetString("Error_InvalidFilePath"); - } - - /// - /// File path must be a non-empty string. - /// - internal static string FormatError_InvalidFilePath() - => GetString("Error_InvalidFilePath"); - - /// - /// Could not parse the JSON file. Error on line number '{0}': '{1}'. - /// - internal static string Error_JSONParseError - { - get => GetString("Error_JSONParseError"); - } - - /// - /// Could not parse the JSON file. Error on line number '{0}': '{1}'. - /// - internal static string FormatError_JSONParseError(object p0, object p1) - => string.Format(CultureInfo.CurrentCulture, GetString("Error_JSONParseError"), p0, p1); - - /// - /// A duplicate key '{0}' was found. - /// - internal static string Error_KeyIsDuplicated - { - get => GetString("Error_KeyIsDuplicated"); - } - - /// - /// A duplicate key '{0}' was found. - /// - internal static string FormatError_KeyIsDuplicated(object p0) - => string.Format(CultureInfo.CurrentCulture, GetString("Error_KeyIsDuplicated"), p0); - - /// - /// Unsupported JSON token '{0}' was found. Path '{1}', line {2} position {3}. - /// - internal static string Error_UnsupportedJSONToken - { - get => GetString("Error_UnsupportedJSONToken"); - } - - /// - /// Unsupported JSON token '{0}' was found. Path '{1}', line {2} position {3}. - /// - internal static string FormatError_UnsupportedJSONToken(object p0, object p1, object p2, object p3) - => string.Format(CultureInfo.CurrentCulture, GetString("Error_UnsupportedJSONToken"), p0, p1, p2, p3); - - private static string GetString(string name, params string[] formatterNames) - { - var value = _resourceManager.GetString(name); - - System.Diagnostics.Debug.Assert(value != null); - - if (formatterNames != null) - { - for (var i = 0; i < formatterNames.Length; i++) - { - value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); - } - } - - return value; - } - } -} diff --git a/tooling/Microsoft.VisualStudio.SecretManager/Resources.resx b/tooling/Microsoft.VisualStudio.SecretManager/Resources.resx deleted file mode 100644 index 1057cd7926..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager/Resources.resx +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - File path must be a non-empty string. - - - Could not parse the JSON file. Error on line number '{0}': '{1}'. - - - A duplicate key '{0}' was found. - - - Unsupported JSON token '{0}' was found. Path '{1}', line {2} position {3}. - - - Value cannot be null or an empty string. - - - Invalid character '{0}' found in the user secrets ID at index '{1}'. - - - Could not find 'UserSecretsIdAttribute' on assembly '{0}'. -Check that the project for '{0}' has set the 'UserSecretsId' build property. -If the 'UserSecretsId' property is already set then add a reference to the Microsoft.Extensions.Configuration.UserSecrets package. - - - A secret with this name already exists. - - \ No newline at end of file diff --git a/tooling/Microsoft.VisualStudio.SecretManager/SecretManagerFactory.cs b/tooling/Microsoft.VisualStudio.SecretManager/SecretManagerFactory.cs deleted file mode 100644 index b37212e23b..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager/SecretManagerFactory.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.ComponentModel.Composition; -using Microsoft.VisualStudio.ProjectSystem; -using Microsoft.VisualStudio.Shell; - -namespace Microsoft.VisualStudio.SecretManager -{ - internal class SecretManagerFactory - { - // This is capability is set in Microsoft.Extensions.Configuration.UserSecrets - private const string CapabilityName = "LocalUserSecrets"; - - private readonly Lazy _secretManager; - private readonly UnconfiguredProject _project; - - [ImportingConstructor] - public SecretManagerFactory(UnconfiguredProject project, SVsServiceProvider vsServiceProvider) - { - _project = project; - - var serviceProvider = new Lazy(() => vsServiceProvider); - - _secretManager = new Lazy(() => - { - var propertiesProvider = _project.Services.ActiveConfiguredProjectProvider.ActiveConfiguredProject.Services.ProjectPropertiesProvider; - return new ProjectLocalSecretsManager(propertiesProvider, serviceProvider); - }); - } - - [ExportVsProfferedProjectService(typeof(SVsProjectLocalSecrets))] - [AppliesTo(CapabilityName)] - public SVsProjectLocalSecrets ProjectLocalSecretsManager => _secretManager.Value; - } -} diff --git a/tooling/Microsoft.VisualStudio.SecretManager/SecretStore.cs b/tooling/Microsoft.VisualStudio.SecretManager/SecretStore.cs deleted file mode 100644 index ee10d5069c..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager/SecretStore.cs +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.Configuration.Json; -using Microsoft.Extensions.Configuration.UserSecrets; -using Microsoft.VisualStudio.Threading; -using Newtonsoft.Json.Linq; -using Task = System.Threading.Tasks.Task; - -namespace Microsoft.VisualStudio.SecretManager -{ - /// - /// Provides read and write access to the secrets.json file for local user secrets. - /// This is not thread-safe. - /// This object is meant to have a short lifetime. - /// When calling , this will overwrite the secrets.json file. It does not check for concurrency issues if another process has edited this file. - /// - internal class SecretStore : IDisposable - { - private Dictionary _secrets; - private string _fileDir; - private string _filePath; - private bool _isDirty; - private volatile bool _disposed; - - public SecretStore(string userSecretsId) - { - _filePath = PathHelper.GetSecretsPathFromSecretsId(userSecretsId); - _fileDir = Path.GetDirectoryName(_filePath); - } - - public IReadOnlyCollection ReadOnlyKeys - { - get - { - EnsureNotDisposed(); - return _secrets.Keys; - } - } - - public IReadOnlyDictionary Values - { - get - { - EnsureNotDisposed(); - - return _secrets; - } - } - - public bool ContainsKey(string key) - { - EnsureNotDisposed(); - - return _secrets.ContainsKey(key); - } - - public string Get(string name) - { - EnsureNotDisposed(); - - return _secrets[name]; - } - - public void Set(string key, string value) - { - EnsureNotDisposed(); - - _isDirty = true; - _secrets[key] = value; - } - - public bool Remove(string key) - { - EnsureNotDisposed(); - _isDirty = true; - return _secrets.Remove(key); - } - - public async Task LoadAsync(CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - await TaskScheduler.Default; - - EnsureNotDisposed(); - - string text = null; - - if (File.Exists(_filePath)) - { - text = File.ReadAllText(_filePath); - } - - _secrets = DeserializeJson(text); - } - - public async Task SaveAsync(CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - await TaskScheduler.Default; - - EnsureNotDisposed(); - - if (!_isDirty) - { - return; - } - - Directory.CreateDirectory(_fileDir); - File.WriteAllText(_filePath, Stringify(_secrets), Encoding.UTF8); - - _isDirty = false; - } - - private void EnsureNotDisposed() - { - if (_disposed) - { - throw new ObjectDisposedException(nameof(SecretStore)); - } - } - - private static string Stringify(Dictionary secrets) - { - var contents = new JObject(); - if (secrets != null) - { - foreach (var secret in secrets) - { - contents[secret.Key] = secret.Value; - } - } - - return contents.ToString(); - } - - private static Dictionary DeserializeJson(string text) - { - if (string.IsNullOrEmpty(text)) - { - return new Dictionary(StringComparer.OrdinalIgnoreCase); - } - - using (var stream = new MemoryStream()) - { - var bytes = Encoding.UTF8.GetBytes(text); - stream.Write(bytes, 0, bytes.Length); - stream.Position = 0; - - // might throw FormatException if JSON is malformed. - var data = JsonConfigurationFileParser.Parse(stream); - - return new Dictionary(data, StringComparer.OrdinalIgnoreCase); - } - } - - public void Dispose() - { - if (_disposed) return; - _disposed = true; - } - } -} diff --git a/tooling/Microsoft.VisualStudio.SecretManager/Sources/ConfigurationPath.cs b/tooling/Microsoft.VisualStudio.SecretManager/Sources/ConfigurationPath.cs deleted file mode 100644 index d4f277e0d1..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager/Sources/ConfigurationPath.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; - -namespace Microsoft.Extensions.Configuration -{ - /// - /// Utility methods and constants for manipulating Configuration paths - /// - internal static class ConfigurationPath - { - /// - /// The delimiter ":" used to separate individual keys in a path. - /// - public static readonly string KeyDelimiter = ":"; - - /// - /// Combines path segments into one path. - /// - /// The path segments to combine. - /// The combined path. - public static string Combine(params string[] pathSegments) - { - if (pathSegments == null) - { - throw new ArgumentNullException(nameof(pathSegments)); - } - return string.Join(KeyDelimiter, pathSegments); - } - - /// - /// Combines path segments into one path. - /// - /// The path segments to combine. - /// The combined path. - public static string Combine(IEnumerable pathSegments) - { - if (pathSegments == null) - { - throw new ArgumentNullException(nameof(pathSegments)); - } - return string.Join(KeyDelimiter, pathSegments); - } - - /// - /// Extracts the last path segment from the path. - /// - /// The path. - /// The last path segment of the path. - public static string GetSectionKey(string path) - { - if (string.IsNullOrEmpty(path)) - { - return path; - } - - var lastDelimiterIndex = path.LastIndexOf(KeyDelimiter, StringComparison.OrdinalIgnoreCase); - return lastDelimiterIndex == -1 ? path : path.Substring(lastDelimiterIndex + 1); - } - - /// - /// Extracts the path corresponding to the parent node for a given path. - /// - /// The path. - /// The original path minus the last individual segment found in it. Null if the original path corresponds to a top level node. - public static string GetParentPath(string path) - { - if (string.IsNullOrEmpty(path)) - { - return null; - } - - var lastDelimiterIndex = path.LastIndexOf(KeyDelimiter, StringComparison.OrdinalIgnoreCase); - return lastDelimiterIndex == -1 ? null : path.Substring(0, lastDelimiterIndex); - } - } -} diff --git a/tooling/Microsoft.VisualStudio.SecretManager/Sources/JsonConfigurationFileParser.cs b/tooling/Microsoft.VisualStudio.SecretManager/Sources/JsonConfigurationFileParser.cs deleted file mode 100644 index 1cc65407c5..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager/Sources/JsonConfigurationFileParser.cs +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using Microsoft.VisualStudio.SecretManager; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace Microsoft.Extensions.Configuration.Json -{ - internal class JsonConfigurationFileParser - { - private JsonConfigurationFileParser() { } - - private readonly IDictionary _data = new SortedDictionary(StringComparer.OrdinalIgnoreCase); - private readonly Stack _context = new Stack(); - private string _currentPath; - - private JsonTextReader _reader; - - public static IDictionary Parse(Stream input) - => new JsonConfigurationFileParser().ParseStream(input); - - private IDictionary ParseStream(Stream input) - { - _data.Clear(); - _reader = new JsonTextReader(new StreamReader(input)); - _reader.DateParseHandling = DateParseHandling.None; - - var jsonConfig = JObject.Load(_reader); - - VisitJObject(jsonConfig); - - return _data; - } - - private void VisitJObject(JObject jObject) - { - foreach (var property in jObject.Properties()) - { - EnterContext(property.Name); - VisitProperty(property); - ExitContext(); - } - } - - private void VisitProperty(JProperty property) - { - VisitToken(property.Value); - } - - private void VisitToken(JToken token) - { - switch (token.Type) - { - case JTokenType.Object: - VisitJObject(token.Value()); - break; - - case JTokenType.Array: - VisitArray(token.Value()); - break; - - case JTokenType.Integer: - case JTokenType.Float: - case JTokenType.String: - case JTokenType.Boolean: - case JTokenType.Bytes: - case JTokenType.Raw: - case JTokenType.Null: - VisitPrimitive(token.Value()); - break; - - default: - throw new FormatException(Resources.FormatError_UnsupportedJSONToken( - _reader.TokenType, - _reader.Path, - _reader.LineNumber, - _reader.LinePosition)); - } - } - - private void VisitArray(JArray array) - { - for (int index = 0; index < array.Count; index++) - { - EnterContext(index.ToString()); - VisitToken(array[index]); - ExitContext(); - } - } - - private void VisitPrimitive(JValue data) - { - var key = _currentPath; - - if (_data.ContainsKey(key)) - { - throw new FormatException(Resources.FormatError_KeyIsDuplicated(key)); - } - _data[key] = data.ToString(CultureInfo.InvariantCulture); - } - - private void EnterContext(string context) - { - _context.Push(context); - _currentPath = ConfigurationPath.Combine(_context.Reverse()); - } - - private void ExitContext() - { - _context.Pop(); - _currentPath = ConfigurationPath.Combine(_context.Reverse()); - } - } -} diff --git a/tooling/Microsoft.VisualStudio.SecretManager/Sources/PathHelper.cs b/tooling/Microsoft.VisualStudio.SecretManager/Sources/PathHelper.cs deleted file mode 100644 index ae135cb5c4..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager/Sources/PathHelper.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.IO; -using Microsoft.VisualStudio.SecretManager; - -namespace Microsoft.Extensions.Configuration.UserSecrets -{ - /// - /// Provides paths for user secrets configuration files. - /// - internal class PathHelper - { - internal const string SecretsFileName = "secrets.json"; - - /// - /// - /// Returns the path to the JSON file that stores user secrets. - /// - /// - /// This uses the current user profile to locate the secrets file on disk in a location outside of source control. - /// - /// - /// The user secret ID. - /// The full path to the secret file. - public static string GetSecretsPathFromSecretsId(string userSecretsId) - { - if (string.IsNullOrEmpty(userSecretsId)) - { - throw new ArgumentException(Resources.Common_StringNullOrEmpty, nameof(userSecretsId)); - } - - var badCharIndex = userSecretsId.IndexOfAny(Path.GetInvalidFileNameChars()); - if (badCharIndex != -1) - { - throw new InvalidOperationException( - string.Format( - Resources.Error_Invalid_Character_In_UserSecrets_Id, - userSecretsId[badCharIndex], - badCharIndex)); - } - - var root = Environment.GetEnvironmentVariable("APPDATA") ?? // On Windows it goes to %APPDATA%\Microsoft\UserSecrets\ - Environment.GetEnvironmentVariable("HOME"); // On Mac/Linux it goes to ~/.microsoft/usersecrets/ - - if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("APPDATA"))) - { - return Path.Combine(root, "Microsoft", "UserSecrets", userSecretsId, SecretsFileName); - } - else - { - return Path.Combine(root, ".microsoft", "usersecrets", userSecretsId, SecretsFileName); - } - } - } -} diff --git a/tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest b/tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest deleted file mode 100644 index 37bb50c5da..0000000000 --- a/tooling/Microsoft.VisualStudio.SecretManager/source.extension.vsixmanifest +++ /dev/null @@ -1,22 +0,0 @@ - - - - - ASP.NET Core User Secrets Extension - Microsoft.VisualStudio.SecretManager - Enables IVsProjectSecrets for ASP.NET Core projects that use Microsoft.Extensions.Configuration.UserSecrets. - - - - - - - - - - - - - - - diff --git a/version.props b/version.props deleted file mode 100644 index 4078cfc422..0000000000 --- a/version.props +++ /dev/null @@ -1,15 +0,0 @@ - - - 2.1.1 - 15.6 - rtm - $(VersionPrefix) - $(VersionPrefix)-$(VersionSuffix)-final - $(VsixVersion).$(BuildNumber) - $(VsixVersion).999999 - t000 - a- - $(FeatureBranchVersionPrefix)$(VersionSuffix)-$([System.Text.RegularExpressions.Regex]::Replace('$(FeatureBranchVersionSuffix)', '[^\w-]', '-')) - $(VersionSuffix)-$(BuildNumber) - - From 87092a25904eca65008a58714ed3938724ee95e5 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 13 Nov 2018 15:54:28 -0800 Subject: [PATCH 1026/1029] Update targets and infrastructure for dotnet-watch et. al. --- .gitmodules | 4 -- build/buildorder.props | 1 - build/repo.props | 6 ++- build/submodules.props | 1 - eng/Baseline.props | 50 +++++++++++++------ eng/Dependencies.props | 6 +++ eng/ProjectReferences.props | 5 ++ eng/tools/BaselineGenerator/baseline.xml | 6 ++- modules/DotNetTools | 1 - src/Tools/Directory.Build.props | 9 ++++ src/Tools/Directory.Build.targets | 4 ++ .../dotnet-watch/src/dotnet-watch.csproj | 2 +- .../test/dotnet-watch.Tests.csproj | 5 -- 13 files changed, 70 insertions(+), 30 deletions(-) delete mode 160000 modules/DotNetTools create mode 100644 src/Tools/Directory.Build.props diff --git a/.gitmodules b/.gitmodules index 57b1b97fdf..696da212f5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -30,10 +30,6 @@ path = modules/Diagnostics url = https://github.com/aspnet/Diagnostics.git branch = release/2.1 -[submodule "modules/DotNetTools"] - path = modules/DotNetTools - url = https://github.com/aspnet/DotNetTools.git - branch = release/2.1 [submodule "modules/EntityFrameworkCore"] path = modules/EntityFrameworkCore url = https://github.com/aspnet/EntityFrameworkCore.git diff --git a/build/buildorder.props b/build/buildorder.props index 89ee48312e..4f36b48031 100644 --- a/build/buildorder.props +++ b/build/buildorder.props @@ -7,7 +7,6 @@ - diff --git a/build/repo.props b/build/repo.props index dbda0b55d0..cec72fd000 100644 --- a/build/repo.props +++ b/build/repo.props @@ -42,12 +42,16 @@ - + diff --git a/build/submodules.props b/build/submodules.props index 8db8e4fe1f..2553946610 100644 --- a/build/submodules.props +++ b/build/submodules.props @@ -55,7 +55,6 @@ - diff --git a/eng/Baseline.props b/eng/Baseline.props index f638420950..143bb89af7 100644 --- a/eng/Baseline.props +++ b/eng/Baseline.props @@ -4,6 +4,26 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 2.1.6 + + + 2.1.1 + + + + + 2.1.1 + + + + + 2.1.1 + + + + + 2.1.1 + + 2.1.1 @@ -19,21 +39,6 @@ - - - 2.1.1 - - - - - - - - - - - - 2.1.1 @@ -80,6 +85,21 @@ + + + 2.1.1 + + + + + + + + + + + + 2.1.1 diff --git a/eng/Dependencies.props b/eng/Dependencies.props index a8a2f8543d..95ff7fb38f 100644 --- a/eng/Dependencies.props +++ b/eng/Dependencies.props @@ -7,20 +7,26 @@ + + + + + + diff --git a/eng/ProjectReferences.props b/eng/ProjectReferences.props index 7d310275de..ce1657d68b 100644 --- a/eng/ProjectReferences.props +++ b/eng/ProjectReferences.props @@ -12,6 +12,11 @@ + + + + + diff --git a/eng/tools/BaselineGenerator/baseline.xml b/eng/tools/BaselineGenerator/baseline.xml index 86dc5fab87..1bb113b638 100644 --- a/eng/tools/BaselineGenerator/baseline.xml +++ b/eng/tools/BaselineGenerator/baseline.xml @@ -1,13 +1,17 @@ + + + + - + diff --git a/modules/DotNetTools b/modules/DotNetTools deleted file mode 160000 index eba014d534..0000000000 --- a/modules/DotNetTools +++ /dev/null @@ -1 +0,0 @@ -Subproject commit eba014d534ef34ea88ce6c3879b92743b825a7fe diff --git a/src/Tools/Directory.Build.props b/src/Tools/Directory.Build.props new file mode 100644 index 0000000000..6b35802689 --- /dev/null +++ b/src/Tools/Directory.Build.props @@ -0,0 +1,9 @@ + + + + + $(RepositoryRoot)obj\$(MSBuildProjectName)\ + $(RepositoryRoot)bin\$(MSBuildProjectName)\ + + + diff --git a/src/Tools/Directory.Build.targets b/src/Tools/Directory.Build.targets index 3d2647b41b..7928d3f6cf 100644 --- a/src/Tools/Directory.Build.targets +++ b/src/Tools/Directory.Build.targets @@ -1,6 +1,10 @@ + + true + + diff --git a/src/Tools/dotnet-watch/src/dotnet-watch.csproj b/src/Tools/dotnet-watch/src/dotnet-watch.csproj index fa2f617f41..4aff804186 100644 --- a/src/Tools/dotnet-watch/src/dotnet-watch.csproj +++ b/src/Tools/dotnet-watch/src/dotnet-watch.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/Tools/dotnet-watch/test/dotnet-watch.Tests.csproj b/src/Tools/dotnet-watch/test/dotnet-watch.Tests.csproj index ce23611f24..2bad8c40c4 100644 --- a/src/Tools/dotnet-watch/test/dotnet-watch.Tests.csproj +++ b/src/Tools/dotnet-watch/test/dotnet-watch.Tests.csproj @@ -15,11 +15,6 @@ - - - - - <_Parameter1>TestSettings:RestoreSources From a8ec75aac41d971869d49f3396c39efce072045b Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 13 Nov 2018 12:35:17 -0800 Subject: [PATCH 1027/1029] Prepare for the 2.2.1 patch * Generate 2.2.0 package baselines * Update dependencies to 2.2.0 * Update branding to 2.2.1-servicing --- build/CodeSign.targets | 14 + build/dependencies.folderbuilds.props | 46 +- build/dependencies.props | 133 +- build/repo.targets | 1 + build/sources.props | 7 + build/submodules.props | 67 +- modules/Templating | 2 +- src/IISIntegration/version.props | 12 +- .../ArchiveBaseline.2.2.0.txt | 1817 +++++++++++++++++ .../ArchiveBaseline.2.2.0.txt | 1629 +++++++++++++++ .../ZipManifestGenerator/README.md | 4 +- .../ZipManifestGenerator/UpdateBaselines.ps1 | 15 + src/WebSockets/src/Directory.Build.props | 2 +- src/WebSockets/test/Directory.Build.props | 4 +- src/WebSockets/version.props | 11 +- version.props | 4 +- 16 files changed, 3626 insertions(+), 142 deletions(-) create mode 100644 src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.2.0.txt create mode 100644 src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.2.0.txt create mode 100644 src/PackageArchive/ZipManifestGenerator/UpdateBaselines.ps1 diff --git a/build/CodeSign.targets b/build/CodeSign.targets index 032fbd1c84..308a95817f 100644 --- a/build/CodeSign.targets +++ b/build/CodeSign.targets @@ -12,6 +12,10 @@ RepositoryRoot=%(Repository.RootPath) %(Repository.Build) + <_ShippedRepositoryProject Include="$(MSBuildProjectFullPath)" Condition="'%(ShippedRepository.Identity)' != ''"> + RepositoryRoot=%(ShippedRepository.RootPath) + false + @@ -28,17 +32,27 @@ + + + <_FilesToSign Include="@(_RepoFileSignInfo)" Condition="'%(_RepoFileSignInfo.IsFileToSign)' == 'true' AND ('$(_ReposWereBuilt)' == 'true' OR '%(_RepoFileSignInfo.Container)' != '' ) " /> + <_FilesToSign Include="@(_ShippedRepoFileSignInfo)" Condition="'%(_ShippedRepoFileSignInfo.IsFileToSign)' == 'true' AND '%(_ShippedRepoFileSignInfo.Container)' != '' " /> + diff --git a/build/dependencies.folderbuilds.props b/build/dependencies.folderbuilds.props index e027154252..a8179a8e37 100644 --- a/build/dependencies.folderbuilds.props +++ b/build/dependencies.folderbuilds.props @@ -2,28 +2,28 @@ 2.2.0-preview2-20181108.4 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 - 0.6.0-rtm-35665 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 - 2.2.0-rtm-35665 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 0.6.0-rtm-final + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 diff --git a/build/dependencies.props b/build/dependencies.props index ffc4e9b097..dbc107a6b3 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -2,71 +2,8 @@ - 2.2.0-rtm-27109-04 - 2.2.0-rtm-27109-04 - 4.6.0-rtm-27109-02 - - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 - 2.2.0-rtm-181109-01 + 2.2.0 + 2.2.0 @@ -86,6 +23,71 @@ + + + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + 2.2.0 + + 0.9.9 0.10.13 @@ -198,6 +200,7 @@ 4.5.0 1.5.0 4.5.0 + 4.6.0 4.5.0 4.5.0 5.3.0 diff --git a/build/repo.targets b/build/repo.targets index 697ee8f180..57a608810c 100644 --- a/build/repo.targets +++ b/build/repo.targets @@ -245,6 +245,7 @@ <_UndeclaredPackageArtifact Include="%(ArtifactInfo.PackageId)" Condition="'%(ArtifactInfo.ArtifactType)' == 'NuGetPackage'" /> <_UndeclaredPackageArtifact Remove="@(PackageArtifact)" /> + + + + + $(RestoreSources); + https://dotnetfeed.blob.core.windows.net/orchestrated-release-2-2/20181110-02/final/index.json; + + $(RestoreSources); https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json; diff --git a/build/submodules.props b/build/submodules.props index 656d1643f3..d3321d9ea7 100644 --- a/build/submodules.props +++ b/build/submodules.props @@ -36,44 +36,47 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/Templating b/modules/Templating index a504c40165..d26f89a6bc 160000 --- a/modules/Templating +++ b/modules/Templating @@ -1 +1 @@ -Subproject commit a504c40165b1289d24ffa8daab6c1c3780263c85 +Subproject commit d26f89a6bcb649438cee1b851a682caac4363204 diff --git a/src/IISIntegration/version.props b/src/IISIntegration/version.props index 9b96613b4a..a66579d599 100644 --- a/src/IISIntegration/version.props +++ b/src/IISIntegration/version.props @@ -3,17 +3,15 @@ 2 2 1 - 0 + 1 $(DotNetMajorVersion).$(DotNetMinorVersion).$(DotNetPatchVersion) 12 2 $(DotNetPatchVersion) - rtm - ancm-oob - $(VersionPrefix) - $(VersionPrefix)-$(VersionSuffix)-final - t000 - $(VersionSuffix)-$(BuildNumber) + ancm-oob + $(VersionPrefix) + $(VersionPrefix)-$(PreReleaseLabel)-$(BuildNumber) + $(PackageVersion) 2.0.0 diff --git a/src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.2.0.txt b/src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.2.0.txt new file mode 100644 index 0000000000..08d3462b03 --- /dev/null +++ b/src/PackageArchive/Archive.CiServer.Patch.Compat/ArchiveBaseline.2.2.0.txt @@ -0,0 +1,1817 @@ +libuv\1.10.0\.nupkg.metadata +libuv\1.10.0\.signature.p7s +messagepack\1.7.3.4\.nupkg.metadata +messagepack\1.7.3.4\.signature.p7s +microsoft.applicationinsights.aspnetcore\2.1.1\.nupkg.metadata +microsoft.applicationinsights.aspnetcore\2.1.1\.signature.p7s +microsoft.applicationinsights.dependencycollector\2.4.1\.nupkg.metadata +microsoft.applicationinsights.dependencycollector\2.4.1\.signature.p7s +microsoft.applicationinsights\2.4.0\.nupkg.metadata +microsoft.applicationinsights\2.4.0\.signature.p7s +microsoft.aspnet.webapi.client\5.2.6\.nupkg.metadata +microsoft.aspnetcore.all\2.2.0\.nupkg.metadata +microsoft.aspnetcore.all\2.2.0\.signature.p7s +microsoft.aspnetcore.all\2.2.0\build\netcoreapp2.2\Microsoft.AspNetCore.All.props +microsoft.aspnetcore.all\2.2.0\build\netcoreapp2.2\Microsoft.AspNetCore.All.targets +microsoft.aspnetcore.all\2.2.0\lib\netcoreapp2.2\_._ +microsoft.aspnetcore.all\2.2.0\microsoft.aspnetcore.all.2.2.0.nupkg +microsoft.aspnetcore.all\2.2.0\microsoft.aspnetcore.all.2.2.0.nupkg.sha512 +microsoft.aspnetcore.all\2.2.0\microsoft.aspnetcore.all.nuspec +microsoft.aspnetcore.antiforgery\2.2.0\.nupkg.metadata +microsoft.aspnetcore.antiforgery\2.2.0\.signature.p7s +microsoft.aspnetcore.antiforgery\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Antiforgery.dll +microsoft.aspnetcore.antiforgery\2.2.0\microsoft.aspnetcore.antiforgery.2.2.0.nupkg +microsoft.aspnetcore.antiforgery\2.2.0\microsoft.aspnetcore.antiforgery.2.2.0.nupkg.sha512 +microsoft.aspnetcore.antiforgery\2.2.0\microsoft.aspnetcore.antiforgery.nuspec +microsoft.aspnetcore.app\2.2.0\.nupkg.metadata +microsoft.aspnetcore.app\2.2.0\.signature.p7s +microsoft.aspnetcore.app\2.2.0\build\netcoreapp2.2\Microsoft.AspNetCore.App.props +microsoft.aspnetcore.app\2.2.0\build\netcoreapp2.2\Microsoft.AspNetCore.App.targets +microsoft.aspnetcore.app\2.2.0\lib\netcoreapp2.2\_._ +microsoft.aspnetcore.app\2.2.0\microsoft.aspnetcore.app.2.2.0.nupkg +microsoft.aspnetcore.app\2.2.0\microsoft.aspnetcore.app.2.2.0.nupkg.sha512 +microsoft.aspnetcore.app\2.2.0\microsoft.aspnetcore.app.nuspec +microsoft.aspnetcore.applicationinsights.hostingstartup\2.2.0\.nupkg.metadata +microsoft.aspnetcore.applicationinsights.hostingstartup\2.2.0\.signature.p7s +microsoft.aspnetcore.applicationinsights.hostingstartup\2.2.0\lib\net461\Microsoft.AspNetCore.ApplicationInsights.HostingStartup.dll +microsoft.aspnetcore.applicationinsights.hostingstartup\2.2.0\lib\netcoreapp2.0\Microsoft.AspNetCore.ApplicationInsights.HostingStartup.dll +microsoft.aspnetcore.applicationinsights.hostingstartup\2.2.0\lib\netcoreapp2.1\Microsoft.AspNetCore.ApplicationInsights.HostingStartup.dll +microsoft.aspnetcore.applicationinsights.hostingstartup\2.2.0\microsoft.aspnetcore.applicationinsights.hostingstartup.2.2.0.nupkg +microsoft.aspnetcore.applicationinsights.hostingstartup\2.2.0\microsoft.aspnetcore.applicationinsights.hostingstartup.2.2.0.nupkg.sha512 +microsoft.aspnetcore.applicationinsights.hostingstartup\2.2.0\microsoft.aspnetcore.applicationinsights.hostingstartup.nuspec +microsoft.aspnetcore.authentication.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Abstractions.dll +microsoft.aspnetcore.authentication.abstractions\2.2.0\microsoft.aspnetcore.authentication.abstractions.2.2.0.nupkg +microsoft.aspnetcore.authentication.abstractions\2.2.0\microsoft.aspnetcore.authentication.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.abstractions\2.2.0\microsoft.aspnetcore.authentication.abstractions.nuspec +microsoft.aspnetcore.authentication.azuread.ui\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.azuread.ui\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.azuread.ui\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.AzureAD.UI.dll +microsoft.aspnetcore.authentication.azuread.ui\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.AzureAD.UI.Views.dll +microsoft.aspnetcore.authentication.azuread.ui\2.2.0\microsoft.aspnetcore.authentication.azuread.ui.2.2.0.nupkg +microsoft.aspnetcore.authentication.azuread.ui\2.2.0\microsoft.aspnetcore.authentication.azuread.ui.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.azuread.ui\2.2.0\microsoft.aspnetcore.authentication.azuread.ui.nuspec +microsoft.aspnetcore.authentication.azureadb2c.ui\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.azureadb2c.ui\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.azureadb2c.ui\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.AzureADB2C.UI.dll +microsoft.aspnetcore.authentication.azureadb2c.ui\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.AzureADB2C.UI.Views.dll +microsoft.aspnetcore.authentication.azureadb2c.ui\2.2.0\microsoft.aspnetcore.authentication.azureadb2c.ui.2.2.0.nupkg +microsoft.aspnetcore.authentication.azureadb2c.ui\2.2.0\microsoft.aspnetcore.authentication.azureadb2c.ui.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.azureadb2c.ui\2.2.0\microsoft.aspnetcore.authentication.azureadb2c.ui.nuspec +microsoft.aspnetcore.authentication.cookies\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.cookies\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.cookies\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Cookies.dll +microsoft.aspnetcore.authentication.cookies\2.2.0\microsoft.aspnetcore.authentication.cookies.2.2.0.nupkg +microsoft.aspnetcore.authentication.cookies\2.2.0\microsoft.aspnetcore.authentication.cookies.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.cookies\2.2.0\microsoft.aspnetcore.authentication.cookies.nuspec +microsoft.aspnetcore.authentication.core\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.core\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.core\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Core.dll +microsoft.aspnetcore.authentication.core\2.2.0\microsoft.aspnetcore.authentication.core.2.2.0.nupkg +microsoft.aspnetcore.authentication.core\2.2.0\microsoft.aspnetcore.authentication.core.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.core\2.2.0\microsoft.aspnetcore.authentication.core.nuspec +microsoft.aspnetcore.authentication.facebook\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.facebook\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.facebook\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Facebook.dll +microsoft.aspnetcore.authentication.facebook\2.2.0\microsoft.aspnetcore.authentication.facebook.2.2.0.nupkg +microsoft.aspnetcore.authentication.facebook\2.2.0\microsoft.aspnetcore.authentication.facebook.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.facebook\2.2.0\microsoft.aspnetcore.authentication.facebook.nuspec +microsoft.aspnetcore.authentication.google\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.google\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.google\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Google.dll +microsoft.aspnetcore.authentication.google\2.2.0\microsoft.aspnetcore.authentication.google.2.2.0.nupkg +microsoft.aspnetcore.authentication.google\2.2.0\microsoft.aspnetcore.authentication.google.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.google\2.2.0\microsoft.aspnetcore.authentication.google.nuspec +microsoft.aspnetcore.authentication.jwtbearer\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.jwtbearer\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.jwtbearer\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.JwtBearer.dll +microsoft.aspnetcore.authentication.jwtbearer\2.2.0\microsoft.aspnetcore.authentication.jwtbearer.2.2.0.nupkg +microsoft.aspnetcore.authentication.jwtbearer\2.2.0\microsoft.aspnetcore.authentication.jwtbearer.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.jwtbearer\2.2.0\microsoft.aspnetcore.authentication.jwtbearer.nuspec +microsoft.aspnetcore.authentication.microsoftaccount\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.microsoftaccount\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.microsoftaccount\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.MicrosoftAccount.dll +microsoft.aspnetcore.authentication.microsoftaccount\2.2.0\microsoft.aspnetcore.authentication.microsoftaccount.2.2.0.nupkg +microsoft.aspnetcore.authentication.microsoftaccount\2.2.0\microsoft.aspnetcore.authentication.microsoftaccount.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.microsoftaccount\2.2.0\microsoft.aspnetcore.authentication.microsoftaccount.nuspec +microsoft.aspnetcore.authentication.oauth\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.oauth\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.oauth\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.OAuth.dll +microsoft.aspnetcore.authentication.oauth\2.2.0\microsoft.aspnetcore.authentication.oauth.2.2.0.nupkg +microsoft.aspnetcore.authentication.oauth\2.2.0\microsoft.aspnetcore.authentication.oauth.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.oauth\2.2.0\microsoft.aspnetcore.authentication.oauth.nuspec +microsoft.aspnetcore.authentication.openidconnect\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.openidconnect\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.openidconnect\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.OpenIdConnect.dll +microsoft.aspnetcore.authentication.openidconnect\2.2.0\microsoft.aspnetcore.authentication.openidconnect.2.2.0.nupkg +microsoft.aspnetcore.authentication.openidconnect\2.2.0\microsoft.aspnetcore.authentication.openidconnect.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.openidconnect\2.2.0\microsoft.aspnetcore.authentication.openidconnect.nuspec +microsoft.aspnetcore.authentication.twitter\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.twitter\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.twitter\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Twitter.dll +microsoft.aspnetcore.authentication.twitter\2.2.0\microsoft.aspnetcore.authentication.twitter.2.2.0.nupkg +microsoft.aspnetcore.authentication.twitter\2.2.0\microsoft.aspnetcore.authentication.twitter.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.twitter\2.2.0\microsoft.aspnetcore.authentication.twitter.nuspec +microsoft.aspnetcore.authentication.wsfederation\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.wsfederation\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.wsfederation\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.WsFederation.dll +microsoft.aspnetcore.authentication.wsfederation\2.2.0\microsoft.aspnetcore.authentication.wsfederation.2.2.0.nupkg +microsoft.aspnetcore.authentication.wsfederation\2.2.0\microsoft.aspnetcore.authentication.wsfederation.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.wsfederation\2.2.0\microsoft.aspnetcore.authentication.wsfederation.nuspec +microsoft.aspnetcore.authentication\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.dll +microsoft.aspnetcore.authentication\2.2.0\microsoft.aspnetcore.authentication.2.2.0.nupkg +microsoft.aspnetcore.authentication\2.2.0\microsoft.aspnetcore.authentication.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication\2.2.0\microsoft.aspnetcore.authentication.nuspec +microsoft.aspnetcore.authorization.policy\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authorization.policy\2.2.0\.signature.p7s +microsoft.aspnetcore.authorization.policy\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authorization.Policy.dll +microsoft.aspnetcore.authorization.policy\2.2.0\microsoft.aspnetcore.authorization.policy.2.2.0.nupkg +microsoft.aspnetcore.authorization.policy\2.2.0\microsoft.aspnetcore.authorization.policy.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authorization.policy\2.2.0\microsoft.aspnetcore.authorization.policy.nuspec +microsoft.aspnetcore.authorization\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authorization\2.2.0\.signature.p7s +microsoft.aspnetcore.authorization\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authorization.dll +microsoft.aspnetcore.authorization\2.2.0\microsoft.aspnetcore.authorization.2.2.0.nupkg +microsoft.aspnetcore.authorization\2.2.0\microsoft.aspnetcore.authorization.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authorization\2.2.0\microsoft.aspnetcore.authorization.nuspec +microsoft.aspnetcore.azureappservices.hostingstartup\2.2.0\.nupkg.metadata +microsoft.aspnetcore.azureappservices.hostingstartup\2.2.0\.signature.p7s +microsoft.aspnetcore.azureappservices.hostingstartup\2.2.0\lib\net461\Microsoft.AspNetCore.AzureAppServices.HostingStartup.dll +microsoft.aspnetcore.azureappservices.hostingstartup\2.2.0\lib\netcoreapp2.0\Microsoft.AspNetCore.AzureAppServices.HostingStartup.dll +microsoft.aspnetcore.azureappservices.hostingstartup\2.2.0\lib\netcoreapp2.1\Microsoft.AspNetCore.AzureAppServices.HostingStartup.dll +microsoft.aspnetcore.azureappservices.hostingstartup\2.2.0\microsoft.aspnetcore.azureappservices.hostingstartup.2.2.0.nupkg +microsoft.aspnetcore.azureappservices.hostingstartup\2.2.0\microsoft.aspnetcore.azureappservices.hostingstartup.2.2.0.nupkg.sha512 +microsoft.aspnetcore.azureappservices.hostingstartup\2.2.0\microsoft.aspnetcore.azureappservices.hostingstartup.nuspec +microsoft.aspnetcore.azureappservicesintegration\2.2.0\.nupkg.metadata +microsoft.aspnetcore.azureappservicesintegration\2.2.0\.signature.p7s +microsoft.aspnetcore.azureappservicesintegration\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.AzureAppServicesIntegration.dll +microsoft.aspnetcore.azureappservicesintegration\2.2.0\microsoft.aspnetcore.azureappservicesintegration.2.2.0.nupkg +microsoft.aspnetcore.azureappservicesintegration\2.2.0\microsoft.aspnetcore.azureappservicesintegration.2.2.0.nupkg.sha512 +microsoft.aspnetcore.azureappservicesintegration\2.2.0\microsoft.aspnetcore.azureappservicesintegration.nuspec +microsoft.aspnetcore.connections.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.connections.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.connections.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Connections.Abstractions.dll +microsoft.aspnetcore.connections.abstractions\2.2.0\microsoft.aspnetcore.connections.abstractions.2.2.0.nupkg +microsoft.aspnetcore.connections.abstractions\2.2.0\microsoft.aspnetcore.connections.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.connections.abstractions\2.2.0\microsoft.aspnetcore.connections.abstractions.nuspec +microsoft.aspnetcore.cookiepolicy\2.2.0\.nupkg.metadata +microsoft.aspnetcore.cookiepolicy\2.2.0\.signature.p7s +microsoft.aspnetcore.cookiepolicy\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.CookiePolicy.dll +microsoft.aspnetcore.cookiepolicy\2.2.0\microsoft.aspnetcore.cookiepolicy.2.2.0.nupkg +microsoft.aspnetcore.cookiepolicy\2.2.0\microsoft.aspnetcore.cookiepolicy.2.2.0.nupkg.sha512 +microsoft.aspnetcore.cookiepolicy\2.2.0\microsoft.aspnetcore.cookiepolicy.nuspec +microsoft.aspnetcore.cors\2.2.0\.nupkg.metadata +microsoft.aspnetcore.cors\2.2.0\.signature.p7s +microsoft.aspnetcore.cors\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Cors.dll +microsoft.aspnetcore.cors\2.2.0\microsoft.aspnetcore.cors.2.2.0.nupkg +microsoft.aspnetcore.cors\2.2.0\microsoft.aspnetcore.cors.2.2.0.nupkg.sha512 +microsoft.aspnetcore.cors\2.2.0\microsoft.aspnetcore.cors.nuspec +microsoft.aspnetcore.cryptography.internal\2.2.0\.nupkg.metadata +microsoft.aspnetcore.cryptography.internal\2.2.0\.signature.p7s +microsoft.aspnetcore.cryptography.internal\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Cryptography.Internal.dll +microsoft.aspnetcore.cryptography.internal\2.2.0\microsoft.aspnetcore.cryptography.internal.2.2.0.nupkg +microsoft.aspnetcore.cryptography.internal\2.2.0\microsoft.aspnetcore.cryptography.internal.2.2.0.nupkg.sha512 +microsoft.aspnetcore.cryptography.internal\2.2.0\microsoft.aspnetcore.cryptography.internal.nuspec +microsoft.aspnetcore.cryptography.keyderivation\2.2.0\.nupkg.metadata +microsoft.aspnetcore.cryptography.keyderivation\2.2.0\.signature.p7s +microsoft.aspnetcore.cryptography.keyderivation\2.2.0\lib\netcoreapp2.0\Microsoft.AspNetCore.Cryptography.KeyDerivation.dll +microsoft.aspnetcore.cryptography.keyderivation\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Cryptography.KeyDerivation.dll +microsoft.aspnetcore.cryptography.keyderivation\2.2.0\microsoft.aspnetcore.cryptography.keyderivation.2.2.0.nupkg +microsoft.aspnetcore.cryptography.keyderivation\2.2.0\microsoft.aspnetcore.cryptography.keyderivation.2.2.0.nupkg.sha512 +microsoft.aspnetcore.cryptography.keyderivation\2.2.0\microsoft.aspnetcore.cryptography.keyderivation.nuspec +microsoft.aspnetcore.dataprotection.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.dataprotection.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.dataprotection.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.Abstractions.dll +microsoft.aspnetcore.dataprotection.abstractions\2.2.0\microsoft.aspnetcore.dataprotection.abstractions.2.2.0.nupkg +microsoft.aspnetcore.dataprotection.abstractions\2.2.0\microsoft.aspnetcore.dataprotection.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.dataprotection.abstractions\2.2.0\microsoft.aspnetcore.dataprotection.abstractions.nuspec +microsoft.aspnetcore.dataprotection.azurekeyvault\2.2.0\.nupkg.metadata +microsoft.aspnetcore.dataprotection.azurekeyvault\2.2.0\.signature.p7s +microsoft.aspnetcore.dataprotection.azurekeyvault\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.AzureKeyVault.dll +microsoft.aspnetcore.dataprotection.azurekeyvault\2.2.0\microsoft.aspnetcore.dataprotection.azurekeyvault.2.2.0.nupkg +microsoft.aspnetcore.dataprotection.azurekeyvault\2.2.0\microsoft.aspnetcore.dataprotection.azurekeyvault.2.2.0.nupkg.sha512 +microsoft.aspnetcore.dataprotection.azurekeyvault\2.2.0\microsoft.aspnetcore.dataprotection.azurekeyvault.nuspec +microsoft.aspnetcore.dataprotection.azurestorage\2.2.0\.nupkg.metadata +microsoft.aspnetcore.dataprotection.azurestorage\2.2.0\.signature.p7s +microsoft.aspnetcore.dataprotection.azurestorage\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.AzureStorage.dll +microsoft.aspnetcore.dataprotection.azurestorage\2.2.0\microsoft.aspnetcore.dataprotection.azurestorage.2.2.0.nupkg +microsoft.aspnetcore.dataprotection.azurestorage\2.2.0\microsoft.aspnetcore.dataprotection.azurestorage.2.2.0.nupkg.sha512 +microsoft.aspnetcore.dataprotection.azurestorage\2.2.0\microsoft.aspnetcore.dataprotection.azurestorage.nuspec +microsoft.aspnetcore.dataprotection.extensions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.dataprotection.extensions\2.2.0\.signature.p7s +microsoft.aspnetcore.dataprotection.extensions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.Extensions.dll +microsoft.aspnetcore.dataprotection.extensions\2.2.0\microsoft.aspnetcore.dataprotection.extensions.2.2.0.nupkg +microsoft.aspnetcore.dataprotection.extensions\2.2.0\microsoft.aspnetcore.dataprotection.extensions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.dataprotection.extensions\2.2.0\microsoft.aspnetcore.dataprotection.extensions.nuspec +microsoft.aspnetcore.dataprotection\2.2.0\.nupkg.metadata +microsoft.aspnetcore.dataprotection\2.2.0\.signature.p7s +microsoft.aspnetcore.dataprotection\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.dll +microsoft.aspnetcore.dataprotection\2.2.0\microsoft.aspnetcore.dataprotection.2.2.0.nupkg +microsoft.aspnetcore.dataprotection\2.2.0\microsoft.aspnetcore.dataprotection.2.2.0.nupkg.sha512 +microsoft.aspnetcore.dataprotection\2.2.0\microsoft.aspnetcore.dataprotection.nuspec +microsoft.aspnetcore.diagnostics.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.diagnostics.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.diagnostics.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Diagnostics.Abstractions.dll +microsoft.aspnetcore.diagnostics.abstractions\2.2.0\microsoft.aspnetcore.diagnostics.abstractions.2.2.0.nupkg +microsoft.aspnetcore.diagnostics.abstractions\2.2.0\microsoft.aspnetcore.diagnostics.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.diagnostics.abstractions\2.2.0\microsoft.aspnetcore.diagnostics.abstractions.nuspec +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.2.0\.nupkg.metadata +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.2.0\.signature.p7s +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.dll +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.2.0\microsoft.aspnetcore.diagnostics.entityframeworkcore.2.2.0.nupkg +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.2.0\microsoft.aspnetcore.diagnostics.entityframeworkcore.2.2.0.nupkg.sha512 +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.2.0\microsoft.aspnetcore.diagnostics.entityframeworkcore.nuspec +microsoft.aspnetcore.diagnostics.healthchecks\2.2.0\.nupkg.metadata +microsoft.aspnetcore.diagnostics.healthchecks\2.2.0\.signature.p7s +microsoft.aspnetcore.diagnostics.healthchecks\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Diagnostics.HealthChecks.dll +microsoft.aspnetcore.diagnostics.healthchecks\2.2.0\microsoft.aspnetcore.diagnostics.healthchecks.2.2.0.nupkg +microsoft.aspnetcore.diagnostics.healthchecks\2.2.0\microsoft.aspnetcore.diagnostics.healthchecks.2.2.0.nupkg.sha512 +microsoft.aspnetcore.diagnostics.healthchecks\2.2.0\microsoft.aspnetcore.diagnostics.healthchecks.nuspec +microsoft.aspnetcore.diagnostics\2.2.0\.nupkg.metadata +microsoft.aspnetcore.diagnostics\2.2.0\.signature.p7s +microsoft.aspnetcore.diagnostics\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Diagnostics.dll +microsoft.aspnetcore.diagnostics\2.2.0\microsoft.aspnetcore.diagnostics.2.2.0.nupkg +microsoft.aspnetcore.diagnostics\2.2.0\microsoft.aspnetcore.diagnostics.2.2.0.nupkg.sha512 +microsoft.aspnetcore.diagnostics\2.2.0\microsoft.aspnetcore.diagnostics.nuspec +microsoft.aspnetcore.hostfiltering\2.2.0\.nupkg.metadata +microsoft.aspnetcore.hostfiltering\2.2.0\.signature.p7s +microsoft.aspnetcore.hostfiltering\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.HostFiltering.dll +microsoft.aspnetcore.hostfiltering\2.2.0\microsoft.aspnetcore.hostfiltering.2.2.0.nupkg +microsoft.aspnetcore.hostfiltering\2.2.0\microsoft.aspnetcore.hostfiltering.2.2.0.nupkg.sha512 +microsoft.aspnetcore.hostfiltering\2.2.0\microsoft.aspnetcore.hostfiltering.nuspec +microsoft.aspnetcore.hosting.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.hosting.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.hosting.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Abstractions.dll +microsoft.aspnetcore.hosting.abstractions\2.2.0\microsoft.aspnetcore.hosting.abstractions.2.2.0.nupkg +microsoft.aspnetcore.hosting.abstractions\2.2.0\microsoft.aspnetcore.hosting.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.hosting.abstractions\2.2.0\microsoft.aspnetcore.hosting.abstractions.nuspec +microsoft.aspnetcore.hosting.server.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.hosting.server.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.hosting.server.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Server.Abstractions.dll +microsoft.aspnetcore.hosting.server.abstractions\2.2.0\microsoft.aspnetcore.hosting.server.abstractions.2.2.0.nupkg +microsoft.aspnetcore.hosting.server.abstractions\2.2.0\microsoft.aspnetcore.hosting.server.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.hosting.server.abstractions\2.2.0\microsoft.aspnetcore.hosting.server.abstractions.nuspec +microsoft.aspnetcore.hosting\2.2.0\.nupkg.metadata +microsoft.aspnetcore.hosting\2.2.0\.signature.p7s +microsoft.aspnetcore.hosting\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.dll +microsoft.aspnetcore.hosting\2.2.0\microsoft.aspnetcore.hosting.2.2.0.nupkg +microsoft.aspnetcore.hosting\2.2.0\microsoft.aspnetcore.hosting.2.2.0.nupkg.sha512 +microsoft.aspnetcore.hosting\2.2.0\microsoft.aspnetcore.hosting.nuspec +microsoft.aspnetcore.html.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.html.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.html.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Html.Abstractions.dll +microsoft.aspnetcore.html.abstractions\2.2.0\microsoft.aspnetcore.html.abstractions.2.2.0.nupkg +microsoft.aspnetcore.html.abstractions\2.2.0\microsoft.aspnetcore.html.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.html.abstractions\2.2.0\microsoft.aspnetcore.html.abstractions.nuspec +microsoft.aspnetcore.http.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.http.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.http.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Abstractions.dll +microsoft.aspnetcore.http.abstractions\2.2.0\microsoft.aspnetcore.http.abstractions.2.2.0.nupkg +microsoft.aspnetcore.http.abstractions\2.2.0\microsoft.aspnetcore.http.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.http.abstractions\2.2.0\microsoft.aspnetcore.http.abstractions.nuspec +microsoft.aspnetcore.http.connections.common\1.1.0\.nupkg.metadata +microsoft.aspnetcore.http.connections.common\1.1.0\.signature.p7s +microsoft.aspnetcore.http.connections.common\1.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Connections.Common.dll +microsoft.aspnetcore.http.connections.common\1.1.0\microsoft.aspnetcore.http.connections.common.1.1.0.nupkg +microsoft.aspnetcore.http.connections.common\1.1.0\microsoft.aspnetcore.http.connections.common.1.1.0.nupkg.sha512 +microsoft.aspnetcore.http.connections.common\1.1.0\microsoft.aspnetcore.http.connections.common.nuspec +microsoft.aspnetcore.http.connections\1.1.0\.nupkg.metadata +microsoft.aspnetcore.http.connections\1.1.0\.signature.p7s +microsoft.aspnetcore.http.connections\1.1.0\lib\netcoreapp2.2\Microsoft.AspNetCore.Http.Connections.dll +microsoft.aspnetcore.http.connections\1.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Connections.dll +microsoft.aspnetcore.http.connections\1.1.0\microsoft.aspnetcore.http.connections.1.1.0.nupkg +microsoft.aspnetcore.http.connections\1.1.0\microsoft.aspnetcore.http.connections.1.1.0.nupkg.sha512 +microsoft.aspnetcore.http.connections\1.1.0\microsoft.aspnetcore.http.connections.nuspec +microsoft.aspnetcore.http.extensions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.http.extensions\2.2.0\.signature.p7s +microsoft.aspnetcore.http.extensions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Extensions.dll +microsoft.aspnetcore.http.extensions\2.2.0\microsoft.aspnetcore.http.extensions.2.2.0.nupkg +microsoft.aspnetcore.http.extensions\2.2.0\microsoft.aspnetcore.http.extensions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.http.extensions\2.2.0\microsoft.aspnetcore.http.extensions.nuspec +microsoft.aspnetcore.http.features\2.2.0\.nupkg.metadata +microsoft.aspnetcore.http.features\2.2.0\.signature.p7s +microsoft.aspnetcore.http.features\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Features.dll +microsoft.aspnetcore.http.features\2.2.0\microsoft.aspnetcore.http.features.2.2.0.nupkg +microsoft.aspnetcore.http.features\2.2.0\microsoft.aspnetcore.http.features.2.2.0.nupkg.sha512 +microsoft.aspnetcore.http.features\2.2.0\microsoft.aspnetcore.http.features.nuspec +microsoft.aspnetcore.http\2.2.0\.nupkg.metadata +microsoft.aspnetcore.http\2.2.0\.signature.p7s +microsoft.aspnetcore.http\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.dll +microsoft.aspnetcore.http\2.2.0\microsoft.aspnetcore.http.2.2.0.nupkg +microsoft.aspnetcore.http\2.2.0\microsoft.aspnetcore.http.2.2.0.nupkg.sha512 +microsoft.aspnetcore.http\2.2.0\microsoft.aspnetcore.http.nuspec +microsoft.aspnetcore.httpoverrides\2.2.0\.nupkg.metadata +microsoft.aspnetcore.httpoverrides\2.2.0\.signature.p7s +microsoft.aspnetcore.httpoverrides\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.HttpOverrides.dll +microsoft.aspnetcore.httpoverrides\2.2.0\microsoft.aspnetcore.httpoverrides.2.2.0.nupkg +microsoft.aspnetcore.httpoverrides\2.2.0\microsoft.aspnetcore.httpoverrides.2.2.0.nupkg.sha512 +microsoft.aspnetcore.httpoverrides\2.2.0\microsoft.aspnetcore.httpoverrides.nuspec +microsoft.aspnetcore.httpspolicy\2.2.0\.nupkg.metadata +microsoft.aspnetcore.httpspolicy\2.2.0\.signature.p7s +microsoft.aspnetcore.httpspolicy\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.HttpsPolicy.dll +microsoft.aspnetcore.httpspolicy\2.2.0\microsoft.aspnetcore.httpspolicy.2.2.0.nupkg +microsoft.aspnetcore.httpspolicy\2.2.0\microsoft.aspnetcore.httpspolicy.2.2.0.nupkg.sha512 +microsoft.aspnetcore.httpspolicy\2.2.0\microsoft.aspnetcore.httpspolicy.nuspec +microsoft.aspnetcore.identity.entityframeworkcore\2.2.0\.nupkg.metadata +microsoft.aspnetcore.identity.entityframeworkcore\2.2.0\.signature.p7s +microsoft.aspnetcore.identity.entityframeworkcore\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Identity.EntityFrameworkCore.dll +microsoft.aspnetcore.identity.entityframeworkcore\2.2.0\microsoft.aspnetcore.identity.entityframeworkcore.2.2.0.nupkg +microsoft.aspnetcore.identity.entityframeworkcore\2.2.0\microsoft.aspnetcore.identity.entityframeworkcore.2.2.0.nupkg.sha512 +microsoft.aspnetcore.identity.entityframeworkcore\2.2.0\microsoft.aspnetcore.identity.entityframeworkcore.nuspec +microsoft.aspnetcore.identity.ui\2.2.0\.nupkg.metadata +microsoft.aspnetcore.identity.ui\2.2.0\.signature.p7s +microsoft.aspnetcore.identity.ui\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Identity.UI.dll +microsoft.aspnetcore.identity.ui\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Identity.UI.Views.V3.dll +microsoft.aspnetcore.identity.ui\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Identity.UI.Views.V4.dll +microsoft.aspnetcore.identity.ui\2.2.0\microsoft.aspnetcore.identity.ui.2.2.0.nupkg +microsoft.aspnetcore.identity.ui\2.2.0\microsoft.aspnetcore.identity.ui.2.2.0.nupkg.sha512 +microsoft.aspnetcore.identity.ui\2.2.0\microsoft.aspnetcore.identity.ui.nuspec +microsoft.aspnetcore.identity.ui\2.2.0\THIRD-PARTY-NOTICES.txt +microsoft.aspnetcore.identity\2.2.0\.nupkg.metadata +microsoft.aspnetcore.identity\2.2.0\.signature.p7s +microsoft.aspnetcore.identity\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Identity.dll +microsoft.aspnetcore.identity\2.2.0\microsoft.aspnetcore.identity.2.2.0.nupkg +microsoft.aspnetcore.identity\2.2.0\microsoft.aspnetcore.identity.2.2.0.nupkg.sha512 +microsoft.aspnetcore.identity\2.2.0\microsoft.aspnetcore.identity.nuspec +microsoft.aspnetcore.jsonpatch\2.2.0\.nupkg.metadata +microsoft.aspnetcore.jsonpatch\2.2.0\.signature.p7s +microsoft.aspnetcore.jsonpatch\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.JsonPatch.dll +microsoft.aspnetcore.jsonpatch\2.2.0\microsoft.aspnetcore.jsonpatch.2.2.0.nupkg +microsoft.aspnetcore.jsonpatch\2.2.0\microsoft.aspnetcore.jsonpatch.2.2.0.nupkg.sha512 +microsoft.aspnetcore.jsonpatch\2.2.0\microsoft.aspnetcore.jsonpatch.nuspec +microsoft.aspnetcore.localization.routing\2.2.0\.nupkg.metadata +microsoft.aspnetcore.localization.routing\2.2.0\.signature.p7s +microsoft.aspnetcore.localization.routing\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Localization.Routing.dll +microsoft.aspnetcore.localization.routing\2.2.0\microsoft.aspnetcore.localization.routing.2.2.0.nupkg +microsoft.aspnetcore.localization.routing\2.2.0\microsoft.aspnetcore.localization.routing.2.2.0.nupkg.sha512 +microsoft.aspnetcore.localization.routing\2.2.0\microsoft.aspnetcore.localization.routing.nuspec +microsoft.aspnetcore.localization\2.2.0\.nupkg.metadata +microsoft.aspnetcore.localization\2.2.0\.signature.p7s +microsoft.aspnetcore.localization\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Localization.dll +microsoft.aspnetcore.localization\2.2.0\microsoft.aspnetcore.localization.2.2.0.nupkg +microsoft.aspnetcore.localization\2.2.0\microsoft.aspnetcore.localization.2.2.0.nupkg.sha512 +microsoft.aspnetcore.localization\2.2.0\microsoft.aspnetcore.localization.nuspec +microsoft.aspnetcore.middlewareanalysis\2.2.0\.nupkg.metadata +microsoft.aspnetcore.middlewareanalysis\2.2.0\.signature.p7s +microsoft.aspnetcore.middlewareanalysis\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.MiddlewareAnalysis.dll +microsoft.aspnetcore.middlewareanalysis\2.2.0\microsoft.aspnetcore.middlewareanalysis.2.2.0.nupkg +microsoft.aspnetcore.middlewareanalysis\2.2.0\microsoft.aspnetcore.middlewareanalysis.2.2.0.nupkg.sha512 +microsoft.aspnetcore.middlewareanalysis\2.2.0\microsoft.aspnetcore.middlewareanalysis.nuspec +microsoft.aspnetcore.mvc.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Abstractions.dll +microsoft.aspnetcore.mvc.abstractions\2.2.0\microsoft.aspnetcore.mvc.abstractions.2.2.0.nupkg +microsoft.aspnetcore.mvc.abstractions\2.2.0\microsoft.aspnetcore.mvc.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.abstractions\2.2.0\microsoft.aspnetcore.mvc.abstractions.nuspec +microsoft.aspnetcore.mvc.analyzers\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.analyzers\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.analyzers\2.2.0\analyzers\dotnet\cs\Microsoft.AspNetCore.Mvc.Analyzers.dll +microsoft.aspnetcore.mvc.analyzers\2.2.0\microsoft.aspnetcore.mvc.analyzers.2.2.0.nupkg +microsoft.aspnetcore.mvc.analyzers\2.2.0\microsoft.aspnetcore.mvc.analyzers.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.analyzers\2.2.0\microsoft.aspnetcore.mvc.analyzers.nuspec +microsoft.aspnetcore.mvc.apiexplorer\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.apiexplorer\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.apiexplorer\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.ApiExplorer.dll +microsoft.aspnetcore.mvc.apiexplorer\2.2.0\microsoft.aspnetcore.mvc.apiexplorer.2.2.0.nupkg +microsoft.aspnetcore.mvc.apiexplorer\2.2.0\microsoft.aspnetcore.mvc.apiexplorer.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.apiexplorer\2.2.0\microsoft.aspnetcore.mvc.apiexplorer.nuspec +microsoft.aspnetcore.mvc.core\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.core\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.core\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Core.dll +microsoft.aspnetcore.mvc.core\2.2.0\microsoft.aspnetcore.mvc.core.2.2.0.nupkg +microsoft.aspnetcore.mvc.core\2.2.0\microsoft.aspnetcore.mvc.core.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.core\2.2.0\microsoft.aspnetcore.mvc.core.nuspec +microsoft.aspnetcore.mvc.cors\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.cors\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.cors\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Cors.dll +microsoft.aspnetcore.mvc.cors\2.2.0\microsoft.aspnetcore.mvc.cors.2.2.0.nupkg +microsoft.aspnetcore.mvc.cors\2.2.0\microsoft.aspnetcore.mvc.cors.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.cors\2.2.0\microsoft.aspnetcore.mvc.cors.nuspec +microsoft.aspnetcore.mvc.dataannotations\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.dataannotations\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.dataannotations\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.DataAnnotations.dll +microsoft.aspnetcore.mvc.dataannotations\2.2.0\microsoft.aspnetcore.mvc.dataannotations.2.2.0.nupkg +microsoft.aspnetcore.mvc.dataannotations\2.2.0\microsoft.aspnetcore.mvc.dataannotations.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.dataannotations\2.2.0\microsoft.aspnetcore.mvc.dataannotations.nuspec +microsoft.aspnetcore.mvc.formatters.json\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.formatters.json\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.formatters.json\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Formatters.Json.dll +microsoft.aspnetcore.mvc.formatters.json\2.2.0\microsoft.aspnetcore.mvc.formatters.json.2.2.0.nupkg +microsoft.aspnetcore.mvc.formatters.json\2.2.0\microsoft.aspnetcore.mvc.formatters.json.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.formatters.json\2.2.0\microsoft.aspnetcore.mvc.formatters.json.nuspec +microsoft.aspnetcore.mvc.formatters.xml\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.formatters.xml\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.formatters.xml\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Formatters.Xml.dll +microsoft.aspnetcore.mvc.formatters.xml\2.2.0\microsoft.aspnetcore.mvc.formatters.xml.2.2.0.nupkg +microsoft.aspnetcore.mvc.formatters.xml\2.2.0\microsoft.aspnetcore.mvc.formatters.xml.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.formatters.xml\2.2.0\microsoft.aspnetcore.mvc.formatters.xml.nuspec +microsoft.aspnetcore.mvc.localization\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.localization\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.localization\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Localization.dll +microsoft.aspnetcore.mvc.localization\2.2.0\microsoft.aspnetcore.mvc.localization.2.2.0.nupkg +microsoft.aspnetcore.mvc.localization\2.2.0\microsoft.aspnetcore.mvc.localization.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.localization\2.2.0\microsoft.aspnetcore.mvc.localization.nuspec +microsoft.aspnetcore.mvc.razor.extensions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.razor.extensions\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.razor.extensions\2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.props +microsoft.aspnetcore.mvc.razor.extensions\2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.targets +microsoft.aspnetcore.mvc.razor.extensions\2.2.0\lib\net46\Microsoft.AspNetCore.Mvc.Razor.Extensions.dll +microsoft.aspnetcore.mvc.razor.extensions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.dll +microsoft.aspnetcore.mvc.razor.extensions\2.2.0\microsoft.aspnetcore.mvc.razor.extensions.2.2.0.nupkg +microsoft.aspnetcore.mvc.razor.extensions\2.2.0\microsoft.aspnetcore.mvc.razor.extensions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.razor.extensions\2.2.0\microsoft.aspnetcore.mvc.razor.extensions.nuspec +microsoft.aspnetcore.mvc.razor.viewcompilation\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.razor.viewcompilation\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.razor.viewcompilation\2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.targets +microsoft.aspnetcore.mvc.razor.viewcompilation\2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.Tasks.dll +microsoft.aspnetcore.mvc.razor.viewcompilation\2.2.0\build\netstandard2.0\net461\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.exe +microsoft.aspnetcore.mvc.razor.viewcompilation\2.2.0\build\netstandard2.0\net461\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation-x86.exe +microsoft.aspnetcore.mvc.razor.viewcompilation\2.2.0\build\netstandard2.0\netcoreapp2.0\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.dll +microsoft.aspnetcore.mvc.razor.viewcompilation\2.2.0\microsoft.aspnetcore.mvc.razor.viewcompilation.2.2.0.nupkg +microsoft.aspnetcore.mvc.razor.viewcompilation\2.2.0\microsoft.aspnetcore.mvc.razor.viewcompilation.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.razor.viewcompilation\2.2.0\microsoft.aspnetcore.mvc.razor.viewcompilation.nuspec +microsoft.aspnetcore.mvc.razor\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.razor\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.razor\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.dll +microsoft.aspnetcore.mvc.razor\2.2.0\microsoft.aspnetcore.mvc.razor.2.2.0.nupkg +microsoft.aspnetcore.mvc.razor\2.2.0\microsoft.aspnetcore.mvc.razor.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.razor\2.2.0\microsoft.aspnetcore.mvc.razor.nuspec +microsoft.aspnetcore.mvc.razorpages\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.razorpages\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.razorpages\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.RazorPages.dll +microsoft.aspnetcore.mvc.razorpages\2.2.0\microsoft.aspnetcore.mvc.razorpages.2.2.0.nupkg +microsoft.aspnetcore.mvc.razorpages\2.2.0\microsoft.aspnetcore.mvc.razorpages.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.razorpages\2.2.0\microsoft.aspnetcore.mvc.razorpages.nuspec +microsoft.aspnetcore.mvc.taghelpers\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.taghelpers\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.taghelpers\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.TagHelpers.dll +microsoft.aspnetcore.mvc.taghelpers\2.2.0\microsoft.aspnetcore.mvc.taghelpers.2.2.0.nupkg +microsoft.aspnetcore.mvc.taghelpers\2.2.0\microsoft.aspnetcore.mvc.taghelpers.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.taghelpers\2.2.0\microsoft.aspnetcore.mvc.taghelpers.nuspec +microsoft.aspnetcore.mvc.viewfeatures\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.viewfeatures\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.viewfeatures\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.ViewFeatures.dll +microsoft.aspnetcore.mvc.viewfeatures\2.2.0\microsoft.aspnetcore.mvc.viewfeatures.2.2.0.nupkg +microsoft.aspnetcore.mvc.viewfeatures\2.2.0\microsoft.aspnetcore.mvc.viewfeatures.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.viewfeatures\2.2.0\microsoft.aspnetcore.mvc.viewfeatures.nuspec +microsoft.aspnetcore.mvc\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.dll +microsoft.aspnetcore.mvc\2.2.0\microsoft.aspnetcore.mvc.2.2.0.nupkg +microsoft.aspnetcore.mvc\2.2.0\microsoft.aspnetcore.mvc.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc\2.2.0\microsoft.aspnetcore.mvc.nuspec +microsoft.aspnetcore.nodeservices\2.2.0\.nupkg.metadata +microsoft.aspnetcore.nodeservices\2.2.0\.signature.p7s +microsoft.aspnetcore.nodeservices\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.NodeServices.dll +microsoft.aspnetcore.nodeservices\2.2.0\microsoft.aspnetcore.nodeservices.2.2.0.nupkg +microsoft.aspnetcore.nodeservices\2.2.0\microsoft.aspnetcore.nodeservices.2.2.0.nupkg.sha512 +microsoft.aspnetcore.nodeservices\2.2.0\microsoft.aspnetcore.nodeservices.nuspec +microsoft.aspnetcore.owin\2.2.0\.nupkg.metadata +microsoft.aspnetcore.owin\2.2.0\.signature.p7s +microsoft.aspnetcore.owin\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Owin.dll +microsoft.aspnetcore.owin\2.2.0\microsoft.aspnetcore.owin.2.2.0.nupkg +microsoft.aspnetcore.owin\2.2.0\microsoft.aspnetcore.owin.2.2.0.nupkg.sha512 +microsoft.aspnetcore.owin\2.2.0\microsoft.aspnetcore.owin.nuspec +microsoft.aspnetcore.razor.design\2.2.0\.nupkg.metadata +microsoft.aspnetcore.razor.design\2.2.0\.signature.p7s +microsoft.aspnetcore.razor.design\2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.CodeGeneration.targets +microsoft.aspnetcore.razor.design\2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.props +microsoft.aspnetcore.razor.design\2.2.0\buildMultiTargeting\Microsoft.AspNetCore.Razor.Design.props +microsoft.aspnetcore.razor.design\2.2.0\microsoft.aspnetcore.razor.design.2.2.0.nupkg +microsoft.aspnetcore.razor.design\2.2.0\microsoft.aspnetcore.razor.design.2.2.0.nupkg.sha512 +microsoft.aspnetcore.razor.design\2.2.0\microsoft.aspnetcore.razor.design.nuspec +microsoft.aspnetcore.razor.design\2.2.0\tools\Microsoft.AspNetCore.Razor.Language.dll +microsoft.aspnetcore.razor.design\2.2.0\tools\Microsoft.CodeAnalysis.CSharp.dll +microsoft.aspnetcore.razor.design\2.2.0\tools\Microsoft.CodeAnalysis.dll +microsoft.aspnetcore.razor.design\2.2.0\tools\Microsoft.CodeAnalysis.Razor.dll +microsoft.aspnetcore.razor.design\2.2.0\tools\Newtonsoft.Json.dll +microsoft.aspnetcore.razor.design\2.2.0\tools\runtimes\unix\lib\netstandard1.3\System.Text.Encoding.CodePages.dll +microsoft.aspnetcore.razor.design\2.2.0\tools\runtimes\win\lib\netstandard1.3\System.Text.Encoding.CodePages.dll +microsoft.aspnetcore.razor.design\2.2.0\tools\rzc.deps.json +microsoft.aspnetcore.razor.design\2.2.0\tools\rzc.dll +microsoft.aspnetcore.razor.design\2.2.0\tools\rzc.runtimeconfig.json +microsoft.aspnetcore.razor.language\2.2.0\.nupkg.metadata +microsoft.aspnetcore.razor.language\2.2.0\.signature.p7s +microsoft.aspnetcore.razor.language\2.2.0\lib\net46\Microsoft.AspNetCore.Razor.Language.dll +microsoft.aspnetcore.razor.language\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Razor.Language.dll +microsoft.aspnetcore.razor.language\2.2.0\microsoft.aspnetcore.razor.language.2.2.0.nupkg +microsoft.aspnetcore.razor.language\2.2.0\microsoft.aspnetcore.razor.language.2.2.0.nupkg.sha512 +microsoft.aspnetcore.razor.language\2.2.0\microsoft.aspnetcore.razor.language.nuspec +microsoft.aspnetcore.razor.runtime\2.2.0\.nupkg.metadata +microsoft.aspnetcore.razor.runtime\2.2.0\.signature.p7s +microsoft.aspnetcore.razor.runtime\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Razor.Runtime.dll +microsoft.aspnetcore.razor.runtime\2.2.0\microsoft.aspnetcore.razor.runtime.2.2.0.nupkg +microsoft.aspnetcore.razor.runtime\2.2.0\microsoft.aspnetcore.razor.runtime.2.2.0.nupkg.sha512 +microsoft.aspnetcore.razor.runtime\2.2.0\microsoft.aspnetcore.razor.runtime.nuspec +microsoft.aspnetcore.razor\2.2.0\.nupkg.metadata +microsoft.aspnetcore.razor\2.2.0\.signature.p7s +microsoft.aspnetcore.razor\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Razor.dll +microsoft.aspnetcore.razor\2.2.0\microsoft.aspnetcore.razor.2.2.0.nupkg +microsoft.aspnetcore.razor\2.2.0\microsoft.aspnetcore.razor.2.2.0.nupkg.sha512 +microsoft.aspnetcore.razor\2.2.0\microsoft.aspnetcore.razor.nuspec +microsoft.aspnetcore.responsecaching.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.responsecaching.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.responsecaching.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.ResponseCaching.Abstractions.dll +microsoft.aspnetcore.responsecaching.abstractions\2.2.0\microsoft.aspnetcore.responsecaching.abstractions.2.2.0.nupkg +microsoft.aspnetcore.responsecaching.abstractions\2.2.0\microsoft.aspnetcore.responsecaching.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.responsecaching.abstractions\2.2.0\microsoft.aspnetcore.responsecaching.abstractions.nuspec +microsoft.aspnetcore.responsecaching\2.2.0\.nupkg.metadata +microsoft.aspnetcore.responsecaching\2.2.0\.signature.p7s +microsoft.aspnetcore.responsecaching\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.ResponseCaching.dll +microsoft.aspnetcore.responsecaching\2.2.0\microsoft.aspnetcore.responsecaching.2.2.0.nupkg +microsoft.aspnetcore.responsecaching\2.2.0\microsoft.aspnetcore.responsecaching.2.2.0.nupkg.sha512 +microsoft.aspnetcore.responsecaching\2.2.0\microsoft.aspnetcore.responsecaching.nuspec +microsoft.aspnetcore.responsecompression\2.2.0\.nupkg.metadata +microsoft.aspnetcore.responsecompression\2.2.0\.signature.p7s +microsoft.aspnetcore.responsecompression\2.2.0\lib\net461\Microsoft.AspNetCore.ResponseCompression.dll +microsoft.aspnetcore.responsecompression\2.2.0\lib\netcoreapp2.1\Microsoft.AspNetCore.ResponseCompression.dll +microsoft.aspnetcore.responsecompression\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.ResponseCompression.dll +microsoft.aspnetcore.responsecompression\2.2.0\microsoft.aspnetcore.responsecompression.2.2.0.nupkg +microsoft.aspnetcore.responsecompression\2.2.0\microsoft.aspnetcore.responsecompression.2.2.0.nupkg.sha512 +microsoft.aspnetcore.responsecompression\2.2.0\microsoft.aspnetcore.responsecompression.nuspec +microsoft.aspnetcore.rewrite\2.2.0\.nupkg.metadata +microsoft.aspnetcore.rewrite\2.2.0\.signature.p7s +microsoft.aspnetcore.rewrite\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Rewrite.dll +microsoft.aspnetcore.rewrite\2.2.0\microsoft.aspnetcore.rewrite.2.2.0.nupkg +microsoft.aspnetcore.rewrite\2.2.0\microsoft.aspnetcore.rewrite.2.2.0.nupkg.sha512 +microsoft.aspnetcore.rewrite\2.2.0\microsoft.aspnetcore.rewrite.nuspec +microsoft.aspnetcore.routing.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.routing.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.routing.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Routing.Abstractions.dll +microsoft.aspnetcore.routing.abstractions\2.2.0\microsoft.aspnetcore.routing.abstractions.2.2.0.nupkg +microsoft.aspnetcore.routing.abstractions\2.2.0\microsoft.aspnetcore.routing.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.routing.abstractions\2.2.0\microsoft.aspnetcore.routing.abstractions.nuspec +microsoft.aspnetcore.routing\2.2.0\.nupkg.metadata +microsoft.aspnetcore.routing\2.2.0\.signature.p7s +microsoft.aspnetcore.routing\2.2.0\lib\netcoreapp2.2\Microsoft.AspNetCore.Routing.dll +microsoft.aspnetcore.routing\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Routing.dll +microsoft.aspnetcore.routing\2.2.0\microsoft.aspnetcore.routing.2.2.0.nupkg +microsoft.aspnetcore.routing\2.2.0\microsoft.aspnetcore.routing.2.2.0.nupkg.sha512 +microsoft.aspnetcore.routing\2.2.0\microsoft.aspnetcore.routing.nuspec +microsoft.aspnetcore.server.httpsys\2.2.0\.nupkg.metadata +microsoft.aspnetcore.server.httpsys\2.2.0\.signature.p7s +microsoft.aspnetcore.server.httpsys\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.HttpSys.dll +microsoft.aspnetcore.server.httpsys\2.2.0\microsoft.aspnetcore.server.httpsys.2.2.0.nupkg +microsoft.aspnetcore.server.httpsys\2.2.0\microsoft.aspnetcore.server.httpsys.2.2.0.nupkg.sha512 +microsoft.aspnetcore.server.httpsys\2.2.0\microsoft.aspnetcore.server.httpsys.nuspec +microsoft.aspnetcore.server.iis\2.2.0\.nupkg.metadata +microsoft.aspnetcore.server.iis\2.2.0\.signature.p7s +microsoft.aspnetcore.server.iis\2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Server.IIS.targets +microsoft.aspnetcore.server.iis\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.IIS.dll +microsoft.aspnetcore.server.iis\2.2.0\microsoft.aspnetcore.server.iis.2.2.0.nupkg +microsoft.aspnetcore.server.iis\2.2.0\microsoft.aspnetcore.server.iis.2.2.0.nupkg.sha512 +microsoft.aspnetcore.server.iis\2.2.0\microsoft.aspnetcore.server.iis.nuspec +microsoft.aspnetcore.server.iis\2.2.0\runtimes\win-x64\nativeassets\netcoreapp2.2\aspnetcorev2_inprocess.dll +microsoft.aspnetcore.server.iis\2.2.0\runtimes\win-x86\nativeassets\netcoreapp2.2\aspnetcorev2_inprocess.dll +microsoft.aspnetcore.server.iisintegration\2.2.0\.nupkg.metadata +microsoft.aspnetcore.server.iisintegration\2.2.0\.signature.p7s +microsoft.aspnetcore.server.iisintegration\2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Server.IISIntegration.targets +microsoft.aspnetcore.server.iisintegration\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.IISIntegration.dll +microsoft.aspnetcore.server.iisintegration\2.2.0\microsoft.aspnetcore.server.iisintegration.2.2.0.nupkg +microsoft.aspnetcore.server.iisintegration\2.2.0\microsoft.aspnetcore.server.iisintegration.2.2.0.nupkg.sha512 +microsoft.aspnetcore.server.iisintegration\2.2.0\microsoft.aspnetcore.server.iisintegration.nuspec +microsoft.aspnetcore.server.kestrel.core\2.2.0\.nupkg.metadata +microsoft.aspnetcore.server.kestrel.core\2.2.0\.signature.p7s +microsoft.aspnetcore.server.kestrel.core\2.2.0\lib\netcoreapp2.1\Microsoft.AspNetCore.Server.Kestrel.Core.dll +microsoft.aspnetcore.server.kestrel.core\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Core.dll +microsoft.aspnetcore.server.kestrel.core\2.2.0\microsoft.aspnetcore.server.kestrel.core.2.2.0.nupkg +microsoft.aspnetcore.server.kestrel.core\2.2.0\microsoft.aspnetcore.server.kestrel.core.2.2.0.nupkg.sha512 +microsoft.aspnetcore.server.kestrel.core\2.2.0\microsoft.aspnetcore.server.kestrel.core.nuspec +microsoft.aspnetcore.server.kestrel.https\2.2.0\.nupkg.metadata +microsoft.aspnetcore.server.kestrel.https\2.2.0\.signature.p7s +microsoft.aspnetcore.server.kestrel.https\2.2.0\lib\netcoreapp2.1\Microsoft.AspNetCore.Server.Kestrel.Https.dll +microsoft.aspnetcore.server.kestrel.https\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Https.dll +microsoft.aspnetcore.server.kestrel.https\2.2.0\microsoft.aspnetcore.server.kestrel.https.2.2.0.nupkg +microsoft.aspnetcore.server.kestrel.https\2.2.0\microsoft.aspnetcore.server.kestrel.https.2.2.0.nupkg.sha512 +microsoft.aspnetcore.server.kestrel.https\2.2.0\microsoft.aspnetcore.server.kestrel.https.nuspec +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.dll +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.2.0\microsoft.aspnetcore.server.kestrel.transport.abstractions.2.2.0.nupkg +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.2.0\microsoft.aspnetcore.server.kestrel.transport.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.2.0\microsoft.aspnetcore.server.kestrel.transport.abstractions.nuspec +microsoft.aspnetcore.server.kestrel.transport.libuv\2.2.0\.nupkg.metadata +microsoft.aspnetcore.server.kestrel.transport.libuv\2.2.0\.signature.p7s +microsoft.aspnetcore.server.kestrel.transport.libuv\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.dll +microsoft.aspnetcore.server.kestrel.transport.libuv\2.2.0\microsoft.aspnetcore.server.kestrel.transport.libuv.2.2.0.nupkg +microsoft.aspnetcore.server.kestrel.transport.libuv\2.2.0\microsoft.aspnetcore.server.kestrel.transport.libuv.2.2.0.nupkg.sha512 +microsoft.aspnetcore.server.kestrel.transport.libuv\2.2.0\microsoft.aspnetcore.server.kestrel.transport.libuv.nuspec +microsoft.aspnetcore.server.kestrel.transport.sockets\2.2.0\.nupkg.metadata +microsoft.aspnetcore.server.kestrel.transport.sockets\2.2.0\.signature.p7s +microsoft.aspnetcore.server.kestrel.transport.sockets\2.2.0\lib\netcoreapp2.1\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.dll +microsoft.aspnetcore.server.kestrel.transport.sockets\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.dll +microsoft.aspnetcore.server.kestrel.transport.sockets\2.2.0\microsoft.aspnetcore.server.kestrel.transport.sockets.2.2.0.nupkg +microsoft.aspnetcore.server.kestrel.transport.sockets\2.2.0\microsoft.aspnetcore.server.kestrel.transport.sockets.2.2.0.nupkg.sha512 +microsoft.aspnetcore.server.kestrel.transport.sockets\2.2.0\microsoft.aspnetcore.server.kestrel.transport.sockets.nuspec +microsoft.aspnetcore.server.kestrel\2.2.0\.nupkg.metadata +microsoft.aspnetcore.server.kestrel\2.2.0\.signature.p7s +microsoft.aspnetcore.server.kestrel\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.dll +microsoft.aspnetcore.server.kestrel\2.2.0\microsoft.aspnetcore.server.kestrel.2.2.0.nupkg +microsoft.aspnetcore.server.kestrel\2.2.0\microsoft.aspnetcore.server.kestrel.2.2.0.nupkg.sha512 +microsoft.aspnetcore.server.kestrel\2.2.0\microsoft.aspnetcore.server.kestrel.nuspec +microsoft.aspnetcore.session\2.2.0\.nupkg.metadata +microsoft.aspnetcore.session\2.2.0\.signature.p7s +microsoft.aspnetcore.session\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Session.dll +microsoft.aspnetcore.session\2.2.0\microsoft.aspnetcore.session.2.2.0.nupkg +microsoft.aspnetcore.session\2.2.0\microsoft.aspnetcore.session.2.2.0.nupkg.sha512 +microsoft.aspnetcore.session\2.2.0\microsoft.aspnetcore.session.nuspec +microsoft.aspnetcore.signalr.common\1.1.0\.nupkg.metadata +microsoft.aspnetcore.signalr.common\1.1.0\.signature.p7s +microsoft.aspnetcore.signalr.common\1.1.0\lib\netcoreapp2.2\Microsoft.AspNetCore.SignalR.Common.dll +microsoft.aspnetcore.signalr.common\1.1.0\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Common.dll +microsoft.aspnetcore.signalr.common\1.1.0\microsoft.aspnetcore.signalr.common.1.1.0.nupkg +microsoft.aspnetcore.signalr.common\1.1.0\microsoft.aspnetcore.signalr.common.1.1.0.nupkg.sha512 +microsoft.aspnetcore.signalr.common\1.1.0\microsoft.aspnetcore.signalr.common.nuspec +microsoft.aspnetcore.signalr.core\1.1.0\.nupkg.metadata +microsoft.aspnetcore.signalr.core\1.1.0\.signature.p7s +microsoft.aspnetcore.signalr.core\1.1.0\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Core.dll +microsoft.aspnetcore.signalr.core\1.1.0\microsoft.aspnetcore.signalr.core.1.1.0.nupkg +microsoft.aspnetcore.signalr.core\1.1.0\microsoft.aspnetcore.signalr.core.1.1.0.nupkg.sha512 +microsoft.aspnetcore.signalr.core\1.1.0\microsoft.aspnetcore.signalr.core.nuspec +microsoft.aspnetcore.signalr.protocols.json\1.1.0\.nupkg.metadata +microsoft.aspnetcore.signalr.protocols.json\1.1.0\.signature.p7s +microsoft.aspnetcore.signalr.protocols.json\1.1.0\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Protocols.Json.dll +microsoft.aspnetcore.signalr.protocols.json\1.1.0\microsoft.aspnetcore.signalr.protocols.json.1.1.0.nupkg +microsoft.aspnetcore.signalr.protocols.json\1.1.0\microsoft.aspnetcore.signalr.protocols.json.1.1.0.nupkg.sha512 +microsoft.aspnetcore.signalr.protocols.json\1.1.0\microsoft.aspnetcore.signalr.protocols.json.nuspec +microsoft.aspnetcore.signalr.redis\1.1.0\.nupkg.metadata +microsoft.aspnetcore.signalr.redis\1.1.0\.signature.p7s +microsoft.aspnetcore.signalr.redis\1.1.0\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Redis.dll +microsoft.aspnetcore.signalr.redis\1.1.0\microsoft.aspnetcore.signalr.redis.1.1.0.nupkg +microsoft.aspnetcore.signalr.redis\1.1.0\microsoft.aspnetcore.signalr.redis.1.1.0.nupkg.sha512 +microsoft.aspnetcore.signalr.redis\1.1.0\microsoft.aspnetcore.signalr.redis.nuspec +microsoft.aspnetcore.signalr\1.1.0\.nupkg.metadata +microsoft.aspnetcore.signalr\1.1.0\.signature.p7s +microsoft.aspnetcore.signalr\1.1.0\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.dll +microsoft.aspnetcore.signalr\1.1.0\microsoft.aspnetcore.signalr.1.1.0.nupkg +microsoft.aspnetcore.signalr\1.1.0\microsoft.aspnetcore.signalr.1.1.0.nupkg.sha512 +microsoft.aspnetcore.signalr\1.1.0\microsoft.aspnetcore.signalr.nuspec +microsoft.aspnetcore.spaservices.extensions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.spaservices.extensions\2.2.0\.signature.p7s +microsoft.aspnetcore.spaservices.extensions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.SpaServices.Extensions.dll +microsoft.aspnetcore.spaservices.extensions\2.2.0\microsoft.aspnetcore.spaservices.extensions.2.2.0.nupkg +microsoft.aspnetcore.spaservices.extensions\2.2.0\microsoft.aspnetcore.spaservices.extensions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.spaservices.extensions\2.2.0\microsoft.aspnetcore.spaservices.extensions.nuspec +microsoft.aspnetcore.spaservices\2.2.0\.nupkg.metadata +microsoft.aspnetcore.spaservices\2.2.0\.signature.p7s +microsoft.aspnetcore.spaservices\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.SpaServices.dll +microsoft.aspnetcore.spaservices\2.2.0\microsoft.aspnetcore.spaservices.2.2.0.nupkg +microsoft.aspnetcore.spaservices\2.2.0\microsoft.aspnetcore.spaservices.2.2.0.nupkg.sha512 +microsoft.aspnetcore.spaservices\2.2.0\microsoft.aspnetcore.spaservices.nuspec +microsoft.aspnetcore.staticfiles\2.2.0\.nupkg.metadata +microsoft.aspnetcore.staticfiles\2.2.0\.signature.p7s +microsoft.aspnetcore.staticfiles\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.StaticFiles.dll +microsoft.aspnetcore.staticfiles\2.2.0\microsoft.aspnetcore.staticfiles.2.2.0.nupkg +microsoft.aspnetcore.staticfiles\2.2.0\microsoft.aspnetcore.staticfiles.2.2.0.nupkg.sha512 +microsoft.aspnetcore.staticfiles\2.2.0\microsoft.aspnetcore.staticfiles.nuspec +microsoft.aspnetcore.websockets\2.2.0\.nupkg.metadata +microsoft.aspnetcore.websockets\2.2.0\.signature.p7s +microsoft.aspnetcore.websockets\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.WebSockets.dll +microsoft.aspnetcore.websockets\2.2.0\microsoft.aspnetcore.websockets.2.2.0.nupkg +microsoft.aspnetcore.websockets\2.2.0\microsoft.aspnetcore.websockets.2.2.0.nupkg.sha512 +microsoft.aspnetcore.websockets\2.2.0\microsoft.aspnetcore.websockets.nuspec +microsoft.aspnetcore.webutilities\2.2.0\.nupkg.metadata +microsoft.aspnetcore.webutilities\2.2.0\.signature.p7s +microsoft.aspnetcore.webutilities\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.WebUtilities.dll +microsoft.aspnetcore.webutilities\2.2.0\microsoft.aspnetcore.webutilities.2.2.0.nupkg +microsoft.aspnetcore.webutilities\2.2.0\microsoft.aspnetcore.webutilities.2.2.0.nupkg.sha512 +microsoft.aspnetcore.webutilities\2.2.0\microsoft.aspnetcore.webutilities.nuspec +microsoft.aspnetcore\2.2.0\.nupkg.metadata +microsoft.aspnetcore\2.2.0\.signature.p7s +microsoft.aspnetcore\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.dll +microsoft.aspnetcore\2.2.0\microsoft.aspnetcore.2.2.0.nupkg +microsoft.aspnetcore\2.2.0\microsoft.aspnetcore.2.2.0.nupkg.sha512 +microsoft.aspnetcore\2.2.0\microsoft.aspnetcore.nuspec +microsoft.azure.keyvault.webkey\2.0.7\.nupkg.metadata +microsoft.azure.keyvault.webkey\2.0.7\.signature.p7s +microsoft.azure.keyvault\2.3.2\.nupkg.metadata +microsoft.azure.keyvault\2.3.2\.signature.p7s +microsoft.azure.services.appauthentication\1.0.1\.nupkg.metadata +microsoft.azure.services.appauthentication\1.0.1\.signature.p7s +microsoft.codeanalysis.analyzers\1.1.0\.nupkg.metadata +microsoft.codeanalysis.common\2.8.0\.nupkg.metadata +microsoft.codeanalysis.csharp\2.8.0\.nupkg.metadata +microsoft.codeanalysis.razor\2.2.0\.nupkg.metadata +microsoft.codeanalysis.razor\2.2.0\.signature.p7s +microsoft.codeanalysis.razor\2.2.0\lib\net46\Microsoft.CodeAnalysis.Razor.dll +microsoft.codeanalysis.razor\2.2.0\lib\netstandard2.0\Microsoft.CodeAnalysis.Razor.dll +microsoft.codeanalysis.razor\2.2.0\microsoft.codeanalysis.razor.2.2.0.nupkg +microsoft.codeanalysis.razor\2.2.0\microsoft.codeanalysis.razor.2.2.0.nupkg.sha512 +microsoft.codeanalysis.razor\2.2.0\microsoft.codeanalysis.razor.nuspec +microsoft.csharp\4.0.1\.nupkg.metadata +microsoft.csharp\4.3.0\.nupkg.metadata +microsoft.csharp\4.5.0\.nupkg.metadata +microsoft.data.edm\5.8.2\.nupkg.metadata +microsoft.data.odata\5.8.2\.nupkg.metadata +microsoft.data.sqlite.core\2.2.0\.nupkg.metadata +microsoft.data.sqlite.core\2.2.0\.signature.p7s +microsoft.data.sqlite.core\2.2.0\lib\netstandard2.0\Microsoft.Data.Sqlite.dll +microsoft.data.sqlite.core\2.2.0\microsoft.data.sqlite.core.2.2.0.nupkg +microsoft.data.sqlite.core\2.2.0\microsoft.data.sqlite.core.2.2.0.nupkg.sha512 +microsoft.data.sqlite.core\2.2.0\microsoft.data.sqlite.core.nuspec +microsoft.data.sqlite\2.2.0\.nupkg.metadata +microsoft.data.sqlite\2.2.0\.signature.p7s +microsoft.data.sqlite\2.2.0\lib\netstandard2.0\_._ +microsoft.data.sqlite\2.2.0\microsoft.data.sqlite.2.2.0.nupkg +microsoft.data.sqlite\2.2.0\microsoft.data.sqlite.2.2.0.nupkg.sha512 +microsoft.data.sqlite\2.2.0\microsoft.data.sqlite.nuspec +microsoft.dotnet.platformabstractions\2.1.0\.nupkg.metadata +microsoft.entityframeworkcore.abstractions\2.2.0\.nupkg.metadata +microsoft.entityframeworkcore.abstractions\2.2.0\.signature.p7s +microsoft.entityframeworkcore.abstractions\2.2.0\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Abstractions.dll +microsoft.entityframeworkcore.abstractions\2.2.0\microsoft.entityframeworkcore.abstractions.2.2.0.nupkg +microsoft.entityframeworkcore.abstractions\2.2.0\microsoft.entityframeworkcore.abstractions.2.2.0.nupkg.sha512 +microsoft.entityframeworkcore.abstractions\2.2.0\microsoft.entityframeworkcore.abstractions.nuspec +microsoft.entityframeworkcore.analyzers\2.2.0\.nupkg.metadata +microsoft.entityframeworkcore.analyzers\2.2.0\.signature.p7s +microsoft.entityframeworkcore.analyzers\2.2.0\analyzers\dotnet\cs\Microsoft.EntityFrameworkCore.Analyzers.dll +microsoft.entityframeworkcore.analyzers\2.2.0\microsoft.entityframeworkcore.analyzers.2.2.0.nupkg +microsoft.entityframeworkcore.analyzers\2.2.0\microsoft.entityframeworkcore.analyzers.2.2.0.nupkg.sha512 +microsoft.entityframeworkcore.analyzers\2.2.0\microsoft.entityframeworkcore.analyzers.nuspec +microsoft.entityframeworkcore.design\2.2.0\.nupkg.metadata +microsoft.entityframeworkcore.design\2.2.0\.signature.p7s +microsoft.entityframeworkcore.design\2.2.0\build\net461\Microsoft.EntityFrameworkCore.Design.props +microsoft.entityframeworkcore.design\2.2.0\build\netcoreapp2.0\Microsoft.EntityFrameworkCore.Design.props +microsoft.entityframeworkcore.design\2.2.0\lib\net461\Microsoft.EntityFrameworkCore.Design.dll +microsoft.entityframeworkcore.design\2.2.0\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Design.dll +microsoft.entityframeworkcore.design\2.2.0\microsoft.entityframeworkcore.design.2.2.0.nupkg +microsoft.entityframeworkcore.design\2.2.0\microsoft.entityframeworkcore.design.2.2.0.nupkg.sha512 +microsoft.entityframeworkcore.design\2.2.0\microsoft.entityframeworkcore.design.nuspec +microsoft.entityframeworkcore.inmemory\2.2.0\.nupkg.metadata +microsoft.entityframeworkcore.inmemory\2.2.0\.signature.p7s +microsoft.entityframeworkcore.inmemory\2.2.0\lib\netstandard2.0\Microsoft.EntityFrameworkCore.InMemory.dll +microsoft.entityframeworkcore.inmemory\2.2.0\microsoft.entityframeworkcore.inmemory.2.2.0.nupkg +microsoft.entityframeworkcore.inmemory\2.2.0\microsoft.entityframeworkcore.inmemory.2.2.0.nupkg.sha512 +microsoft.entityframeworkcore.inmemory\2.2.0\microsoft.entityframeworkcore.inmemory.nuspec +microsoft.entityframeworkcore.relational\2.2.0\.nupkg.metadata +microsoft.entityframeworkcore.relational\2.2.0\.signature.p7s +microsoft.entityframeworkcore.relational\2.2.0\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Relational.dll +microsoft.entityframeworkcore.relational\2.2.0\microsoft.entityframeworkcore.relational.2.2.0.nupkg +microsoft.entityframeworkcore.relational\2.2.0\microsoft.entityframeworkcore.relational.2.2.0.nupkg.sha512 +microsoft.entityframeworkcore.relational\2.2.0\microsoft.entityframeworkcore.relational.nuspec +microsoft.entityframeworkcore.sqlite.core\2.2.0\.nupkg.metadata +microsoft.entityframeworkcore.sqlite.core\2.2.0\.signature.p7s +microsoft.entityframeworkcore.sqlite.core\2.2.0\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Sqlite.dll +microsoft.entityframeworkcore.sqlite.core\2.2.0\microsoft.entityframeworkcore.sqlite.core.2.2.0.nupkg +microsoft.entityframeworkcore.sqlite.core\2.2.0\microsoft.entityframeworkcore.sqlite.core.2.2.0.nupkg.sha512 +microsoft.entityframeworkcore.sqlite.core\2.2.0\microsoft.entityframeworkcore.sqlite.core.nuspec +microsoft.entityframeworkcore.sqlite\2.2.0\.nupkg.metadata +microsoft.entityframeworkcore.sqlite\2.2.0\.signature.p7s +microsoft.entityframeworkcore.sqlite\2.2.0\lib\netstandard2.0\_._ +microsoft.entityframeworkcore.sqlite\2.2.0\microsoft.entityframeworkcore.sqlite.2.2.0.nupkg +microsoft.entityframeworkcore.sqlite\2.2.0\microsoft.entityframeworkcore.sqlite.2.2.0.nupkg.sha512 +microsoft.entityframeworkcore.sqlite\2.2.0\microsoft.entityframeworkcore.sqlite.nuspec +microsoft.entityframeworkcore.sqlserver\2.2.0\.nupkg.metadata +microsoft.entityframeworkcore.sqlserver\2.2.0\.signature.p7s +microsoft.entityframeworkcore.sqlserver\2.2.0\lib\netstandard2.0\Microsoft.EntityFrameworkCore.SqlServer.dll +microsoft.entityframeworkcore.sqlserver\2.2.0\microsoft.entityframeworkcore.sqlserver.2.2.0.nupkg +microsoft.entityframeworkcore.sqlserver\2.2.0\microsoft.entityframeworkcore.sqlserver.2.2.0.nupkg.sha512 +microsoft.entityframeworkcore.sqlserver\2.2.0\microsoft.entityframeworkcore.sqlserver.nuspec +microsoft.entityframeworkcore.tools\2.2.0\.nupkg.metadata +microsoft.entityframeworkcore.tools\2.2.0\.signature.p7s +microsoft.entityframeworkcore.tools\2.2.0\lib\netstandard2.0\_._ +microsoft.entityframeworkcore.tools\2.2.0\microsoft.entityframeworkcore.tools.2.2.0.nupkg +microsoft.entityframeworkcore.tools\2.2.0\microsoft.entityframeworkcore.tools.2.2.0.nupkg.sha512 +microsoft.entityframeworkcore.tools\2.2.0\microsoft.entityframeworkcore.tools.nuspec +microsoft.entityframeworkcore.tools\2.2.0\tools\about_EntityFrameworkCore.help.txt +microsoft.entityframeworkcore.tools\2.2.0\tools\EntityFrameworkCore.PowerShell2.psd1 +microsoft.entityframeworkcore.tools\2.2.0\tools\EntityFrameworkCore.PowerShell2.psm1 +microsoft.entityframeworkcore.tools\2.2.0\tools\EntityFrameworkCore.psd1 +microsoft.entityframeworkcore.tools\2.2.0\tools\EntityFrameworkCore.psm1 +microsoft.entityframeworkcore.tools\2.2.0\tools\init.ps1 +microsoft.entityframeworkcore.tools\2.2.0\tools\install.ps1 +microsoft.entityframeworkcore.tools\2.2.0\tools\net461\any\ef.exe +microsoft.entityframeworkcore.tools\2.2.0\tools\net461\win-x86\ef.exe +microsoft.entityframeworkcore.tools\2.2.0\tools\netcoreapp2.0\any\ef.dll +microsoft.entityframeworkcore.tools\2.2.0\tools\netcoreapp2.0\any\ef.runtimeconfig.json +microsoft.entityframeworkcore\2.2.0\.nupkg.metadata +microsoft.entityframeworkcore\2.2.0\.signature.p7s +microsoft.entityframeworkcore\2.2.0\lib\netstandard2.0\Microsoft.EntityFrameworkCore.dll +microsoft.entityframeworkcore\2.2.0\microsoft.entityframeworkcore.2.2.0.nupkg +microsoft.entityframeworkcore\2.2.0\microsoft.entityframeworkcore.2.2.0.nupkg.sha512 +microsoft.entityframeworkcore\2.2.0\microsoft.entityframeworkcore.nuspec +microsoft.extensions.caching.abstractions\2.2.0\.nupkg.metadata +microsoft.extensions.caching.abstractions\2.2.0\.signature.p7s +microsoft.extensions.caching.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Caching.Abstractions.dll +microsoft.extensions.caching.abstractions\2.2.0\microsoft.extensions.caching.abstractions.2.2.0.nupkg +microsoft.extensions.caching.abstractions\2.2.0\microsoft.extensions.caching.abstractions.2.2.0.nupkg.sha512 +microsoft.extensions.caching.abstractions\2.2.0\microsoft.extensions.caching.abstractions.nuspec +microsoft.extensions.caching.memory\2.2.0\.nupkg.metadata +microsoft.extensions.caching.memory\2.2.0\.signature.p7s +microsoft.extensions.caching.memory\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Caching.Memory.dll +microsoft.extensions.caching.memory\2.2.0\microsoft.extensions.caching.memory.2.2.0.nupkg +microsoft.extensions.caching.memory\2.2.0\microsoft.extensions.caching.memory.2.2.0.nupkg.sha512 +microsoft.extensions.caching.memory\2.2.0\microsoft.extensions.caching.memory.nuspec +microsoft.extensions.caching.redis\2.2.0\.nupkg.metadata +microsoft.extensions.caching.redis\2.2.0\.signature.p7s +microsoft.extensions.caching.redis\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Caching.Redis.dll +microsoft.extensions.caching.redis\2.2.0\microsoft.extensions.caching.redis.2.2.0.nupkg +microsoft.extensions.caching.redis\2.2.0\microsoft.extensions.caching.redis.2.2.0.nupkg.sha512 +microsoft.extensions.caching.redis\2.2.0\microsoft.extensions.caching.redis.nuspec +microsoft.extensions.caching.sqlserver\2.2.0\.nupkg.metadata +microsoft.extensions.caching.sqlserver\2.2.0\.signature.p7s +microsoft.extensions.caching.sqlserver\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Caching.SqlServer.dll +microsoft.extensions.caching.sqlserver\2.2.0\microsoft.extensions.caching.sqlserver.2.2.0.nupkg +microsoft.extensions.caching.sqlserver\2.2.0\microsoft.extensions.caching.sqlserver.2.2.0.nupkg.sha512 +microsoft.extensions.caching.sqlserver\2.2.0\microsoft.extensions.caching.sqlserver.nuspec +microsoft.extensions.configuration.abstractions\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.abstractions\2.2.0\.signature.p7s +microsoft.extensions.configuration.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.Abstractions.dll +microsoft.extensions.configuration.abstractions\2.2.0\microsoft.extensions.configuration.abstractions.2.2.0.nupkg +microsoft.extensions.configuration.abstractions\2.2.0\microsoft.extensions.configuration.abstractions.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.abstractions\2.2.0\microsoft.extensions.configuration.abstractions.nuspec +microsoft.extensions.configuration.azurekeyvault\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.azurekeyvault\2.2.0\.signature.p7s +microsoft.extensions.configuration.azurekeyvault\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.AzureKeyVault.dll +microsoft.extensions.configuration.azurekeyvault\2.2.0\microsoft.extensions.configuration.azurekeyvault.2.2.0.nupkg +microsoft.extensions.configuration.azurekeyvault\2.2.0\microsoft.extensions.configuration.azurekeyvault.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.azurekeyvault\2.2.0\microsoft.extensions.configuration.azurekeyvault.nuspec +microsoft.extensions.configuration.binder\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.binder\2.2.0\.signature.p7s +microsoft.extensions.configuration.binder\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.Binder.dll +microsoft.extensions.configuration.binder\2.2.0\microsoft.extensions.configuration.binder.2.2.0.nupkg +microsoft.extensions.configuration.binder\2.2.0\microsoft.extensions.configuration.binder.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.binder\2.2.0\microsoft.extensions.configuration.binder.nuspec +microsoft.extensions.configuration.commandline\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.commandline\2.2.0\.signature.p7s +microsoft.extensions.configuration.commandline\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.CommandLine.dll +microsoft.extensions.configuration.commandline\2.2.0\microsoft.extensions.configuration.commandline.2.2.0.nupkg +microsoft.extensions.configuration.commandline\2.2.0\microsoft.extensions.configuration.commandline.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.commandline\2.2.0\microsoft.extensions.configuration.commandline.nuspec +microsoft.extensions.configuration.environmentvariables\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.environmentvariables\2.2.0\.signature.p7s +microsoft.extensions.configuration.environmentvariables\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.EnvironmentVariables.dll +microsoft.extensions.configuration.environmentvariables\2.2.0\microsoft.extensions.configuration.environmentvariables.2.2.0.nupkg +microsoft.extensions.configuration.environmentvariables\2.2.0\microsoft.extensions.configuration.environmentvariables.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.environmentvariables\2.2.0\microsoft.extensions.configuration.environmentvariables.nuspec +microsoft.extensions.configuration.fileextensions\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.fileextensions\2.2.0\.signature.p7s +microsoft.extensions.configuration.fileextensions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.FileExtensions.dll +microsoft.extensions.configuration.fileextensions\2.2.0\microsoft.extensions.configuration.fileextensions.2.2.0.nupkg +microsoft.extensions.configuration.fileextensions\2.2.0\microsoft.extensions.configuration.fileextensions.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.fileextensions\2.2.0\microsoft.extensions.configuration.fileextensions.nuspec +microsoft.extensions.configuration.ini\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.ini\2.2.0\.signature.p7s +microsoft.extensions.configuration.ini\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.Ini.dll +microsoft.extensions.configuration.ini\2.2.0\microsoft.extensions.configuration.ini.2.2.0.nupkg +microsoft.extensions.configuration.ini\2.2.0\microsoft.extensions.configuration.ini.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.ini\2.2.0\microsoft.extensions.configuration.ini.nuspec +microsoft.extensions.configuration.json\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.json\2.2.0\.signature.p7s +microsoft.extensions.configuration.json\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.Json.dll +microsoft.extensions.configuration.json\2.2.0\microsoft.extensions.configuration.json.2.2.0.nupkg +microsoft.extensions.configuration.json\2.2.0\microsoft.extensions.configuration.json.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.json\2.2.0\microsoft.extensions.configuration.json.nuspec +microsoft.extensions.configuration.keyperfile\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.keyperfile\2.2.0\.signature.p7s +microsoft.extensions.configuration.keyperfile\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.KeyPerFile.dll +microsoft.extensions.configuration.keyperfile\2.2.0\microsoft.extensions.configuration.keyperfile.2.2.0.nupkg +microsoft.extensions.configuration.keyperfile\2.2.0\microsoft.extensions.configuration.keyperfile.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.keyperfile\2.2.0\microsoft.extensions.configuration.keyperfile.nuspec +microsoft.extensions.configuration.usersecrets\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.usersecrets\2.2.0\.signature.p7s +microsoft.extensions.configuration.usersecrets\2.2.0\build\netstandard2.0\Microsoft.Extensions.Configuration.UserSecrets.props +microsoft.extensions.configuration.usersecrets\2.2.0\build\netstandard2.0\Microsoft.Extensions.Configuration.UserSecrets.targets +microsoft.extensions.configuration.usersecrets\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.UserSecrets.dll +microsoft.extensions.configuration.usersecrets\2.2.0\microsoft.extensions.configuration.usersecrets.2.2.0.nupkg +microsoft.extensions.configuration.usersecrets\2.2.0\microsoft.extensions.configuration.usersecrets.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.usersecrets\2.2.0\microsoft.extensions.configuration.usersecrets.nuspec +microsoft.extensions.configuration.xml\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.xml\2.2.0\.signature.p7s +microsoft.extensions.configuration.xml\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.Xml.dll +microsoft.extensions.configuration.xml\2.2.0\microsoft.extensions.configuration.xml.2.2.0.nupkg +microsoft.extensions.configuration.xml\2.2.0\microsoft.extensions.configuration.xml.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.xml\2.2.0\microsoft.extensions.configuration.xml.nuspec +microsoft.extensions.configuration\2.2.0\.nupkg.metadata +microsoft.extensions.configuration\2.2.0\.signature.p7s +microsoft.extensions.configuration\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.dll +microsoft.extensions.configuration\2.2.0\microsoft.extensions.configuration.2.2.0.nupkg +microsoft.extensions.configuration\2.2.0\microsoft.extensions.configuration.2.2.0.nupkg.sha512 +microsoft.extensions.configuration\2.2.0\microsoft.extensions.configuration.nuspec +microsoft.extensions.dependencyinjection.abstractions\2.2.0\.nupkg.metadata +microsoft.extensions.dependencyinjection.abstractions\2.2.0\.signature.p7s +microsoft.extensions.dependencyinjection.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll +microsoft.extensions.dependencyinjection.abstractions\2.2.0\microsoft.extensions.dependencyinjection.abstractions.2.2.0.nupkg +microsoft.extensions.dependencyinjection.abstractions\2.2.0\microsoft.extensions.dependencyinjection.abstractions.2.2.0.nupkg.sha512 +microsoft.extensions.dependencyinjection.abstractions\2.2.0\microsoft.extensions.dependencyinjection.abstractions.nuspec +microsoft.extensions.dependencyinjection\2.2.0\.nupkg.metadata +microsoft.extensions.dependencyinjection\2.2.0\.signature.p7s +microsoft.extensions.dependencyinjection\2.2.0\lib\net461\Microsoft.Extensions.DependencyInjection.dll +microsoft.extensions.dependencyinjection\2.2.0\lib\netcoreapp2.0\Microsoft.Extensions.DependencyInjection.dll +microsoft.extensions.dependencyinjection\2.2.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.dll +microsoft.extensions.dependencyinjection\2.2.0\microsoft.extensions.dependencyinjection.2.2.0.nupkg +microsoft.extensions.dependencyinjection\2.2.0\microsoft.extensions.dependencyinjection.2.2.0.nupkg.sha512 +microsoft.extensions.dependencyinjection\2.2.0\microsoft.extensions.dependencyinjection.nuspec +microsoft.extensions.dependencymodel\2.1.0\.nupkg.metadata +microsoft.extensions.diagnosticadapter\2.2.0\.nupkg.metadata +microsoft.extensions.diagnosticadapter\2.2.0\.signature.p7s +microsoft.extensions.diagnosticadapter\2.2.0\lib\net461\Microsoft.Extensions.DiagnosticAdapter.dll +microsoft.extensions.diagnosticadapter\2.2.0\lib\netcoreapp2.0\Microsoft.Extensions.DiagnosticAdapter.dll +microsoft.extensions.diagnosticadapter\2.2.0\lib\netstandard2.0\Microsoft.Extensions.DiagnosticAdapter.dll +microsoft.extensions.diagnosticadapter\2.2.0\microsoft.extensions.diagnosticadapter.2.2.0.nupkg +microsoft.extensions.diagnosticadapter\2.2.0\microsoft.extensions.diagnosticadapter.2.2.0.nupkg.sha512 +microsoft.extensions.diagnosticadapter\2.2.0\microsoft.extensions.diagnosticadapter.nuspec +microsoft.extensions.diagnostics.healthchecks.abstractions\2.2.0\.nupkg.metadata +microsoft.extensions.diagnostics.healthchecks.abstractions\2.2.0\.signature.p7s +microsoft.extensions.diagnostics.healthchecks.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.dll +microsoft.extensions.diagnostics.healthchecks.abstractions\2.2.0\microsoft.extensions.diagnostics.healthchecks.abstractions.2.2.0.nupkg +microsoft.extensions.diagnostics.healthchecks.abstractions\2.2.0\microsoft.extensions.diagnostics.healthchecks.abstractions.2.2.0.nupkg.sha512 +microsoft.extensions.diagnostics.healthchecks.abstractions\2.2.0\microsoft.extensions.diagnostics.healthchecks.abstractions.nuspec +microsoft.extensions.diagnostics.healthchecks\2.2.0\.nupkg.metadata +microsoft.extensions.diagnostics.healthchecks\2.2.0\.signature.p7s +microsoft.extensions.diagnostics.healthchecks\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Diagnostics.HealthChecks.dll +microsoft.extensions.diagnostics.healthchecks\2.2.0\microsoft.extensions.diagnostics.healthchecks.2.2.0.nupkg +microsoft.extensions.diagnostics.healthchecks\2.2.0\microsoft.extensions.diagnostics.healthchecks.2.2.0.nupkg.sha512 +microsoft.extensions.diagnostics.healthchecks\2.2.0\microsoft.extensions.diagnostics.healthchecks.nuspec +microsoft.extensions.fileproviders.abstractions\2.2.0\.nupkg.metadata +microsoft.extensions.fileproviders.abstractions\2.2.0\.signature.p7s +microsoft.extensions.fileproviders.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Abstractions.dll +microsoft.extensions.fileproviders.abstractions\2.2.0\microsoft.extensions.fileproviders.abstractions.2.2.0.nupkg +microsoft.extensions.fileproviders.abstractions\2.2.0\microsoft.extensions.fileproviders.abstractions.2.2.0.nupkg.sha512 +microsoft.extensions.fileproviders.abstractions\2.2.0\microsoft.extensions.fileproviders.abstractions.nuspec +microsoft.extensions.fileproviders.composite\2.2.0\.nupkg.metadata +microsoft.extensions.fileproviders.composite\2.2.0\.signature.p7s +microsoft.extensions.fileproviders.composite\2.2.0\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Composite.dll +microsoft.extensions.fileproviders.composite\2.2.0\microsoft.extensions.fileproviders.composite.2.2.0.nupkg +microsoft.extensions.fileproviders.composite\2.2.0\microsoft.extensions.fileproviders.composite.2.2.0.nupkg.sha512 +microsoft.extensions.fileproviders.composite\2.2.0\microsoft.extensions.fileproviders.composite.nuspec +microsoft.extensions.fileproviders.embedded\2.2.0\.nupkg.metadata +microsoft.extensions.fileproviders.embedded\2.2.0\.signature.p7s +microsoft.extensions.fileproviders.embedded\2.2.0\build\netstandard2.0\Microsoft.Extensions.FileProviders.Embedded.props +microsoft.extensions.fileproviders.embedded\2.2.0\build\netstandard2.0\Microsoft.Extensions.FileProviders.Embedded.targets +microsoft.extensions.fileproviders.embedded\2.2.0\buildMultiTargeting\Microsoft.Extensions.FileProviders.Embedded.props +microsoft.extensions.fileproviders.embedded\2.2.0\buildMultiTargeting\Microsoft.Extensions.FileProviders.Embedded.targets +microsoft.extensions.fileproviders.embedded\2.2.0\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Embedded.dll +microsoft.extensions.fileproviders.embedded\2.2.0\microsoft.extensions.fileproviders.embedded.2.2.0.nupkg +microsoft.extensions.fileproviders.embedded\2.2.0\microsoft.extensions.fileproviders.embedded.2.2.0.nupkg.sha512 +microsoft.extensions.fileproviders.embedded\2.2.0\microsoft.extensions.fileproviders.embedded.nuspec +microsoft.extensions.fileproviders.embedded\2.2.0\tasks\net461\Microsoft.Extensions.FileProviders.Embedded.Manifest.Task.dll +microsoft.extensions.fileproviders.embedded\2.2.0\tasks\netstandard1.5\Microsoft.Extensions.FileProviders.Embedded.Manifest.Task.dll +microsoft.extensions.fileproviders.physical\2.2.0\.nupkg.metadata +microsoft.extensions.fileproviders.physical\2.2.0\.signature.p7s +microsoft.extensions.fileproviders.physical\2.2.0\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Physical.dll +microsoft.extensions.fileproviders.physical\2.2.0\microsoft.extensions.fileproviders.physical.2.2.0.nupkg +microsoft.extensions.fileproviders.physical\2.2.0\microsoft.extensions.fileproviders.physical.2.2.0.nupkg.sha512 +microsoft.extensions.fileproviders.physical\2.2.0\microsoft.extensions.fileproviders.physical.nuspec +microsoft.extensions.filesystemglobbing\2.2.0\.nupkg.metadata +microsoft.extensions.filesystemglobbing\2.2.0\.signature.p7s +microsoft.extensions.filesystemglobbing\2.2.0\lib\netstandard2.0\Microsoft.Extensions.FileSystemGlobbing.dll +microsoft.extensions.filesystemglobbing\2.2.0\microsoft.extensions.filesystemglobbing.2.2.0.nupkg +microsoft.extensions.filesystemglobbing\2.2.0\microsoft.extensions.filesystemglobbing.2.2.0.nupkg.sha512 +microsoft.extensions.filesystemglobbing\2.2.0\microsoft.extensions.filesystemglobbing.nuspec +microsoft.extensions.hosting.abstractions\2.2.0\.nupkg.metadata +microsoft.extensions.hosting.abstractions\2.2.0\.signature.p7s +microsoft.extensions.hosting.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Hosting.Abstractions.dll +microsoft.extensions.hosting.abstractions\2.2.0\microsoft.extensions.hosting.abstractions.2.2.0.nupkg +microsoft.extensions.hosting.abstractions\2.2.0\microsoft.extensions.hosting.abstractions.2.2.0.nupkg.sha512 +microsoft.extensions.hosting.abstractions\2.2.0\microsoft.extensions.hosting.abstractions.nuspec +microsoft.extensions.hosting\2.2.0\.nupkg.metadata +microsoft.extensions.hosting\2.2.0\.signature.p7s +microsoft.extensions.hosting\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Hosting.dll +microsoft.extensions.hosting\2.2.0\microsoft.extensions.hosting.2.2.0.nupkg +microsoft.extensions.hosting\2.2.0\microsoft.extensions.hosting.2.2.0.nupkg.sha512 +microsoft.extensions.hosting\2.2.0\microsoft.extensions.hosting.nuspec +microsoft.extensions.http\2.2.0\.nupkg.metadata +microsoft.extensions.http\2.2.0\.signature.p7s +microsoft.extensions.http\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Http.dll +microsoft.extensions.http\2.2.0\microsoft.extensions.http.2.2.0.nupkg +microsoft.extensions.http\2.2.0\microsoft.extensions.http.2.2.0.nupkg.sha512 +microsoft.extensions.http\2.2.0\microsoft.extensions.http.nuspec +microsoft.extensions.identity.core\2.2.0\.nupkg.metadata +microsoft.extensions.identity.core\2.2.0\.signature.p7s +microsoft.extensions.identity.core\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Identity.Core.dll +microsoft.extensions.identity.core\2.2.0\microsoft.extensions.identity.core.2.2.0.nupkg +microsoft.extensions.identity.core\2.2.0\microsoft.extensions.identity.core.2.2.0.nupkg.sha512 +microsoft.extensions.identity.core\2.2.0\microsoft.extensions.identity.core.nuspec +microsoft.extensions.identity.stores\2.2.0\.nupkg.metadata +microsoft.extensions.identity.stores\2.2.0\.signature.p7s +microsoft.extensions.identity.stores\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Identity.Stores.dll +microsoft.extensions.identity.stores\2.2.0\microsoft.extensions.identity.stores.2.2.0.nupkg +microsoft.extensions.identity.stores\2.2.0\microsoft.extensions.identity.stores.2.2.0.nupkg.sha512 +microsoft.extensions.identity.stores\2.2.0\microsoft.extensions.identity.stores.nuspec +microsoft.extensions.localization.abstractions\2.2.0\.nupkg.metadata +microsoft.extensions.localization.abstractions\2.2.0\.signature.p7s +microsoft.extensions.localization.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Localization.Abstractions.dll +microsoft.extensions.localization.abstractions\2.2.0\microsoft.extensions.localization.abstractions.2.2.0.nupkg +microsoft.extensions.localization.abstractions\2.2.0\microsoft.extensions.localization.abstractions.2.2.0.nupkg.sha512 +microsoft.extensions.localization.abstractions\2.2.0\microsoft.extensions.localization.abstractions.nuspec +microsoft.extensions.localization\2.2.0\.nupkg.metadata +microsoft.extensions.localization\2.2.0\.signature.p7s +microsoft.extensions.localization\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Localization.dll +microsoft.extensions.localization\2.2.0\microsoft.extensions.localization.2.2.0.nupkg +microsoft.extensions.localization\2.2.0\microsoft.extensions.localization.2.2.0.nupkg.sha512 +microsoft.extensions.localization\2.2.0\microsoft.extensions.localization.nuspec +microsoft.extensions.logging.abstractions\2.2.0\.nupkg.metadata +microsoft.extensions.logging.abstractions\2.2.0\.signature.p7s +microsoft.extensions.logging.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll +microsoft.extensions.logging.abstractions\2.2.0\microsoft.extensions.logging.abstractions.2.2.0.nupkg +microsoft.extensions.logging.abstractions\2.2.0\microsoft.extensions.logging.abstractions.2.2.0.nupkg.sha512 +microsoft.extensions.logging.abstractions\2.2.0\microsoft.extensions.logging.abstractions.nuspec +microsoft.extensions.logging.azureappservices\2.2.0\.nupkg.metadata +microsoft.extensions.logging.azureappservices\2.2.0\.signature.p7s +microsoft.extensions.logging.azureappservices\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.AzureAppServices.dll +microsoft.extensions.logging.azureappservices\2.2.0\microsoft.extensions.logging.azureappservices.2.2.0.nupkg +microsoft.extensions.logging.azureappservices\2.2.0\microsoft.extensions.logging.azureappservices.2.2.0.nupkg.sha512 +microsoft.extensions.logging.azureappservices\2.2.0\microsoft.extensions.logging.azureappservices.nuspec +microsoft.extensions.logging.configuration\2.2.0\.nupkg.metadata +microsoft.extensions.logging.configuration\2.2.0\.signature.p7s +microsoft.extensions.logging.configuration\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Configuration.dll +microsoft.extensions.logging.configuration\2.2.0\microsoft.extensions.logging.configuration.2.2.0.nupkg +microsoft.extensions.logging.configuration\2.2.0\microsoft.extensions.logging.configuration.2.2.0.nupkg.sha512 +microsoft.extensions.logging.configuration\2.2.0\microsoft.extensions.logging.configuration.nuspec +microsoft.extensions.logging.console\2.2.0\.nupkg.metadata +microsoft.extensions.logging.console\2.2.0\.signature.p7s +microsoft.extensions.logging.console\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Console.dll +microsoft.extensions.logging.console\2.2.0\microsoft.extensions.logging.console.2.2.0.nupkg +microsoft.extensions.logging.console\2.2.0\microsoft.extensions.logging.console.2.2.0.nupkg.sha512 +microsoft.extensions.logging.console\2.2.0\microsoft.extensions.logging.console.nuspec +microsoft.extensions.logging.debug\2.2.0\.nupkg.metadata +microsoft.extensions.logging.debug\2.2.0\.signature.p7s +microsoft.extensions.logging.debug\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Debug.dll +microsoft.extensions.logging.debug\2.2.0\microsoft.extensions.logging.debug.2.2.0.nupkg +microsoft.extensions.logging.debug\2.2.0\microsoft.extensions.logging.debug.2.2.0.nupkg.sha512 +microsoft.extensions.logging.debug\2.2.0\microsoft.extensions.logging.debug.nuspec +microsoft.extensions.logging.eventsource\2.2.0\.nupkg.metadata +microsoft.extensions.logging.eventsource\2.2.0\.signature.p7s +microsoft.extensions.logging.eventsource\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.EventSource.dll +microsoft.extensions.logging.eventsource\2.2.0\microsoft.extensions.logging.eventsource.2.2.0.nupkg +microsoft.extensions.logging.eventsource\2.2.0\microsoft.extensions.logging.eventsource.2.2.0.nupkg.sha512 +microsoft.extensions.logging.eventsource\2.2.0\microsoft.extensions.logging.eventsource.nuspec +microsoft.extensions.logging.tracesource\2.2.0\.nupkg.metadata +microsoft.extensions.logging.tracesource\2.2.0\.signature.p7s +microsoft.extensions.logging.tracesource\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.TraceSource.dll +microsoft.extensions.logging.tracesource\2.2.0\microsoft.extensions.logging.tracesource.2.2.0.nupkg +microsoft.extensions.logging.tracesource\2.2.0\microsoft.extensions.logging.tracesource.2.2.0.nupkg.sha512 +microsoft.extensions.logging.tracesource\2.2.0\microsoft.extensions.logging.tracesource.nuspec +microsoft.extensions.logging\2.2.0\.nupkg.metadata +microsoft.extensions.logging\2.2.0\.signature.p7s +microsoft.extensions.logging\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.dll +microsoft.extensions.logging\2.2.0\microsoft.extensions.logging.2.2.0.nupkg +microsoft.extensions.logging\2.2.0\microsoft.extensions.logging.2.2.0.nupkg.sha512 +microsoft.extensions.logging\2.2.0\microsoft.extensions.logging.nuspec +microsoft.extensions.objectpool\2.2.0\.nupkg.metadata +microsoft.extensions.objectpool\2.2.0\.signature.p7s +microsoft.extensions.objectpool\2.2.0\lib\netstandard2.0\Microsoft.Extensions.ObjectPool.dll +microsoft.extensions.objectpool\2.2.0\microsoft.extensions.objectpool.2.2.0.nupkg +microsoft.extensions.objectpool\2.2.0\microsoft.extensions.objectpool.2.2.0.nupkg.sha512 +microsoft.extensions.objectpool\2.2.0\microsoft.extensions.objectpool.nuspec +microsoft.extensions.options.configurationextensions\2.2.0\.nupkg.metadata +microsoft.extensions.options.configurationextensions\2.2.0\.signature.p7s +microsoft.extensions.options.configurationextensions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Options.ConfigurationExtensions.dll +microsoft.extensions.options.configurationextensions\2.2.0\microsoft.extensions.options.configurationextensions.2.2.0.nupkg +microsoft.extensions.options.configurationextensions\2.2.0\microsoft.extensions.options.configurationextensions.2.2.0.nupkg.sha512 +microsoft.extensions.options.configurationextensions\2.2.0\microsoft.extensions.options.configurationextensions.nuspec +microsoft.extensions.options.dataannotations\2.2.0\.nupkg.metadata +microsoft.extensions.options.dataannotations\2.2.0\.signature.p7s +microsoft.extensions.options.dataannotations\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Options.DataAnnotations.dll +microsoft.extensions.options.dataannotations\2.2.0\microsoft.extensions.options.dataannotations.2.2.0.nupkg +microsoft.extensions.options.dataannotations\2.2.0\microsoft.extensions.options.dataannotations.2.2.0.nupkg.sha512 +microsoft.extensions.options.dataannotations\2.2.0\microsoft.extensions.options.dataannotations.nuspec +microsoft.extensions.options\2.2.0\.nupkg.metadata +microsoft.extensions.options\2.2.0\.signature.p7s +microsoft.extensions.options\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Options.dll +microsoft.extensions.options\2.2.0\microsoft.extensions.options.2.2.0.nupkg +microsoft.extensions.options\2.2.0\microsoft.extensions.options.2.2.0.nupkg.sha512 +microsoft.extensions.options\2.2.0\microsoft.extensions.options.nuspec +microsoft.extensions.platformabstractions\1.1.0\.nupkg.metadata +microsoft.extensions.primitives\2.2.0\.nupkg.metadata +microsoft.extensions.primitives\2.2.0\.signature.p7s +microsoft.extensions.primitives\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Primitives.dll +microsoft.extensions.primitives\2.2.0\microsoft.extensions.primitives.2.2.0.nupkg +microsoft.extensions.primitives\2.2.0\microsoft.extensions.primitives.2.2.0.nupkg.sha512 +microsoft.extensions.primitives\2.2.0\microsoft.extensions.primitives.nuspec +microsoft.extensions.webencoders\2.2.0\.nupkg.metadata +microsoft.extensions.webencoders\2.2.0\.signature.p7s +microsoft.extensions.webencoders\2.2.0\lib\netstandard2.0\Microsoft.Extensions.WebEncoders.dll +microsoft.extensions.webencoders\2.2.0\microsoft.extensions.webencoders.2.2.0.nupkg +microsoft.extensions.webencoders\2.2.0\microsoft.extensions.webencoders.2.2.0.nupkg.sha512 +microsoft.extensions.webencoders\2.2.0\microsoft.extensions.webencoders.nuspec +microsoft.identitymodel.clients.activedirectory\3.14.2\.nupkg.metadata +microsoft.identitymodel.clients.activedirectory\3.14.2\.signature.p7s +microsoft.identitymodel.clients.activedirectory\3.19.8\.nupkg.metadata +microsoft.identitymodel.clients.activedirectory\3.19.8\.signature.p7s +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\MonoAndroid7\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\MonoAndroid7\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\netcore45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\netcore45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\netstandard1.1\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\netstandard1.1\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\netstandard1.3\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\netstandard1.3\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\portable-net45+win\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\portable-net45+win\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\Xamarin.iOS10\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\Xamarin.iOS10\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\microsoft.identitymodel.clients.activedirectory.3.19.8.nupkg +microsoft.identitymodel.clients.activedirectory\3.19.8\microsoft.identitymodel.clients.activedirectory.3.19.8.nupkg.sha512 +microsoft.identitymodel.clients.activedirectory\3.19.8\microsoft.identitymodel.clients.activedirectory.nuspec +microsoft.identitymodel.jsonwebtokens\5.3.0\.nupkg.metadata +microsoft.identitymodel.jsonwebtokens\5.3.0\.signature.p7s +microsoft.identitymodel.jsonwebtokens\5.3.0\lib\net45\Microsoft.IdentityModel.JsonWebTokens.dll +microsoft.identitymodel.jsonwebtokens\5.3.0\lib\net45\Microsoft.IdentityModel.JsonWebTokens.pdb +microsoft.identitymodel.jsonwebtokens\5.3.0\lib\net451\Microsoft.IdentityModel.JsonWebTokens.dll +microsoft.identitymodel.jsonwebtokens\5.3.0\lib\net451\Microsoft.IdentityModel.JsonWebTokens.pdb +microsoft.identitymodel.jsonwebtokens\5.3.0\lib\net461\Microsoft.IdentityModel.JsonWebTokens.dll +microsoft.identitymodel.jsonwebtokens\5.3.0\lib\net461\Microsoft.IdentityModel.JsonWebTokens.pdb +microsoft.identitymodel.jsonwebtokens\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.JsonWebTokens.dll +microsoft.identitymodel.jsonwebtokens\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.JsonWebTokens.pdb +microsoft.identitymodel.jsonwebtokens\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.JsonWebTokens.dll +microsoft.identitymodel.jsonwebtokens\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.JsonWebTokens.pdb +microsoft.identitymodel.jsonwebtokens\5.3.0\microsoft.identitymodel.jsonwebtokens.5.3.0.nupkg +microsoft.identitymodel.jsonwebtokens\5.3.0\microsoft.identitymodel.jsonwebtokens.5.3.0.nupkg.sha512 +microsoft.identitymodel.jsonwebtokens\5.3.0\microsoft.identitymodel.jsonwebtokens.nuspec +microsoft.identitymodel.logging\5.3.0\.nupkg.metadata +microsoft.identitymodel.logging\5.3.0\.signature.p7s +microsoft.identitymodel.logging\5.3.0\lib\net45\Microsoft.IdentityModel.Logging.dll +microsoft.identitymodel.logging\5.3.0\lib\net45\Microsoft.IdentityModel.Logging.pdb +microsoft.identitymodel.logging\5.3.0\lib\net451\Microsoft.IdentityModel.Logging.dll +microsoft.identitymodel.logging\5.3.0\lib\net451\Microsoft.IdentityModel.Logging.pdb +microsoft.identitymodel.logging\5.3.0\lib\net461\Microsoft.IdentityModel.Logging.dll +microsoft.identitymodel.logging\5.3.0\lib\net461\Microsoft.IdentityModel.Logging.pdb +microsoft.identitymodel.logging\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Logging.dll +microsoft.identitymodel.logging\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Logging.pdb +microsoft.identitymodel.logging\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Logging.dll +microsoft.identitymodel.logging\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Logging.pdb +microsoft.identitymodel.logging\5.3.0\microsoft.identitymodel.logging.5.3.0.nupkg +microsoft.identitymodel.logging\5.3.0\microsoft.identitymodel.logging.5.3.0.nupkg.sha512 +microsoft.identitymodel.logging\5.3.0\microsoft.identitymodel.logging.nuspec +microsoft.identitymodel.protocols.openidconnect\5.3.0\.nupkg.metadata +microsoft.identitymodel.protocols.openidconnect\5.3.0\.signature.p7s +microsoft.identitymodel.protocols.openidconnect\5.3.0\lib\net45\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll +microsoft.identitymodel.protocols.openidconnect\5.3.0\lib\net45\Microsoft.IdentityModel.Protocols.OpenIdConnect.pdb +microsoft.identitymodel.protocols.openidconnect\5.3.0\lib\net451\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll +microsoft.identitymodel.protocols.openidconnect\5.3.0\lib\net451\Microsoft.IdentityModel.Protocols.OpenIdConnect.pdb +microsoft.identitymodel.protocols.openidconnect\5.3.0\lib\net461\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll +microsoft.identitymodel.protocols.openidconnect\5.3.0\lib\net461\Microsoft.IdentityModel.Protocols.OpenIdConnect.pdb +microsoft.identitymodel.protocols.openidconnect\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll +microsoft.identitymodel.protocols.openidconnect\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Protocols.OpenIdConnect.pdb +microsoft.identitymodel.protocols.openidconnect\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll +microsoft.identitymodel.protocols.openidconnect\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Protocols.OpenIdConnect.pdb +microsoft.identitymodel.protocols.openidconnect\5.3.0\microsoft.identitymodel.protocols.openidconnect.5.3.0.nupkg +microsoft.identitymodel.protocols.openidconnect\5.3.0\microsoft.identitymodel.protocols.openidconnect.5.3.0.nupkg.sha512 +microsoft.identitymodel.protocols.openidconnect\5.3.0\microsoft.identitymodel.protocols.openidconnect.nuspec +microsoft.identitymodel.protocols.wsfederation\5.3.0\.nupkg.metadata +microsoft.identitymodel.protocols.wsfederation\5.3.0\.signature.p7s +microsoft.identitymodel.protocols.wsfederation\5.3.0\lib\net45\Microsoft.IdentityModel.Protocols.WsFederation.dll +microsoft.identitymodel.protocols.wsfederation\5.3.0\lib\net45\Microsoft.IdentityModel.Protocols.WsFederation.pdb +microsoft.identitymodel.protocols.wsfederation\5.3.0\lib\net451\Microsoft.IdentityModel.Protocols.WsFederation.dll +microsoft.identitymodel.protocols.wsfederation\5.3.0\lib\net451\Microsoft.IdentityModel.Protocols.WsFederation.pdb +microsoft.identitymodel.protocols.wsfederation\5.3.0\lib\net461\Microsoft.IdentityModel.Protocols.WsFederation.dll +microsoft.identitymodel.protocols.wsfederation\5.3.0\lib\net461\Microsoft.IdentityModel.Protocols.WsFederation.pdb +microsoft.identitymodel.protocols.wsfederation\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Protocols.WsFederation.dll +microsoft.identitymodel.protocols.wsfederation\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Protocols.WsFederation.pdb +microsoft.identitymodel.protocols.wsfederation\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Protocols.WsFederation.dll +microsoft.identitymodel.protocols.wsfederation\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Protocols.WsFederation.pdb +microsoft.identitymodel.protocols.wsfederation\5.3.0\microsoft.identitymodel.protocols.wsfederation.5.3.0.nupkg +microsoft.identitymodel.protocols.wsfederation\5.3.0\microsoft.identitymodel.protocols.wsfederation.5.3.0.nupkg.sha512 +microsoft.identitymodel.protocols.wsfederation\5.3.0\microsoft.identitymodel.protocols.wsfederation.nuspec +microsoft.identitymodel.protocols\5.3.0\.nupkg.metadata +microsoft.identitymodel.protocols\5.3.0\.signature.p7s +microsoft.identitymodel.protocols\5.3.0\lib\net45\Microsoft.IdentityModel.Protocols.dll +microsoft.identitymodel.protocols\5.3.0\lib\net45\Microsoft.IdentityModel.Protocols.pdb +microsoft.identitymodel.protocols\5.3.0\lib\net451\Microsoft.IdentityModel.Protocols.dll +microsoft.identitymodel.protocols\5.3.0\lib\net451\Microsoft.IdentityModel.Protocols.pdb +microsoft.identitymodel.protocols\5.3.0\lib\net461\Microsoft.IdentityModel.Protocols.dll +microsoft.identitymodel.protocols\5.3.0\lib\net461\Microsoft.IdentityModel.Protocols.pdb +microsoft.identitymodel.protocols\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Protocols.dll +microsoft.identitymodel.protocols\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Protocols.pdb +microsoft.identitymodel.protocols\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Protocols.dll +microsoft.identitymodel.protocols\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Protocols.pdb +microsoft.identitymodel.protocols\5.3.0\microsoft.identitymodel.protocols.5.3.0.nupkg +microsoft.identitymodel.protocols\5.3.0\microsoft.identitymodel.protocols.5.3.0.nupkg.sha512 +microsoft.identitymodel.protocols\5.3.0\microsoft.identitymodel.protocols.nuspec +microsoft.identitymodel.tokens.saml\5.3.0\.nupkg.metadata +microsoft.identitymodel.tokens.saml\5.3.0\.signature.p7s +microsoft.identitymodel.tokens.saml\5.3.0\lib\net45\Microsoft.IdentityModel.Tokens.Saml.dll +microsoft.identitymodel.tokens.saml\5.3.0\lib\net45\Microsoft.IdentityModel.Tokens.Saml.pdb +microsoft.identitymodel.tokens.saml\5.3.0\lib\net451\Microsoft.IdentityModel.Tokens.Saml.dll +microsoft.identitymodel.tokens.saml\5.3.0\lib\net451\Microsoft.IdentityModel.Tokens.Saml.pdb +microsoft.identitymodel.tokens.saml\5.3.0\lib\net461\Microsoft.IdentityModel.Tokens.Saml.dll +microsoft.identitymodel.tokens.saml\5.3.0\lib\net461\Microsoft.IdentityModel.Tokens.Saml.pdb +microsoft.identitymodel.tokens.saml\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Tokens.Saml.dll +microsoft.identitymodel.tokens.saml\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Tokens.Saml.pdb +microsoft.identitymodel.tokens.saml\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Tokens.Saml.dll +microsoft.identitymodel.tokens.saml\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Tokens.Saml.pdb +microsoft.identitymodel.tokens.saml\5.3.0\microsoft.identitymodel.tokens.saml.5.3.0.nupkg +microsoft.identitymodel.tokens.saml\5.3.0\microsoft.identitymodel.tokens.saml.5.3.0.nupkg.sha512 +microsoft.identitymodel.tokens.saml\5.3.0\microsoft.identitymodel.tokens.saml.nuspec +microsoft.identitymodel.tokens\5.3.0\.nupkg.metadata +microsoft.identitymodel.tokens\5.3.0\.signature.p7s +microsoft.identitymodel.tokens\5.3.0\lib\net45\Microsoft.IdentityModel.Tokens.dll +microsoft.identitymodel.tokens\5.3.0\lib\net45\Microsoft.IdentityModel.Tokens.pdb +microsoft.identitymodel.tokens\5.3.0\lib\net451\Microsoft.IdentityModel.Tokens.dll +microsoft.identitymodel.tokens\5.3.0\lib\net451\Microsoft.IdentityModel.Tokens.pdb +microsoft.identitymodel.tokens\5.3.0\lib\net461\Microsoft.IdentityModel.Tokens.dll +microsoft.identitymodel.tokens\5.3.0\lib\net461\Microsoft.IdentityModel.Tokens.pdb +microsoft.identitymodel.tokens\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Tokens.dll +microsoft.identitymodel.tokens\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Tokens.pdb +microsoft.identitymodel.tokens\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Tokens.dll +microsoft.identitymodel.tokens\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Tokens.pdb +microsoft.identitymodel.tokens\5.3.0\microsoft.identitymodel.tokens.5.3.0.nupkg +microsoft.identitymodel.tokens\5.3.0\microsoft.identitymodel.tokens.5.3.0.nupkg.sha512 +microsoft.identitymodel.tokens\5.3.0\microsoft.identitymodel.tokens.nuspec +microsoft.identitymodel.xml\5.3.0\.nupkg.metadata +microsoft.identitymodel.xml\5.3.0\.signature.p7s +microsoft.identitymodel.xml\5.3.0\lib\net45\Microsoft.IdentityModel.Xml.dll +microsoft.identitymodel.xml\5.3.0\lib\net45\Microsoft.IdentityModel.Xml.pdb +microsoft.identitymodel.xml\5.3.0\lib\net451\Microsoft.IdentityModel.Xml.dll +microsoft.identitymodel.xml\5.3.0\lib\net451\Microsoft.IdentityModel.Xml.pdb +microsoft.identitymodel.xml\5.3.0\lib\net461\Microsoft.IdentityModel.Xml.dll +microsoft.identitymodel.xml\5.3.0\lib\net461\Microsoft.IdentityModel.Xml.pdb +microsoft.identitymodel.xml\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Xml.dll +microsoft.identitymodel.xml\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Xml.pdb +microsoft.identitymodel.xml\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Xml.dll +microsoft.identitymodel.xml\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Xml.pdb +microsoft.identitymodel.xml\5.3.0\microsoft.identitymodel.xml.5.3.0.nupkg +microsoft.identitymodel.xml\5.3.0\microsoft.identitymodel.xml.5.3.0.nupkg.sha512 +microsoft.identitymodel.xml\5.3.0\microsoft.identitymodel.xml.nuspec +microsoft.net.http.headers\2.2.0\.nupkg.metadata +microsoft.net.http.headers\2.2.0\.signature.p7s +microsoft.net.http.headers\2.2.0\lib\netstandard2.0\Microsoft.Net.Http.Headers.dll +microsoft.net.http.headers\2.2.0\microsoft.net.http.headers.2.2.0.nupkg +microsoft.net.http.headers\2.2.0\microsoft.net.http.headers.2.2.0.nupkg.sha512 +microsoft.net.http.headers\2.2.0\microsoft.net.http.headers.nuspec +microsoft.netcore.app\2.2.0\.nupkg.metadata +microsoft.netcore.app\2.2.0\.signature.p7s +microsoft.netcore.app\2.2.0\build\netcoreapp2.2\Microsoft.NETCore.App.PlatformManifest.txt +microsoft.netcore.app\2.2.0\build\netcoreapp2.2\Microsoft.NETCore.App.props +microsoft.netcore.app\2.2.0\build\netcoreapp2.2\Microsoft.NETCore.App.targets +microsoft.netcore.app\2.2.0\LICENSE.TXT +microsoft.netcore.app\2.2.0\microsoft.netcore.app.2.2.0.nupkg +microsoft.netcore.app\2.2.0\microsoft.netcore.app.2.2.0.nupkg.sha512 +microsoft.netcore.app\2.2.0\microsoft.netcore.app.nuspec +microsoft.netcore.app\2.2.0\Microsoft.NETCore.App.versions.txt +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\Microsoft.CSharp.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\Microsoft.VisualBasic.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\Microsoft.Win32.Primitives.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\mscorlib.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\netstandard.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.AppContext.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Buffers.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Collections.Concurrent.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Collections.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Collections.Immutable.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Collections.NonGeneric.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Collections.Specialized.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.ComponentModel.Annotations.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.ComponentModel.DataAnnotations.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.ComponentModel.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.ComponentModel.EventBasedAsync.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.ComponentModel.Primitives.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.ComponentModel.TypeConverter.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Configuration.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Console.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Core.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Data.Common.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Data.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Diagnostics.Contracts.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Diagnostics.Debug.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Diagnostics.DiagnosticSource.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Diagnostics.FileVersionInfo.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Diagnostics.Process.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Diagnostics.StackTrace.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Diagnostics.TextWriterTraceListener.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Diagnostics.Tools.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Diagnostics.TraceSource.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Diagnostics.Tracing.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Drawing.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Drawing.Primitives.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Dynamic.Runtime.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Globalization.Calendars.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Globalization.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Globalization.Extensions.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.Compression.Brotli.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.Compression.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.Compression.FileSystem.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.Compression.ZipFile.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.FileSystem.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.FileSystem.DriveInfo.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.FileSystem.Primitives.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.FileSystem.Watcher.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.IsolatedStorage.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.MemoryMappedFiles.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.Pipes.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.UnmanagedMemoryStream.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Linq.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Linq.Expressions.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Linq.Parallel.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Linq.Queryable.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Memory.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.Http.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.HttpListener.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.Mail.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.NameResolution.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.NetworkInformation.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.Ping.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.Primitives.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.Requests.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.Security.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.ServicePoint.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.Sockets.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.WebClient.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.WebHeaderCollection.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.WebProxy.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.WebSockets.Client.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.WebSockets.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Numerics.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Numerics.Vectors.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.ObjectModel.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Reflection.DispatchProxy.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Reflection.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Reflection.Emit.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Reflection.Emit.ILGeneration.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Reflection.Emit.Lightweight.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Reflection.Extensions.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Reflection.Metadata.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Reflection.Primitives.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Reflection.TypeExtensions.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Resources.Reader.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Resources.ResourceManager.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Resources.Writer.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.CompilerServices.VisualC.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.Extensions.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.Handles.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.InteropServices.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.InteropServices.RuntimeInformation.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.InteropServices.WindowsRuntime.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.Loader.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.Numerics.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.Serialization.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.Serialization.Formatters.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.Serialization.Json.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.Serialization.Primitives.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.Serialization.Xml.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Security.Claims.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Security.Cryptography.Algorithms.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Security.Cryptography.Csp.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Security.Cryptography.Encoding.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Security.Cryptography.Primitives.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Security.Cryptography.X509Certificates.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Security.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Security.Principal.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Security.SecureString.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.ServiceModel.Web.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.ServiceProcess.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Text.Encoding.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Text.Encoding.Extensions.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Text.RegularExpressions.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Threading.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Threading.Overlapped.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Threading.Tasks.Dataflow.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Threading.Tasks.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Threading.Tasks.Extensions.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Threading.Tasks.Parallel.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Threading.Thread.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Threading.ThreadPool.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Threading.Timer.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Transactions.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Transactions.Local.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.ValueTuple.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Web.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Web.HttpUtility.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Windows.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Xml.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Xml.Linq.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Xml.ReaderWriter.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Xml.Serialization.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Xml.XDocument.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Xml.XmlDocument.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Xml.XmlSerializer.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Xml.XPath.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Xml.XPath.XDocument.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\WindowsBase.dll +microsoft.netcore.app\2.2.0\runtime.json +microsoft.netcore.app\2.2.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.dotnetapphost\2.2.0\.nupkg.metadata +microsoft.netcore.dotnetapphost\2.2.0\.signature.p7s +microsoft.netcore.dotnetapphost\2.2.0\LICENSE.TXT +microsoft.netcore.dotnetapphost\2.2.0\microsoft.netcore.dotnetapphost.2.2.0.nupkg +microsoft.netcore.dotnetapphost\2.2.0\microsoft.netcore.dotnetapphost.2.2.0.nupkg.sha512 +microsoft.netcore.dotnetapphost\2.2.0\microsoft.netcore.dotnetapphost.nuspec +microsoft.netcore.dotnetapphost\2.2.0\runtime.json +microsoft.netcore.dotnetapphost\2.2.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.dotnethostpolicy\2.2.0\.nupkg.metadata +microsoft.netcore.dotnethostpolicy\2.2.0\.signature.p7s +microsoft.netcore.dotnethostpolicy\2.2.0\LICENSE.TXT +microsoft.netcore.dotnethostpolicy\2.2.0\microsoft.netcore.dotnethostpolicy.2.2.0.nupkg +microsoft.netcore.dotnethostpolicy\2.2.0\microsoft.netcore.dotnethostpolicy.2.2.0.nupkg.sha512 +microsoft.netcore.dotnethostpolicy\2.2.0\microsoft.netcore.dotnethostpolicy.nuspec +microsoft.netcore.dotnethostpolicy\2.2.0\runtime.json +microsoft.netcore.dotnethostpolicy\2.2.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.dotnethostresolver\2.2.0\.nupkg.metadata +microsoft.netcore.dotnethostresolver\2.2.0\.signature.p7s +microsoft.netcore.dotnethostresolver\2.2.0\LICENSE.TXT +microsoft.netcore.dotnethostresolver\2.2.0\microsoft.netcore.dotnethostresolver.2.2.0.nupkg +microsoft.netcore.dotnethostresolver\2.2.0\microsoft.netcore.dotnethostresolver.2.2.0.nupkg.sha512 +microsoft.netcore.dotnethostresolver\2.2.0\microsoft.netcore.dotnethostresolver.nuspec +microsoft.netcore.dotnethostresolver\2.2.0\runtime.json +microsoft.netcore.dotnethostresolver\2.2.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.platforms\1.0.1\.nupkg.metadata +microsoft.netcore.platforms\1.0.1\.signature.p7s +microsoft.netcore.platforms\1.0.2\.nupkg.metadata +microsoft.netcore.platforms\1.0.2\.signature.p7s +microsoft.netcore.platforms\1.1.0\.nupkg.metadata +microsoft.netcore.platforms\1.1.0\.signature.p7s +microsoft.netcore.platforms\2.0.0\.nupkg.metadata +microsoft.netcore.platforms\2.0.0\.signature.p7s +microsoft.netcore.platforms\2.2.0\.nupkg.metadata +microsoft.netcore.platforms\2.2.0\.signature.p7s +microsoft.netcore.platforms\2.2.0\lib\netstandard1.0\_._ +microsoft.netcore.platforms\2.2.0\LICENSE.TXT +microsoft.netcore.platforms\2.2.0\microsoft.netcore.platforms.2.2.0.nupkg +microsoft.netcore.platforms\2.2.0\microsoft.netcore.platforms.2.2.0.nupkg.sha512 +microsoft.netcore.platforms\2.2.0\microsoft.netcore.platforms.nuspec +microsoft.netcore.platforms\2.2.0\runtime.json +microsoft.netcore.platforms\2.2.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.platforms\2.2.0\useSharedDesignerContext.txt +microsoft.netcore.platforms\2.2.0\version.txt +microsoft.netcore.targets\1.0.1\.nupkg.metadata +microsoft.netcore.targets\1.1.0\.nupkg.metadata +microsoft.netcore.targets\2.0.0\.nupkg.metadata +microsoft.rest.clientruntime.azure\3.3.7\.nupkg.metadata +microsoft.rest.clientruntime.azure\3.3.7\.signature.p7s +microsoft.rest.clientruntime\2.3.8\.nupkg.metadata +microsoft.rest.clientruntime\2.3.8\.signature.p7s +microsoft.visualstudio.web.browserlink\2.2.0\.nupkg.metadata +microsoft.visualstudio.web.browserlink\2.2.0\.signature.p7s +microsoft.visualstudio.web.browserlink\2.2.0\lib\netstandard2.0\Microsoft.VisualStudio.Web.BrowserLink.dll +microsoft.visualstudio.web.browserlink\2.2.0\microsoft.visualstudio.web.browserlink.2.2.0.nupkg +microsoft.visualstudio.web.browserlink\2.2.0\microsoft.visualstudio.web.browserlink.2.2.0.nupkg.sha512 +microsoft.visualstudio.web.browserlink\2.2.0\microsoft.visualstudio.web.browserlink.nuspec +microsoft.win32.primitives\4.0.1\.nupkg.metadata +microsoft.win32.primitives\4.3.0\.nupkg.metadata +microsoft.win32.registry\4.3.0\.nupkg.metadata +microsoft.win32.registry\4.5.0\.nupkg.metadata +netstandard.library\1.6.0\.nupkg.metadata +netstandard.library\1.6.1\.nupkg.metadata +netstandard.library\2.0.3\.nupkg.metadata +newtonsoft.json.bson\1.0.1\.nupkg.metadata +newtonsoft.json.bson\1.0.1\.signature.p7s +newtonsoft.json\10.0.1\.nupkg.metadata +newtonsoft.json\10.0.1\.signature.p7s +newtonsoft.json\11.0.2\.nupkg.metadata +newtonsoft.json\11.0.2\.signature.p7s +newtonsoft.json\9.0.1\.nupkg.metadata +remotion.linq\2.2.0\.nupkg.metadata +remotion.linq\2.2.0\.signature.p7s +runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.native.system.data.sqlclient.sni\4.5.0\.nupkg.metadata +runtime.native.system.data.sqlclient.sni\4.5.0\.signature.p7s +runtime.native.system.data.sqlclient.sni\4.5.0\LICENSE.TXT +runtime.native.system.data.sqlclient.sni\4.5.0\runtime.native.system.data.sqlclient.sni.4.5.0.nupkg +runtime.native.system.data.sqlclient.sni\4.5.0\runtime.native.system.data.sqlclient.sni.4.5.0.nupkg.sha512 +runtime.native.system.data.sqlclient.sni\4.5.0\runtime.native.system.data.sqlclient.sni.nuspec +runtime.native.system.data.sqlclient.sni\4.5.0\THIRD-PARTY-NOTICES.TXT +runtime.native.system.data.sqlclient.sni\4.5.0\useSharedDesignerContext.txt +runtime.native.system.data.sqlclient.sni\4.5.0\version.txt +runtime.native.system.io.compression\4.1.0\.nupkg.metadata +runtime.native.system.io.compression\4.3.0\.nupkg.metadata +runtime.native.system.net.http\4.0.1\.nupkg.metadata +runtime.native.system.net.http\4.3.0\.nupkg.metadata +runtime.native.system.net.security\4.3.0\.nupkg.metadata +runtime.native.system.security.cryptography.apple\4.3.0\.nupkg.metadata +runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.native.system.security.cryptography\4.0.0\.nupkg.metadata +runtime.native.system\4.0.0\.nupkg.metadata +runtime.native.system\4.3.0\.nupkg.metadata +runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple\4.3.0\.nupkg.metadata +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.win-arm64.runtime.native.system.data.sqlclient.sni\4.4.0\.nupkg.metadata +runtime.win-x64.runtime.native.system.data.sqlclient.sni\4.4.0\.nupkg.metadata +runtime.win-x86.runtime.native.system.data.sqlclient.sni\4.4.0\.nupkg.metadata +sqlitepclraw.bundle_green\1.1.11\.nupkg.metadata +sqlitepclraw.bundle_green\1.1.11\.signature.p7s +sqlitepclraw.core\1.1.11\.nupkg.metadata +sqlitepclraw.core\1.1.11\.signature.p7s +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\.nupkg.metadata +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\.signature.p7s +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\.nupkg.metadata +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\.signature.p7s +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\.nupkg.metadata +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\.signature.p7s +sqlitepclraw.provider.e_sqlite3.netstandard11\1.1.11\.nupkg.metadata +sqlitepclraw.provider.e_sqlite3.netstandard11\1.1.11\.signature.p7s +stackexchange.redis.strongname\1.2.6\.nupkg.metadata +stackexchange.redis.strongname\1.2.6\.signature.p7s +stackexchange.redis.strongname\1.2.6\lib\net45\StackExchange.Redis.StrongName.dll +stackexchange.redis.strongname\1.2.6\lib\net46\StackExchange.Redis.StrongName.dll +stackexchange.redis.strongname\1.2.6\lib\netstandard1.5\StackExchange.Redis.StrongName.dll +stackexchange.redis.strongname\1.2.6\stackexchange.redis.strongname.1.2.6.nupkg +stackexchange.redis.strongname\1.2.6\stackexchange.redis.strongname.1.2.6.nupkg.sha512 +stackexchange.redis.strongname\1.2.6\stackexchange.redis.strongname.nuspec +system.appcontext\4.1.0\.nupkg.metadata +system.appcontext\4.3.0\.nupkg.metadata +system.buffers\4.0.0\.nupkg.metadata +system.buffers\4.3.0\.nupkg.metadata +system.buffers\4.5.0\.nupkg.metadata +system.collections.concurrent\4.0.12\.nupkg.metadata +system.collections.concurrent\4.3.0\.nupkg.metadata +system.collections.immutable\1.3.0\.nupkg.metadata +system.collections.immutable\1.3.1\.nupkg.metadata +system.collections.immutable\1.5.0\.nupkg.metadata +system.collections.nongeneric\4.3.0\.nupkg.metadata +system.collections.nongeneric\4.3.0\.signature.p7s +system.collections.specialized\4.3.0\.nupkg.metadata +system.collections\4.0.11\.nupkg.metadata +system.collections\4.3.0\.nupkg.metadata +system.componentmodel.annotations\4.5.0\.nupkg.metadata +system.componentmodel.primitives\4.3.0\.nupkg.metadata +system.componentmodel.typeconverter\4.3.0\.nupkg.metadata +system.componentmodel\4.3.0\.nupkg.metadata +system.console\4.0.0\.nupkg.metadata +system.console\4.3.0\.nupkg.metadata +system.data.sqlclient\4.6.0\.nupkg.metadata +system.data.sqlclient\4.6.0\.signature.p7s +system.data.sqlclient\4.6.0\lib\MonoAndroid10\_._ +system.data.sqlclient\4.6.0\lib\MonoTouch10\_._ +system.data.sqlclient\4.6.0\lib\net451\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\lib\net46\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\lib\net461\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\lib\netcoreapp2.1\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\lib\netstandard1.2\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\lib\netstandard1.3\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\lib\netstandard2.0\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\lib\xamarinios10\_._ +system.data.sqlclient\4.6.0\lib\xamarinmac20\_._ +system.data.sqlclient\4.6.0\lib\xamarintvos10\_._ +system.data.sqlclient\4.6.0\lib\xamarinwatchos10\_._ +system.data.sqlclient\4.6.0\LICENSE.TXT +system.data.sqlclient\4.6.0\ref\MonoAndroid10\_._ +system.data.sqlclient\4.6.0\ref\MonoTouch10\_._ +system.data.sqlclient\4.6.0\ref\net451\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\ref\net46\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\ref\net461\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\ref\netcoreapp2.1\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\ref\netstandard1.2\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\ref\netstandard1.3\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\ref\netstandard2.0\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\ref\xamarinios10\_._ +system.data.sqlclient\4.6.0\ref\xamarinmac20\_._ +system.data.sqlclient\4.6.0\ref\xamarintvos10\_._ +system.data.sqlclient\4.6.0\ref\xamarinwatchos10\_._ +system.data.sqlclient\4.6.0\runtimes\unix\lib\netcoreapp2.1\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\runtimes\unix\lib\netstandard1.3\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\runtimes\unix\lib\netstandard2.0\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\runtimes\win\lib\net451\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\runtimes\win\lib\net46\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\runtimes\win\lib\net461\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\runtimes\win\lib\netcoreapp2.1\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\runtimes\win\lib\netstandard1.3\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\runtimes\win\lib\netstandard2.0\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\runtimes\win\lib\uap10.0.16299\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\system.data.sqlclient.4.6.0.nupkg +system.data.sqlclient\4.6.0\system.data.sqlclient.4.6.0.nupkg.sha512 +system.data.sqlclient\4.6.0\system.data.sqlclient.nuspec +system.data.sqlclient\4.6.0\THIRD-PARTY-NOTICES.TXT +system.data.sqlclient\4.6.0\useSharedDesignerContext.txt +system.data.sqlclient\4.6.0\version.txt +system.diagnostics.contracts\4.3.0\.nupkg.metadata +system.diagnostics.contracts\4.3.0\.signature.p7s +system.diagnostics.debug\4.0.11\.nupkg.metadata +system.diagnostics.debug\4.3.0\.nupkg.metadata +system.diagnostics.diagnosticsource\4.0.0\.nupkg.metadata +system.diagnostics.diagnosticsource\4.3.0\.nupkg.metadata +system.diagnostics.diagnosticsource\4.4.0\.nupkg.metadata +system.diagnostics.diagnosticsource\4.4.0\.signature.p7s +system.diagnostics.diagnosticsource\4.5.0\.nupkg.metadata +system.diagnostics.fileversioninfo\4.3.0\.nupkg.metadata +system.diagnostics.fileversioninfo\4.3.0\.signature.p7s +system.diagnostics.process\4.3.0\.nupkg.metadata +system.diagnostics.stacktrace\4.3.0\.nupkg.metadata +system.diagnostics.tools\4.0.1\.nupkg.metadata +system.diagnostics.tools\4.3.0\.nupkg.metadata +system.diagnostics.tracing\4.1.0\.nupkg.metadata +system.diagnostics.tracing\4.3.0\.nupkg.metadata +system.dynamic.runtime\4.0.11\.nupkg.metadata +system.dynamic.runtime\4.3.0\.nupkg.metadata +system.globalization.calendars\4.0.1\.nupkg.metadata +system.globalization.calendars\4.3.0\.nupkg.metadata +system.globalization.extensions\4.0.1\.nupkg.metadata +system.globalization.extensions\4.3.0\.nupkg.metadata +system.globalization\4.0.11\.nupkg.metadata +system.globalization\4.3.0\.nupkg.metadata +system.identitymodel.tokens.jwt\5.3.0\.nupkg.metadata +system.identitymodel.tokens.jwt\5.3.0\.signature.p7s +system.identitymodel.tokens.jwt\5.3.0\lib\net45\System.IdentityModel.Tokens.Jwt.dll +system.identitymodel.tokens.jwt\5.3.0\lib\net45\System.IdentityModel.Tokens.Jwt.pdb +system.identitymodel.tokens.jwt\5.3.0\lib\net451\System.IdentityModel.Tokens.Jwt.dll +system.identitymodel.tokens.jwt\5.3.0\lib\net451\System.IdentityModel.Tokens.Jwt.pdb +system.identitymodel.tokens.jwt\5.3.0\lib\net461\System.IdentityModel.Tokens.Jwt.dll +system.identitymodel.tokens.jwt\5.3.0\lib\net461\System.IdentityModel.Tokens.Jwt.pdb +system.identitymodel.tokens.jwt\5.3.0\lib\netstandard1.4\System.IdentityModel.Tokens.Jwt.dll +system.identitymodel.tokens.jwt\5.3.0\lib\netstandard1.4\System.IdentityModel.Tokens.Jwt.pdb +system.identitymodel.tokens.jwt\5.3.0\lib\netstandard2.0\System.IdentityModel.Tokens.Jwt.dll +system.identitymodel.tokens.jwt\5.3.0\lib\netstandard2.0\System.IdentityModel.Tokens.Jwt.pdb +system.identitymodel.tokens.jwt\5.3.0\system.identitymodel.tokens.jwt.5.3.0.nupkg +system.identitymodel.tokens.jwt\5.3.0\system.identitymodel.tokens.jwt.5.3.0.nupkg.sha512 +system.identitymodel.tokens.jwt\5.3.0\system.identitymodel.tokens.jwt.nuspec +system.interactive.async\3.2.0\.nupkg.metadata +system.interactive.async\3.2.0\.signature.p7s +system.interactive.async\3.2.0\lib\net45\System.Interactive.Async.dll +system.interactive.async\3.2.0\lib\net46\System.Interactive.Async.dll +system.interactive.async\3.2.0\lib\netstandard1.0\System.Interactive.Async.dll +system.interactive.async\3.2.0\lib\netstandard1.3\System.Interactive.Async.dll +system.interactive.async\3.2.0\lib\netstandard2.0\System.Interactive.Async.dll +system.interactive.async\3.2.0\system.interactive.async.3.2.0.nupkg +system.interactive.async\3.2.0\system.interactive.async.3.2.0.nupkg.sha512 +system.interactive.async\3.2.0\system.interactive.async.nuspec +system.io.compression.zipfile\4.0.1\.nupkg.metadata +system.io.compression.zipfile\4.3.0\.nupkg.metadata +system.io.compression\4.1.0\.nupkg.metadata +system.io.compression\4.3.0\.nupkg.metadata +system.io.filesystem.primitives\4.0.1\.nupkg.metadata +system.io.filesystem.primitives\4.3.0\.nupkg.metadata +system.io.filesystem\4.0.1\.nupkg.metadata +system.io.filesystem\4.3.0\.nupkg.metadata +system.io.pipelines\4.5.2\.nupkg.metadata +system.io.pipelines\4.5.2\.signature.p7s +system.io.pipelines\4.5.2\lib\netcoreapp2.1\System.IO.Pipelines.dll +system.io.pipelines\4.5.2\lib\netstandard1.3\System.IO.Pipelines.dll +system.io.pipelines\4.5.2\lib\netstandard2.0\System.IO.Pipelines.dll +system.io.pipelines\4.5.2\LICENSE.TXT +system.io.pipelines\4.5.2\ref\netstandard1.3\System.IO.Pipelines.dll +system.io.pipelines\4.5.2\system.io.pipelines.4.5.2.nupkg +system.io.pipelines\4.5.2\system.io.pipelines.4.5.2.nupkg.sha512 +system.io.pipelines\4.5.2\system.io.pipelines.nuspec +system.io.pipelines\4.5.2\THIRD-PARTY-NOTICES.TXT +system.io.pipelines\4.5.2\useSharedDesignerContext.txt +system.io.pipelines\4.5.2\version.txt +system.io\4.1.0\.nupkg.metadata +system.io\4.3.0\.nupkg.metadata +system.linq.expressions\4.1.0\.nupkg.metadata +system.linq.expressions\4.3.0\.nupkg.metadata +system.linq.queryable\4.0.1\.nupkg.metadata +system.linq\4.1.0\.nupkg.metadata +system.linq\4.3.0\.nupkg.metadata +system.memory\4.5.1\.nupkg.metadata +system.net.http\4.1.0\.nupkg.metadata +system.net.http\4.1.0\.signature.p7s +system.net.http\4.3.0\.nupkg.metadata +system.net.http\4.3.0\.signature.p7s +system.net.nameresolution\4.3.0\.nupkg.metadata +system.net.primitives\4.0.11\.nupkg.metadata +system.net.primitives\4.3.0\.nupkg.metadata +system.net.security\4.3.0\.nupkg.metadata +system.net.sockets\4.1.0\.nupkg.metadata +system.net.sockets\4.3.0\.nupkg.metadata +system.net.websockets.websocketprotocol\4.5.1\.nupkg.metadata +system.numerics.vectors\4.5.0\.nupkg.metadata +system.objectmodel\4.0.12\.nupkg.metadata +system.objectmodel\4.3.0\.nupkg.metadata +system.private.datacontractserialization\4.1.1\.nupkg.metadata +system.private.datacontractserialization\4.3.0\.nupkg.metadata +system.private.datacontractserialization\4.3.0\.signature.p7s +system.reflection.emit.ilgeneration\4.0.1\.nupkg.metadata +system.reflection.emit.ilgeneration\4.3.0\.nupkg.metadata +system.reflection.emit.lightweight\4.0.1\.nupkg.metadata +system.reflection.emit.lightweight\4.3.0\.nupkg.metadata +system.reflection.emit\4.0.1\.nupkg.metadata +system.reflection.emit\4.3.0\.nupkg.metadata +system.reflection.extensions\4.0.1\.nupkg.metadata +system.reflection.extensions\4.3.0\.nupkg.metadata +system.reflection.metadata\1.4.1\.nupkg.metadata +system.reflection.metadata\1.4.2\.nupkg.metadata +system.reflection.metadata\1.6.0\.nupkg.metadata +system.reflection.primitives\4.0.1\.nupkg.metadata +system.reflection.primitives\4.3.0\.nupkg.metadata +system.reflection.typeextensions\4.1.0\.nupkg.metadata +system.reflection.typeextensions\4.3.0\.nupkg.metadata +system.reflection\4.1.0\.nupkg.metadata +system.reflection\4.3.0\.nupkg.metadata +system.resources.resourcemanager\4.0.1\.nupkg.metadata +system.resources.resourcemanager\4.3.0\.nupkg.metadata +system.runtime.compilerservices.unsafe\4.5.0\.nupkg.metadata +system.runtime.compilerservices.unsafe\4.5.1\.nupkg.metadata +system.runtime.extensions\4.1.0\.nupkg.metadata +system.runtime.extensions\4.3.0\.nupkg.metadata +system.runtime.handles\4.0.1\.nupkg.metadata +system.runtime.handles\4.3.0\.nupkg.metadata +system.runtime.interopservices.runtimeinformation\4.0.0\.nupkg.metadata +system.runtime.interopservices.runtimeinformation\4.3.0\.nupkg.metadata +system.runtime.interopservices\4.1.0\.nupkg.metadata +system.runtime.interopservices\4.3.0\.nupkg.metadata +system.runtime.numerics\4.0.1\.nupkg.metadata +system.runtime.numerics\4.3.0\.nupkg.metadata +system.runtime.serialization.formatters\4.3.0\.nupkg.metadata +system.runtime.serialization.json\4.0.2\.nupkg.metadata +system.runtime.serialization.json\4.3.0\.nupkg.metadata +system.runtime.serialization.json\4.3.0\dotnet_library_license.txt +system.runtime.serialization.json\4.3.0\lib\MonoAndroid10\_._ +system.runtime.serialization.json\4.3.0\lib\MonoTouch10\_._ +system.runtime.serialization.json\4.3.0\lib\net45\_._ +system.runtime.serialization.json\4.3.0\lib\netcore50\System.Runtime.Serialization.Json.dll +system.runtime.serialization.json\4.3.0\lib\netstandard1.3\System.Runtime.Serialization.Json.dll +system.runtime.serialization.json\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.runtime.serialization.json\4.3.0\lib\win8\_._ +system.runtime.serialization.json\4.3.0\lib\wp80\_._ +system.runtime.serialization.json\4.3.0\lib\wpa81\_._ +system.runtime.serialization.json\4.3.0\lib\xamarinios10\_._ +system.runtime.serialization.json\4.3.0\lib\xamarinmac20\_._ +system.runtime.serialization.json\4.3.0\lib\xamarintvos10\_._ +system.runtime.serialization.json\4.3.0\lib\xamarinwatchos10\_._ +system.runtime.serialization.json\4.3.0\ref\MonoAndroid10\_._ +system.runtime.serialization.json\4.3.0\ref\MonoTouch10\_._ +system.runtime.serialization.json\4.3.0\ref\net45\_._ +system.runtime.serialization.json\4.3.0\ref\netcore50\System.Runtime.Serialization.Json.dll +system.runtime.serialization.json\4.3.0\ref\netstandard1.0\System.Runtime.Serialization.Json.dll +system.runtime.serialization.json\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.runtime.serialization.json\4.3.0\ref\win8\_._ +system.runtime.serialization.json\4.3.0\ref\wp80\_._ +system.runtime.serialization.json\4.3.0\ref\wpa81\_._ +system.runtime.serialization.json\4.3.0\ref\xamarinios10\_._ +system.runtime.serialization.json\4.3.0\ref\xamarinmac20\_._ +system.runtime.serialization.json\4.3.0\ref\xamarintvos10\_._ +system.runtime.serialization.json\4.3.0\ref\xamarinwatchos10\_._ +system.runtime.serialization.json\4.3.0\system.runtime.serialization.json.4.3.0.nupkg +system.runtime.serialization.json\4.3.0\system.runtime.serialization.json.4.3.0.nupkg.sha512 +system.runtime.serialization.json\4.3.0\system.runtime.serialization.json.nuspec +system.runtime.serialization.json\4.3.0\ThirdPartyNotices.txt +system.runtime.serialization.primitives\4.1.1\.nupkg.metadata +system.runtime.serialization.primitives\4.3.0\.nupkg.metadata +system.runtime.serialization.xml\4.3.0\.nupkg.metadata +system.runtime.serialization.xml\4.3.0\.signature.p7s +system.runtime\4.1.0\.nupkg.metadata +system.runtime\4.3.0\.nupkg.metadata +system.security.accesscontrol\4.5.0\.nupkg.metadata +system.security.claims\4.3.0\.nupkg.metadata +system.security.cryptography.algorithms\4.2.0\.nupkg.metadata +system.security.cryptography.algorithms\4.3.0\.nupkg.metadata +system.security.cryptography.cng\4.2.0\.nupkg.metadata +system.security.cryptography.cng\4.3.0\.nupkg.metadata +system.security.cryptography.cng\4.5.0\.nupkg.metadata +system.security.cryptography.csp\4.0.0\.nupkg.metadata +system.security.cryptography.csp\4.3.0\.nupkg.metadata +system.security.cryptography.encoding\4.0.0\.nupkg.metadata +system.security.cryptography.encoding\4.3.0\.nupkg.metadata +system.security.cryptography.openssl\4.0.0\.nupkg.metadata +system.security.cryptography.openssl\4.3.0\.nupkg.metadata +system.security.cryptography.pkcs\4.5.0\.nupkg.metadata +system.security.cryptography.primitives\4.0.0\.nupkg.metadata +system.security.cryptography.primitives\4.3.0\.nupkg.metadata +system.security.cryptography.x509certificates\4.1.0\.nupkg.metadata +system.security.cryptography.x509certificates\4.3.0\.nupkg.metadata +system.security.cryptography.xml\4.5.0\.nupkg.metadata +system.security.permissions\4.5.0\.nupkg.metadata +system.security.principal.windows\4.3.0\.nupkg.metadata +system.security.principal.windows\4.5.0\.nupkg.metadata +system.security.principal\4.3.0\.nupkg.metadata +system.spatial\5.8.2\.nupkg.metadata +system.text.encoding.codepages\4.3.0\.nupkg.metadata +system.text.encoding.codepages\4.5.0\.nupkg.metadata +system.text.encoding.extensions\4.0.11\.nupkg.metadata +system.text.encoding.extensions\4.3.0\.nupkg.metadata +system.text.encoding\4.0.11\.nupkg.metadata +system.text.encoding\4.3.0\.nupkg.metadata +system.text.encodings.web\4.3.1\.nupkg.metadata +system.text.encodings.web\4.3.1\.signature.p7s +system.text.encodings.web\4.5.0\.nupkg.metadata +system.text.regularexpressions\4.1.0\.nupkg.metadata +system.text.regularexpressions\4.3.0\.nupkg.metadata +system.threading.channels\4.5.0\.nupkg.metadata +system.threading.tasks.extensions\4.0.0\.nupkg.metadata +system.threading.tasks.extensions\4.3.0\.nupkg.metadata +system.threading.tasks.extensions\4.5.1\.nupkg.metadata +system.threading.tasks.parallel\4.3.0\.nupkg.metadata +system.threading.tasks.parallel\4.3.0\.signature.p7s +system.threading.tasks\4.0.11\.nupkg.metadata +system.threading.tasks\4.3.0\.nupkg.metadata +system.threading.thread\4.3.0\.nupkg.metadata +system.threading.threadpool\4.3.0\.nupkg.metadata +system.threading.timer\4.0.1\.nupkg.metadata +system.threading.timer\4.3.0\.nupkg.metadata +system.threading\4.0.11\.nupkg.metadata +system.threading\4.3.0\.nupkg.metadata +system.valuetuple\4.3.0\.nupkg.metadata +system.valuetuple\4.5.0\.nupkg.metadata +system.xml.readerwriter\4.0.11\.nupkg.metadata +system.xml.readerwriter\4.3.0\.nupkg.metadata +system.xml.xdocument\4.0.11\.nupkg.metadata +system.xml.xdocument\4.3.0\.nupkg.metadata +system.xml.xmldocument\4.0.1\.nupkg.metadata +system.xml.xmldocument\4.3.0\.nupkg.metadata +system.xml.xmldocument\4.3.0\.signature.p7s +system.xml.xmlserializer\4.0.11\.nupkg.metadata +system.xml.xmlserializer\4.3.0\.nupkg.metadata +system.xml.xmlserializer\4.3.0\.signature.p7s +system.xml.xpath.xdocument\4.3.0\.nupkg.metadata +system.xml.xpath\4.3.0\.nupkg.metadata +system.xml.xpath\4.3.0\.signature.p7s +windowsazure.storage\8.1.4\.nupkg.metadata +windowsazure.storage\8.1.4\.signature.p7s diff --git a/src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.2.0.txt b/src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.2.0.txt new file mode 100644 index 0000000000..7579756141 --- /dev/null +++ b/src/PackageArchive/Archive.CiServer.Patch/ArchiveBaseline.2.2.0.txt @@ -0,0 +1,1629 @@ +libuv\1.10.0\.nupkg.metadata +libuv\1.10.0\.signature.p7s +messagepack\1.7.3.4\.nupkg.metadata +messagepack\1.7.3.4\.signature.p7s +microsoft.applicationinsights.aspnetcore\2.1.1\.nupkg.metadata +microsoft.applicationinsights.aspnetcore\2.1.1\.signature.p7s +microsoft.applicationinsights.dependencycollector\2.4.1\.nupkg.metadata +microsoft.applicationinsights.dependencycollector\2.4.1\.signature.p7s +microsoft.applicationinsights\2.4.0\.nupkg.metadata +microsoft.applicationinsights\2.4.0\.signature.p7s +microsoft.aspnet.webapi.client\5.2.6\.nupkg.metadata +microsoft.aspnetcore.all\2.2.0\.nupkg.metadata +microsoft.aspnetcore.all\2.2.0\.signature.p7s +microsoft.aspnetcore.all\2.2.0\build\netcoreapp2.2\Microsoft.AspNetCore.All.props +microsoft.aspnetcore.all\2.2.0\build\netcoreapp2.2\Microsoft.AspNetCore.All.targets +microsoft.aspnetcore.all\2.2.0\lib\netcoreapp2.2\_._ +microsoft.aspnetcore.all\2.2.0\microsoft.aspnetcore.all.2.2.0.nupkg.sha512 +microsoft.aspnetcore.all\2.2.0\microsoft.aspnetcore.all.nuspec +microsoft.aspnetcore.antiforgery\2.2.0\.nupkg.metadata +microsoft.aspnetcore.antiforgery\2.2.0\.signature.p7s +microsoft.aspnetcore.antiforgery\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Antiforgery.dll +microsoft.aspnetcore.antiforgery\2.2.0\microsoft.aspnetcore.antiforgery.2.2.0.nupkg.sha512 +microsoft.aspnetcore.antiforgery\2.2.0\microsoft.aspnetcore.antiforgery.nuspec +microsoft.aspnetcore.app\2.2.0\.nupkg.metadata +microsoft.aspnetcore.app\2.2.0\.signature.p7s +microsoft.aspnetcore.app\2.2.0\build\netcoreapp2.2\Microsoft.AspNetCore.App.props +microsoft.aspnetcore.app\2.2.0\build\netcoreapp2.2\Microsoft.AspNetCore.App.targets +microsoft.aspnetcore.app\2.2.0\lib\netcoreapp2.2\_._ +microsoft.aspnetcore.app\2.2.0\microsoft.aspnetcore.app.2.2.0.nupkg.sha512 +microsoft.aspnetcore.app\2.2.0\microsoft.aspnetcore.app.nuspec +microsoft.aspnetcore.applicationinsights.hostingstartup\2.2.0\.nupkg.metadata +microsoft.aspnetcore.applicationinsights.hostingstartup\2.2.0\.signature.p7s +microsoft.aspnetcore.applicationinsights.hostingstartup\2.2.0\lib\net461\Microsoft.AspNetCore.ApplicationInsights.HostingStartup.dll +microsoft.aspnetcore.applicationinsights.hostingstartup\2.2.0\lib\netcoreapp2.0\Microsoft.AspNetCore.ApplicationInsights.HostingStartup.dll +microsoft.aspnetcore.applicationinsights.hostingstartup\2.2.0\lib\netcoreapp2.1\Microsoft.AspNetCore.ApplicationInsights.HostingStartup.dll +microsoft.aspnetcore.applicationinsights.hostingstartup\2.2.0\microsoft.aspnetcore.applicationinsights.hostingstartup.2.2.0.nupkg.sha512 +microsoft.aspnetcore.applicationinsights.hostingstartup\2.2.0\microsoft.aspnetcore.applicationinsights.hostingstartup.nuspec +microsoft.aspnetcore.authentication.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Abstractions.dll +microsoft.aspnetcore.authentication.abstractions\2.2.0\microsoft.aspnetcore.authentication.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.abstractions\2.2.0\microsoft.aspnetcore.authentication.abstractions.nuspec +microsoft.aspnetcore.authentication.azuread.ui\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.azuread.ui\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.azuread.ui\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.AzureAD.UI.dll +microsoft.aspnetcore.authentication.azuread.ui\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.AzureAD.UI.Views.dll +microsoft.aspnetcore.authentication.azuread.ui\2.2.0\microsoft.aspnetcore.authentication.azuread.ui.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.azuread.ui\2.2.0\microsoft.aspnetcore.authentication.azuread.ui.nuspec +microsoft.aspnetcore.authentication.azureadb2c.ui\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.azureadb2c.ui\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.azureadb2c.ui\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.AzureADB2C.UI.dll +microsoft.aspnetcore.authentication.azureadb2c.ui\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.AzureADB2C.UI.Views.dll +microsoft.aspnetcore.authentication.azureadb2c.ui\2.2.0\microsoft.aspnetcore.authentication.azureadb2c.ui.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.azureadb2c.ui\2.2.0\microsoft.aspnetcore.authentication.azureadb2c.ui.nuspec +microsoft.aspnetcore.authentication.cookies\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.cookies\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.cookies\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Cookies.dll +microsoft.aspnetcore.authentication.cookies\2.2.0\microsoft.aspnetcore.authentication.cookies.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.cookies\2.2.0\microsoft.aspnetcore.authentication.cookies.nuspec +microsoft.aspnetcore.authentication.core\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.core\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.core\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Core.dll +microsoft.aspnetcore.authentication.core\2.2.0\microsoft.aspnetcore.authentication.core.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.core\2.2.0\microsoft.aspnetcore.authentication.core.nuspec +microsoft.aspnetcore.authentication.facebook\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.facebook\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.facebook\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Facebook.dll +microsoft.aspnetcore.authentication.facebook\2.2.0\microsoft.aspnetcore.authentication.facebook.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.facebook\2.2.0\microsoft.aspnetcore.authentication.facebook.nuspec +microsoft.aspnetcore.authentication.google\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.google\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.google\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Google.dll +microsoft.aspnetcore.authentication.google\2.2.0\microsoft.aspnetcore.authentication.google.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.google\2.2.0\microsoft.aspnetcore.authentication.google.nuspec +microsoft.aspnetcore.authentication.jwtbearer\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.jwtbearer\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.jwtbearer\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.JwtBearer.dll +microsoft.aspnetcore.authentication.jwtbearer\2.2.0\microsoft.aspnetcore.authentication.jwtbearer.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.jwtbearer\2.2.0\microsoft.aspnetcore.authentication.jwtbearer.nuspec +microsoft.aspnetcore.authentication.microsoftaccount\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.microsoftaccount\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.microsoftaccount\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.MicrosoftAccount.dll +microsoft.aspnetcore.authentication.microsoftaccount\2.2.0\microsoft.aspnetcore.authentication.microsoftaccount.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.microsoftaccount\2.2.0\microsoft.aspnetcore.authentication.microsoftaccount.nuspec +microsoft.aspnetcore.authentication.oauth\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.oauth\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.oauth\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.OAuth.dll +microsoft.aspnetcore.authentication.oauth\2.2.0\microsoft.aspnetcore.authentication.oauth.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.oauth\2.2.0\microsoft.aspnetcore.authentication.oauth.nuspec +microsoft.aspnetcore.authentication.openidconnect\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.openidconnect\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.openidconnect\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.OpenIdConnect.dll +microsoft.aspnetcore.authentication.openidconnect\2.2.0\microsoft.aspnetcore.authentication.openidconnect.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.openidconnect\2.2.0\microsoft.aspnetcore.authentication.openidconnect.nuspec +microsoft.aspnetcore.authentication.twitter\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.twitter\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.twitter\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Twitter.dll +microsoft.aspnetcore.authentication.twitter\2.2.0\microsoft.aspnetcore.authentication.twitter.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.twitter\2.2.0\microsoft.aspnetcore.authentication.twitter.nuspec +microsoft.aspnetcore.authentication.wsfederation\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication.wsfederation\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication.wsfederation\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.WsFederation.dll +microsoft.aspnetcore.authentication.wsfederation\2.2.0\microsoft.aspnetcore.authentication.wsfederation.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication.wsfederation\2.2.0\microsoft.aspnetcore.authentication.wsfederation.nuspec +microsoft.aspnetcore.authentication\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authentication\2.2.0\.signature.p7s +microsoft.aspnetcore.authentication\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.dll +microsoft.aspnetcore.authentication\2.2.0\microsoft.aspnetcore.authentication.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authentication\2.2.0\microsoft.aspnetcore.authentication.nuspec +microsoft.aspnetcore.authorization.policy\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authorization.policy\2.2.0\.signature.p7s +microsoft.aspnetcore.authorization.policy\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authorization.Policy.dll +microsoft.aspnetcore.authorization.policy\2.2.0\microsoft.aspnetcore.authorization.policy.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authorization.policy\2.2.0\microsoft.aspnetcore.authorization.policy.nuspec +microsoft.aspnetcore.authorization\2.2.0\.nupkg.metadata +microsoft.aspnetcore.authorization\2.2.0\.signature.p7s +microsoft.aspnetcore.authorization\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authorization.dll +microsoft.aspnetcore.authorization\2.2.0\microsoft.aspnetcore.authorization.2.2.0.nupkg.sha512 +microsoft.aspnetcore.authorization\2.2.0\microsoft.aspnetcore.authorization.nuspec +microsoft.aspnetcore.azureappservices.hostingstartup\2.2.0\.nupkg.metadata +microsoft.aspnetcore.azureappservices.hostingstartup\2.2.0\.signature.p7s +microsoft.aspnetcore.azureappservices.hostingstartup\2.2.0\lib\net461\Microsoft.AspNetCore.AzureAppServices.HostingStartup.dll +microsoft.aspnetcore.azureappservices.hostingstartup\2.2.0\lib\netcoreapp2.0\Microsoft.AspNetCore.AzureAppServices.HostingStartup.dll +microsoft.aspnetcore.azureappservices.hostingstartup\2.2.0\lib\netcoreapp2.1\Microsoft.AspNetCore.AzureAppServices.HostingStartup.dll +microsoft.aspnetcore.azureappservices.hostingstartup\2.2.0\microsoft.aspnetcore.azureappservices.hostingstartup.2.2.0.nupkg.sha512 +microsoft.aspnetcore.azureappservices.hostingstartup\2.2.0\microsoft.aspnetcore.azureappservices.hostingstartup.nuspec +microsoft.aspnetcore.azureappservicesintegration\2.2.0\.nupkg.metadata +microsoft.aspnetcore.azureappservicesintegration\2.2.0\.signature.p7s +microsoft.aspnetcore.azureappservicesintegration\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.AzureAppServicesIntegration.dll +microsoft.aspnetcore.azureappservicesintegration\2.2.0\microsoft.aspnetcore.azureappservicesintegration.2.2.0.nupkg.sha512 +microsoft.aspnetcore.azureappservicesintegration\2.2.0\microsoft.aspnetcore.azureappservicesintegration.nuspec +microsoft.aspnetcore.connections.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.connections.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.connections.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Connections.Abstractions.dll +microsoft.aspnetcore.connections.abstractions\2.2.0\microsoft.aspnetcore.connections.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.connections.abstractions\2.2.0\microsoft.aspnetcore.connections.abstractions.nuspec +microsoft.aspnetcore.cookiepolicy\2.2.0\.nupkg.metadata +microsoft.aspnetcore.cookiepolicy\2.2.0\.signature.p7s +microsoft.aspnetcore.cookiepolicy\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.CookiePolicy.dll +microsoft.aspnetcore.cookiepolicy\2.2.0\microsoft.aspnetcore.cookiepolicy.2.2.0.nupkg.sha512 +microsoft.aspnetcore.cookiepolicy\2.2.0\microsoft.aspnetcore.cookiepolicy.nuspec +microsoft.aspnetcore.cors\2.2.0\.nupkg.metadata +microsoft.aspnetcore.cors\2.2.0\.signature.p7s +microsoft.aspnetcore.cors\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Cors.dll +microsoft.aspnetcore.cors\2.2.0\microsoft.aspnetcore.cors.2.2.0.nupkg.sha512 +microsoft.aspnetcore.cors\2.2.0\microsoft.aspnetcore.cors.nuspec +microsoft.aspnetcore.cryptography.internal\2.2.0\.nupkg.metadata +microsoft.aspnetcore.cryptography.internal\2.2.0\.signature.p7s +microsoft.aspnetcore.cryptography.internal\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Cryptography.Internal.dll +microsoft.aspnetcore.cryptography.internal\2.2.0\microsoft.aspnetcore.cryptography.internal.2.2.0.nupkg.sha512 +microsoft.aspnetcore.cryptography.internal\2.2.0\microsoft.aspnetcore.cryptography.internal.nuspec +microsoft.aspnetcore.cryptography.keyderivation\2.2.0\.nupkg.metadata +microsoft.aspnetcore.cryptography.keyderivation\2.2.0\.signature.p7s +microsoft.aspnetcore.cryptography.keyderivation\2.2.0\lib\netcoreapp2.0\Microsoft.AspNetCore.Cryptography.KeyDerivation.dll +microsoft.aspnetcore.cryptography.keyderivation\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Cryptography.KeyDerivation.dll +microsoft.aspnetcore.cryptography.keyderivation\2.2.0\microsoft.aspnetcore.cryptography.keyderivation.2.2.0.nupkg.sha512 +microsoft.aspnetcore.cryptography.keyderivation\2.2.0\microsoft.aspnetcore.cryptography.keyderivation.nuspec +microsoft.aspnetcore.dataprotection.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.dataprotection.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.dataprotection.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.Abstractions.dll +microsoft.aspnetcore.dataprotection.abstractions\2.2.0\microsoft.aspnetcore.dataprotection.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.dataprotection.abstractions\2.2.0\microsoft.aspnetcore.dataprotection.abstractions.nuspec +microsoft.aspnetcore.dataprotection.azurekeyvault\2.2.0\.nupkg.metadata +microsoft.aspnetcore.dataprotection.azurekeyvault\2.2.0\.signature.p7s +microsoft.aspnetcore.dataprotection.azurekeyvault\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.AzureKeyVault.dll +microsoft.aspnetcore.dataprotection.azurekeyvault\2.2.0\microsoft.aspnetcore.dataprotection.azurekeyvault.2.2.0.nupkg.sha512 +microsoft.aspnetcore.dataprotection.azurekeyvault\2.2.0\microsoft.aspnetcore.dataprotection.azurekeyvault.nuspec +microsoft.aspnetcore.dataprotection.azurestorage\2.2.0\.nupkg.metadata +microsoft.aspnetcore.dataprotection.azurestorage\2.2.0\.signature.p7s +microsoft.aspnetcore.dataprotection.azurestorage\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.AzureStorage.dll +microsoft.aspnetcore.dataprotection.azurestorage\2.2.0\microsoft.aspnetcore.dataprotection.azurestorage.2.2.0.nupkg.sha512 +microsoft.aspnetcore.dataprotection.azurestorage\2.2.0\microsoft.aspnetcore.dataprotection.azurestorage.nuspec +microsoft.aspnetcore.dataprotection.extensions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.dataprotection.extensions\2.2.0\.signature.p7s +microsoft.aspnetcore.dataprotection.extensions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.Extensions.dll +microsoft.aspnetcore.dataprotection.extensions\2.2.0\microsoft.aspnetcore.dataprotection.extensions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.dataprotection.extensions\2.2.0\microsoft.aspnetcore.dataprotection.extensions.nuspec +microsoft.aspnetcore.dataprotection\2.2.0\.nupkg.metadata +microsoft.aspnetcore.dataprotection\2.2.0\.signature.p7s +microsoft.aspnetcore.dataprotection\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.DataProtection.dll +microsoft.aspnetcore.dataprotection\2.2.0\microsoft.aspnetcore.dataprotection.2.2.0.nupkg.sha512 +microsoft.aspnetcore.dataprotection\2.2.0\microsoft.aspnetcore.dataprotection.nuspec +microsoft.aspnetcore.diagnostics.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.diagnostics.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.diagnostics.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Diagnostics.Abstractions.dll +microsoft.aspnetcore.diagnostics.abstractions\2.2.0\microsoft.aspnetcore.diagnostics.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.diagnostics.abstractions\2.2.0\microsoft.aspnetcore.diagnostics.abstractions.nuspec +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.2.0\.nupkg.metadata +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.2.0\.signature.p7s +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.dll +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.2.0\microsoft.aspnetcore.diagnostics.entityframeworkcore.2.2.0.nupkg.sha512 +microsoft.aspnetcore.diagnostics.entityframeworkcore\2.2.0\microsoft.aspnetcore.diagnostics.entityframeworkcore.nuspec +microsoft.aspnetcore.diagnostics.healthchecks\2.2.0\.nupkg.metadata +microsoft.aspnetcore.diagnostics.healthchecks\2.2.0\.signature.p7s +microsoft.aspnetcore.diagnostics.healthchecks\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Diagnostics.HealthChecks.dll +microsoft.aspnetcore.diagnostics.healthchecks\2.2.0\microsoft.aspnetcore.diagnostics.healthchecks.2.2.0.nupkg.sha512 +microsoft.aspnetcore.diagnostics.healthchecks\2.2.0\microsoft.aspnetcore.diagnostics.healthchecks.nuspec +microsoft.aspnetcore.diagnostics\2.2.0\.nupkg.metadata +microsoft.aspnetcore.diagnostics\2.2.0\.signature.p7s +microsoft.aspnetcore.diagnostics\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Diagnostics.dll +microsoft.aspnetcore.diagnostics\2.2.0\microsoft.aspnetcore.diagnostics.2.2.0.nupkg.sha512 +microsoft.aspnetcore.diagnostics\2.2.0\microsoft.aspnetcore.diagnostics.nuspec +microsoft.aspnetcore.hostfiltering\2.2.0\.nupkg.metadata +microsoft.aspnetcore.hostfiltering\2.2.0\.signature.p7s +microsoft.aspnetcore.hostfiltering\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.HostFiltering.dll +microsoft.aspnetcore.hostfiltering\2.2.0\microsoft.aspnetcore.hostfiltering.2.2.0.nupkg.sha512 +microsoft.aspnetcore.hostfiltering\2.2.0\microsoft.aspnetcore.hostfiltering.nuspec +microsoft.aspnetcore.hosting.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.hosting.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.hosting.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Abstractions.dll +microsoft.aspnetcore.hosting.abstractions\2.2.0\microsoft.aspnetcore.hosting.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.hosting.abstractions\2.2.0\microsoft.aspnetcore.hosting.abstractions.nuspec +microsoft.aspnetcore.hosting.server.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.hosting.server.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.hosting.server.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Server.Abstractions.dll +microsoft.aspnetcore.hosting.server.abstractions\2.2.0\microsoft.aspnetcore.hosting.server.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.hosting.server.abstractions\2.2.0\microsoft.aspnetcore.hosting.server.abstractions.nuspec +microsoft.aspnetcore.hosting\2.2.0\.nupkg.metadata +microsoft.aspnetcore.hosting\2.2.0\.signature.p7s +microsoft.aspnetcore.hosting\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.dll +microsoft.aspnetcore.hosting\2.2.0\microsoft.aspnetcore.hosting.2.2.0.nupkg.sha512 +microsoft.aspnetcore.hosting\2.2.0\microsoft.aspnetcore.hosting.nuspec +microsoft.aspnetcore.html.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.html.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.html.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Html.Abstractions.dll +microsoft.aspnetcore.html.abstractions\2.2.0\microsoft.aspnetcore.html.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.html.abstractions\2.2.0\microsoft.aspnetcore.html.abstractions.nuspec +microsoft.aspnetcore.http.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.http.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.http.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Abstractions.dll +microsoft.aspnetcore.http.abstractions\2.2.0\microsoft.aspnetcore.http.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.http.abstractions\2.2.0\microsoft.aspnetcore.http.abstractions.nuspec +microsoft.aspnetcore.http.connections.common\1.1.0\.nupkg.metadata +microsoft.aspnetcore.http.connections.common\1.1.0\.signature.p7s +microsoft.aspnetcore.http.connections.common\1.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Connections.Common.dll +microsoft.aspnetcore.http.connections.common\1.1.0\microsoft.aspnetcore.http.connections.common.1.1.0.nupkg.sha512 +microsoft.aspnetcore.http.connections.common\1.1.0\microsoft.aspnetcore.http.connections.common.nuspec +microsoft.aspnetcore.http.connections\1.1.0\.nupkg.metadata +microsoft.aspnetcore.http.connections\1.1.0\.signature.p7s +microsoft.aspnetcore.http.connections\1.1.0\lib\netcoreapp2.2\Microsoft.AspNetCore.Http.Connections.dll +microsoft.aspnetcore.http.connections\1.1.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Connections.dll +microsoft.aspnetcore.http.connections\1.1.0\microsoft.aspnetcore.http.connections.1.1.0.nupkg.sha512 +microsoft.aspnetcore.http.connections\1.1.0\microsoft.aspnetcore.http.connections.nuspec +microsoft.aspnetcore.http.extensions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.http.extensions\2.2.0\.signature.p7s +microsoft.aspnetcore.http.extensions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Extensions.dll +microsoft.aspnetcore.http.extensions\2.2.0\microsoft.aspnetcore.http.extensions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.http.extensions\2.2.0\microsoft.aspnetcore.http.extensions.nuspec +microsoft.aspnetcore.http.features\2.2.0\.nupkg.metadata +microsoft.aspnetcore.http.features\2.2.0\.signature.p7s +microsoft.aspnetcore.http.features\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Features.dll +microsoft.aspnetcore.http.features\2.2.0\microsoft.aspnetcore.http.features.2.2.0.nupkg.sha512 +microsoft.aspnetcore.http.features\2.2.0\microsoft.aspnetcore.http.features.nuspec +microsoft.aspnetcore.http\2.2.0\.nupkg.metadata +microsoft.aspnetcore.http\2.2.0\.signature.p7s +microsoft.aspnetcore.http\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.dll +microsoft.aspnetcore.http\2.2.0\microsoft.aspnetcore.http.2.2.0.nupkg.sha512 +microsoft.aspnetcore.http\2.2.0\microsoft.aspnetcore.http.nuspec +microsoft.aspnetcore.httpoverrides\2.2.0\.nupkg.metadata +microsoft.aspnetcore.httpoverrides\2.2.0\.signature.p7s +microsoft.aspnetcore.httpoverrides\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.HttpOverrides.dll +microsoft.aspnetcore.httpoverrides\2.2.0\microsoft.aspnetcore.httpoverrides.2.2.0.nupkg.sha512 +microsoft.aspnetcore.httpoverrides\2.2.0\microsoft.aspnetcore.httpoverrides.nuspec +microsoft.aspnetcore.httpspolicy\2.2.0\.nupkg.metadata +microsoft.aspnetcore.httpspolicy\2.2.0\.signature.p7s +microsoft.aspnetcore.httpspolicy\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.HttpsPolicy.dll +microsoft.aspnetcore.httpspolicy\2.2.0\microsoft.aspnetcore.httpspolicy.2.2.0.nupkg.sha512 +microsoft.aspnetcore.httpspolicy\2.2.0\microsoft.aspnetcore.httpspolicy.nuspec +microsoft.aspnetcore.identity.entityframeworkcore\2.2.0\.nupkg.metadata +microsoft.aspnetcore.identity.entityframeworkcore\2.2.0\.signature.p7s +microsoft.aspnetcore.identity.entityframeworkcore\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Identity.EntityFrameworkCore.dll +microsoft.aspnetcore.identity.entityframeworkcore\2.2.0\microsoft.aspnetcore.identity.entityframeworkcore.2.2.0.nupkg.sha512 +microsoft.aspnetcore.identity.entityframeworkcore\2.2.0\microsoft.aspnetcore.identity.entityframeworkcore.nuspec +microsoft.aspnetcore.identity.ui\2.2.0\.nupkg.metadata +microsoft.aspnetcore.identity.ui\2.2.0\.signature.p7s +microsoft.aspnetcore.identity.ui\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Identity.UI.dll +microsoft.aspnetcore.identity.ui\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Identity.UI.Views.V3.dll +microsoft.aspnetcore.identity.ui\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Identity.UI.Views.V4.dll +microsoft.aspnetcore.identity.ui\2.2.0\microsoft.aspnetcore.identity.ui.2.2.0.nupkg.sha512 +microsoft.aspnetcore.identity.ui\2.2.0\microsoft.aspnetcore.identity.ui.nuspec +microsoft.aspnetcore.identity.ui\2.2.0\THIRD-PARTY-NOTICES.txt +microsoft.aspnetcore.identity\2.2.0\.nupkg.metadata +microsoft.aspnetcore.identity\2.2.0\.signature.p7s +microsoft.aspnetcore.identity\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Identity.dll +microsoft.aspnetcore.identity\2.2.0\microsoft.aspnetcore.identity.2.2.0.nupkg.sha512 +microsoft.aspnetcore.identity\2.2.0\microsoft.aspnetcore.identity.nuspec +microsoft.aspnetcore.jsonpatch\2.2.0\.nupkg.metadata +microsoft.aspnetcore.jsonpatch\2.2.0\.signature.p7s +microsoft.aspnetcore.jsonpatch\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.JsonPatch.dll +microsoft.aspnetcore.jsonpatch\2.2.0\microsoft.aspnetcore.jsonpatch.2.2.0.nupkg.sha512 +microsoft.aspnetcore.jsonpatch\2.2.0\microsoft.aspnetcore.jsonpatch.nuspec +microsoft.aspnetcore.localization.routing\2.2.0\.nupkg.metadata +microsoft.aspnetcore.localization.routing\2.2.0\.signature.p7s +microsoft.aspnetcore.localization.routing\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Localization.Routing.dll +microsoft.aspnetcore.localization.routing\2.2.0\microsoft.aspnetcore.localization.routing.2.2.0.nupkg.sha512 +microsoft.aspnetcore.localization.routing\2.2.0\microsoft.aspnetcore.localization.routing.nuspec +microsoft.aspnetcore.localization\2.2.0\.nupkg.metadata +microsoft.aspnetcore.localization\2.2.0\.signature.p7s +microsoft.aspnetcore.localization\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Localization.dll +microsoft.aspnetcore.localization\2.2.0\microsoft.aspnetcore.localization.2.2.0.nupkg.sha512 +microsoft.aspnetcore.localization\2.2.0\microsoft.aspnetcore.localization.nuspec +microsoft.aspnetcore.middlewareanalysis\2.2.0\.nupkg.metadata +microsoft.aspnetcore.middlewareanalysis\2.2.0\.signature.p7s +microsoft.aspnetcore.middlewareanalysis\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.MiddlewareAnalysis.dll +microsoft.aspnetcore.middlewareanalysis\2.2.0\microsoft.aspnetcore.middlewareanalysis.2.2.0.nupkg.sha512 +microsoft.aspnetcore.middlewareanalysis\2.2.0\microsoft.aspnetcore.middlewareanalysis.nuspec +microsoft.aspnetcore.mvc.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Abstractions.dll +microsoft.aspnetcore.mvc.abstractions\2.2.0\microsoft.aspnetcore.mvc.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.abstractions\2.2.0\microsoft.aspnetcore.mvc.abstractions.nuspec +microsoft.aspnetcore.mvc.analyzers\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.analyzers\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.analyzers\2.2.0\analyzers\dotnet\cs\Microsoft.AspNetCore.Mvc.Analyzers.dll +microsoft.aspnetcore.mvc.analyzers\2.2.0\microsoft.aspnetcore.mvc.analyzers.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.analyzers\2.2.0\microsoft.aspnetcore.mvc.analyzers.nuspec +microsoft.aspnetcore.mvc.apiexplorer\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.apiexplorer\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.apiexplorer\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.ApiExplorer.dll +microsoft.aspnetcore.mvc.apiexplorer\2.2.0\microsoft.aspnetcore.mvc.apiexplorer.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.apiexplorer\2.2.0\microsoft.aspnetcore.mvc.apiexplorer.nuspec +microsoft.aspnetcore.mvc.core\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.core\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.core\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Core.dll +microsoft.aspnetcore.mvc.core\2.2.0\microsoft.aspnetcore.mvc.core.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.core\2.2.0\microsoft.aspnetcore.mvc.core.nuspec +microsoft.aspnetcore.mvc.cors\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.cors\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.cors\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Cors.dll +microsoft.aspnetcore.mvc.cors\2.2.0\microsoft.aspnetcore.mvc.cors.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.cors\2.2.0\microsoft.aspnetcore.mvc.cors.nuspec +microsoft.aspnetcore.mvc.dataannotations\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.dataannotations\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.dataannotations\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.DataAnnotations.dll +microsoft.aspnetcore.mvc.dataannotations\2.2.0\microsoft.aspnetcore.mvc.dataannotations.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.dataannotations\2.2.0\microsoft.aspnetcore.mvc.dataannotations.nuspec +microsoft.aspnetcore.mvc.formatters.json\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.formatters.json\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.formatters.json\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Formatters.Json.dll +microsoft.aspnetcore.mvc.formatters.json\2.2.0\microsoft.aspnetcore.mvc.formatters.json.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.formatters.json\2.2.0\microsoft.aspnetcore.mvc.formatters.json.nuspec +microsoft.aspnetcore.mvc.formatters.xml\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.formatters.xml\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.formatters.xml\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Formatters.Xml.dll +microsoft.aspnetcore.mvc.formatters.xml\2.2.0\microsoft.aspnetcore.mvc.formatters.xml.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.formatters.xml\2.2.0\microsoft.aspnetcore.mvc.formatters.xml.nuspec +microsoft.aspnetcore.mvc.localization\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.localization\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.localization\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Localization.dll +microsoft.aspnetcore.mvc.localization\2.2.0\microsoft.aspnetcore.mvc.localization.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.localization\2.2.0\microsoft.aspnetcore.mvc.localization.nuspec +microsoft.aspnetcore.mvc.razor.extensions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.razor.extensions\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.razor.extensions\2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.props +microsoft.aspnetcore.mvc.razor.extensions\2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.targets +microsoft.aspnetcore.mvc.razor.extensions\2.2.0\lib\net46\Microsoft.AspNetCore.Mvc.Razor.Extensions.dll +microsoft.aspnetcore.mvc.razor.extensions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.dll +microsoft.aspnetcore.mvc.razor.extensions\2.2.0\microsoft.aspnetcore.mvc.razor.extensions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.razor.extensions\2.2.0\microsoft.aspnetcore.mvc.razor.extensions.nuspec +microsoft.aspnetcore.mvc.razor.viewcompilation\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.razor.viewcompilation\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.razor.viewcompilation\2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.targets +microsoft.aspnetcore.mvc.razor.viewcompilation\2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.Tasks.dll +microsoft.aspnetcore.mvc.razor.viewcompilation\2.2.0\build\netstandard2.0\net461\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.exe +microsoft.aspnetcore.mvc.razor.viewcompilation\2.2.0\build\netstandard2.0\net461\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation-x86.exe +microsoft.aspnetcore.mvc.razor.viewcompilation\2.2.0\build\netstandard2.0\netcoreapp2.0\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.dll +microsoft.aspnetcore.mvc.razor.viewcompilation\2.2.0\microsoft.aspnetcore.mvc.razor.viewcompilation.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.razor.viewcompilation\2.2.0\microsoft.aspnetcore.mvc.razor.viewcompilation.nuspec +microsoft.aspnetcore.mvc.razor\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.razor\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.razor\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.dll +microsoft.aspnetcore.mvc.razor\2.2.0\microsoft.aspnetcore.mvc.razor.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.razor\2.2.0\microsoft.aspnetcore.mvc.razor.nuspec +microsoft.aspnetcore.mvc.razorpages\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.razorpages\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.razorpages\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.RazorPages.dll +microsoft.aspnetcore.mvc.razorpages\2.2.0\microsoft.aspnetcore.mvc.razorpages.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.razorpages\2.2.0\microsoft.aspnetcore.mvc.razorpages.nuspec +microsoft.aspnetcore.mvc.taghelpers\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.taghelpers\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.taghelpers\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.TagHelpers.dll +microsoft.aspnetcore.mvc.taghelpers\2.2.0\microsoft.aspnetcore.mvc.taghelpers.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.taghelpers\2.2.0\microsoft.aspnetcore.mvc.taghelpers.nuspec +microsoft.aspnetcore.mvc.viewfeatures\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc.viewfeatures\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc.viewfeatures\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.ViewFeatures.dll +microsoft.aspnetcore.mvc.viewfeatures\2.2.0\microsoft.aspnetcore.mvc.viewfeatures.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc.viewfeatures\2.2.0\microsoft.aspnetcore.mvc.viewfeatures.nuspec +microsoft.aspnetcore.mvc\2.2.0\.nupkg.metadata +microsoft.aspnetcore.mvc\2.2.0\.signature.p7s +microsoft.aspnetcore.mvc\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.dll +microsoft.aspnetcore.mvc\2.2.0\microsoft.aspnetcore.mvc.2.2.0.nupkg.sha512 +microsoft.aspnetcore.mvc\2.2.0\microsoft.aspnetcore.mvc.nuspec +microsoft.aspnetcore.nodeservices\2.2.0\.nupkg.metadata +microsoft.aspnetcore.nodeservices\2.2.0\.signature.p7s +microsoft.aspnetcore.nodeservices\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.NodeServices.dll +microsoft.aspnetcore.nodeservices\2.2.0\microsoft.aspnetcore.nodeservices.2.2.0.nupkg.sha512 +microsoft.aspnetcore.nodeservices\2.2.0\microsoft.aspnetcore.nodeservices.nuspec +microsoft.aspnetcore.owin\2.2.0\.nupkg.metadata +microsoft.aspnetcore.owin\2.2.0\.signature.p7s +microsoft.aspnetcore.owin\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Owin.dll +microsoft.aspnetcore.owin\2.2.0\microsoft.aspnetcore.owin.2.2.0.nupkg.sha512 +microsoft.aspnetcore.owin\2.2.0\microsoft.aspnetcore.owin.nuspec +microsoft.aspnetcore.razor.design\2.2.0\.nupkg.metadata +microsoft.aspnetcore.razor.design\2.2.0\.signature.p7s +microsoft.aspnetcore.razor.design\2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.CodeGeneration.targets +microsoft.aspnetcore.razor.design\2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.props +microsoft.aspnetcore.razor.design\2.2.0\buildMultiTargeting\Microsoft.AspNetCore.Razor.Design.props +microsoft.aspnetcore.razor.design\2.2.0\microsoft.aspnetcore.razor.design.2.2.0.nupkg.sha512 +microsoft.aspnetcore.razor.design\2.2.0\microsoft.aspnetcore.razor.design.nuspec +microsoft.aspnetcore.razor.design\2.2.0\tools\Microsoft.AspNetCore.Razor.Language.dll +microsoft.aspnetcore.razor.design\2.2.0\tools\Microsoft.CodeAnalysis.CSharp.dll +microsoft.aspnetcore.razor.design\2.2.0\tools\Microsoft.CodeAnalysis.dll +microsoft.aspnetcore.razor.design\2.2.0\tools\Microsoft.CodeAnalysis.Razor.dll +microsoft.aspnetcore.razor.design\2.2.0\tools\Newtonsoft.Json.dll +microsoft.aspnetcore.razor.design\2.2.0\tools\runtimes\unix\lib\netstandard1.3\System.Text.Encoding.CodePages.dll +microsoft.aspnetcore.razor.design\2.2.0\tools\runtimes\win\lib\netstandard1.3\System.Text.Encoding.CodePages.dll +microsoft.aspnetcore.razor.design\2.2.0\tools\rzc.deps.json +microsoft.aspnetcore.razor.design\2.2.0\tools\rzc.dll +microsoft.aspnetcore.razor.design\2.2.0\tools\rzc.runtimeconfig.json +microsoft.aspnetcore.razor.language\2.2.0\.nupkg.metadata +microsoft.aspnetcore.razor.language\2.2.0\.signature.p7s +microsoft.aspnetcore.razor.language\2.2.0\lib\net46\Microsoft.AspNetCore.Razor.Language.dll +microsoft.aspnetcore.razor.language\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Razor.Language.dll +microsoft.aspnetcore.razor.language\2.2.0\microsoft.aspnetcore.razor.language.2.2.0.nupkg.sha512 +microsoft.aspnetcore.razor.language\2.2.0\microsoft.aspnetcore.razor.language.nuspec +microsoft.aspnetcore.razor.runtime\2.2.0\.nupkg.metadata +microsoft.aspnetcore.razor.runtime\2.2.0\.signature.p7s +microsoft.aspnetcore.razor.runtime\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Razor.Runtime.dll +microsoft.aspnetcore.razor.runtime\2.2.0\microsoft.aspnetcore.razor.runtime.2.2.0.nupkg.sha512 +microsoft.aspnetcore.razor.runtime\2.2.0\microsoft.aspnetcore.razor.runtime.nuspec +microsoft.aspnetcore.razor\2.2.0\.nupkg.metadata +microsoft.aspnetcore.razor\2.2.0\.signature.p7s +microsoft.aspnetcore.razor\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Razor.dll +microsoft.aspnetcore.razor\2.2.0\microsoft.aspnetcore.razor.2.2.0.nupkg.sha512 +microsoft.aspnetcore.razor\2.2.0\microsoft.aspnetcore.razor.nuspec +microsoft.aspnetcore.responsecaching.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.responsecaching.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.responsecaching.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.ResponseCaching.Abstractions.dll +microsoft.aspnetcore.responsecaching.abstractions\2.2.0\microsoft.aspnetcore.responsecaching.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.responsecaching.abstractions\2.2.0\microsoft.aspnetcore.responsecaching.abstractions.nuspec +microsoft.aspnetcore.responsecaching\2.2.0\.nupkg.metadata +microsoft.aspnetcore.responsecaching\2.2.0\.signature.p7s +microsoft.aspnetcore.responsecaching\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.ResponseCaching.dll +microsoft.aspnetcore.responsecaching\2.2.0\microsoft.aspnetcore.responsecaching.2.2.0.nupkg.sha512 +microsoft.aspnetcore.responsecaching\2.2.0\microsoft.aspnetcore.responsecaching.nuspec +microsoft.aspnetcore.responsecompression\2.2.0\.nupkg.metadata +microsoft.aspnetcore.responsecompression\2.2.0\.signature.p7s +microsoft.aspnetcore.responsecompression\2.2.0\lib\net461\Microsoft.AspNetCore.ResponseCompression.dll +microsoft.aspnetcore.responsecompression\2.2.0\lib\netcoreapp2.1\Microsoft.AspNetCore.ResponseCompression.dll +microsoft.aspnetcore.responsecompression\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.ResponseCompression.dll +microsoft.aspnetcore.responsecompression\2.2.0\microsoft.aspnetcore.responsecompression.2.2.0.nupkg.sha512 +microsoft.aspnetcore.responsecompression\2.2.0\microsoft.aspnetcore.responsecompression.nuspec +microsoft.aspnetcore.rewrite\2.2.0\.nupkg.metadata +microsoft.aspnetcore.rewrite\2.2.0\.signature.p7s +microsoft.aspnetcore.rewrite\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Rewrite.dll +microsoft.aspnetcore.rewrite\2.2.0\microsoft.aspnetcore.rewrite.2.2.0.nupkg.sha512 +microsoft.aspnetcore.rewrite\2.2.0\microsoft.aspnetcore.rewrite.nuspec +microsoft.aspnetcore.routing.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.routing.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.routing.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Routing.Abstractions.dll +microsoft.aspnetcore.routing.abstractions\2.2.0\microsoft.aspnetcore.routing.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.routing.abstractions\2.2.0\microsoft.aspnetcore.routing.abstractions.nuspec +microsoft.aspnetcore.routing\2.2.0\.nupkg.metadata +microsoft.aspnetcore.routing\2.2.0\.signature.p7s +microsoft.aspnetcore.routing\2.2.0\lib\netcoreapp2.2\Microsoft.AspNetCore.Routing.dll +microsoft.aspnetcore.routing\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Routing.dll +microsoft.aspnetcore.routing\2.2.0\microsoft.aspnetcore.routing.2.2.0.nupkg.sha512 +microsoft.aspnetcore.routing\2.2.0\microsoft.aspnetcore.routing.nuspec +microsoft.aspnetcore.server.httpsys\2.2.0\.nupkg.metadata +microsoft.aspnetcore.server.httpsys\2.2.0\.signature.p7s +microsoft.aspnetcore.server.httpsys\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.HttpSys.dll +microsoft.aspnetcore.server.httpsys\2.2.0\microsoft.aspnetcore.server.httpsys.2.2.0.nupkg.sha512 +microsoft.aspnetcore.server.httpsys\2.2.0\microsoft.aspnetcore.server.httpsys.nuspec +microsoft.aspnetcore.server.iis\2.2.0\.nupkg.metadata +microsoft.aspnetcore.server.iis\2.2.0\.signature.p7s +microsoft.aspnetcore.server.iis\2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Server.IIS.targets +microsoft.aspnetcore.server.iis\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.IIS.dll +microsoft.aspnetcore.server.iis\2.2.0\microsoft.aspnetcore.server.iis.2.2.0.nupkg.sha512 +microsoft.aspnetcore.server.iis\2.2.0\microsoft.aspnetcore.server.iis.nuspec +microsoft.aspnetcore.server.iis\2.2.0\runtimes\win-x64\nativeassets\netcoreapp2.2\aspnetcorev2_inprocess.dll +microsoft.aspnetcore.server.iis\2.2.0\runtimes\win-x86\nativeassets\netcoreapp2.2\aspnetcorev2_inprocess.dll +microsoft.aspnetcore.server.iisintegration\2.2.0\.nupkg.metadata +microsoft.aspnetcore.server.iisintegration\2.2.0\.signature.p7s +microsoft.aspnetcore.server.iisintegration\2.2.0\build\netstandard2.0\Microsoft.AspNetCore.Server.IISIntegration.targets +microsoft.aspnetcore.server.iisintegration\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.IISIntegration.dll +microsoft.aspnetcore.server.iisintegration\2.2.0\microsoft.aspnetcore.server.iisintegration.2.2.0.nupkg.sha512 +microsoft.aspnetcore.server.iisintegration\2.2.0\microsoft.aspnetcore.server.iisintegration.nuspec +microsoft.aspnetcore.server.kestrel.core\2.2.0\.nupkg.metadata +microsoft.aspnetcore.server.kestrel.core\2.2.0\.signature.p7s +microsoft.aspnetcore.server.kestrel.core\2.2.0\lib\netcoreapp2.1\Microsoft.AspNetCore.Server.Kestrel.Core.dll +microsoft.aspnetcore.server.kestrel.core\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Core.dll +microsoft.aspnetcore.server.kestrel.core\2.2.0\microsoft.aspnetcore.server.kestrel.core.2.2.0.nupkg.sha512 +microsoft.aspnetcore.server.kestrel.core\2.2.0\microsoft.aspnetcore.server.kestrel.core.nuspec +microsoft.aspnetcore.server.kestrel.https\2.2.0\.nupkg.metadata +microsoft.aspnetcore.server.kestrel.https\2.2.0\.signature.p7s +microsoft.aspnetcore.server.kestrel.https\2.2.0\lib\netcoreapp2.1\Microsoft.AspNetCore.Server.Kestrel.Https.dll +microsoft.aspnetcore.server.kestrel.https\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Https.dll +microsoft.aspnetcore.server.kestrel.https\2.2.0\microsoft.aspnetcore.server.kestrel.https.2.2.0.nupkg.sha512 +microsoft.aspnetcore.server.kestrel.https\2.2.0\microsoft.aspnetcore.server.kestrel.https.nuspec +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.2.0\.signature.p7s +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.dll +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.2.0\microsoft.aspnetcore.server.kestrel.transport.abstractions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.server.kestrel.transport.abstractions\2.2.0\microsoft.aspnetcore.server.kestrel.transport.abstractions.nuspec +microsoft.aspnetcore.server.kestrel.transport.libuv\2.2.0\.nupkg.metadata +microsoft.aspnetcore.server.kestrel.transport.libuv\2.2.0\.signature.p7s +microsoft.aspnetcore.server.kestrel.transport.libuv\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.dll +microsoft.aspnetcore.server.kestrel.transport.libuv\2.2.0\microsoft.aspnetcore.server.kestrel.transport.libuv.2.2.0.nupkg.sha512 +microsoft.aspnetcore.server.kestrel.transport.libuv\2.2.0\microsoft.aspnetcore.server.kestrel.transport.libuv.nuspec +microsoft.aspnetcore.server.kestrel.transport.sockets\2.2.0\.nupkg.metadata +microsoft.aspnetcore.server.kestrel.transport.sockets\2.2.0\.signature.p7s +microsoft.aspnetcore.server.kestrel.transport.sockets\2.2.0\lib\netcoreapp2.1\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.dll +microsoft.aspnetcore.server.kestrel.transport.sockets\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.dll +microsoft.aspnetcore.server.kestrel.transport.sockets\2.2.0\microsoft.aspnetcore.server.kestrel.transport.sockets.2.2.0.nupkg.sha512 +microsoft.aspnetcore.server.kestrel.transport.sockets\2.2.0\microsoft.aspnetcore.server.kestrel.transport.sockets.nuspec +microsoft.aspnetcore.server.kestrel\2.2.0\.nupkg.metadata +microsoft.aspnetcore.server.kestrel\2.2.0\.signature.p7s +microsoft.aspnetcore.server.kestrel\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.dll +microsoft.aspnetcore.server.kestrel\2.2.0\microsoft.aspnetcore.server.kestrel.2.2.0.nupkg.sha512 +microsoft.aspnetcore.server.kestrel\2.2.0\microsoft.aspnetcore.server.kestrel.nuspec +microsoft.aspnetcore.session\2.2.0\.nupkg.metadata +microsoft.aspnetcore.session\2.2.0\.signature.p7s +microsoft.aspnetcore.session\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Session.dll +microsoft.aspnetcore.session\2.2.0\microsoft.aspnetcore.session.2.2.0.nupkg.sha512 +microsoft.aspnetcore.session\2.2.0\microsoft.aspnetcore.session.nuspec +microsoft.aspnetcore.signalr.common\1.1.0\.nupkg.metadata +microsoft.aspnetcore.signalr.common\1.1.0\.signature.p7s +microsoft.aspnetcore.signalr.common\1.1.0\lib\netcoreapp2.2\Microsoft.AspNetCore.SignalR.Common.dll +microsoft.aspnetcore.signalr.common\1.1.0\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Common.dll +microsoft.aspnetcore.signalr.common\1.1.0\microsoft.aspnetcore.signalr.common.1.1.0.nupkg.sha512 +microsoft.aspnetcore.signalr.common\1.1.0\microsoft.aspnetcore.signalr.common.nuspec +microsoft.aspnetcore.signalr.core\1.1.0\.nupkg.metadata +microsoft.aspnetcore.signalr.core\1.1.0\.signature.p7s +microsoft.aspnetcore.signalr.core\1.1.0\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Core.dll +microsoft.aspnetcore.signalr.core\1.1.0\microsoft.aspnetcore.signalr.core.1.1.0.nupkg.sha512 +microsoft.aspnetcore.signalr.core\1.1.0\microsoft.aspnetcore.signalr.core.nuspec +microsoft.aspnetcore.signalr.protocols.json\1.1.0\.nupkg.metadata +microsoft.aspnetcore.signalr.protocols.json\1.1.0\.signature.p7s +microsoft.aspnetcore.signalr.protocols.json\1.1.0\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Protocols.Json.dll +microsoft.aspnetcore.signalr.protocols.json\1.1.0\microsoft.aspnetcore.signalr.protocols.json.1.1.0.nupkg.sha512 +microsoft.aspnetcore.signalr.protocols.json\1.1.0\microsoft.aspnetcore.signalr.protocols.json.nuspec +microsoft.aspnetcore.signalr.redis\1.1.0\.nupkg.metadata +microsoft.aspnetcore.signalr.redis\1.1.0\.signature.p7s +microsoft.aspnetcore.signalr.redis\1.1.0\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Redis.dll +microsoft.aspnetcore.signalr.redis\1.1.0\microsoft.aspnetcore.signalr.redis.1.1.0.nupkg.sha512 +microsoft.aspnetcore.signalr.redis\1.1.0\microsoft.aspnetcore.signalr.redis.nuspec +microsoft.aspnetcore.signalr\1.1.0\.nupkg.metadata +microsoft.aspnetcore.signalr\1.1.0\.signature.p7s +microsoft.aspnetcore.signalr\1.1.0\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.dll +microsoft.aspnetcore.signalr\1.1.0\microsoft.aspnetcore.signalr.1.1.0.nupkg.sha512 +microsoft.aspnetcore.signalr\1.1.0\microsoft.aspnetcore.signalr.nuspec +microsoft.aspnetcore.spaservices.extensions\2.2.0\.nupkg.metadata +microsoft.aspnetcore.spaservices.extensions\2.2.0\.signature.p7s +microsoft.aspnetcore.spaservices.extensions\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.SpaServices.Extensions.dll +microsoft.aspnetcore.spaservices.extensions\2.2.0\microsoft.aspnetcore.spaservices.extensions.2.2.0.nupkg.sha512 +microsoft.aspnetcore.spaservices.extensions\2.2.0\microsoft.aspnetcore.spaservices.extensions.nuspec +microsoft.aspnetcore.spaservices\2.2.0\.nupkg.metadata +microsoft.aspnetcore.spaservices\2.2.0\.signature.p7s +microsoft.aspnetcore.spaservices\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.SpaServices.dll +microsoft.aspnetcore.spaservices\2.2.0\microsoft.aspnetcore.spaservices.2.2.0.nupkg.sha512 +microsoft.aspnetcore.spaservices\2.2.0\microsoft.aspnetcore.spaservices.nuspec +microsoft.aspnetcore.staticfiles\2.2.0\.nupkg.metadata +microsoft.aspnetcore.staticfiles\2.2.0\.signature.p7s +microsoft.aspnetcore.staticfiles\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.StaticFiles.dll +microsoft.aspnetcore.staticfiles\2.2.0\microsoft.aspnetcore.staticfiles.2.2.0.nupkg.sha512 +microsoft.aspnetcore.staticfiles\2.2.0\microsoft.aspnetcore.staticfiles.nuspec +microsoft.aspnetcore.websockets\2.2.0\.nupkg.metadata +microsoft.aspnetcore.websockets\2.2.0\.signature.p7s +microsoft.aspnetcore.websockets\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.WebSockets.dll +microsoft.aspnetcore.websockets\2.2.0\microsoft.aspnetcore.websockets.2.2.0.nupkg.sha512 +microsoft.aspnetcore.websockets\2.2.0\microsoft.aspnetcore.websockets.nuspec +microsoft.aspnetcore.webutilities\2.2.0\.nupkg.metadata +microsoft.aspnetcore.webutilities\2.2.0\.signature.p7s +microsoft.aspnetcore.webutilities\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.WebUtilities.dll +microsoft.aspnetcore.webutilities\2.2.0\microsoft.aspnetcore.webutilities.2.2.0.nupkg.sha512 +microsoft.aspnetcore.webutilities\2.2.0\microsoft.aspnetcore.webutilities.nuspec +microsoft.aspnetcore\2.2.0\.nupkg.metadata +microsoft.aspnetcore\2.2.0\.signature.p7s +microsoft.aspnetcore\2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.dll +microsoft.aspnetcore\2.2.0\microsoft.aspnetcore.2.2.0.nupkg.sha512 +microsoft.aspnetcore\2.2.0\microsoft.aspnetcore.nuspec +microsoft.azure.keyvault.webkey\2.0.7\.nupkg.metadata +microsoft.azure.keyvault.webkey\2.0.7\.signature.p7s +microsoft.azure.keyvault\2.3.2\.nupkg.metadata +microsoft.azure.keyvault\2.3.2\.signature.p7s +microsoft.azure.services.appauthentication\1.0.1\.nupkg.metadata +microsoft.azure.services.appauthentication\1.0.1\.signature.p7s +microsoft.codeanalysis.analyzers\1.1.0\.nupkg.metadata +microsoft.codeanalysis.common\2.8.0\.nupkg.metadata +microsoft.codeanalysis.csharp\2.8.0\.nupkg.metadata +microsoft.codeanalysis.razor\2.2.0\.nupkg.metadata +microsoft.codeanalysis.razor\2.2.0\.signature.p7s +microsoft.codeanalysis.razor\2.2.0\lib\net46\Microsoft.CodeAnalysis.Razor.dll +microsoft.codeanalysis.razor\2.2.0\lib\netstandard2.0\Microsoft.CodeAnalysis.Razor.dll +microsoft.codeanalysis.razor\2.2.0\microsoft.codeanalysis.razor.2.2.0.nupkg.sha512 +microsoft.codeanalysis.razor\2.2.0\microsoft.codeanalysis.razor.nuspec +microsoft.csharp\4.0.1\.nupkg.metadata +microsoft.csharp\4.3.0\.nupkg.metadata +microsoft.csharp\4.5.0\.nupkg.metadata +microsoft.data.edm\5.8.2\.nupkg.metadata +microsoft.data.odata\5.8.2\.nupkg.metadata +microsoft.data.sqlite.core\2.2.0\.nupkg.metadata +microsoft.data.sqlite.core\2.2.0\.signature.p7s +microsoft.data.sqlite.core\2.2.0\lib\netstandard2.0\Microsoft.Data.Sqlite.dll +microsoft.data.sqlite.core\2.2.0\microsoft.data.sqlite.core.2.2.0.nupkg.sha512 +microsoft.data.sqlite.core\2.2.0\microsoft.data.sqlite.core.nuspec +microsoft.data.sqlite\2.2.0\.nupkg.metadata +microsoft.data.sqlite\2.2.0\.signature.p7s +microsoft.data.sqlite\2.2.0\lib\netstandard2.0\_._ +microsoft.data.sqlite\2.2.0\microsoft.data.sqlite.2.2.0.nupkg.sha512 +microsoft.data.sqlite\2.2.0\microsoft.data.sqlite.nuspec +microsoft.dotnet.platformabstractions\2.1.0\.nupkg.metadata +microsoft.entityframeworkcore.abstractions\2.2.0\.nupkg.metadata +microsoft.entityframeworkcore.abstractions\2.2.0\.signature.p7s +microsoft.entityframeworkcore.abstractions\2.2.0\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Abstractions.dll +microsoft.entityframeworkcore.abstractions\2.2.0\microsoft.entityframeworkcore.abstractions.2.2.0.nupkg.sha512 +microsoft.entityframeworkcore.abstractions\2.2.0\microsoft.entityframeworkcore.abstractions.nuspec +microsoft.entityframeworkcore.analyzers\2.2.0\.nupkg.metadata +microsoft.entityframeworkcore.analyzers\2.2.0\.signature.p7s +microsoft.entityframeworkcore.analyzers\2.2.0\analyzers\dotnet\cs\Microsoft.EntityFrameworkCore.Analyzers.dll +microsoft.entityframeworkcore.analyzers\2.2.0\microsoft.entityframeworkcore.analyzers.2.2.0.nupkg.sha512 +microsoft.entityframeworkcore.analyzers\2.2.0\microsoft.entityframeworkcore.analyzers.nuspec +microsoft.entityframeworkcore.design\2.2.0\.nupkg.metadata +microsoft.entityframeworkcore.design\2.2.0\.signature.p7s +microsoft.entityframeworkcore.design\2.2.0\build\net461\Microsoft.EntityFrameworkCore.Design.props +microsoft.entityframeworkcore.design\2.2.0\build\netcoreapp2.0\Microsoft.EntityFrameworkCore.Design.props +microsoft.entityframeworkcore.design\2.2.0\lib\net461\Microsoft.EntityFrameworkCore.Design.dll +microsoft.entityframeworkcore.design\2.2.0\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Design.dll +microsoft.entityframeworkcore.design\2.2.0\microsoft.entityframeworkcore.design.2.2.0.nupkg.sha512 +microsoft.entityframeworkcore.design\2.2.0\microsoft.entityframeworkcore.design.nuspec +microsoft.entityframeworkcore.inmemory\2.2.0\.nupkg.metadata +microsoft.entityframeworkcore.inmemory\2.2.0\.signature.p7s +microsoft.entityframeworkcore.inmemory\2.2.0\lib\netstandard2.0\Microsoft.EntityFrameworkCore.InMemory.dll +microsoft.entityframeworkcore.inmemory\2.2.0\microsoft.entityframeworkcore.inmemory.2.2.0.nupkg.sha512 +microsoft.entityframeworkcore.inmemory\2.2.0\microsoft.entityframeworkcore.inmemory.nuspec +microsoft.entityframeworkcore.relational\2.2.0\.nupkg.metadata +microsoft.entityframeworkcore.relational\2.2.0\.signature.p7s +microsoft.entityframeworkcore.relational\2.2.0\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Relational.dll +microsoft.entityframeworkcore.relational\2.2.0\microsoft.entityframeworkcore.relational.2.2.0.nupkg.sha512 +microsoft.entityframeworkcore.relational\2.2.0\microsoft.entityframeworkcore.relational.nuspec +microsoft.entityframeworkcore.sqlite.core\2.2.0\.nupkg.metadata +microsoft.entityframeworkcore.sqlite.core\2.2.0\.signature.p7s +microsoft.entityframeworkcore.sqlite.core\2.2.0\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Sqlite.dll +microsoft.entityframeworkcore.sqlite.core\2.2.0\microsoft.entityframeworkcore.sqlite.core.2.2.0.nupkg.sha512 +microsoft.entityframeworkcore.sqlite.core\2.2.0\microsoft.entityframeworkcore.sqlite.core.nuspec +microsoft.entityframeworkcore.sqlite\2.2.0\.nupkg.metadata +microsoft.entityframeworkcore.sqlite\2.2.0\.signature.p7s +microsoft.entityframeworkcore.sqlite\2.2.0\lib\netstandard2.0\_._ +microsoft.entityframeworkcore.sqlite\2.2.0\microsoft.entityframeworkcore.sqlite.2.2.0.nupkg.sha512 +microsoft.entityframeworkcore.sqlite\2.2.0\microsoft.entityframeworkcore.sqlite.nuspec +microsoft.entityframeworkcore.sqlserver\2.2.0\.nupkg.metadata +microsoft.entityframeworkcore.sqlserver\2.2.0\.signature.p7s +microsoft.entityframeworkcore.sqlserver\2.2.0\lib\netstandard2.0\Microsoft.EntityFrameworkCore.SqlServer.dll +microsoft.entityframeworkcore.sqlserver\2.2.0\microsoft.entityframeworkcore.sqlserver.2.2.0.nupkg.sha512 +microsoft.entityframeworkcore.sqlserver\2.2.0\microsoft.entityframeworkcore.sqlserver.nuspec +microsoft.entityframeworkcore.tools\2.2.0\.nupkg.metadata +microsoft.entityframeworkcore.tools\2.2.0\.signature.p7s +microsoft.entityframeworkcore.tools\2.2.0\lib\netstandard2.0\_._ +microsoft.entityframeworkcore.tools\2.2.0\microsoft.entityframeworkcore.tools.2.2.0.nupkg.sha512 +microsoft.entityframeworkcore.tools\2.2.0\microsoft.entityframeworkcore.tools.nuspec +microsoft.entityframeworkcore.tools\2.2.0\tools\about_EntityFrameworkCore.help.txt +microsoft.entityframeworkcore.tools\2.2.0\tools\EntityFrameworkCore.PowerShell2.psd1 +microsoft.entityframeworkcore.tools\2.2.0\tools\EntityFrameworkCore.PowerShell2.psm1 +microsoft.entityframeworkcore.tools\2.2.0\tools\EntityFrameworkCore.psd1 +microsoft.entityframeworkcore.tools\2.2.0\tools\EntityFrameworkCore.psm1 +microsoft.entityframeworkcore.tools\2.2.0\tools\init.ps1 +microsoft.entityframeworkcore.tools\2.2.0\tools\install.ps1 +microsoft.entityframeworkcore.tools\2.2.0\tools\net461\any\ef.exe +microsoft.entityframeworkcore.tools\2.2.0\tools\net461\win-x86\ef.exe +microsoft.entityframeworkcore.tools\2.2.0\tools\netcoreapp2.0\any\ef.dll +microsoft.entityframeworkcore.tools\2.2.0\tools\netcoreapp2.0\any\ef.runtimeconfig.json +microsoft.entityframeworkcore\2.2.0\.nupkg.metadata +microsoft.entityframeworkcore\2.2.0\.signature.p7s +microsoft.entityframeworkcore\2.2.0\lib\netstandard2.0\Microsoft.EntityFrameworkCore.dll +microsoft.entityframeworkcore\2.2.0\microsoft.entityframeworkcore.2.2.0.nupkg.sha512 +microsoft.entityframeworkcore\2.2.0\microsoft.entityframeworkcore.nuspec +microsoft.extensions.caching.abstractions\2.2.0\.nupkg.metadata +microsoft.extensions.caching.abstractions\2.2.0\.signature.p7s +microsoft.extensions.caching.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Caching.Abstractions.dll +microsoft.extensions.caching.abstractions\2.2.0\microsoft.extensions.caching.abstractions.2.2.0.nupkg.sha512 +microsoft.extensions.caching.abstractions\2.2.0\microsoft.extensions.caching.abstractions.nuspec +microsoft.extensions.caching.memory\2.2.0\.nupkg.metadata +microsoft.extensions.caching.memory\2.2.0\.signature.p7s +microsoft.extensions.caching.memory\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Caching.Memory.dll +microsoft.extensions.caching.memory\2.2.0\microsoft.extensions.caching.memory.2.2.0.nupkg.sha512 +microsoft.extensions.caching.memory\2.2.0\microsoft.extensions.caching.memory.nuspec +microsoft.extensions.caching.redis\2.2.0\.nupkg.metadata +microsoft.extensions.caching.redis\2.2.0\.signature.p7s +microsoft.extensions.caching.redis\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Caching.Redis.dll +microsoft.extensions.caching.redis\2.2.0\microsoft.extensions.caching.redis.2.2.0.nupkg.sha512 +microsoft.extensions.caching.redis\2.2.0\microsoft.extensions.caching.redis.nuspec +microsoft.extensions.caching.sqlserver\2.2.0\.nupkg.metadata +microsoft.extensions.caching.sqlserver\2.2.0\.signature.p7s +microsoft.extensions.caching.sqlserver\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Caching.SqlServer.dll +microsoft.extensions.caching.sqlserver\2.2.0\microsoft.extensions.caching.sqlserver.2.2.0.nupkg.sha512 +microsoft.extensions.caching.sqlserver\2.2.0\microsoft.extensions.caching.sqlserver.nuspec +microsoft.extensions.configuration.abstractions\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.abstractions\2.2.0\.signature.p7s +microsoft.extensions.configuration.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.Abstractions.dll +microsoft.extensions.configuration.abstractions\2.2.0\microsoft.extensions.configuration.abstractions.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.abstractions\2.2.0\microsoft.extensions.configuration.abstractions.nuspec +microsoft.extensions.configuration.azurekeyvault\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.azurekeyvault\2.2.0\.signature.p7s +microsoft.extensions.configuration.azurekeyvault\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.AzureKeyVault.dll +microsoft.extensions.configuration.azurekeyvault\2.2.0\microsoft.extensions.configuration.azurekeyvault.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.azurekeyvault\2.2.0\microsoft.extensions.configuration.azurekeyvault.nuspec +microsoft.extensions.configuration.binder\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.binder\2.2.0\.signature.p7s +microsoft.extensions.configuration.binder\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.Binder.dll +microsoft.extensions.configuration.binder\2.2.0\microsoft.extensions.configuration.binder.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.binder\2.2.0\microsoft.extensions.configuration.binder.nuspec +microsoft.extensions.configuration.commandline\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.commandline\2.2.0\.signature.p7s +microsoft.extensions.configuration.commandline\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.CommandLine.dll +microsoft.extensions.configuration.commandline\2.2.0\microsoft.extensions.configuration.commandline.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.commandline\2.2.0\microsoft.extensions.configuration.commandline.nuspec +microsoft.extensions.configuration.environmentvariables\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.environmentvariables\2.2.0\.signature.p7s +microsoft.extensions.configuration.environmentvariables\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.EnvironmentVariables.dll +microsoft.extensions.configuration.environmentvariables\2.2.0\microsoft.extensions.configuration.environmentvariables.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.environmentvariables\2.2.0\microsoft.extensions.configuration.environmentvariables.nuspec +microsoft.extensions.configuration.fileextensions\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.fileextensions\2.2.0\.signature.p7s +microsoft.extensions.configuration.fileextensions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.FileExtensions.dll +microsoft.extensions.configuration.fileextensions\2.2.0\microsoft.extensions.configuration.fileextensions.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.fileextensions\2.2.0\microsoft.extensions.configuration.fileextensions.nuspec +microsoft.extensions.configuration.ini\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.ini\2.2.0\.signature.p7s +microsoft.extensions.configuration.ini\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.Ini.dll +microsoft.extensions.configuration.ini\2.2.0\microsoft.extensions.configuration.ini.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.ini\2.2.0\microsoft.extensions.configuration.ini.nuspec +microsoft.extensions.configuration.json\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.json\2.2.0\.signature.p7s +microsoft.extensions.configuration.json\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.Json.dll +microsoft.extensions.configuration.json\2.2.0\microsoft.extensions.configuration.json.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.json\2.2.0\microsoft.extensions.configuration.json.nuspec +microsoft.extensions.configuration.keyperfile\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.keyperfile\2.2.0\.signature.p7s +microsoft.extensions.configuration.keyperfile\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.KeyPerFile.dll +microsoft.extensions.configuration.keyperfile\2.2.0\microsoft.extensions.configuration.keyperfile.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.keyperfile\2.2.0\microsoft.extensions.configuration.keyperfile.nuspec +microsoft.extensions.configuration.usersecrets\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.usersecrets\2.2.0\.signature.p7s +microsoft.extensions.configuration.usersecrets\2.2.0\build\netstandard2.0\Microsoft.Extensions.Configuration.UserSecrets.props +microsoft.extensions.configuration.usersecrets\2.2.0\build\netstandard2.0\Microsoft.Extensions.Configuration.UserSecrets.targets +microsoft.extensions.configuration.usersecrets\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.UserSecrets.dll +microsoft.extensions.configuration.usersecrets\2.2.0\microsoft.extensions.configuration.usersecrets.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.usersecrets\2.2.0\microsoft.extensions.configuration.usersecrets.nuspec +microsoft.extensions.configuration.xml\2.2.0\.nupkg.metadata +microsoft.extensions.configuration.xml\2.2.0\.signature.p7s +microsoft.extensions.configuration.xml\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.Xml.dll +microsoft.extensions.configuration.xml\2.2.0\microsoft.extensions.configuration.xml.2.2.0.nupkg.sha512 +microsoft.extensions.configuration.xml\2.2.0\microsoft.extensions.configuration.xml.nuspec +microsoft.extensions.configuration\2.2.0\.nupkg.metadata +microsoft.extensions.configuration\2.2.0\.signature.p7s +microsoft.extensions.configuration\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.dll +microsoft.extensions.configuration\2.2.0\microsoft.extensions.configuration.2.2.0.nupkg.sha512 +microsoft.extensions.configuration\2.2.0\microsoft.extensions.configuration.nuspec +microsoft.extensions.dependencyinjection.abstractions\2.2.0\.nupkg.metadata +microsoft.extensions.dependencyinjection.abstractions\2.2.0\.signature.p7s +microsoft.extensions.dependencyinjection.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll +microsoft.extensions.dependencyinjection.abstractions\2.2.0\microsoft.extensions.dependencyinjection.abstractions.2.2.0.nupkg.sha512 +microsoft.extensions.dependencyinjection.abstractions\2.2.0\microsoft.extensions.dependencyinjection.abstractions.nuspec +microsoft.extensions.dependencyinjection\2.2.0\.nupkg.metadata +microsoft.extensions.dependencyinjection\2.2.0\.signature.p7s +microsoft.extensions.dependencyinjection\2.2.0\lib\net461\Microsoft.Extensions.DependencyInjection.dll +microsoft.extensions.dependencyinjection\2.2.0\lib\netcoreapp2.0\Microsoft.Extensions.DependencyInjection.dll +microsoft.extensions.dependencyinjection\2.2.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.dll +microsoft.extensions.dependencyinjection\2.2.0\microsoft.extensions.dependencyinjection.2.2.0.nupkg.sha512 +microsoft.extensions.dependencyinjection\2.2.0\microsoft.extensions.dependencyinjection.nuspec +microsoft.extensions.dependencymodel\2.1.0\.nupkg.metadata +microsoft.extensions.diagnosticadapter\2.2.0\.nupkg.metadata +microsoft.extensions.diagnosticadapter\2.2.0\.signature.p7s +microsoft.extensions.diagnosticadapter\2.2.0\lib\net461\Microsoft.Extensions.DiagnosticAdapter.dll +microsoft.extensions.diagnosticadapter\2.2.0\lib\netcoreapp2.0\Microsoft.Extensions.DiagnosticAdapter.dll +microsoft.extensions.diagnosticadapter\2.2.0\lib\netstandard2.0\Microsoft.Extensions.DiagnosticAdapter.dll +microsoft.extensions.diagnosticadapter\2.2.0\microsoft.extensions.diagnosticadapter.2.2.0.nupkg.sha512 +microsoft.extensions.diagnosticadapter\2.2.0\microsoft.extensions.diagnosticadapter.nuspec +microsoft.extensions.diagnostics.healthchecks.abstractions\2.2.0\.nupkg.metadata +microsoft.extensions.diagnostics.healthchecks.abstractions\2.2.0\.signature.p7s +microsoft.extensions.diagnostics.healthchecks.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.dll +microsoft.extensions.diagnostics.healthchecks.abstractions\2.2.0\microsoft.extensions.diagnostics.healthchecks.abstractions.2.2.0.nupkg.sha512 +microsoft.extensions.diagnostics.healthchecks.abstractions\2.2.0\microsoft.extensions.diagnostics.healthchecks.abstractions.nuspec +microsoft.extensions.diagnostics.healthchecks\2.2.0\.nupkg.metadata +microsoft.extensions.diagnostics.healthchecks\2.2.0\.signature.p7s +microsoft.extensions.diagnostics.healthchecks\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Diagnostics.HealthChecks.dll +microsoft.extensions.diagnostics.healthchecks\2.2.0\microsoft.extensions.diagnostics.healthchecks.2.2.0.nupkg.sha512 +microsoft.extensions.diagnostics.healthchecks\2.2.0\microsoft.extensions.diagnostics.healthchecks.nuspec +microsoft.extensions.fileproviders.abstractions\2.2.0\.nupkg.metadata +microsoft.extensions.fileproviders.abstractions\2.2.0\.signature.p7s +microsoft.extensions.fileproviders.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Abstractions.dll +microsoft.extensions.fileproviders.abstractions\2.2.0\microsoft.extensions.fileproviders.abstractions.2.2.0.nupkg.sha512 +microsoft.extensions.fileproviders.abstractions\2.2.0\microsoft.extensions.fileproviders.abstractions.nuspec +microsoft.extensions.fileproviders.composite\2.2.0\.nupkg.metadata +microsoft.extensions.fileproviders.composite\2.2.0\.signature.p7s +microsoft.extensions.fileproviders.composite\2.2.0\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Composite.dll +microsoft.extensions.fileproviders.composite\2.2.0\microsoft.extensions.fileproviders.composite.2.2.0.nupkg.sha512 +microsoft.extensions.fileproviders.composite\2.2.0\microsoft.extensions.fileproviders.composite.nuspec +microsoft.extensions.fileproviders.embedded\2.2.0\.nupkg.metadata +microsoft.extensions.fileproviders.embedded\2.2.0\.signature.p7s +microsoft.extensions.fileproviders.embedded\2.2.0\build\netstandard2.0\Microsoft.Extensions.FileProviders.Embedded.props +microsoft.extensions.fileproviders.embedded\2.2.0\build\netstandard2.0\Microsoft.Extensions.FileProviders.Embedded.targets +microsoft.extensions.fileproviders.embedded\2.2.0\buildMultiTargeting\Microsoft.Extensions.FileProviders.Embedded.props +microsoft.extensions.fileproviders.embedded\2.2.0\buildMultiTargeting\Microsoft.Extensions.FileProviders.Embedded.targets +microsoft.extensions.fileproviders.embedded\2.2.0\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Embedded.dll +microsoft.extensions.fileproviders.embedded\2.2.0\microsoft.extensions.fileproviders.embedded.2.2.0.nupkg.sha512 +microsoft.extensions.fileproviders.embedded\2.2.0\microsoft.extensions.fileproviders.embedded.nuspec +microsoft.extensions.fileproviders.embedded\2.2.0\tasks\net461\Microsoft.Extensions.FileProviders.Embedded.Manifest.Task.dll +microsoft.extensions.fileproviders.embedded\2.2.0\tasks\netstandard1.5\Microsoft.Extensions.FileProviders.Embedded.Manifest.Task.dll +microsoft.extensions.fileproviders.physical\2.2.0\.nupkg.metadata +microsoft.extensions.fileproviders.physical\2.2.0\.signature.p7s +microsoft.extensions.fileproviders.physical\2.2.0\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Physical.dll +microsoft.extensions.fileproviders.physical\2.2.0\microsoft.extensions.fileproviders.physical.2.2.0.nupkg.sha512 +microsoft.extensions.fileproviders.physical\2.2.0\microsoft.extensions.fileproviders.physical.nuspec +microsoft.extensions.filesystemglobbing\2.2.0\.nupkg.metadata +microsoft.extensions.filesystemglobbing\2.2.0\.signature.p7s +microsoft.extensions.filesystemglobbing\2.2.0\lib\netstandard2.0\Microsoft.Extensions.FileSystemGlobbing.dll +microsoft.extensions.filesystemglobbing\2.2.0\microsoft.extensions.filesystemglobbing.2.2.0.nupkg.sha512 +microsoft.extensions.filesystemglobbing\2.2.0\microsoft.extensions.filesystemglobbing.nuspec +microsoft.extensions.hosting.abstractions\2.2.0\.nupkg.metadata +microsoft.extensions.hosting.abstractions\2.2.0\.signature.p7s +microsoft.extensions.hosting.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Hosting.Abstractions.dll +microsoft.extensions.hosting.abstractions\2.2.0\microsoft.extensions.hosting.abstractions.2.2.0.nupkg.sha512 +microsoft.extensions.hosting.abstractions\2.2.0\microsoft.extensions.hosting.abstractions.nuspec +microsoft.extensions.hosting\2.2.0\.nupkg.metadata +microsoft.extensions.hosting\2.2.0\.signature.p7s +microsoft.extensions.hosting\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Hosting.dll +microsoft.extensions.hosting\2.2.0\microsoft.extensions.hosting.2.2.0.nupkg.sha512 +microsoft.extensions.hosting\2.2.0\microsoft.extensions.hosting.nuspec +microsoft.extensions.http\2.2.0\.nupkg.metadata +microsoft.extensions.http\2.2.0\.signature.p7s +microsoft.extensions.http\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Http.dll +microsoft.extensions.http\2.2.0\microsoft.extensions.http.2.2.0.nupkg.sha512 +microsoft.extensions.http\2.2.0\microsoft.extensions.http.nuspec +microsoft.extensions.identity.core\2.2.0\.nupkg.metadata +microsoft.extensions.identity.core\2.2.0\.signature.p7s +microsoft.extensions.identity.core\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Identity.Core.dll +microsoft.extensions.identity.core\2.2.0\microsoft.extensions.identity.core.2.2.0.nupkg.sha512 +microsoft.extensions.identity.core\2.2.0\microsoft.extensions.identity.core.nuspec +microsoft.extensions.identity.stores\2.2.0\.nupkg.metadata +microsoft.extensions.identity.stores\2.2.0\.signature.p7s +microsoft.extensions.identity.stores\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Identity.Stores.dll +microsoft.extensions.identity.stores\2.2.0\microsoft.extensions.identity.stores.2.2.0.nupkg.sha512 +microsoft.extensions.identity.stores\2.2.0\microsoft.extensions.identity.stores.nuspec +microsoft.extensions.localization.abstractions\2.2.0\.nupkg.metadata +microsoft.extensions.localization.abstractions\2.2.0\.signature.p7s +microsoft.extensions.localization.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Localization.Abstractions.dll +microsoft.extensions.localization.abstractions\2.2.0\microsoft.extensions.localization.abstractions.2.2.0.nupkg.sha512 +microsoft.extensions.localization.abstractions\2.2.0\microsoft.extensions.localization.abstractions.nuspec +microsoft.extensions.localization\2.2.0\.nupkg.metadata +microsoft.extensions.localization\2.2.0\.signature.p7s +microsoft.extensions.localization\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Localization.dll +microsoft.extensions.localization\2.2.0\microsoft.extensions.localization.2.2.0.nupkg.sha512 +microsoft.extensions.localization\2.2.0\microsoft.extensions.localization.nuspec +microsoft.extensions.logging.abstractions\2.2.0\.nupkg.metadata +microsoft.extensions.logging.abstractions\2.2.0\.signature.p7s +microsoft.extensions.logging.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll +microsoft.extensions.logging.abstractions\2.2.0\microsoft.extensions.logging.abstractions.2.2.0.nupkg.sha512 +microsoft.extensions.logging.abstractions\2.2.0\microsoft.extensions.logging.abstractions.nuspec +microsoft.extensions.logging.azureappservices\2.2.0\.nupkg.metadata +microsoft.extensions.logging.azureappservices\2.2.0\.signature.p7s +microsoft.extensions.logging.azureappservices\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.AzureAppServices.dll +microsoft.extensions.logging.azureappservices\2.2.0\microsoft.extensions.logging.azureappservices.2.2.0.nupkg.sha512 +microsoft.extensions.logging.azureappservices\2.2.0\microsoft.extensions.logging.azureappservices.nuspec +microsoft.extensions.logging.configuration\2.2.0\.nupkg.metadata +microsoft.extensions.logging.configuration\2.2.0\.signature.p7s +microsoft.extensions.logging.configuration\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Configuration.dll +microsoft.extensions.logging.configuration\2.2.0\microsoft.extensions.logging.configuration.2.2.0.nupkg.sha512 +microsoft.extensions.logging.configuration\2.2.0\microsoft.extensions.logging.configuration.nuspec +microsoft.extensions.logging.console\2.2.0\.nupkg.metadata +microsoft.extensions.logging.console\2.2.0\.signature.p7s +microsoft.extensions.logging.console\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Console.dll +microsoft.extensions.logging.console\2.2.0\microsoft.extensions.logging.console.2.2.0.nupkg.sha512 +microsoft.extensions.logging.console\2.2.0\microsoft.extensions.logging.console.nuspec +microsoft.extensions.logging.debug\2.2.0\.nupkg.metadata +microsoft.extensions.logging.debug\2.2.0\.signature.p7s +microsoft.extensions.logging.debug\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Debug.dll +microsoft.extensions.logging.debug\2.2.0\microsoft.extensions.logging.debug.2.2.0.nupkg.sha512 +microsoft.extensions.logging.debug\2.2.0\microsoft.extensions.logging.debug.nuspec +microsoft.extensions.logging.eventsource\2.2.0\.nupkg.metadata +microsoft.extensions.logging.eventsource\2.2.0\.signature.p7s +microsoft.extensions.logging.eventsource\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.EventSource.dll +microsoft.extensions.logging.eventsource\2.2.0\microsoft.extensions.logging.eventsource.2.2.0.nupkg.sha512 +microsoft.extensions.logging.eventsource\2.2.0\microsoft.extensions.logging.eventsource.nuspec +microsoft.extensions.logging.tracesource\2.2.0\.nupkg.metadata +microsoft.extensions.logging.tracesource\2.2.0\.signature.p7s +microsoft.extensions.logging.tracesource\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.TraceSource.dll +microsoft.extensions.logging.tracesource\2.2.0\microsoft.extensions.logging.tracesource.2.2.0.nupkg.sha512 +microsoft.extensions.logging.tracesource\2.2.0\microsoft.extensions.logging.tracesource.nuspec +microsoft.extensions.logging\2.2.0\.nupkg.metadata +microsoft.extensions.logging\2.2.0\.signature.p7s +microsoft.extensions.logging\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.dll +microsoft.extensions.logging\2.2.0\microsoft.extensions.logging.2.2.0.nupkg.sha512 +microsoft.extensions.logging\2.2.0\microsoft.extensions.logging.nuspec +microsoft.extensions.objectpool\2.2.0\.nupkg.metadata +microsoft.extensions.objectpool\2.2.0\.signature.p7s +microsoft.extensions.objectpool\2.2.0\lib\netstandard2.0\Microsoft.Extensions.ObjectPool.dll +microsoft.extensions.objectpool\2.2.0\microsoft.extensions.objectpool.2.2.0.nupkg.sha512 +microsoft.extensions.objectpool\2.2.0\microsoft.extensions.objectpool.nuspec +microsoft.extensions.options.configurationextensions\2.2.0\.nupkg.metadata +microsoft.extensions.options.configurationextensions\2.2.0\.signature.p7s +microsoft.extensions.options.configurationextensions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Options.ConfigurationExtensions.dll +microsoft.extensions.options.configurationextensions\2.2.0\microsoft.extensions.options.configurationextensions.2.2.0.nupkg.sha512 +microsoft.extensions.options.configurationextensions\2.2.0\microsoft.extensions.options.configurationextensions.nuspec +microsoft.extensions.options.dataannotations\2.2.0\.nupkg.metadata +microsoft.extensions.options.dataannotations\2.2.0\.signature.p7s +microsoft.extensions.options.dataannotations\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Options.DataAnnotations.dll +microsoft.extensions.options.dataannotations\2.2.0\microsoft.extensions.options.dataannotations.2.2.0.nupkg.sha512 +microsoft.extensions.options.dataannotations\2.2.0\microsoft.extensions.options.dataannotations.nuspec +microsoft.extensions.options\2.2.0\.nupkg.metadata +microsoft.extensions.options\2.2.0\.signature.p7s +microsoft.extensions.options\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Options.dll +microsoft.extensions.options\2.2.0\microsoft.extensions.options.2.2.0.nupkg.sha512 +microsoft.extensions.options\2.2.0\microsoft.extensions.options.nuspec +microsoft.extensions.platformabstractions\1.1.0\.nupkg.metadata +microsoft.extensions.primitives\2.2.0\.nupkg.metadata +microsoft.extensions.primitives\2.2.0\.signature.p7s +microsoft.extensions.primitives\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Primitives.dll +microsoft.extensions.primitives\2.2.0\microsoft.extensions.primitives.2.2.0.nupkg.sha512 +microsoft.extensions.primitives\2.2.0\microsoft.extensions.primitives.nuspec +microsoft.extensions.webencoders\2.2.0\.nupkg.metadata +microsoft.extensions.webencoders\2.2.0\.signature.p7s +microsoft.extensions.webencoders\2.2.0\lib\netstandard2.0\Microsoft.Extensions.WebEncoders.dll +microsoft.extensions.webencoders\2.2.0\microsoft.extensions.webencoders.2.2.0.nupkg.sha512 +microsoft.extensions.webencoders\2.2.0\microsoft.extensions.webencoders.nuspec +microsoft.identitymodel.clients.activedirectory\3.14.2\.nupkg.metadata +microsoft.identitymodel.clients.activedirectory\3.14.2\.signature.p7s +microsoft.identitymodel.clients.activedirectory\3.19.8\.nupkg.metadata +microsoft.identitymodel.clients.activedirectory\3.19.8\.signature.p7s +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\MonoAndroid7\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\MonoAndroid7\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\netcore45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\netcore45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\netstandard1.1\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\netstandard1.1\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\netstandard1.3\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\netstandard1.3\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\portable-net45+win\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\portable-net45+win\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\Xamarin.iOS10\Microsoft.IdentityModel.Clients.ActiveDirectory.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\lib\Xamarin.iOS10\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll +microsoft.identitymodel.clients.activedirectory\3.19.8\microsoft.identitymodel.clients.activedirectory.3.19.8.nupkg.sha512 +microsoft.identitymodel.clients.activedirectory\3.19.8\microsoft.identitymodel.clients.activedirectory.nuspec +microsoft.identitymodel.jsonwebtokens\5.3.0\.nupkg.metadata +microsoft.identitymodel.jsonwebtokens\5.3.0\.signature.p7s +microsoft.identitymodel.jsonwebtokens\5.3.0\lib\net45\Microsoft.IdentityModel.JsonWebTokens.dll +microsoft.identitymodel.jsonwebtokens\5.3.0\lib\net45\Microsoft.IdentityModel.JsonWebTokens.pdb +microsoft.identitymodel.jsonwebtokens\5.3.0\lib\net451\Microsoft.IdentityModel.JsonWebTokens.dll +microsoft.identitymodel.jsonwebtokens\5.3.0\lib\net451\Microsoft.IdentityModel.JsonWebTokens.pdb +microsoft.identitymodel.jsonwebtokens\5.3.0\lib\net461\Microsoft.IdentityModel.JsonWebTokens.dll +microsoft.identitymodel.jsonwebtokens\5.3.0\lib\net461\Microsoft.IdentityModel.JsonWebTokens.pdb +microsoft.identitymodel.jsonwebtokens\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.JsonWebTokens.dll +microsoft.identitymodel.jsonwebtokens\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.JsonWebTokens.pdb +microsoft.identitymodel.jsonwebtokens\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.JsonWebTokens.dll +microsoft.identitymodel.jsonwebtokens\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.JsonWebTokens.pdb +microsoft.identitymodel.jsonwebtokens\5.3.0\microsoft.identitymodel.jsonwebtokens.5.3.0.nupkg.sha512 +microsoft.identitymodel.jsonwebtokens\5.3.0\microsoft.identitymodel.jsonwebtokens.nuspec +microsoft.identitymodel.logging\5.3.0\.nupkg.metadata +microsoft.identitymodel.logging\5.3.0\.signature.p7s +microsoft.identitymodel.logging\5.3.0\lib\net45\Microsoft.IdentityModel.Logging.dll +microsoft.identitymodel.logging\5.3.0\lib\net45\Microsoft.IdentityModel.Logging.pdb +microsoft.identitymodel.logging\5.3.0\lib\net451\Microsoft.IdentityModel.Logging.dll +microsoft.identitymodel.logging\5.3.0\lib\net451\Microsoft.IdentityModel.Logging.pdb +microsoft.identitymodel.logging\5.3.0\lib\net461\Microsoft.IdentityModel.Logging.dll +microsoft.identitymodel.logging\5.3.0\lib\net461\Microsoft.IdentityModel.Logging.pdb +microsoft.identitymodel.logging\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Logging.dll +microsoft.identitymodel.logging\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Logging.pdb +microsoft.identitymodel.logging\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Logging.dll +microsoft.identitymodel.logging\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Logging.pdb +microsoft.identitymodel.logging\5.3.0\microsoft.identitymodel.logging.5.3.0.nupkg.sha512 +microsoft.identitymodel.logging\5.3.0\microsoft.identitymodel.logging.nuspec +microsoft.identitymodel.protocols.openidconnect\5.3.0\.nupkg.metadata +microsoft.identitymodel.protocols.openidconnect\5.3.0\.signature.p7s +microsoft.identitymodel.protocols.openidconnect\5.3.0\lib\net45\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll +microsoft.identitymodel.protocols.openidconnect\5.3.0\lib\net45\Microsoft.IdentityModel.Protocols.OpenIdConnect.pdb +microsoft.identitymodel.protocols.openidconnect\5.3.0\lib\net451\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll +microsoft.identitymodel.protocols.openidconnect\5.3.0\lib\net451\Microsoft.IdentityModel.Protocols.OpenIdConnect.pdb +microsoft.identitymodel.protocols.openidconnect\5.3.0\lib\net461\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll +microsoft.identitymodel.protocols.openidconnect\5.3.0\lib\net461\Microsoft.IdentityModel.Protocols.OpenIdConnect.pdb +microsoft.identitymodel.protocols.openidconnect\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll +microsoft.identitymodel.protocols.openidconnect\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Protocols.OpenIdConnect.pdb +microsoft.identitymodel.protocols.openidconnect\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll +microsoft.identitymodel.protocols.openidconnect\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Protocols.OpenIdConnect.pdb +microsoft.identitymodel.protocols.openidconnect\5.3.0\microsoft.identitymodel.protocols.openidconnect.5.3.0.nupkg.sha512 +microsoft.identitymodel.protocols.openidconnect\5.3.0\microsoft.identitymodel.protocols.openidconnect.nuspec +microsoft.identitymodel.protocols.wsfederation\5.3.0\.nupkg.metadata +microsoft.identitymodel.protocols.wsfederation\5.3.0\.signature.p7s +microsoft.identitymodel.protocols.wsfederation\5.3.0\lib\net45\Microsoft.IdentityModel.Protocols.WsFederation.dll +microsoft.identitymodel.protocols.wsfederation\5.3.0\lib\net45\Microsoft.IdentityModel.Protocols.WsFederation.pdb +microsoft.identitymodel.protocols.wsfederation\5.3.0\lib\net451\Microsoft.IdentityModel.Protocols.WsFederation.dll +microsoft.identitymodel.protocols.wsfederation\5.3.0\lib\net451\Microsoft.IdentityModel.Protocols.WsFederation.pdb +microsoft.identitymodel.protocols.wsfederation\5.3.0\lib\net461\Microsoft.IdentityModel.Protocols.WsFederation.dll +microsoft.identitymodel.protocols.wsfederation\5.3.0\lib\net461\Microsoft.IdentityModel.Protocols.WsFederation.pdb +microsoft.identitymodel.protocols.wsfederation\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Protocols.WsFederation.dll +microsoft.identitymodel.protocols.wsfederation\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Protocols.WsFederation.pdb +microsoft.identitymodel.protocols.wsfederation\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Protocols.WsFederation.dll +microsoft.identitymodel.protocols.wsfederation\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Protocols.WsFederation.pdb +microsoft.identitymodel.protocols.wsfederation\5.3.0\microsoft.identitymodel.protocols.wsfederation.5.3.0.nupkg.sha512 +microsoft.identitymodel.protocols.wsfederation\5.3.0\microsoft.identitymodel.protocols.wsfederation.nuspec +microsoft.identitymodel.protocols\5.3.0\.nupkg.metadata +microsoft.identitymodel.protocols\5.3.0\.signature.p7s +microsoft.identitymodel.protocols\5.3.0\lib\net45\Microsoft.IdentityModel.Protocols.dll +microsoft.identitymodel.protocols\5.3.0\lib\net45\Microsoft.IdentityModel.Protocols.pdb +microsoft.identitymodel.protocols\5.3.0\lib\net451\Microsoft.IdentityModel.Protocols.dll +microsoft.identitymodel.protocols\5.3.0\lib\net451\Microsoft.IdentityModel.Protocols.pdb +microsoft.identitymodel.protocols\5.3.0\lib\net461\Microsoft.IdentityModel.Protocols.dll +microsoft.identitymodel.protocols\5.3.0\lib\net461\Microsoft.IdentityModel.Protocols.pdb +microsoft.identitymodel.protocols\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Protocols.dll +microsoft.identitymodel.protocols\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Protocols.pdb +microsoft.identitymodel.protocols\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Protocols.dll +microsoft.identitymodel.protocols\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Protocols.pdb +microsoft.identitymodel.protocols\5.3.0\microsoft.identitymodel.protocols.5.3.0.nupkg.sha512 +microsoft.identitymodel.protocols\5.3.0\microsoft.identitymodel.protocols.nuspec +microsoft.identitymodel.tokens.saml\5.3.0\.nupkg.metadata +microsoft.identitymodel.tokens.saml\5.3.0\.signature.p7s +microsoft.identitymodel.tokens.saml\5.3.0\lib\net45\Microsoft.IdentityModel.Tokens.Saml.dll +microsoft.identitymodel.tokens.saml\5.3.0\lib\net45\Microsoft.IdentityModel.Tokens.Saml.pdb +microsoft.identitymodel.tokens.saml\5.3.0\lib\net451\Microsoft.IdentityModel.Tokens.Saml.dll +microsoft.identitymodel.tokens.saml\5.3.0\lib\net451\Microsoft.IdentityModel.Tokens.Saml.pdb +microsoft.identitymodel.tokens.saml\5.3.0\lib\net461\Microsoft.IdentityModel.Tokens.Saml.dll +microsoft.identitymodel.tokens.saml\5.3.0\lib\net461\Microsoft.IdentityModel.Tokens.Saml.pdb +microsoft.identitymodel.tokens.saml\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Tokens.Saml.dll +microsoft.identitymodel.tokens.saml\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Tokens.Saml.pdb +microsoft.identitymodel.tokens.saml\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Tokens.Saml.dll +microsoft.identitymodel.tokens.saml\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Tokens.Saml.pdb +microsoft.identitymodel.tokens.saml\5.3.0\microsoft.identitymodel.tokens.saml.5.3.0.nupkg.sha512 +microsoft.identitymodel.tokens.saml\5.3.0\microsoft.identitymodel.tokens.saml.nuspec +microsoft.identitymodel.tokens\5.3.0\.nupkg.metadata +microsoft.identitymodel.tokens\5.3.0\.signature.p7s +microsoft.identitymodel.tokens\5.3.0\lib\net45\Microsoft.IdentityModel.Tokens.dll +microsoft.identitymodel.tokens\5.3.0\lib\net45\Microsoft.IdentityModel.Tokens.pdb +microsoft.identitymodel.tokens\5.3.0\lib\net451\Microsoft.IdentityModel.Tokens.dll +microsoft.identitymodel.tokens\5.3.0\lib\net451\Microsoft.IdentityModel.Tokens.pdb +microsoft.identitymodel.tokens\5.3.0\lib\net461\Microsoft.IdentityModel.Tokens.dll +microsoft.identitymodel.tokens\5.3.0\lib\net461\Microsoft.IdentityModel.Tokens.pdb +microsoft.identitymodel.tokens\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Tokens.dll +microsoft.identitymodel.tokens\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Tokens.pdb +microsoft.identitymodel.tokens\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Tokens.dll +microsoft.identitymodel.tokens\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Tokens.pdb +microsoft.identitymodel.tokens\5.3.0\microsoft.identitymodel.tokens.5.3.0.nupkg.sha512 +microsoft.identitymodel.tokens\5.3.0\microsoft.identitymodel.tokens.nuspec +microsoft.identitymodel.xml\5.3.0\.nupkg.metadata +microsoft.identitymodel.xml\5.3.0\.signature.p7s +microsoft.identitymodel.xml\5.3.0\lib\net45\Microsoft.IdentityModel.Xml.dll +microsoft.identitymodel.xml\5.3.0\lib\net45\Microsoft.IdentityModel.Xml.pdb +microsoft.identitymodel.xml\5.3.0\lib\net451\Microsoft.IdentityModel.Xml.dll +microsoft.identitymodel.xml\5.3.0\lib\net451\Microsoft.IdentityModel.Xml.pdb +microsoft.identitymodel.xml\5.3.0\lib\net461\Microsoft.IdentityModel.Xml.dll +microsoft.identitymodel.xml\5.3.0\lib\net461\Microsoft.IdentityModel.Xml.pdb +microsoft.identitymodel.xml\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Xml.dll +microsoft.identitymodel.xml\5.3.0\lib\netstandard1.4\Microsoft.IdentityModel.Xml.pdb +microsoft.identitymodel.xml\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Xml.dll +microsoft.identitymodel.xml\5.3.0\lib\netstandard2.0\Microsoft.IdentityModel.Xml.pdb +microsoft.identitymodel.xml\5.3.0\microsoft.identitymodel.xml.5.3.0.nupkg.sha512 +microsoft.identitymodel.xml\5.3.0\microsoft.identitymodel.xml.nuspec +microsoft.net.http.headers\2.2.0\.nupkg.metadata +microsoft.net.http.headers\2.2.0\.signature.p7s +microsoft.net.http.headers\2.2.0\lib\netstandard2.0\Microsoft.Net.Http.Headers.dll +microsoft.net.http.headers\2.2.0\microsoft.net.http.headers.2.2.0.nupkg.sha512 +microsoft.net.http.headers\2.2.0\microsoft.net.http.headers.nuspec +microsoft.netcore.app\2.2.0\.nupkg.metadata +microsoft.netcore.app\2.2.0\.signature.p7s +microsoft.netcore.app\2.2.0\build\netcoreapp2.2\Microsoft.NETCore.App.PlatformManifest.txt +microsoft.netcore.app\2.2.0\build\netcoreapp2.2\Microsoft.NETCore.App.props +microsoft.netcore.app\2.2.0\build\netcoreapp2.2\Microsoft.NETCore.App.targets +microsoft.netcore.app\2.2.0\LICENSE.TXT +microsoft.netcore.app\2.2.0\microsoft.netcore.app.2.2.0.nupkg.sha512 +microsoft.netcore.app\2.2.0\microsoft.netcore.app.nuspec +microsoft.netcore.app\2.2.0\Microsoft.NETCore.App.versions.txt +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\Microsoft.CSharp.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\Microsoft.VisualBasic.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\Microsoft.Win32.Primitives.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\mscorlib.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\netstandard.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.AppContext.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Buffers.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Collections.Concurrent.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Collections.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Collections.Immutable.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Collections.NonGeneric.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Collections.Specialized.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.ComponentModel.Annotations.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.ComponentModel.DataAnnotations.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.ComponentModel.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.ComponentModel.EventBasedAsync.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.ComponentModel.Primitives.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.ComponentModel.TypeConverter.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Configuration.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Console.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Core.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Data.Common.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Data.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Diagnostics.Contracts.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Diagnostics.Debug.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Diagnostics.DiagnosticSource.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Diagnostics.FileVersionInfo.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Diagnostics.Process.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Diagnostics.StackTrace.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Diagnostics.TextWriterTraceListener.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Diagnostics.Tools.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Diagnostics.TraceSource.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Diagnostics.Tracing.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Drawing.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Drawing.Primitives.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Dynamic.Runtime.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Globalization.Calendars.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Globalization.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Globalization.Extensions.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.Compression.Brotli.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.Compression.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.Compression.FileSystem.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.Compression.ZipFile.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.FileSystem.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.FileSystem.DriveInfo.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.FileSystem.Primitives.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.FileSystem.Watcher.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.IsolatedStorage.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.MemoryMappedFiles.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.Pipes.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.IO.UnmanagedMemoryStream.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Linq.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Linq.Expressions.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Linq.Parallel.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Linq.Queryable.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Memory.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.Http.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.HttpListener.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.Mail.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.NameResolution.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.NetworkInformation.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.Ping.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.Primitives.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.Requests.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.Security.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.ServicePoint.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.Sockets.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.WebClient.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.WebHeaderCollection.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.WebProxy.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.WebSockets.Client.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Net.WebSockets.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Numerics.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Numerics.Vectors.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.ObjectModel.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Reflection.DispatchProxy.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Reflection.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Reflection.Emit.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Reflection.Emit.ILGeneration.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Reflection.Emit.Lightweight.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Reflection.Extensions.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Reflection.Metadata.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Reflection.Primitives.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Reflection.TypeExtensions.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Resources.Reader.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Resources.ResourceManager.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Resources.Writer.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.CompilerServices.VisualC.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.Extensions.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.Handles.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.InteropServices.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.InteropServices.RuntimeInformation.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.InteropServices.WindowsRuntime.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.Loader.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.Numerics.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.Serialization.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.Serialization.Formatters.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.Serialization.Json.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.Serialization.Primitives.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Runtime.Serialization.Xml.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Security.Claims.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Security.Cryptography.Algorithms.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Security.Cryptography.Csp.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Security.Cryptography.Encoding.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Security.Cryptography.Primitives.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Security.Cryptography.X509Certificates.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Security.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Security.Principal.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Security.SecureString.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.ServiceModel.Web.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.ServiceProcess.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Text.Encoding.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Text.Encoding.Extensions.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Text.RegularExpressions.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Threading.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Threading.Overlapped.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Threading.Tasks.Dataflow.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Threading.Tasks.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Threading.Tasks.Extensions.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Threading.Tasks.Parallel.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Threading.Thread.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Threading.ThreadPool.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Threading.Timer.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Transactions.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Transactions.Local.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.ValueTuple.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Web.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Web.HttpUtility.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Windows.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Xml.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Xml.Linq.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Xml.ReaderWriter.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Xml.Serialization.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Xml.XDocument.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Xml.XmlDocument.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Xml.XmlSerializer.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Xml.XPath.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\System.Xml.XPath.XDocument.dll +microsoft.netcore.app\2.2.0\ref\netcoreapp2.2\WindowsBase.dll +microsoft.netcore.app\2.2.0\runtime.json +microsoft.netcore.app\2.2.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.dotnetapphost\2.2.0\.nupkg.metadata +microsoft.netcore.dotnetapphost\2.2.0\.signature.p7s +microsoft.netcore.dotnetapphost\2.2.0\LICENSE.TXT +microsoft.netcore.dotnetapphost\2.2.0\microsoft.netcore.dotnetapphost.2.2.0.nupkg.sha512 +microsoft.netcore.dotnetapphost\2.2.0\microsoft.netcore.dotnetapphost.nuspec +microsoft.netcore.dotnetapphost\2.2.0\runtime.json +microsoft.netcore.dotnetapphost\2.2.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.dotnethostpolicy\2.2.0\.nupkg.metadata +microsoft.netcore.dotnethostpolicy\2.2.0\.signature.p7s +microsoft.netcore.dotnethostpolicy\2.2.0\LICENSE.TXT +microsoft.netcore.dotnethostpolicy\2.2.0\microsoft.netcore.dotnethostpolicy.2.2.0.nupkg.sha512 +microsoft.netcore.dotnethostpolicy\2.2.0\microsoft.netcore.dotnethostpolicy.nuspec +microsoft.netcore.dotnethostpolicy\2.2.0\runtime.json +microsoft.netcore.dotnethostpolicy\2.2.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.dotnethostresolver\2.2.0\.nupkg.metadata +microsoft.netcore.dotnethostresolver\2.2.0\.signature.p7s +microsoft.netcore.dotnethostresolver\2.2.0\LICENSE.TXT +microsoft.netcore.dotnethostresolver\2.2.0\microsoft.netcore.dotnethostresolver.2.2.0.nupkg.sha512 +microsoft.netcore.dotnethostresolver\2.2.0\microsoft.netcore.dotnethostresolver.nuspec +microsoft.netcore.dotnethostresolver\2.2.0\runtime.json +microsoft.netcore.dotnethostresolver\2.2.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.platforms\1.0.1\.nupkg.metadata +microsoft.netcore.platforms\1.0.1\.signature.p7s +microsoft.netcore.platforms\1.0.2\.nupkg.metadata +microsoft.netcore.platforms\1.0.2\.signature.p7s +microsoft.netcore.platforms\1.1.0\.nupkg.metadata +microsoft.netcore.platforms\1.1.0\.signature.p7s +microsoft.netcore.platforms\2.0.0\.nupkg.metadata +microsoft.netcore.platforms\2.0.0\.signature.p7s +microsoft.netcore.platforms\2.2.0\.nupkg.metadata +microsoft.netcore.platforms\2.2.0\.signature.p7s +microsoft.netcore.platforms\2.2.0\lib\netstandard1.0\_._ +microsoft.netcore.platforms\2.2.0\LICENSE.TXT +microsoft.netcore.platforms\2.2.0\microsoft.netcore.platforms.2.2.0.nupkg.sha512 +microsoft.netcore.platforms\2.2.0\microsoft.netcore.platforms.nuspec +microsoft.netcore.platforms\2.2.0\runtime.json +microsoft.netcore.platforms\2.2.0\THIRD-PARTY-NOTICES.TXT +microsoft.netcore.platforms\2.2.0\useSharedDesignerContext.txt +microsoft.netcore.platforms\2.2.0\version.txt +microsoft.netcore.targets\1.0.1\.nupkg.metadata +microsoft.netcore.targets\1.1.0\.nupkg.metadata +microsoft.netcore.targets\2.0.0\.nupkg.metadata +microsoft.rest.clientruntime.azure\3.3.7\.nupkg.metadata +microsoft.rest.clientruntime.azure\3.3.7\.signature.p7s +microsoft.rest.clientruntime\2.3.8\.nupkg.metadata +microsoft.rest.clientruntime\2.3.8\.signature.p7s +microsoft.visualstudio.web.browserlink\2.2.0\.nupkg.metadata +microsoft.visualstudio.web.browserlink\2.2.0\.signature.p7s +microsoft.visualstudio.web.browserlink\2.2.0\lib\netstandard2.0\Microsoft.VisualStudio.Web.BrowserLink.dll +microsoft.visualstudio.web.browserlink\2.2.0\microsoft.visualstudio.web.browserlink.2.2.0.nupkg.sha512 +microsoft.visualstudio.web.browserlink\2.2.0\microsoft.visualstudio.web.browserlink.nuspec +microsoft.win32.primitives\4.0.1\.nupkg.metadata +microsoft.win32.primitives\4.3.0\.nupkg.metadata +microsoft.win32.registry\4.3.0\.nupkg.metadata +microsoft.win32.registry\4.5.0\.nupkg.metadata +netstandard.library\1.6.0\.nupkg.metadata +netstandard.library\1.6.1\.nupkg.metadata +netstandard.library\2.0.3\.nupkg.metadata +newtonsoft.json.bson\1.0.1\.nupkg.metadata +newtonsoft.json.bson\1.0.1\.signature.p7s +newtonsoft.json\10.0.1\.nupkg.metadata +newtonsoft.json\10.0.1\.signature.p7s +newtonsoft.json\11.0.2\.nupkg.metadata +newtonsoft.json\11.0.2\.signature.p7s +newtonsoft.json\9.0.1\.nupkg.metadata +remotion.linq\2.2.0\.nupkg.metadata +remotion.linq\2.2.0\.signature.p7s +runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.native.system.data.sqlclient.sni\4.5.0\.nupkg.metadata +runtime.native.system.data.sqlclient.sni\4.5.0\.signature.p7s +runtime.native.system.data.sqlclient.sni\4.5.0\LICENSE.TXT +runtime.native.system.data.sqlclient.sni\4.5.0\runtime.native.system.data.sqlclient.sni.4.5.0.nupkg.sha512 +runtime.native.system.data.sqlclient.sni\4.5.0\runtime.native.system.data.sqlclient.sni.nuspec +runtime.native.system.data.sqlclient.sni\4.5.0\THIRD-PARTY-NOTICES.TXT +runtime.native.system.data.sqlclient.sni\4.5.0\useSharedDesignerContext.txt +runtime.native.system.data.sqlclient.sni\4.5.0\version.txt +runtime.native.system.io.compression\4.1.0\.nupkg.metadata +runtime.native.system.io.compression\4.3.0\.nupkg.metadata +runtime.native.system.net.http\4.0.1\.nupkg.metadata +runtime.native.system.net.http\4.3.0\.nupkg.metadata +runtime.native.system.net.security\4.3.0\.nupkg.metadata +runtime.native.system.security.cryptography.apple\4.3.0\.nupkg.metadata +runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.native.system.security.cryptography\4.0.0\.nupkg.metadata +runtime.native.system\4.0.0\.nupkg.metadata +runtime.native.system\4.3.0\.nupkg.metadata +runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple\4.3.0\.nupkg.metadata +runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl\4.3.0\.nupkg.metadata +runtime.win-arm64.runtime.native.system.data.sqlclient.sni\4.4.0\.nupkg.metadata +runtime.win-x64.runtime.native.system.data.sqlclient.sni\4.4.0\.nupkg.metadata +runtime.win-x86.runtime.native.system.data.sqlclient.sni\4.4.0\.nupkg.metadata +sqlitepclraw.bundle_green\1.1.11\.nupkg.metadata +sqlitepclraw.bundle_green\1.1.11\.signature.p7s +sqlitepclraw.core\1.1.11\.nupkg.metadata +sqlitepclraw.core\1.1.11\.signature.p7s +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\.nupkg.metadata +sqlitepclraw.lib.e_sqlite3.linux\1.1.11\.signature.p7s +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\.nupkg.metadata +sqlitepclraw.lib.e_sqlite3.osx\1.1.11\.signature.p7s +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\.nupkg.metadata +sqlitepclraw.lib.e_sqlite3.v110_xp\1.1.11\.signature.p7s +sqlitepclraw.provider.e_sqlite3.netstandard11\1.1.11\.nupkg.metadata +sqlitepclraw.provider.e_sqlite3.netstandard11\1.1.11\.signature.p7s +stackexchange.redis.strongname\1.2.6\.nupkg.metadata +stackexchange.redis.strongname\1.2.6\.signature.p7s +stackexchange.redis.strongname\1.2.6\lib\net45\StackExchange.Redis.StrongName.dll +stackexchange.redis.strongname\1.2.6\lib\net46\StackExchange.Redis.StrongName.dll +stackexchange.redis.strongname\1.2.6\lib\netstandard1.5\StackExchange.Redis.StrongName.dll +stackexchange.redis.strongname\1.2.6\stackexchange.redis.strongname.1.2.6.nupkg.sha512 +stackexchange.redis.strongname\1.2.6\stackexchange.redis.strongname.nuspec +system.appcontext\4.1.0\.nupkg.metadata +system.appcontext\4.3.0\.nupkg.metadata +system.buffers\4.0.0\.nupkg.metadata +system.buffers\4.3.0\.nupkg.metadata +system.buffers\4.5.0\.nupkg.metadata +system.collections.concurrent\4.0.12\.nupkg.metadata +system.collections.concurrent\4.3.0\.nupkg.metadata +system.collections.immutable\1.3.0\.nupkg.metadata +system.collections.immutable\1.3.1\.nupkg.metadata +system.collections.immutable\1.5.0\.nupkg.metadata +system.collections.nongeneric\4.3.0\.nupkg.metadata +system.collections.nongeneric\4.3.0\.signature.p7s +system.collections.specialized\4.3.0\.nupkg.metadata +system.collections\4.0.11\.nupkg.metadata +system.collections\4.3.0\.nupkg.metadata +system.componentmodel.annotations\4.5.0\.nupkg.metadata +system.componentmodel.primitives\4.3.0\.nupkg.metadata +system.componentmodel.typeconverter\4.3.0\.nupkg.metadata +system.componentmodel\4.3.0\.nupkg.metadata +system.console\4.0.0\.nupkg.metadata +system.console\4.3.0\.nupkg.metadata +system.data.sqlclient\4.6.0\.nupkg.metadata +system.data.sqlclient\4.6.0\.signature.p7s +system.data.sqlclient\4.6.0\lib\MonoAndroid10\_._ +system.data.sqlclient\4.6.0\lib\MonoTouch10\_._ +system.data.sqlclient\4.6.0\lib\net451\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\lib\net46\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\lib\net461\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\lib\netcoreapp2.1\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\lib\netstandard1.2\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\lib\netstandard1.3\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\lib\netstandard2.0\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\lib\xamarinios10\_._ +system.data.sqlclient\4.6.0\lib\xamarinmac20\_._ +system.data.sqlclient\4.6.0\lib\xamarintvos10\_._ +system.data.sqlclient\4.6.0\lib\xamarinwatchos10\_._ +system.data.sqlclient\4.6.0\LICENSE.TXT +system.data.sqlclient\4.6.0\ref\MonoAndroid10\_._ +system.data.sqlclient\4.6.0\ref\MonoTouch10\_._ +system.data.sqlclient\4.6.0\ref\net451\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\ref\net46\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\ref\net461\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\ref\netcoreapp2.1\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\ref\netstandard1.2\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\ref\netstandard1.3\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\ref\netstandard2.0\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\ref\xamarinios10\_._ +system.data.sqlclient\4.6.0\ref\xamarinmac20\_._ +system.data.sqlclient\4.6.0\ref\xamarintvos10\_._ +system.data.sqlclient\4.6.0\ref\xamarinwatchos10\_._ +system.data.sqlclient\4.6.0\runtimes\unix\lib\netcoreapp2.1\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\runtimes\unix\lib\netstandard1.3\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\runtimes\unix\lib\netstandard2.0\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\runtimes\win\lib\net451\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\runtimes\win\lib\net46\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\runtimes\win\lib\net461\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\runtimes\win\lib\netcoreapp2.1\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\runtimes\win\lib\netstandard1.3\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\runtimes\win\lib\netstandard2.0\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\runtimes\win\lib\uap10.0.16299\System.Data.SqlClient.dll +system.data.sqlclient\4.6.0\system.data.sqlclient.4.6.0.nupkg.sha512 +system.data.sqlclient\4.6.0\system.data.sqlclient.nuspec +system.data.sqlclient\4.6.0\THIRD-PARTY-NOTICES.TXT +system.data.sqlclient\4.6.0\useSharedDesignerContext.txt +system.data.sqlclient\4.6.0\version.txt +system.diagnostics.contracts\4.3.0\.nupkg.metadata +system.diagnostics.contracts\4.3.0\.signature.p7s +system.diagnostics.debug\4.0.11\.nupkg.metadata +system.diagnostics.debug\4.3.0\.nupkg.metadata +system.diagnostics.diagnosticsource\4.0.0\.nupkg.metadata +system.diagnostics.diagnosticsource\4.3.0\.nupkg.metadata +system.diagnostics.diagnosticsource\4.4.0\.nupkg.metadata +system.diagnostics.diagnosticsource\4.4.0\.signature.p7s +system.diagnostics.diagnosticsource\4.5.0\.nupkg.metadata +system.diagnostics.fileversioninfo\4.3.0\.nupkg.metadata +system.diagnostics.fileversioninfo\4.3.0\.signature.p7s +system.diagnostics.process\4.3.0\.nupkg.metadata +system.diagnostics.stacktrace\4.3.0\.nupkg.metadata +system.diagnostics.tools\4.0.1\.nupkg.metadata +system.diagnostics.tools\4.3.0\.nupkg.metadata +system.diagnostics.tracing\4.1.0\.nupkg.metadata +system.diagnostics.tracing\4.3.0\.nupkg.metadata +system.dynamic.runtime\4.0.11\.nupkg.metadata +system.dynamic.runtime\4.3.0\.nupkg.metadata +system.globalization.calendars\4.0.1\.nupkg.metadata +system.globalization.calendars\4.3.0\.nupkg.metadata +system.globalization.extensions\4.0.1\.nupkg.metadata +system.globalization.extensions\4.3.0\.nupkg.metadata +system.globalization\4.0.11\.nupkg.metadata +system.globalization\4.3.0\.nupkg.metadata +system.identitymodel.tokens.jwt\5.3.0\.nupkg.metadata +system.identitymodel.tokens.jwt\5.3.0\.signature.p7s +system.identitymodel.tokens.jwt\5.3.0\lib\net45\System.IdentityModel.Tokens.Jwt.dll +system.identitymodel.tokens.jwt\5.3.0\lib\net45\System.IdentityModel.Tokens.Jwt.pdb +system.identitymodel.tokens.jwt\5.3.0\lib\net451\System.IdentityModel.Tokens.Jwt.dll +system.identitymodel.tokens.jwt\5.3.0\lib\net451\System.IdentityModel.Tokens.Jwt.pdb +system.identitymodel.tokens.jwt\5.3.0\lib\net461\System.IdentityModel.Tokens.Jwt.dll +system.identitymodel.tokens.jwt\5.3.0\lib\net461\System.IdentityModel.Tokens.Jwt.pdb +system.identitymodel.tokens.jwt\5.3.0\lib\netstandard1.4\System.IdentityModel.Tokens.Jwt.dll +system.identitymodel.tokens.jwt\5.3.0\lib\netstandard1.4\System.IdentityModel.Tokens.Jwt.pdb +system.identitymodel.tokens.jwt\5.3.0\lib\netstandard2.0\System.IdentityModel.Tokens.Jwt.dll +system.identitymodel.tokens.jwt\5.3.0\lib\netstandard2.0\System.IdentityModel.Tokens.Jwt.pdb +system.identitymodel.tokens.jwt\5.3.0\system.identitymodel.tokens.jwt.5.3.0.nupkg.sha512 +system.identitymodel.tokens.jwt\5.3.0\system.identitymodel.tokens.jwt.nuspec +system.interactive.async\3.2.0\.nupkg.metadata +system.interactive.async\3.2.0\.signature.p7s +system.interactive.async\3.2.0\lib\net45\System.Interactive.Async.dll +system.interactive.async\3.2.0\lib\net46\System.Interactive.Async.dll +system.interactive.async\3.2.0\lib\netstandard1.0\System.Interactive.Async.dll +system.interactive.async\3.2.0\lib\netstandard1.3\System.Interactive.Async.dll +system.interactive.async\3.2.0\lib\netstandard2.0\System.Interactive.Async.dll +system.interactive.async\3.2.0\system.interactive.async.3.2.0.nupkg.sha512 +system.interactive.async\3.2.0\system.interactive.async.nuspec +system.io.compression.zipfile\4.0.1\.nupkg.metadata +system.io.compression.zipfile\4.3.0\.nupkg.metadata +system.io.compression\4.1.0\.nupkg.metadata +system.io.compression\4.3.0\.nupkg.metadata +system.io.filesystem.primitives\4.0.1\.nupkg.metadata +system.io.filesystem.primitives\4.3.0\.nupkg.metadata +system.io.filesystem\4.0.1\.nupkg.metadata +system.io.filesystem\4.3.0\.nupkg.metadata +system.io.pipelines\4.5.2\.nupkg.metadata +system.io.pipelines\4.5.2\.signature.p7s +system.io.pipelines\4.5.2\lib\netcoreapp2.1\System.IO.Pipelines.dll +system.io.pipelines\4.5.2\lib\netstandard1.3\System.IO.Pipelines.dll +system.io.pipelines\4.5.2\lib\netstandard2.0\System.IO.Pipelines.dll +system.io.pipelines\4.5.2\LICENSE.TXT +system.io.pipelines\4.5.2\ref\netstandard1.3\System.IO.Pipelines.dll +system.io.pipelines\4.5.2\system.io.pipelines.4.5.2.nupkg.sha512 +system.io.pipelines\4.5.2\system.io.pipelines.nuspec +system.io.pipelines\4.5.2\THIRD-PARTY-NOTICES.TXT +system.io.pipelines\4.5.2\useSharedDesignerContext.txt +system.io.pipelines\4.5.2\version.txt +system.io\4.1.0\.nupkg.metadata +system.io\4.3.0\.nupkg.metadata +system.linq.expressions\4.1.0\.nupkg.metadata +system.linq.expressions\4.3.0\.nupkg.metadata +system.linq.queryable\4.0.1\.nupkg.metadata +system.linq\4.1.0\.nupkg.metadata +system.linq\4.3.0\.nupkg.metadata +system.memory\4.5.1\.nupkg.metadata +system.net.http\4.1.0\.nupkg.metadata +system.net.http\4.1.0\.signature.p7s +system.net.http\4.3.0\.nupkg.metadata +system.net.http\4.3.0\.signature.p7s +system.net.nameresolution\4.3.0\.nupkg.metadata +system.net.primitives\4.0.11\.nupkg.metadata +system.net.primitives\4.3.0\.nupkg.metadata +system.net.security\4.3.0\.nupkg.metadata +system.net.sockets\4.1.0\.nupkg.metadata +system.net.sockets\4.3.0\.nupkg.metadata +system.net.websockets.websocketprotocol\4.5.1\.nupkg.metadata +system.numerics.vectors\4.5.0\.nupkg.metadata +system.objectmodel\4.0.12\.nupkg.metadata +system.objectmodel\4.3.0\.nupkg.metadata +system.private.datacontractserialization\4.1.1\.nupkg.metadata +system.private.datacontractserialization\4.3.0\.nupkg.metadata +system.private.datacontractserialization\4.3.0\.signature.p7s +system.reflection.emit.ilgeneration\4.0.1\.nupkg.metadata +system.reflection.emit.ilgeneration\4.3.0\.nupkg.metadata +system.reflection.emit.lightweight\4.0.1\.nupkg.metadata +system.reflection.emit.lightweight\4.3.0\.nupkg.metadata +system.reflection.emit\4.0.1\.nupkg.metadata +system.reflection.emit\4.3.0\.nupkg.metadata +system.reflection.extensions\4.0.1\.nupkg.metadata +system.reflection.extensions\4.3.0\.nupkg.metadata +system.reflection.metadata\1.4.1\.nupkg.metadata +system.reflection.metadata\1.4.2\.nupkg.metadata +system.reflection.metadata\1.6.0\.nupkg.metadata +system.reflection.primitives\4.0.1\.nupkg.metadata +system.reflection.primitives\4.3.0\.nupkg.metadata +system.reflection.typeextensions\4.1.0\.nupkg.metadata +system.reflection.typeextensions\4.3.0\.nupkg.metadata +system.reflection\4.1.0\.nupkg.metadata +system.reflection\4.3.0\.nupkg.metadata +system.resources.resourcemanager\4.0.1\.nupkg.metadata +system.resources.resourcemanager\4.3.0\.nupkg.metadata +system.runtime.compilerservices.unsafe\4.5.0\.nupkg.metadata +system.runtime.compilerservices.unsafe\4.5.1\.nupkg.metadata +system.runtime.extensions\4.1.0\.nupkg.metadata +system.runtime.extensions\4.3.0\.nupkg.metadata +system.runtime.handles\4.0.1\.nupkg.metadata +system.runtime.handles\4.3.0\.nupkg.metadata +system.runtime.interopservices.runtimeinformation\4.0.0\.nupkg.metadata +system.runtime.interopservices.runtimeinformation\4.3.0\.nupkg.metadata +system.runtime.interopservices\4.1.0\.nupkg.metadata +system.runtime.interopservices\4.3.0\.nupkg.metadata +system.runtime.numerics\4.0.1\.nupkg.metadata +system.runtime.numerics\4.3.0\.nupkg.metadata +system.runtime.serialization.formatters\4.3.0\.nupkg.metadata +system.runtime.serialization.json\4.0.2\.nupkg.metadata +system.runtime.serialization.json\4.3.0\.nupkg.metadata +system.runtime.serialization.json\4.3.0\dotnet_library_license.txt +system.runtime.serialization.json\4.3.0\lib\MonoAndroid10\_._ +system.runtime.serialization.json\4.3.0\lib\MonoTouch10\_._ +system.runtime.serialization.json\4.3.0\lib\net45\_._ +system.runtime.serialization.json\4.3.0\lib\netcore50\System.Runtime.Serialization.Json.dll +system.runtime.serialization.json\4.3.0\lib\netstandard1.3\System.Runtime.Serialization.Json.dll +system.runtime.serialization.json\4.3.0\lib\portable-net45+win8+wp8+wpa81\_._ +system.runtime.serialization.json\4.3.0\lib\win8\_._ +system.runtime.serialization.json\4.3.0\lib\wp80\_._ +system.runtime.serialization.json\4.3.0\lib\wpa81\_._ +system.runtime.serialization.json\4.3.0\lib\xamarinios10\_._ +system.runtime.serialization.json\4.3.0\lib\xamarinmac20\_._ +system.runtime.serialization.json\4.3.0\lib\xamarintvos10\_._ +system.runtime.serialization.json\4.3.0\lib\xamarinwatchos10\_._ +system.runtime.serialization.json\4.3.0\ref\MonoAndroid10\_._ +system.runtime.serialization.json\4.3.0\ref\MonoTouch10\_._ +system.runtime.serialization.json\4.3.0\ref\net45\_._ +system.runtime.serialization.json\4.3.0\ref\netcore50\System.Runtime.Serialization.Json.dll +system.runtime.serialization.json\4.3.0\ref\netstandard1.0\System.Runtime.Serialization.Json.dll +system.runtime.serialization.json\4.3.0\ref\portable-net45+win8+wp8+wpa81\_._ +system.runtime.serialization.json\4.3.0\ref\win8\_._ +system.runtime.serialization.json\4.3.0\ref\wp80\_._ +system.runtime.serialization.json\4.3.0\ref\wpa81\_._ +system.runtime.serialization.json\4.3.0\ref\xamarinios10\_._ +system.runtime.serialization.json\4.3.0\ref\xamarinmac20\_._ +system.runtime.serialization.json\4.3.0\ref\xamarintvos10\_._ +system.runtime.serialization.json\4.3.0\ref\xamarinwatchos10\_._ +system.runtime.serialization.json\4.3.0\system.runtime.serialization.json.4.3.0.nupkg.sha512 +system.runtime.serialization.json\4.3.0\system.runtime.serialization.json.nuspec +system.runtime.serialization.json\4.3.0\ThirdPartyNotices.txt +system.runtime.serialization.primitives\4.1.1\.nupkg.metadata +system.runtime.serialization.primitives\4.3.0\.nupkg.metadata +system.runtime.serialization.xml\4.3.0\.nupkg.metadata +system.runtime.serialization.xml\4.3.0\.signature.p7s +system.runtime\4.1.0\.nupkg.metadata +system.runtime\4.3.0\.nupkg.metadata +system.security.accesscontrol\4.5.0\.nupkg.metadata +system.security.claims\4.3.0\.nupkg.metadata +system.security.cryptography.algorithms\4.2.0\.nupkg.metadata +system.security.cryptography.algorithms\4.3.0\.nupkg.metadata +system.security.cryptography.cng\4.2.0\.nupkg.metadata +system.security.cryptography.cng\4.3.0\.nupkg.metadata +system.security.cryptography.cng\4.5.0\.nupkg.metadata +system.security.cryptography.csp\4.0.0\.nupkg.metadata +system.security.cryptography.csp\4.3.0\.nupkg.metadata +system.security.cryptography.encoding\4.0.0\.nupkg.metadata +system.security.cryptography.encoding\4.3.0\.nupkg.metadata +system.security.cryptography.openssl\4.0.0\.nupkg.metadata +system.security.cryptography.openssl\4.3.0\.nupkg.metadata +system.security.cryptography.pkcs\4.5.0\.nupkg.metadata +system.security.cryptography.primitives\4.0.0\.nupkg.metadata +system.security.cryptography.primitives\4.3.0\.nupkg.metadata +system.security.cryptography.x509certificates\4.1.0\.nupkg.metadata +system.security.cryptography.x509certificates\4.3.0\.nupkg.metadata +system.security.cryptography.xml\4.5.0\.nupkg.metadata +system.security.permissions\4.5.0\.nupkg.metadata +system.security.principal.windows\4.3.0\.nupkg.metadata +system.security.principal.windows\4.5.0\.nupkg.metadata +system.security.principal\4.3.0\.nupkg.metadata +system.spatial\5.8.2\.nupkg.metadata +system.text.encoding.codepages\4.3.0\.nupkg.metadata +system.text.encoding.codepages\4.5.0\.nupkg.metadata +system.text.encoding.extensions\4.0.11\.nupkg.metadata +system.text.encoding.extensions\4.3.0\.nupkg.metadata +system.text.encoding\4.0.11\.nupkg.metadata +system.text.encoding\4.3.0\.nupkg.metadata +system.text.encodings.web\4.3.1\.nupkg.metadata +system.text.encodings.web\4.3.1\.signature.p7s +system.text.encodings.web\4.5.0\.nupkg.metadata +system.text.regularexpressions\4.1.0\.nupkg.metadata +system.text.regularexpressions\4.3.0\.nupkg.metadata +system.threading.channels\4.5.0\.nupkg.metadata +system.threading.tasks.extensions\4.0.0\.nupkg.metadata +system.threading.tasks.extensions\4.3.0\.nupkg.metadata +system.threading.tasks.extensions\4.5.1\.nupkg.metadata +system.threading.tasks.parallel\4.3.0\.nupkg.metadata +system.threading.tasks.parallel\4.3.0\.signature.p7s +system.threading.tasks\4.0.11\.nupkg.metadata +system.threading.tasks\4.3.0\.nupkg.metadata +system.threading.thread\4.3.0\.nupkg.metadata +system.threading.threadpool\4.3.0\.nupkg.metadata +system.threading.timer\4.0.1\.nupkg.metadata +system.threading.timer\4.3.0\.nupkg.metadata +system.threading\4.0.11\.nupkg.metadata +system.threading\4.3.0\.nupkg.metadata +system.valuetuple\4.3.0\.nupkg.metadata +system.valuetuple\4.5.0\.nupkg.metadata +system.xml.readerwriter\4.0.11\.nupkg.metadata +system.xml.readerwriter\4.3.0\.nupkg.metadata +system.xml.xdocument\4.0.11\.nupkg.metadata +system.xml.xdocument\4.3.0\.nupkg.metadata +system.xml.xmldocument\4.0.1\.nupkg.metadata +system.xml.xmldocument\4.3.0\.nupkg.metadata +system.xml.xmldocument\4.3.0\.signature.p7s +system.xml.xmlserializer\4.0.11\.nupkg.metadata +system.xml.xmlserializer\4.3.0\.nupkg.metadata +system.xml.xmlserializer\4.3.0\.signature.p7s +system.xml.xpath.xdocument\4.3.0\.nupkg.metadata +system.xml.xpath\4.3.0\.nupkg.metadata +system.xml.xpath\4.3.0\.signature.p7s +windowsazure.storage\8.1.4\.nupkg.metadata +windowsazure.storage\8.1.4\.signature.p7s diff --git a/src/PackageArchive/ZipManifestGenerator/README.md b/src/PackageArchive/ZipManifestGenerator/README.md index 9922f2e465..6022e996b8 100644 --- a/src/PackageArchive/ZipManifestGenerator/README.md +++ b/src/PackageArchive/ZipManifestGenerator/README.md @@ -1,5 +1,5 @@ ZipManifestGenerator ---------- +-------------------- This console app is used to generate the list of files in a zip archive. @@ -29,3 +29,5 @@ $compatPatchUrl = "https://dotnetfeed.blob.core.windows.net/orchestrated-release dotnet run $compatPatchUrl "../Archive.CiServer.Patch.Compat/ArchiveBaseline.${Version}.txt" ``` + +For convenience, this folder contains [./UpdateBaselines.ps1](./UpdateBaselines.ps1) to run these steps. diff --git a/src/PackageArchive/ZipManifestGenerator/UpdateBaselines.ps1 b/src/PackageArchive/ZipManifestGenerator/UpdateBaselines.ps1 new file mode 100644 index 0000000000..d129443473 --- /dev/null +++ b/src/PackageArchive/ZipManifestGenerator/UpdateBaselines.ps1 @@ -0,0 +1,15 @@ +param( + [Parameter(Mandatory = $true)] + $ProdConBuildId, + [Parameter(Mandatory = $true)] + $ProductVersion, + $FeedContainer = 'orchestrated-release-2-2' +) + +$patchUrl = "https://dotnetfeed.blob.core.windows.net/${FeedContainer}/${ProdconBuildId}/final/assets/aspnetcore/Runtime/${ProductVersion}/nuGetPackagesArchive-ci-server-${ProductVersion}.patch.zip" + +dotnet run $patchUrl "../Archive.CiServer.Patch/ArchiveBaseline.${ProductVersion}.txt" + +$compatPatchUrl = "https://dotnetfeed.blob.core.windows.net/${FeedContainer}/${ProdconBuildId}/final/assets/aspnetcore/Runtime/${ProductVersion}/nuGetPackagesArchive-ci-server-compat-${ProductVersion}.patch.zip" + +dotnet run $compatPatchUrl "../Archive.CiServer.Patch.Compat/ArchiveBaseline.${ProductVersion}.txt" diff --git a/src/WebSockets/src/Directory.Build.props b/src/WebSockets/src/Directory.Build.props index 1e0980f663..b1162b313a 100644 --- a/src/WebSockets/src/Directory.Build.props +++ b/src/WebSockets/src/Directory.Build.props @@ -1,5 +1,5 @@  - + diff --git a/src/WebSockets/test/Directory.Build.props b/src/WebSockets/test/Directory.Build.props index a84a332640..b7071b5a9d 100644 --- a/src/WebSockets/test/Directory.Build.props +++ b/src/WebSockets/test/Directory.Build.props @@ -1,5 +1,5 @@ - + netcoreapp2.2 @@ -7,7 +7,7 @@ $(StandardTestTfms);net461 - + + 2.2.0 + 2.2.0 diff --git a/version.props b/version.props index bddf99d8db..b56e745b10 100644 --- a/version.props +++ b/version.props @@ -2,8 +2,8 @@ 2 2 - 0 - rtm + 1 + servicing $([System.DateTime]::Now.ToString('yyMMdd'))-99 $(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).$(AspNetCorePatchVersion) From b4dbaa95d0d31405f4ecc81e56a742fbba8eaf59 Mon Sep 17 00:00:00 2001 From: John Luo Date: Wed, 14 Nov 2018 11:24:59 -0800 Subject: [PATCH 1028/1029] Add ChromeDriver dependency --- build/dependencies.props | 1 + 1 file changed, 1 insertion(+) diff --git a/build/dependencies.props b/build/dependencies.props index 2bda6136dc..1b032a8889 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -190,6 +190,7 @@ 2.2.0 0.20.0 3.12.1 + 2.43.0 17.17134.0 3.12.1 1.4.0 From 289050b9f2f208dce4bd2707456269b61e1822bd Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 14 Nov 2018 15:14:27 -0800 Subject: [PATCH 1029/1029] Normalize code sign metadata to avoid duplication between projects and cross-gen config settings --- build/CodeSign.targets | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/build/CodeSign.targets b/build/CodeSign.targets index a7ad37a754..13d89fc64f 100644 --- a/build/CodeSign.targets +++ b/build/CodeSign.targets @@ -52,11 +52,17 @@ <_FilesToSign Include="@(_ShippedRepoFileSignInfo)" Condition="'%(_ShippedRepoFileSignInfo.IsFileToSign)' == 'true' AND '%(_ShippedRepoFileSignInfo.Container)' != '' " /> + + <_Temp Remove="@(_Temp)" /> + <_Temp Include="@(FilesToExcludeFromSigning)" /> + + + <_Temp Remove="@(_Temp)" /> + -