From eb9383fe409ebc678170c696a35d9dd43551ae27 Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Thu, 17 Sep 2015 08:38:38 -0700 Subject: [PATCH 001/407] 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 002/407] 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 003/407] 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 3f40980d0200aa4491ec94042dd49987c52f3c3a Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Thu, 17 Sep 2015 14:05:33 -0700 Subject: [PATCH 004/407] 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 005/407] 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 006/407] 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 007/407] 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 ac6e441f15e75b74faea1209b3d9e4a03116c8dc Mon Sep 17 00:00:00 2001 From: Pranav K Date: Sat, 3 Oct 2015 15:44:58 -0700 Subject: [PATCH 008/407] 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 009/407] 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 3d61bbf3579f35f53c30c05f2850bd723cbbe0da Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Sun, 11 Oct 2015 00:50:01 -0700 Subject: [PATCH 010/407] 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 011/407] 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 54af2c339f0cb3204d2564202bb1d792ba499dd3 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Mon, 26 Oct 2015 09:17:10 -0700 Subject: [PATCH 012/407] 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 013/407] 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 42f3a89db5e65092d19f55721904d0403b2bcb26 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 28 Oct 2015 12:43:11 -0700 Subject: [PATCH 014/407] 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 74d89b2e3265794cbb2a6a347ac73639fbfb6552 Mon Sep 17 00:00:00 2001 From: Cesar Blum Silveira Date: Mon, 2 Nov 2015 14:40:58 -0800 Subject: [PATCH 015/407] 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 bba44597fccaa172fceddd471bf92861895c5bd4 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Thu, 12 Nov 2015 12:25:07 -0800 Subject: [PATCH 016/407] 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 017/407] 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 018/407] 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 d6542506a8f3c3498509d525b00be602b5efdbb6 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Tue, 17 Nov 2015 12:40:19 -0800 Subject: [PATCH 019/407] 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 03a04917d096c1b15a4058e8e8b432778246a2a6 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Tue, 17 Nov 2015 14:53:54 -0800 Subject: [PATCH 020/407] 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 021/407] 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 086f87a3567e55390f6fe415641f3eb0517aa8dc Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Thu, 3 Dec 2015 12:33:01 -0800 Subject: [PATCH 022/407] 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 023/407] 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 b3f4ab1ddd6af01cf160c8a98a3034c05e2c46a5 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 11 Dec 2015 12:25:21 -0800 Subject: [PATCH 024/407] 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 025/407] 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 cbc201ac26114f211dba53788b155717dee5983d Mon Sep 17 00:00:00 2001 From: Brennan Date: Tue, 15 Dec 2015 08:53:41 -0800 Subject: [PATCH 026/407] 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 54ae0b929655ddafc2922c038863a9c73892de77 Mon Sep 17 00:00:00 2001 From: Brennan Date: Wed, 6 Jan 2016 13:19:33 -0800 Subject: [PATCH 027/407] 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 9a05ea80c47bc6b61b1a85143eb4b3132b39102e Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 20 Jan 2016 20:47:18 -0800 Subject: [PATCH 028/407] 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 d20b14d84645b071b502f737b09f22ebff9f8c1a Mon Sep 17 00:00:00 2001 From: Brennan Date: Thu, 21 Jan 2016 16:45:43 -0800 Subject: [PATCH 029/407] 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 030/407] 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 3fce15bc6a0d05287aca2233a53f784968073dd0 Mon Sep 17 00:00:00 2001 From: Brennan Date: Thu, 21 Jan 2016 09:42:54 -0800 Subject: [PATCH 031/407] 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 f452597452c3c0b359bb5cffc795429328268325 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Tue, 2 Feb 2016 12:44:07 -0800 Subject: [PATCH 032/407] 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 4bef698f3bc77e071601a67fbd9a3fb857215c3a Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 8 Feb 2016 09:33:43 -0800 Subject: [PATCH 033/407] 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 59cb4fe65ab50371f7632c0dd738d3fb0de49a1d Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Tue, 2 Feb 2016 12:24:33 -0800 Subject: [PATCH 034/407] 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 58525b0369a559d1f4f0cdb8e89c520476b5e66e Mon Sep 17 00:00:00 2001 From: John Luo Date: Fri, 19 Feb 2016 16:55:51 -0800 Subject: [PATCH 035/407] 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 24d4c027b11148bc83b15f8d87b964835f503f71 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Wed, 24 Feb 2016 12:37:07 -0800 Subject: [PATCH 036/407] 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 037/407] 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 e4e39b686f4a9fe246bd2c056eb2ccf29d6cbdae Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Sat, 27 Feb 2016 12:51:17 -0800 Subject: [PATCH 038/407] 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 b64b30b02d62459440ffa1e91f3291e0f6f4134a Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Sun, 28 Feb 2016 10:12:21 -0800 Subject: [PATCH 039/407] 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 5f2f4340349a2eba1cb88e97a49b58d376d2a4ec Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Tue, 1 Mar 2016 13:40:42 -0800 Subject: [PATCH 040/407] 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 e5c6f5ed14e0a5fdc56ea5be1e3d8e4f025305c6 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Wed, 2 Mar 2016 09:57:58 -0800 Subject: [PATCH 041/407] 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 042/407] 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 b62d90d7dc0cf8bc0c09c8c3cf4cf19a73d4035b Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Thu, 3 Mar 2016 12:15:50 -0800 Subject: [PATCH 043/407] 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 044/407] - 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 467e520b35878fe180b237854bd291573ee3a3fc Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Thu, 3 Mar 2016 17:54:13 -0800 Subject: [PATCH 045/407] 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 52244da9e83ce267e0af5fb2081dc397c56f94da Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Fri, 4 Mar 2016 10:11:01 -0800 Subject: [PATCH 046/407] 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 3bccd97ff604c53b9aae4775643035ca494884e4 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Mon, 7 Mar 2016 20:55:07 -0800 Subject: [PATCH 047/407] 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 048/407] 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 30cd2b88b3b55d03da179bc98f530be59df2c61f Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 9 Mar 2016 16:35:15 -0800 Subject: [PATCH 049/407] 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 d8607779fd8bcd3453930c9e80764c5eeb7ab660 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 9 Mar 2016 17:44:48 -0800 Subject: [PATCH 050/407] 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 051/407] 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 052/407] 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 73d50bbac381b747de61af1dea68085e764cae4e Mon Sep 17 00:00:00 2001 From: Cesar Blum Silveira Date: Mon, 14 Mar 2016 21:47:24 -0700 Subject: [PATCH 053/407] 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 054/407] 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 73217edba52fae43c254334aa8802f5b3e52c09f Mon Sep 17 00:00:00 2001 From: John Luo Date: Thu, 17 Mar 2016 16:36:27 -0700 Subject: [PATCH 055/407] 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 056/407] 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 057/407] 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 058/407] 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 182cbc276cd742224feaa57f165613ffe89bc9db Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Wed, 30 Mar 2016 15:06:20 -0700 Subject: [PATCH 059/407] 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 4788506b57c736c7d54f4c05fd2c3b1cbe620a10 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 1 Apr 2016 06:41:43 -0700 Subject: [PATCH 060/407] 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 061/407] 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 062/407] 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 063/407] 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 62d452abebcddffd372919755122477c1ed423e1 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 6 Apr 2016 09:45:59 -0700 Subject: [PATCH 064/407] 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 09434e56256f1cfc4d07c4a2f579ba946c86cde2 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Wed, 6 Apr 2016 09:33:55 -0700 Subject: [PATCH 065/407] 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 066/407] 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 46d4c6edcb374060b4e8ebf83e3ccd399f8f61ae Mon Sep 17 00:00:00 2001 From: moozzyk Date: Mon, 28 Mar 2016 16:47:18 -0700 Subject: [PATCH 067/407] 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 8f1f3c0772953c95e95b1b614f8ecf6e20cf14c0 Mon Sep 17 00:00:00 2001 From: moozzyk Date: Mon, 28 Mar 2016 16:47:18 -0700 Subject: [PATCH 068/407] 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 069/407] 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 070/407] 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 684ee87f20be9cdf0af3442fa4032780e4168da2 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Mon, 18 Apr 2016 16:57:52 -0700 Subject: [PATCH 071/407] 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 072/407] 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 073/407] 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 074/407] 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 075/407] 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 21951d62f3c923d4dcc7934ca78154660de1a26c Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Fri, 22 Apr 2016 10:38:24 -0700 Subject: [PATCH 076/407] 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 077/407] 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 078/407] 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 079/407] 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 080/407] 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 912971120fb76ba2e4081e573b6e7a7a4c3a807b Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 6 May 2016 14:52:50 -0700 Subject: [PATCH 081/407] 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 c68145f44f47da4ab5af8f371bb2ef9605a86b29 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Fri, 20 May 2016 14:18:56 -0700 Subject: [PATCH 082/407] 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 083/407] 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 084/407] 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 085/407] 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 086/407] 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 087/407] 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 088/407] 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 089/407] 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 090/407] - 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 bf5f6b927585251f3c4041de95f377f4191e907f Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 27 May 2016 07:36:33 -0700 Subject: [PATCH 091/407] 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 092/407] 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 c5abb2e2ebdc73d7814d09aae56490fdb32921b2 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Tue, 31 May 2016 09:18:02 -0700 Subject: [PATCH 093/407] 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 094/407] 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 095/407] 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 096/407] 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 097/407] 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 098/407] 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 099/407] 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 2cf172c66e7455585154989a4e450e5667f4ef1a Mon Sep 17 00:00:00 2001 From: jacalvar Date: Mon, 6 Jun 2016 23:18:24 -0700 Subject: [PATCH 100/407] 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 101/407] 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 ad9e22d42acbec4d92e950deb234494659f72911 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 8 Jun 2016 16:52:27 -0700 Subject: [PATCH 102/407] 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 3df9256f123a9cd78dbc69006e511532888abbd2 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 14 Jun 2016 16:22:14 -0700 Subject: [PATCH 103/407] 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 a86db45a19cd0812e7efef5f33dc3658befcdd1f Mon Sep 17 00:00:00 2001 From: jacalvar Date: Mon, 13 Jun 2016 14:24:25 -0700 Subject: [PATCH 104/407] 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 105/407] 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 92c658216f76f8700ec2fef5e3012c747d0bb36f Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 29 Jun 2016 16:43:38 -0700 Subject: [PATCH 106/407] 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 21b35259332877ef60730971a8d1a28b99e63475 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Tue, 5 Jul 2016 09:57:11 -0700 Subject: [PATCH 107/407] 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 108/407] 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 109/407] 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 c769d8dee9991b9adff83455afae8797b01084eb Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Thu, 14 Jul 2016 11:48:48 -0700 Subject: [PATCH 110/407] 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 111/407] - 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 112/407] 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 79cb3b0ed9f6740f30fb9c4a3af8f1186ea70168 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 9 Aug 2016 14:58:36 -0700 Subject: [PATCH 113/407] 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 ac2f21514f2627484dd545e2e6243a231fddf1a4 Mon Sep 17 00:00:00 2001 From: Victor Hurdugaci Date: Wed, 31 Aug 2016 09:30:33 -0700 Subject: [PATCH 114/407] 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 115/407] 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 484f35691a49f8c13165a3a41f47cd0f7cb49bb2 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 7 Sep 2016 11:19:56 -0700 Subject: [PATCH 116/407] 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 117/407] 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 118/407] 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 119/407] :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 120/407] 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 121/407] 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 122/407] 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 123/407] 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 124/407] 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 125/407] 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 126/407] 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 127/407] 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 3b1f650d3be8bd4dcf5a22a07179b4778deb6bf4 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 20 Sep 2016 15:50:04 -0700 Subject: [PATCH 128/407] 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 129/407] 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 130/407] 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 131/407] 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 132/407] 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 133/407] 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 134/407] 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 135/407] 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 136/407] 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 137/407] 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 138/407] 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 c20b9ae8940ef90237ee2fb5fc9fc83d16a864aa Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 10 Oct 2016 11:30:12 -0700 Subject: [PATCH 139/407] 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 140/407] 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 141/407] 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 142/407] 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 143/407] 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 144/407] 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 145/407] 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 146/407] 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 0627d859aff01eca2562893ed1ffb265cf37216a Mon Sep 17 00:00:00 2001 From: Prafull Bhosale Date: Wed, 12 Oct 2016 14:39:12 -0700 Subject: [PATCH 147/407] 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 5d998a16d847fb0c507892943899e91c4d89e20e Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 12 Oct 2016 16:12:52 -0700 Subject: [PATCH 148/407] 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 149/407] 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 4cbd904154a06e03f1b2dd772f0caee81048797a Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 13 Oct 2016 09:05:17 -0700 Subject: [PATCH 150/407] 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 151/407] 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 62df63ada82ce80e4744f98179c0a90424e2a9da Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 17 Oct 2016 09:55:51 -0700 Subject: [PATCH 152/407] 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 721cbe34353e0e99c10c98f7767090df805e16ea Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 12 Oct 2016 17:34:59 -0700 Subject: [PATCH 153/407] 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 154/407] 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 155/407] 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 156/407] 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 157/407] 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 158/407] 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 159/407] 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 160/407] 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 161/407] 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 162/407] 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 163/407] 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 164/407] 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 165/407] 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 166/407] 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 167/407] 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 168/407] 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 169/407] 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 170/407] 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 171/407] 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 172/407] 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 173/407] 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 174/407] 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 175/407] 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 176/407] 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 177/407] 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 42d8ccbc47e00803def90e2f34e193263e764011 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 3 Nov 2016 17:54:09 -0700 Subject: [PATCH 178/407] 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 179/407] 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 180/407] 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 181/407] 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 c84bdb35d314058faadff19796b4c92efe98e91d Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 3 Nov 2016 17:54:09 -0700 Subject: [PATCH 182/407] 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 183/407] 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 184/407] 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 0b0abe054c9533e7486f1db9e26ede4e5d49880f Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 9 Nov 2016 11:30:11 -0800 Subject: [PATCH 185/407] 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 3461bf92c6206eb9e8af1b20e4e0f7576fa49cf8 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 9 Nov 2016 15:06:21 -0800 Subject: [PATCH 186/407] 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 187/407] 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 188/407] 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 189/407] 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 190/407] 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 191/407] 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 192/407] 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 193/407] 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 194/407] 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 195/407] :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 196/407] 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 197/407] 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 40f042dc495f2ee4bbfbedfe0a9eb596ad5f30fd Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 18 Nov 2016 10:57:03 -0800 Subject: [PATCH 198/407] 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 587376200be0cd35c9e2ba235fcc4c22f9a8f5b7 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 21 Nov 2016 10:16:39 -0800 Subject: [PATCH 199/407] 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 200/407] 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 201/407] 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 202/407] 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 203/407] 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 e5c4e96705ed93aa923896c085d034f843f1baf4 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Wed, 23 Nov 2016 15:57:49 -0800 Subject: [PATCH 204/407] 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 f63006dc1a48a3db939f356204a4d6e50eb7e590 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 28 Nov 2016 16:39:14 -0800 Subject: [PATCH 205/407] 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 206/407] 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 207/407] 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 208/407] 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 209/407] 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 210/407] 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 00fc430658cb734338e87f6daf1edeaed8bbefe8 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Thu, 8 Dec 2016 10:02:26 -0800 Subject: [PATCH 211/407] 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 d6079d6595a1a8d043bae2d1a738ad5146a0bbc3 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 12 Dec 2016 09:48:02 -0800 Subject: [PATCH 212/407] 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 213/407] 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 214/407] 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 215/407] 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 216/407] 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 217/407] 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 218/407] 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 219/407] 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 220/407] 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 221/407] 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 c8b37f47d0f95f7fde490c45eafcfefa08d8210f Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 14 Dec 2016 16:34:19 -0800 Subject: [PATCH 222/407] 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 223/407] 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 224/407] :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 225/407] 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 cc84b8402d0a607e0d7926e0f3923134dad5c237 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 3 Jan 2017 11:16:34 -0800 Subject: [PATCH 226/407] 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 cb3c5d77ade283538af441be9792590422c789a5 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 9 Jan 2017 10:36:52 -0800 Subject: [PATCH 227/407] 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 228/407] 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 229/407] 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 230/407] :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 231/407] 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 232/407] 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 233/407] 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 234/407] 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 235/407] 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 ca7b6f65e945e396c68dd336bdee2b96c0408751 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 31 Jan 2017 10:57:05 -0800 Subject: [PATCH 236/407] 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 7019c552197a50074c77a6eb91b23cf1f822b9ec Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 3 Feb 2017 10:15:28 -0800 Subject: [PATCH 237/407] 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 238/407] 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 239/407] 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 60a06b2e07287753384a86bbf07eb7229d07aca0 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 14 Feb 2017 12:11:39 -0800 Subject: [PATCH 240/407] 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 8764af8a3633d8910eaad02b0c3a5005367f3708 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 14 Feb 2017 16:03:54 -0800 Subject: [PATCH 241/407] 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 242/407] 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 e2e0c8dadf93704621ccdafb1c50d7053d25b0f0 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 27 Feb 2017 11:00:04 -0800 Subject: [PATCH 243/407] 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 4f83e641a733d372e57898921a31c9a6f3b5b71c Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 1 Mar 2017 18:14:13 -0800 Subject: [PATCH 244/407] 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 047e4a8533bbcdf22831c40dd9d9aaf0c80d1953 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 1 Mar 2017 18:25:45 -0800 Subject: [PATCH 245/407] 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 c97dd446eb2aafd65e8bd5a9531c6d9713510aae Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 10 Mar 2017 09:18:38 -0800 Subject: [PATCH 246/407] 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 247/407] 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 248/407] 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 d1d656d5b895690ad5b9c5aaeaa21c02d88f7285 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 15 Mar 2017 09:29:05 -0700 Subject: [PATCH 249/407] 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 cac669df3d627831611b698fb9f7ca54f0b7107e Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 21 Mar 2017 12:07:05 -0700 Subject: [PATCH 250/407] 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 1f8e8fae5defe460a6322783e8059c5f7671ddb6 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 21 Mar 2017 15:48:04 -0700 Subject: [PATCH 251/407] 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 252/407] 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 13219fafa9b669f5b1fd83e8bcd45e39dcd13c7f Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 21 Mar 2017 16:55:42 -0700 Subject: [PATCH 253/407] 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 254/407] 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 0e8b790a0876a183304b6406b38ccee39f6d3745 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Sat, 25 Mar 2017 15:30:49 -0700 Subject: [PATCH 255/407] 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 e4e62b31561536519ba8489f8fa568f76e50567a Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 29 Mar 2017 11:30:32 -0700 Subject: [PATCH 256/407] 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 023b1d7db86356237744a5f7b5ab86c72d2f45f6 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 3 Apr 2017 21:41:09 -0700 Subject: [PATCH 257/407] 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 cd5fa7ec1f809f6d68c28dd407b105cc83264bc0 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 11 Apr 2017 14:27:56 -0700 Subject: [PATCH 258/407] 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 259/407] 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 260/407] 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 261/407] 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 d3d88481e2cc74ca01d1060ed041448d661fe3a9 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 25 Apr 2017 11:04:07 -0700 Subject: [PATCH 262/407] 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 263/407] 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 f86cd6b9b4ed1fe5fab1368e199ec8f0bc8adc9b Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 26 Apr 2017 07:12:47 -0700 Subject: [PATCH 264/407] 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 3a248e22c80d0742abc4cddc4aba694fd29bfe50 Mon Sep 17 00:00:00 2001 From: Mike Harder Date: Thu, 27 Apr 2017 13:37:20 -0700 Subject: [PATCH 265/407] 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 266/407] :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 267/407] 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 268/407] 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 269/407] 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 ed07fbe94a33c3238dc0ec2f7abb5de9ede78a68 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 28 Apr 2017 16:57:16 -0700 Subject: [PATCH 270/407] 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 271/407] 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 272/407] 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 276/407] 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 eb4be67863c3f907847c266c35f24176b1169e4d Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Tue, 30 May 2017 09:52:51 -0700 Subject: [PATCH 277/407] 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 278/407] 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 483d06734a2839cc7a99ea90a235511e6bc2cee7 Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Thu, 15 Jun 2017 05:28:10 -0700 Subject: [PATCH 284/407] 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 0742f56dbda0abbbd5e7c5f1e0e5c5458cb9b813 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Sat, 17 Jun 2017 13:45:20 -0700 Subject: [PATCH 285/407] 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 286/407] 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 b5ccc996f087f487d6f04c56bedb7f879d545fad Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 26 Jun 2017 09:36:15 -0700 Subject: [PATCH 287/407] 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 61505b88a558be83bd2112f4a97954cbb1d1ce7f Mon Sep 17 00:00:00 2001 From: Jass Bagga Date: Wed, 28 Jun 2017 12:11:17 -0700 Subject: [PATCH 288/407] 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 4ce09ef0bd0a39bb8e6e7c737e3d0b1be3f9db7c Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 3 Jul 2017 14:05:27 -0700 Subject: [PATCH 289/407] 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 290/407] 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 7bbcd150a2750b2615de0dedf87932bbb60551db Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Thu, 6 Jul 2017 12:07:31 -0700 Subject: [PATCH 291/407] 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 c2d4d223e7827d9dd0d0ce18d3515367c4a46cfc Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 6 Jul 2017 15:08:09 -0700 Subject: [PATCH 292/407] 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 78ee75c32f42ca5d5159fe017b0b1ff1fc6b1ce4 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 10 Jul 2017 11:42:05 -0700 Subject: [PATCH 293/407] 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 294/407] 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 3c50592c9b3608d662294208b33b007596664939 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Fri, 7 Jul 2017 14:55:05 -0700 Subject: [PATCH 295/407] 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 296/407] 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 297/407] 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 298/407] 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 299/407] 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 08c6291db29791729e35d36484c26c2a4cb32698 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Thu, 20 Jul 2017 14:23:02 -0700 Subject: [PATCH 300/407] 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 301/407] 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 44607ecf18c3858f585002b700443dc504217cae Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Mon, 24 Jul 2017 17:55:29 -0700 Subject: [PATCH 302/407] 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 3cdc49764270fec53e80644f87fc216c9871d4d3 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 25 Jul 2017 15:12:54 -0700 Subject: [PATCH 303/407] 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 04b98cf1b091d8a7fa27d3bfd8330b16114c7a0f Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 25 Jul 2017 16:31:31 -0700 Subject: [PATCH 304/407] 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 4cfeca184c7be130a67912f58f70bb036306b8b3 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 26 Jul 2017 10:27:09 -0700 Subject: [PATCH 305/407] 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 306/407] 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 307/407] 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 308/407] 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 309/407] 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 a4320ccbda79d587e931c21bb2df8adf55d6399d Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 18 Aug 2017 09:55:10 -0700 Subject: [PATCH 310/407] 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 29fd1b3b33972bc452e043309c901620ef519894 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 25 Aug 2017 09:13:43 -0700 Subject: [PATCH 311/407] 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 312/407] 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 313/407] 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 71a11d5ed6408af6417b2b9ed1e48c0246b67291 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 22 Aug 2017 16:02:46 -0700 Subject: [PATCH 314/407] 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 315/407] 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 316/407] 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 3dd029a8b54a3dac3542f11ba479ad40a29246f3 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 22 Sep 2017 12:19:39 -0700 Subject: [PATCH 317/407] 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 318/407] 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 c4788107f50d58bc730a420516f9f62505159652 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Wed, 20 Sep 2017 13:19:32 -0700 Subject: [PATCH 319/407] 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 ff0f112d7bc6b6d8f84f7ec3655f14d3d3d64a4e Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Mon, 9 Oct 2017 13:29:57 -0700 Subject: [PATCH 320/407] 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 321/407] 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 1836201beecf81c3e2b4a50cc1666f5aa51f5786 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 31 Oct 2017 17:33:49 -0700 Subject: [PATCH 322/407] 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 1cc289cf1dbdc67d1bff112f8c349c5dfba8d9d9 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 13 Nov 2017 08:49:25 -0800 Subject: [PATCH 323/407] 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 324/407] 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 6c4427cde5f05c64d792062036a7312a0edae309 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Wed, 15 Nov 2017 11:42:49 -0800 Subject: [PATCH 325/407] 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 326/407] 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 bd725635c7b03c6d840c5bee0ef3e9bf3de3653f Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 20 Nov 2017 12:15:49 -0800 Subject: [PATCH 327/407] 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 4ecabacc7642431bc7d1529e46e07354cf6a870f Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 21 Nov 2017 14:16:39 -0800 Subject: [PATCH 328/407] 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 zcmV;F1Z(?=P)AHIP00001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGqB>(^xB>_oNB=7(L1Sv^GK~z{r&6rO} zR8bVhMO+m@n`n^>S1nuxLD3=*TeOfsmlen?+6F={#2~abZOoueAZTJ(h!8>v{t3;> za?E)|5DA$%%#4KTQ&4A9oX&T-XSj3Ub>17D7(e)!JLjHr)!%vdzW1y+tlHh(J<9H6 zC)uRE&VI~3rPB^9A}Xs7r5JEE`&%NBp!)jyJP!>G(f0N>8gX8yD`m6Unw_1U4t9(0 z`^R-SPl)q;AA1VsnwSfU>5DfL{NbJ}g%6z=Y!y2`Ha4b!&wZSu_228{Z}{|MX*t&j zZo(SpokR_TtlRpvN}qckDl^<=y9pd?++5B0pB~($m6=KGCJ#9-DB`AjX=;A-hyG_1 zN-BV`t*0W3!CXzHQVMc9m8MO9D`43PoZE#OT-5;IfBKm6Z09Y^y}%qG^SC?X#c8;% zmPW2zAT)v-cn0$>D6qi4bZ1++_WElMyK_xfRaTMM6*J>-K>W+fd8@3$k!07x#Wsa& zh6e@)sHdmL2_OEsyh5>94C^nU#%=(NtDNIFl9sXrroHe%Qf zR#RHk57Kf$F@4Ym6oL;2B#=yiGL}!B8j$3hx#l>m9^&~A$eWpY>x2()toyQ7R+pg( zF;^30j9tL+`*eCvE-0oC(tt4duu~>1a~uXx^37ax999qU{L_hv32JL=bHaz`K$0hxe2L3grw7Dy*V%vN z@pF89A^<;=&QMcR6D=$(V6A3ds#K@}eDzQ1v^=?>zyKfhChP(p#i(@(kW64QmQS4) zkXbK z3DUMSq1eYz6R-(fVy2zqKPCsu9LuLp3rKRrQR_M8gpZvtIXRj8-rL(t$z&3146={t za`hC1ryCPE8iCz_=YDAha^&$-WCO9ipLYNow%GtP4m$-%g{;#8a^T^2W)0ic`s=u3>eS(!53jy;Ap}TwK(!j{X4>h0jPj$#%z}oK71%7O)%j{Z2*9CjSurx-l4;Lit}qY m*JGpEo(&`nZYkjtQN=$$-bTw6(Xv|r0000RpVtU*8~r_ZFd4k7cV&(R$~0mE^Iv%p}VGO8-7vf^b_R#j%ytLpdl?(59T$c&8m z;`{Q|D|Yu3#iqDf6vb`VUM>Fc--_b@xT|l!t*@^Y#ee+oMR9ssUH{vaqWB-L-R#@d z^*5WM_=o@L7PzlX@mcZBzuOf5`+w2;>iQqQDvE#p^Tw^OuRkk_=l{HM>#OTO{H`ee z{l7XV<@(d&o71bsfBk=(;{JWIyXyx<@%F~G+TUsMkAG7X|Mx##tNpoa=jR{(^R?RF zY4L}vMe!g0%eCU0%3)Escqy;)Yg;w@-<^SM+ilgj@2=}!+v5EE+!=P||BKy@dhX@^ zM?>_@`*PQ_e0}ux^t-cc?l!^xKI&~B_|Jm?_}6mI@6Cfg^bh{|tZVz=UxmPTMqi9? zjDJSke~0}m1b~05dB4Z}0RLI$w$J#4Fk>6H{v7J_xNQA-Yy(8M+kIUAd$2Q>KV(#}CpAcqj~A*v73thx$A&TYnzg zfPag*-(!42n6Zspe-8C|T(S-Mz(SfY3FNy9*<%Fw&s41 z@d;tZHg5en)aP;8`t#TZ{C(8hKI0R@jBVWdbEwbbvi0Y&4fwa1`#r`dgc;ko_2*EZ z$7So!V;k`IQE&Thrj4{dsHy{w?NykMRj%#x`#KIn?KI+4}R?2K;^0+dktH!i;U)`g5qyxb^2ypT}kE&tn_#_fc>Aj86zNwsGsvp+1kx)}O~V;NN2I_ZXiLW^Ciu zpF@2fm#sgKZNT40z3nqTAX^?6*j{yeq; ze;@U>&-nP5j>fKMmdfyYJ5Aj@|1?`~Nz8`|rMc(cMs7P1=9V_WH-+GLk9#4=#Qc zXDSE2S$VEq1Lv#0rjbl&CY{YMtRidLt<*!@3M4#$2!^HT0~ zNA5qN_*JMH1xD^aHt%+RC+qfN-2Rh_U&WwMVATGf+H}VE&f28C-kAL-7rzQNNP#i? zkI%Wg!b`j9YWvfj$gO5p*-0pV6^Ece-`3@gPIIL-IHw{bNf(BIE?e}ug5kM587yKBFHC$=9@{OUgY)BbjQBSR?A zjd6(A;rq)^1c3^4w;xhfzQx+hHZ<^}>whl*fquxv-dK(5kVksH z?FAMZ=%)b3HO6Ceha1{%f2@v{cj{Dt2dj2i@momu_X>{a6cFeKSMLut34PkP1xLDB zwiFQC?}k;sePbJlmta8qYrx&O+|{sz+GW9P<)DDyt*$B1`e}MYGCFH!4~lnx`#J!L ze&se^gHiiS?5j;m3WWEM=hUVje-8>J@77loR04?9pp#Jqt={b&3;a~Pey`UvZ(=`K zok+b^-U*~Y(5C~>k?Tsbd)Kk#%P^DxdTKCq|3TZ2ufbV&e+{Vt*mD^a2o%pEEd?ks zi(_t&Uf!HqC4jJNcEzn%@U}Z@dlvya6Ky~TXJSf70VA+y7!(NhYcOE{vB{S)C;{x% zK&HR1z)9N=tw8|VZjk~L%8(i8o>qaNQ-eMD#e4SD+T(uB4L!tc>u;*CXteTyu!! z>aMr&Xm?KVN))m?=d5(w9rLeXCxCoJx_#gSe87*cCj2Yt1NwkId_{Eo&7Kp$OA_*c-!WzffN>({jHZzwtX zYKOYL%DVflJKA2|t0w%~j&yr>EBi%vw7t4s+0WaNZttYBcL)8e(*9R}q}xBE32Jyn zahL2p|Dsj?YuI_$r+-xjxb;W6eL}b=yrMYU>FAQHd%fY6|73d6-LiY-5Z-o2x>qj1 z?tr}N56=bIgD&~H8?*PqLjax2ko;>`fZh%6#_{jlpsa7t2F`u&24`f~H>mloZg96; zt~2PYvTGaE?p26t_nizj+ZJAS?`PoI8~6SOC+E%j#=XCRXK&qm8(hEO^`3iggIkSS zJ@?)Qt=)IuZqV?t7eaNlgecHzF+fb}Td^9Hqj&wagt z)AN=9+;d-V;MSd!ecyd$sOxa;bxBR<43O&w=DK=#Wt z?xX4Fm1`V$(!EF*&FMHhG@BnqFMr^<(b1=Ni!(Qi$2-5i@S+`WXH%~lcXF(qpM9$A zZVTtgojld$cQ2Zb(>1BLzUJS7a2r$$DuY{II;3HDHk8K!jhvM~OI^la4p%?m_G|fD zo#hWwm(f=yx77Khy=ouz3OZV<1EzA#!=*3UsqsoM6=C;rv%N*_Zzt#XsNMbjKT(P3edg4??z?A0%^RDZYQjLwhp^r+677tVpJms?NYs&j`1{z%vLrQ-t?mdfh7)z>Y$ zcD~)$g=6a+uXCq{t)nvSRo;?qw!7WG{BcJ-zwKV9?!`Rcx_Q(Xj_3Przn>WSVw{MGg@7@*f-@h*|E-s1>A3hX6|Mao=<(FUBGg=@31Xh4R zdA=!e-nndFN}k&AWlR5#mZ&n0{4W^-N}aXgOP2i|@L#KRcpUY=WC(=Itd3r??4f_P z(qRMYf5{LCmsuUXWZ6UiYNf*l)c=wp5H7PiDzo3L>`TU%*D4(zm-umgWSgsA>^GM`89(YD zuCq2O@#Ff)HdnpaZ!Ui_e$-#9ba-6i$MunIu6nWGT>fPIsDHT5+Ni{j>m%D-^GJe!wt8{o=;>Y!oZLWH;-(3D={HTAp&f2KNkLx4bT=inVx%|oa zQGcz{;ccxI@`IGUZ{^2@nqY^)^k8E?*i~Z*EC*w!`wMvJ_C4O8V+2*Pj z`_1J~#*g}k>#U7R{J1`{%~dbUl>L0GNHY)Ms z`p7m{z1VLqe=>g5U#oO@T;j*|k!`MevEN+&Wc;XqxX#+B#E2bflMQk@2JcN}-iuiQh7-tVbo|NBxyTE5i~$4e4C}Uc>%# z`IGTm)jwCf$iG4$7oMoUKtR#CHY`@F|NfDyUf@6YPYC4VljJYXe@*G(afu)6Q?|M4 z#eQ@7lkube;W}%h5GJe!w zt8{o=;>Y!oZLWH;-(3D={HTAp&f2KNkLx4bT=inVx%|oaQGcz{;ccxI@ z`IGUZ{^2@nqY^)^k8E?*i~Z*EC*w!`wMvJ_C4O8V+2*Pj`_1J~#*g}k>#U7R{J1`{ z%~dbUl>L0GNHY)Ms`p7m{z1VLqe=>g5U#oO@ zT;j*|k!`MevEN+&Wc;XqxX#+B#EhwH43O8mG!vdvX5 z_M6L}j34#aDjgn|_;G#K(#rU)>c3PxkiS46OmlTqtX6;i9ra%(0LE^W} zD(g|n_)-60nbkpwpN{l0Ei!)8UoCaeAn{vfmG!7({HTAh%<7=TPe*#078yV4ua-J! zkoYaL%6e2Xe$+o$W_3{Frz5>gi;N%jS4$lK+QC47?5*2W!~aXqd+)Kb+k<`-kZDllPI8O8aBkU z<{5`5{sany(^N+}yJ&lu;*Y0*nrYY&&AXa#xZ;ncKse3#XfF`S#Xm`XP!Rc07|$;< zqc8mo#lLx@s$;_U{ttzb^djcI?C&HOf3vxE=g#jEQm>ZUQJ^pV48`AExpn8xt>pYS z8ygDrWuK$?b=;q40KkF*ed*^Y{$_JhZgD&H2rTi-O@Y4b^Avxxxmj(JegqN%c`4AB zexBl&hhMc#`Vp9!0)5%%Dt>wRRU73v0&`NJFa2D_?;P4Wj=*db=*vD^@%iwpHp_Da z=Al4e`uU3A9Ddbyd5*vg6zI!7WAVMiui7!w5tvGWzVvez-#h%OEpr`#NfhYIK5Owi zhhMd8wj*#l1^Uv@TKw+eS8bc`2%JcPzU=SZx&38Eg^I(k+BxG9=uVd}`_tL~X^_Z# zXTJ4$mK${{kNeoW|CJ5klP}!I%Gg);gMVyxZNGW_O3ALoZ}hQu|0~ZCc;))g9~AKr z*bhb<$)W@0vs#8DFv@#BuNDA*G}=$rLG`hBf1lJNa1igkZQJ~d!W$mYP18aBv3Gx; zlp}CB@9Ta2?92XsJUt@`ItU(q)mD>_z)`$+d+jA(4fG_uZ;TO*Tj&}qep7%)*v^oeKewAy# z^mU()z=iNW34%%o;lob@pgaPX#QP)!NC)A=Ps{(#=gZ@L5(KvcBySz=8$n6TvXFuTRl4ipG+U1Ni zLH2h-0r#(Htf8fg8fzl$>4XCAnckQ}>lQfH#H)0|AuE%c;qamvQ=7r? zngx$Gk?(c1p!X&=1KNs(k2mpmI(pEZY0ZT`fBBXs39q9^?M-UB`s|fhnoR0WU)W>j z_W2oZ+wFGxQ$A7bajZX2GlA@a~y*jyBqb@!WQzgJE8RkPo%>=&B- zdSyS?>?f67GuHwBRkxp!12w#&xJ&kr`ubaBKiBPLfLq;82=|0n9^fjv3GdqNP!*c=lpi7?b#_YZD5J2aB0lEV8Zg4k_f8PdWeS0==?t3>l zBfGvq&2M#syXA77L1&d++n{!@LR7o&WU$$`aI7F;J?R)O)4V<301mK?gdIPuaob3DVD?@D$xUV*F=gEaz9&lf6P}@W9%MILl zK73d_dGe%q`t)h>?Af#8`Sa(+%a<>U*RNj}Z{EBq-oAZXynFYqc>n%=adB}`eE9I8 z`1z-g#V^17QvCX>D&=YedPpFY1seDLkEFXy{!_x0J{ z-zB{AS!HqGJLf-*-n=Tk()HDw^$IzE-+8s1x9HCAI=_C+->TYz=YLK6b)8@N>Z?vB z)fQiuE6V7;@ZGsTqv{-VN4_Yhxdo;7+qb{^%=@dASIOvIpM3UJIsJCEL%rli^H&~k zkoC)YgDcm|%iHzjGNyXP?Jvq-SifF5D^vbm6-Z~czr@9L#clqz^YGOb5l1=C`^Kp_ z_eJ5p)rG2p_U5%+j*CXBp!}%Yd0vl}lpdRoXDo{HlgnMSV{y136t5S>IkhK6v8C31 zp8QDdt)eKO7u<6X(zb5cJ#5>3+-z@A``gL+J!*G<|4(%LNuN_s-Rr)4HJ?+jx(oga zd`^Az=+WM1)mN`xsh?HxIhDag3k24OK>azjKJWugl~TY^53#-bmdaOrCvp2Wk96Bn z_Uf*f95lVo`et;Y_HOFsRVV&b`_l7|#h03Y?|P!Ef1k;>uFPL&7Pp1f-Ed=X7B~O> zwbDgt?<~H-cYm7=xo{KQ_xg6vg?R1u?dDGvl{b9kfo`Cx+fKT}`-(C-`J8Svn;W+B z_RQU8mQj6n<$8HT*I3Ia$|FKB@P5LhV!)qTnh?~4-g z{^;F}>iWws-RVo;23|Ms8TEX5o#^kz4SJT~9s}H{{L_d2YwpAT@4l$6Z@B*F?r%3< zt*(n3H?Cc~dGp$}YPw75CiQOIxJlWayU&7CUKj4Ocj)>b z2&*CM@9y6{Kx%2_`hcUAA9W3KkomJT?5CQKlBg%A2a`tJ$L9I`agCJ9CQBAKlFdh z{6F^Gp?~QA*fns>`9uHE|1tCb*mH;eq5osoz%l0!{X_r9%>QH09r}m|JZYf{-OV4*T6C7 z5B)>`$ISm@&mH=Q{*PS)$DBX(5B(oA|BpR)=zrPz|M{nnyEVTKt*

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 329/407] 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 e07a19446b03076af6f57bb263d8831867de5509 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 21 Nov 2017 16:27:06 -0800 Subject: [PATCH 330/407] 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 331/407] 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 03130b55f4c89fe80a980ba5e34fd74a1fe4435e Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Fri, 1 Dec 2017 10:22:53 -0800 Subject: [PATCH 332/407] 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 333/407] 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 1f3f010f873f22bfdaa23d6855ad3750a4058dfc Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 12 Dec 2017 14:37:42 -0800 Subject: [PATCH 334/407] 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 335/407] 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 336/407] 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 888e4e0724f136b8b944544fadf2c46576cbd5e1 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Mon, 18 Dec 2017 16:44:45 -0800 Subject: [PATCH 337/407] 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 aac7ad71e1b5520d5147704e02b19669ce1ff873 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 20 Dec 2017 11:29:46 -0800 Subject: [PATCH 338/407] 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 339/407] 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 340/407] 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 341/407] 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 342/407] 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 343/407] 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 b7e29773337096bed5b602869b5d0d3e4e3f15b2 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 4 Jan 2018 00:51:33 +0000 Subject: [PATCH 344/407] 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 9f5b1aa18a689ea92f04012078943aa594e8a446 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Sat, 6 Jan 2018 12:25:23 -0800 Subject: [PATCH 345/407] 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 74229e57db589fac3d836e424966692629037d89 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Tue, 9 Jan 2018 11:10:29 -0800 Subject: [PATCH 346/407] 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 347/407] 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 348/407] 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 349/407] 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 350/407] 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 da8675306bf0ede6f13c3cefcc58d8898db536e8 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 24 Jan 2018 09:48:04 -0800 Subject: [PATCH 351/407] 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 af8d61395f0aa052dbde8a053c8198982587013f Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 24 Jan 2018 16:09:20 -0800 Subject: [PATCH 352/407] 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 353/407] 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 354/407] 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 e792400c311d2cebd70ea3d45baaca08b21cdad4 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 1 Feb 2018 03:08:57 +0000 Subject: [PATCH 355/407] 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 01aa75eb2995a5d3ec19c91d2ac3ffcf9b54db59 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sat, 3 Feb 2018 02:41:47 +0000 Subject: [PATCH 356/407] 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 3f03428b0cd9104b35405a49a59c434763303bb1 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 8 Feb 2018 12:24:36 -0800 Subject: [PATCH 357/407] 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 358/407] 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 f14799c4ae7becf77d39cb553caff8c28289848b Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 11 Feb 2018 12:20:11 -0800 Subject: [PATCH 359/407] 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 d51a6951c7e40a0dc6a8eb8f2a47f2517a1cb275 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Mon, 12 Feb 2018 12:29:13 -0800 Subject: [PATCH 360/407] 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 361/407] 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 362/407] 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 f897a147181ab930e9ddf2d14468cc4bf21ab5ec Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 21 Feb 2018 18:26:53 -0800 Subject: [PATCH 363/407] 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 590c621c6f202758d0c4a151e73b1c422d5c8d2e Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 22 Feb 2018 12:01:50 -0800 Subject: [PATCH 364/407] 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 365/407] 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 0b579cda2f10e7079a73a6f683ef37e24c4909c7 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 27 Feb 2018 13:59:56 -0800 Subject: [PATCH 366/407] 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 9bd4a67f7dd422ed2eefdbddb88f07d2d640ddd9 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 28 Feb 2018 11:03:13 -0800 Subject: [PATCH 367/407] 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 368/407] 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 369/407] 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 370/407] 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 abd4d62a80ba53cd94e11838756c63ac5547eb78 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 8 Mar 2018 12:56:55 -0800 Subject: [PATCH 371/407] 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 b65bd7eb22510c3cc28f56968f8287d8e6bb8f71 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 16 Mar 2018 11:14:06 -0700 Subject: [PATCH 372/407] 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 1f84511e2337789aab161cf964bf334b18fb91b4 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 16 Mar 2018 11:25:55 -0700 Subject: [PATCH 373/407] 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 86ceed533619b6ef7e042feebc30801fb22ece02 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 16 Mar 2018 12:28:58 -0700 Subject: [PATCH 374/407] 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 39fc608adb59987e6a97f4d482a2544ebfda7924 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 21 Mar 2018 09:37:08 -0700 Subject: [PATCH 375/407] 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 7e13e83348bea331ee8943c6649b27a681e872af Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 23 Mar 2018 16:34:43 -0700 Subject: [PATCH 376/407] 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 377/407] 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 bcbc4f2a499749797fa94bfb038e7e6b1d889c74 Mon Sep 17 00:00:00 2001 From: "Nate McMaster (automated)" Date: Wed, 28 Mar 2018 10:41:01 -0700 Subject: [PATCH 378/407] 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 1f41b26145b5f554c67fb0e3da9a0073c9948ca3 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Thu, 29 Mar 2018 11:13:36 -0700 Subject: [PATCH 379/407] 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 380/407] 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 381/407] 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 382/407] 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 383/407] 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 9b5015d6fee90cc77c9130d3faf7904bcdd36ed6 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 4 Apr 2018 22:22:07 -0700 Subject: [PATCH 384/407] 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 385/407] 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 386/407] 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 3385cfea1b33f0d1f74b0d312b75b4aad969620c Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Mon, 16 Apr 2018 16:56:17 -0700 Subject: [PATCH 387/407] 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 a59aaa120332db52b95449ec8850a09e1a4ccb59 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 19 Apr 2018 16:32:37 -0700 Subject: [PATCH 388/407] 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 e2f4487d098bb118a0662c2ba6b31117e10fc64d Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Thu, 19 Apr 2018 22:18:35 -0700 Subject: [PATCH 389/407] 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 aa181128ac60fb9164e7529c5bcc7e803615b7ad Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Thu, 19 Apr 2018 18:24:52 -0700 Subject: [PATCH 390/407] 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 174ca79d25b1a6b4b4dd71b5f1914449b1250848 Mon Sep 17 00:00:00 2001 From: "Nate McMaster (automated)" Date: Mon, 30 Apr 2018 14:51:39 -0700 Subject: [PATCH 391/407] 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 e0e9eb0b3609807912b1b885c67a5d0047800686 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 1 May 2018 16:57:36 -0700 Subject: [PATCH 392/407] 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 e5da69070229a88393a1e63ce51754d983db81f0 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 3 May 2018 18:01:56 -0700 Subject: [PATCH 393/407] 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 394/407] 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 e1e2970a41a4ab106774fbe87d075c284f6ac121 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 8 May 2018 15:40:53 -0700 Subject: [PATCH 395/407] 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 8d1011fe29d8acf4c30f8c9844660b7f16553004 Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 29 May 2018 09:34:54 -0700 Subject: [PATCH 396/407] 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 9b7f097870af894b6ceb375ae9ba3825100a354c Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 29 May 2018 10:03:19 -0700 Subject: [PATCH 397/407] 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 0ce4004cde8798b377608f14bc54bafcb0dc52af Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 5 Jun 2018 09:11:31 -0700 Subject: [PATCH 398/407] 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 ee20ecf20e4ac1f2aaffac591580d2fdc6d6f6de Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Tue, 12 Jun 2018 19:16:34 +0000 Subject: [PATCH 399/407] 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 4d3886fa378e61ccc21e8b8adb5e1666de0ecb40 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 27 Jun 2018 13:39:45 -0700 Subject: [PATCH 400/407] 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 498c77ed2986383c6d0d2043c64e15e347af1f92 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 11 Jul 2018 15:06:29 -0700 Subject: [PATCH 401/407] 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 349ccf680bc4491cf3c3e97aca36a6893ccc14e8 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 11 Jul 2018 18:48:17 -0700 Subject: [PATCH 402/407] 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 084406441e607886565bca38b9a756442bc7469e Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 12 Jul 2018 11:52:23 -0700 Subject: [PATCH 403/407] 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 d957ac9da0e250d38d826bbc489b6882ff157eaa Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Sat, 27 Oct 2018 01:28:14 -0700 Subject: [PATCH 404/407] 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 eba014d534ef34ea88ce6c3879b92743b825a7fe Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Sat, 27 Oct 2018 01:59:37 -0700 Subject: [PATCH 405/407] 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 a2d855406b837c17f4119bfc9767e32182969194 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Tue, 13 Nov 2018 15:30:21 -0800 Subject: [PATCH 406/407] 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 zcmV;F1Z(?=P)AHIP00001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGqB>(^xB>_oNB=7(L1Sv^GK~z{r&6rO} zR8bVhMO+m@n`n^>S1nuxLD3=*TeOfsmlen?+6F={#2~abZOoueAZTJ(h!8>v{t3;> za?E)|5DA$%%#4KTQ&4A9oX&T-XSj3Ub>17D7(e)!JLjHr)!%vdzW1y+tlHh(J<9H6 zC)uRE&VI~3rPB^9A}Xs7r5JEE`&%NBp!)jyJP!>G(f0N>8gX8yD`m6Unw_1U4t9(0 z`^R-SPl)q;AA1VsnwSfU>5DfL{NbJ}g%6z=Y!y2`Ha4b!&wZSu_228{Z}{|MX*t&j zZo(SpokR_TtlRpvN}qckDl^<=y9pd?++5B0pB~($m6=KGCJ#9-DB`AjX=;A-hyG_1 zN-BV`t*0W3!CXzHQVMc9m8MO9D`43PoZE#OT-5;IfBKm6Z09Y^y}%qG^SC?X#c8;% zmPW2zAT)v-cn0$>D6qi4bZ1++_WElMyK_xfRaTMM6*J>-K>W+fd8@3$k!07x#Wsa& zh6e@)sHdmL2_OEsyh5>94C^nU#%=(NtDNIFl9sXrroHe%Qf zR#RHk57Kf$F@4Ym6oL;2B#=yiGL}!B8j$3hx#l>m9^&~A$eWpY>x2()toyQ7R+pg( zF;^30j9tL+`*eCvE-0oC(tt4duu~>1a~uXx^37ax999qU{L_hv32JL=bHaz`K$0hxe2L3grw7Dy*V%vN z@pF89A^<;=&QMcR6D=$(V6A3ds#K@}eDzQ1v^=?>zyKfhChP(p#i(@(kW64QmQS4) zkXbK z3DUMSq1eYz6R-(fVy2zqKPCsu9LuLp3rKRrQR_M8gpZvtIXRj8-rL(t$z&3146={t za`hC1ryCPE8iCz_=YDAha^&$-WCO9ipLYNow%GtP4m$-%g{;#8a^T^2W)0ic`s=u3>eS(!53jy;Ap}TwK(!j{X4>h0jPj$#%z}oK71%7O)%j{Z2*9CjSurx-l4;Lit}qY m*JGpEo(&`nZYkjtQN=$$-bTw6(Xv|r0000RpVtU*8~r_ZFd4k7cV&(R$~0mE^Iv%p}VGO8-7vf^b_R#j%ytLpdl?(59T$c&8m z;`{Q|D|Yu3#iqDf6vb`VUM>Fc--_b@xT|l!t*@^Y#ee+oMR9ssUH{vaqWB-L-R#@d z^*5WM_=o@L7PzlX@mcZBzuOf5`+w2;>iQqQDvE#p^Tw^OuRkk_=l{HM>#OTO{H`ee z{l7XV<@(d&o71bsfBk=(;{JWIyXyx<@%F~G+TUsMkAG7X|Mx##tNpoa=jR{(^R?RF zY4L}vMe!g0%eCU0%3)Escqy;)Yg;w@-<^SM+ilgj@2=}!+v5EE+!=P||BKy@dhX@^ zM?>_@`*PQ_e0}ux^t-cc?l!^xKI&~B_|Jm?_}6mI@6Cfg^bh{|tZVz=UxmPTMqi9? zjDJSke~0}m1b~05dB4Z}0RLI$w$J#4Fk>6H{v7J_xNQA-Yy(8M+kIUAd$2Q>KV(#}CpAcqj~A*v73thx$A&TYnzg zfPag*-(!42n6Zspe-8C|T(S-Mz(SfY3FNy9*<%Fw&s41 z@d;tZHg5en)aP;8`t#TZ{C(8hKI0R@jBVWdbEwbbvi0Y&4fwa1`#r`dgc;ko_2*EZ z$7So!V;k`IQE&Thrj4{dsHy{w?NykMRj%#x`#KIn?KI+4}R?2K;^0+dktH!i;U)`g5qyxb^2ypT}kE&tn_#_fc>Aj86zNwsGsvp+1kx)}O~V;NN2I_ZXiLW^Ciu zpF@2fm#sgKZNT40z3nqTAX^?6*j{yeq; ze;@U>&-nP5j>fKMmdfyYJ5Aj@|1?`~Nz8`|rMc(cMs7P1=9V_WH-+GLk9#4=#Qc zXDSE2S$VEq1Lv#0rjbl&CY{YMtRidLt<*!@3M4#$2!^HT0~ zNA5qN_*JMH1xD^aHt%+RC+qfN-2Rh_U&WwMVATGf+H}VE&f28C-kAL-7rzQNNP#i? zkI%Wg!b`j9YWvfj$gO5p*-0pV6^Ece-`3@gPIIL-IHw{bNf(BIE?e}ug5kM587yKBFHC$=9@{OUgY)BbjQBSR?A zjd6(A;rq)^1c3^4w;xhfzQx+hHZ<^}>whl*fquxv-dK(5kVksH z?FAMZ=%)b3HO6Ceha1{%f2@v{cj{Dt2dj2i@momu_X>{a6cFeKSMLut34PkP1xLDB zwiFQC?}k;sePbJlmta8qYrx&O+|{sz+GW9P<)DDyt*$B1`e}MYGCFH!4~lnx`#J!L ze&se^gHiiS?5j;m3WWEM=hUVje-8>J@77loR04?9pp#Jqt={b&3;a~Pey`UvZ(=`K zok+b^-U*~Y(5C~>k?Tsbd)Kk#%P^DxdTKCq|3TZ2ufbV&e+{Vt*mD^a2o%pEEd?ks zi(_t&Uf!HqC4jJNcEzn%@U}Z@dlvya6Ky~TXJSf70VA+y7!(NhYcOE{vB{S)C;{x% zK&HR1z)9N=tw8|VZjk~L%8(i8o>qaNQ-eMD#e4SD+T(uB4L!tc>u;*CXteTyu!! z>aMr&Xm?KVN))m?=d5(w9rLeXCxCoJx_#gSe87*cCj2Yt1NwkId_{Eo&7Kp$OA_*c-!WzffN>({jHZzwtX zYKOYL%DVflJKA2|t0w%~j&yr>EBi%vw7t4s+0WaNZttYBcL)8e(*9R}q}xBE32Jyn zahL2p|Dsj?YuI_$r+-xjxb;W6eL}b=yrMYU>FAQHd%fY6|73d6-LiY-5Z-o2x>qj1 z?tr}N56=bIgD&~H8?*PqLjax2ko;>`fZh%6#_{jlpsa7t2F`u&24`f~H>mloZg96; zt~2PYvTGaE?p26t_nizj+ZJAS?`PoI8~6SOC+E%j#=XCRXK&qm8(hEO^`3iggIkSS zJ@?)Qt=)IuZqV?t7eaNlgecHzF+fb}Td^9Hqj&wagt z)AN=9+;d-V;MSd!ecyd$sOxa;bxBR<43O&w=DK=#Wt z?xX4Fm1`V$(!EF*&FMHhG@BnqFMr^<(b1=Ni!(Qi$2-5i@S+`WXH%~lcXF(qpM9$A zZVTtgojld$cQ2Zb(>1BLzUJS7a2r$$DuY{II;3HDHk8K!jhvM~OI^la4p%?m_G|fD zo#hWwm(f=yx77Khy=ouz3OZV<1EzA#!=*3UsqsoM6=C;rv%N*_Zzt#XsNMbjKT(P3edg4??z?A0%^RDZYQjLwhp^r+677tVpJms?NYs&j`1{z%vLrQ-t?mdfh7)z>Y$ zcD~)$g=6a+uXCq{t)nvSRo;?qw!7WG{BcJ-zwKV9?!`Rcx_Q(Xj_3Przn>WSVw{MGg@7@*f-@h*|E-s1>A3hX6|Mao=<(FUBGg=@31Xh4R zdA=!e-nndFN}k&AWlR5#mZ&n0{4W^-N}aXgOP2i|@L#KRcpUY=WC(=Itd3r??4f_P z(qRMYf5{LCmsuUXWZ6UiYNf*l)c=wp5H7PiDzo3L>`TU%*D4(zm-umgWSgsA>^GM`89(YD zuCq2O@#Ff)HdnpaZ!Ui_e$-#9ba-6i$MunIu6nWGT>fPIsDHT5+Ni{j>m%D-^GJe!wt8{o=;>Y!oZLWH;-(3D={HTAp&f2KNkLx4bT=inVx%|oa zQGcz{;ccxI@`IGUZ{^2@nqY^)^k8E?*i~Z*EC*w!`wMvJ_C4O8V+2*Pj z`_1J~#*g}k>#U7R{J1`{%~dbUl>L0GNHY)Ms z`p7m{z1VLqe=>g5U#oO@T;j*|k!`MevEN+&Wc;XqxX#+B#E2bflMQk@2JcN}-iuiQh7-tVbo|NBxyTE5i~$4e4C}Uc>%# z`IGTm)jwCf$iG4$7oMoUKtR#CHY`@F|NfDyUf@6YPYC4VljJYXe@*G(afu)6Q?|M4 z#eQ@7lkube;W}%h5GJe!w zt8{o=;>Y!oZLWH;-(3D={HTAp&f2KNkLx4bT=inVx%|oaQGcz{;ccxI@ z`IGUZ{^2@nqY^)^k8E?*i~Z*EC*w!`wMvJ_C4O8V+2*Pj`_1J~#*g}k>#U7R{J1`{ z%~dbUl>L0GNHY)Ms`p7m{z1VLqe=>g5U#oO@ zT;j*|k!`MevEN+&Wc;XqxX#+B#EhwH43O8mG!vdvX5 z_M6L}j34#aDjgn|_;G#K(#rU)>c3PxkiS46OmlTqtX6;i9ra%(0LE^W} zD(g|n_)-60nbkpwpN{l0Ei!)8UoCaeAn{vfmG!7({HTAh%<7=TPe*#078yV4ua-J! zkoYaL%6e2Xe$+o$W_3{Frz5>gi;N%jS4$lK+QC47?5*2W!~aXqd+)Kb+k<`-kZDllPI8O8aBkU z<{5`5{sany(^N+}yJ&lu;*Y0*nrYY&&AXa#xZ;ncKse3#XfF`S#Xm`XP!Rc07|$;< zqc8mo#lLx@s$;_U{ttzb^djcI?C&HOf3vxE=g#jEQm>ZUQJ^pV48`AExpn8xt>pYS z8ygDrWuK$?b=;q40KkF*ed*^Y{$_JhZgD&H2rTi-O@Y4b^Avxxxmj(JegqN%c`4AB zexBl&hhMc#`Vp9!0)5%%Dt>wRRU73v0&`NJFa2D_?;P4Wj=*db=*vD^@%iwpHp_Da z=Al4e`uU3A9Ddbyd5*vg6zI!7WAVMiui7!w5tvGWzVvez-#h%OEpr`#NfhYIK5Owi zhhMd8wj*#l1^Uv@TKw+eS8bc`2%JcPzU=SZx&38Eg^I(k+BxG9=uVd}`_tL~X^_Z# zXTJ4$mK${{kNeoW|CJ5klP}!I%Gg);gMVyxZNGW_O3ALoZ}hQu|0~ZCc;))g9~AKr z*bhb<$)W@0vs#8DFv@#BuNDA*G}=$rLG`hBf1lJNa1igkZQJ~d!W$mYP18aBv3Gx; zlp}CB@9Ta2?92XsJUt@`ItU(q)mD>_z)`$+d+jA(4fG_uZ;TO*Tj&}qep7%)*v^oeKewAy# z^mU()z=iNW34%%o;lob@pgaPX#QP)!NC)A=Ps{(#=gZ@L5(KvcBySz=8$n6TvXFuTRl4ipG+U1Ni zLH2h-0r#(Htf8fg8fzl$>4XCAnckQ}>lQfH#H)0|AuE%c;qamvQ=7r? zngx$Gk?(c1p!X&=1KNs(k2mpmI(pEZY0ZT`fBBXs39q9^?M-UB`s|fhnoR0WU)W>j z_W2oZ+wFGxQ$A7bajZX2GlA@a~y*jyBqb@!WQzgJE8RkPo%>=&B- zdSyS?>?f67GuHwBRkxp!12w#&xJ&kr`ubaBKiBPLfLq;82=|0n9^fjv3GdqNP!*c=lpi7?b#_YZD5J2aB0lEV8Zg4k_f8PdWeS0==?t3>l zBfGvq&2M#syXA77L1&d++n{!@LR7o&WU$$`aI7F;J?R)O)4V<301mK?gdIPuaob3DVD?@D$xUV*F=gEaz9&lf6P}@W9%MILl zK73d_dGe%q`t)h>?Af#8`Sa(+%a<>U*RNj}Z{EBq-oAZXynFYqc>n%=adB}`eE9I8 z`1z-g#V^17QvCX>D&=YedPpFY1seDLkEFXy{!_x0J{ z-zB{AS!HqGJLf-*-n=Tk()HDw^$IzE-+8s1x9HCAI=_C+->TYz=YLK6b)8@N>Z?vB z)fQiuE6V7;@ZGsTqv{-VN4_Yhxdo;7+qb{^%=@dASIOvIpM3UJIsJCEL%rli^H&~k zkoC)YgDcm|%iHzjGNyXP?Jvq-SifF5D^vbm6-Z~czr@9L#clqz^YGOb5l1=C`^Kp_ z_eJ5p)rG2p_U5%+j*CXBp!}%Yd0vl}lpdRoXDo{HlgnMSV{y136t5S>IkhK6v8C31 zp8QDdt)eKO7u<6X(zb5cJ#5>3+-z@A``gL+J!*G<|4(%LNuN_s-Rr)4HJ?+jx(oga zd`^Az=+WM1)mN`xsh?HxIhDag3k24OK>azjKJWugl~TY^53#-bmdaOrCvp2Wk96Bn z_Uf*f95lVo`et;Y_HOFsRVV&b`_l7|#h03Y?|P!Ef1k;>uFPL&7Pp1f-Ed=X7B~O> zwbDgt?<~H-cYm7=xo{KQ_xg6vg?R1u?dDGvl{b9kfo`Cx+fKT}`-(C-`J8Svn;W+B z_RQU8mQj6n<$8HT*I3Ia$|FKB@P5LhV!)qTnh?~4-g z{^;F}>iWws-RVo;23|Ms8TEX5o#^kz4SJT~9s}H{{L_d2YwpAT@4l$6Z@B*F?r%3< zt*(n3H?Cc~dGp$}YPw75CiQOIxJlWayU&7CUKj4Ocj)>b z2&*CM@9y6{Kx%2_`hcUAA9W3KkomJT?5CQKlBg%A2a`tJ$L9I`agCJ9CQBAKlFdh z{6F^Gp?~QA*fns>`9uHE|1tCb*mH;eq5osoz%l0!{X_r9%>QH09r}m|JZYf{-OV4*T6C7 z5B)>`$ISm@&mH=Q{*PS)$DBX(5B(oA|BpR)=zrPz|M{nnyEVTKt*

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 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 407/407] 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